Skip to content

Commit 37dec18

Browse files
committed
support aliases in zsh
1 parent 698a762 commit 37dec18

File tree

7 files changed

+64
-33
lines changed

7 files changed

+64
-33
lines changed

src/vs/platform/terminal/common/terminal.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,7 @@ export interface IProcessReadyEvent {
612612
pid: number;
613613
cwd: string;
614614
requiresWindowsMode?: boolean;
615+
aliases?: string;
615616
}
616617

617618
/**

src/vs/platform/terminal/node/terminalProcess.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
102102
};
103103
private static _lastKillOrStart = 0;
104104
private _exitCode: number | undefined;
105+
private _aliases: string | undefined;
105106
private _exitMessage: string | undefined;
106107
private _closeTimeout: any;
107108
private _ptyProcess: pty.IPty | undefined;
@@ -293,6 +294,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
293294
this._logService.trace('IPty#spawn', shellLaunchConfig.executable, args, options);
294295
const ptyProcess = (await import('node-pty')).spawn(shellLaunchConfig.executable!, args, options);
295296
this._ptyProcess = ptyProcess;
297+
this._aliases = options.env ? options.env['USER_ALIASES'] : undefined;
296298
this._childProcessMonitor = this._register(new ChildProcessMonitor(ptyProcess.pid, this._logService));
297299
this._childProcessMonitor.onDidChangeHasChildProcesses(value => this._onDidChangeProperty.fire({ type: ProcessPropertyType.HasChildProcesses, value }));
298300
this._processStartupComplete = new Promise<void>(c => {
@@ -394,7 +396,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
394396
}
395397

396398
private _sendProcessId(pid: number) {
397-
this._onProcessReady.fire({ pid, cwd: this._initialCwd, requiresWindowsMode: isWindows && getWindowsBuildNumber() < 21376 });
399+
this._onProcessReady.fire({ pid, cwd: this._initialCwd, requiresWindowsMode: isWindows && getWindowsBuildNumber() < 21376, aliases: this._aliases });
398400
}
399401

400402
private _sendProcessTitle(ptyProcess: pty.IPty): void {

src/vs/workbench/contrib/terminal/browser/media/shellIntegration-rc.zsh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,4 @@ add-zsh-hook preexec __vsc_preexec
130130
if [[ $options[login] = off && $USER_ZDOTDIR != $VSCODE_ZDOTDIR ]]; then
131131
ZDOTDIR=$USER_ZDOTDIR
132132
fi
133+
export USER_ALIASES=$(alias)

src/vs/workbench/contrib/terminal/browser/terminalInstance.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
161161
private _exitCode: number | undefined;
162162
private _exitReason: TerminalExitReason | undefined;
163163
private _skipTerminalCommands: string[];
164+
private _aliases: string[][] | undefined;
164165
private _shellType: TerminalShellType;
165166
private _title: string = '';
166167
private _titleSource: TitleEventSource = TitleEventSource.Process;
@@ -729,7 +730,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
729730

730731
const xterm = this._scopedInstantiationService.createInstance(XtermTerminal, Terminal, this._configHelper, this._cols, this._rows, this.target || TerminalLocation.Panel, this.capabilities, this.disableShellIntegrationReporting);
731732
this.xterm = xterm;
732-
this._quickFixAddon = this._scopedInstantiationService.createInstance(TerminalQuickFixAddon, this.capabilities);
733+
this._quickFixAddon = this._scopedInstantiationService.createInstance(TerminalQuickFixAddon, this._aliases, this.capabilities);
733734
this.xterm?.raw.loadAddon(this._quickFixAddon);
734735
this.registerQuickFixProvider(gitTwoDashes(), freePort(this), gitSimilar(), gitPushSetUpstream(), gitCreatePr());
735736
this._register(this._quickFixAddon.onDidRequestRerunCommand(async (e) => await this.runCommand(e.command, e.addNewLine || false)));
@@ -821,6 +822,15 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
821822
return xterm;
822823
}
823824

825+
private _parseAliases(aliasString: string): string[][] {
826+
const aliases: string[][] = [];
827+
const rows = aliasString.split('\n');
828+
for (const row of rows) {
829+
aliases.push(row.split('='));
830+
}
831+
return aliases;
832+
}
833+
824834
async runCommand(commandLine: string, addNewLine: boolean): Promise<void> {
825835
// Determine whether to send ETX (ctrl+c) before running the command. This should always
826836
// happen unless command detection can reliably say that a command is being entered and
@@ -1408,6 +1418,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
14081418
const processManager = this._scopedInstantiationService.createInstance(TerminalProcessManager, this._instanceId, this._configHelper, this.shellLaunchConfig?.cwd, deserializedCollections);
14091419
this.capabilities.add(processManager.capabilities);
14101420
processManager.onProcessReady(async (e) => {
1421+
if (e.aliases) {
1422+
this._aliases = this._parseAliases(e.aliases);
1423+
}
14111424
this._onProcessIdReady.fire(this);
14121425
this._initialCwd = await this.getInitialCwd();
14131426
// Set the initial name based on the _resolved_ shell launch config, this will also

src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,6 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
373373
this._onRestoreCommands.fire(e);
374374
}));
375375
}
376-
377376
setTimeout(() => {
378377
if (this.processState === ProcessState.Launching) {
379378
this._setProcessState(ProcessState.Running);

src/vs/workbench/contrib/terminal/browser/xterm/quickFixAddon.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
7070
private _fixId: string | undefined;
7171

7272
constructor(
73+
private readonly _aliases: string[][] | undefined,
7374
private readonly _capabilities: ITerminalCapabilityStore,
7475
@ITerminalQuickFixService private readonly _quickFixService: ITerminalQuickFixService,
7576
@IConfigurationService private readonly _configurationService: IConfigurationService,
@@ -154,7 +155,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
154155
this._expectedCommands = undefined;
155156
this._fixId = undefined;
156157
}
157-
await this._resolveQuickFixes(command);
158+
await this._resolveQuickFixes(command, this._aliases);
158159
this._fixesShown = false;
159160
}));
160161

@@ -170,7 +171,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
170171
* Resolves quick fixes, if any, based on the
171172
* @param command & its output
172173
*/
173-
private async _resolveQuickFixes(command: ITerminalCommand): Promise<void> {
174+
private async _resolveQuickFixes(command: ITerminalCommand, aliases?: string[][]): Promise<void> {
174175
const terminal = this._terminal;
175176
if (!terminal) {
176177
return;
@@ -188,7 +189,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
188189
}
189190
return provider.provideTerminalQuickFixes(command, lines, { type: 'resolved', commandLineMatcher: selector.commandLineMatcher, outputMatcher: selector.outputMatcher, exitStatus: selector.exitStatus, id: selector.id }, new CancellationTokenSource().token);
190191
};
191-
const result = await getQuickFixesForCommand(terminal, command, this._commandListeners, this._openerService, this._onDidRequestRerunCommand, resolver);
192+
const result = await getQuickFixesForCommand(aliases, terminal, command, this._commandListeners, this._openerService, this._onDidRequestRerunCommand, resolver);
192193
if (!result) {
193194
return;
194195
}
@@ -299,6 +300,7 @@ export interface ITerminalAction extends IAction {
299300
}
300301

301302
export async function getQuickFixesForCommand(
303+
aliases: string[][] | undefined,
302304
terminal: Terminal,
303305
terminalCommand: ITerminalCommand,
304306
quickFixOptions: Map<string, ITerminalQuickFixOptions[]>,
@@ -309,7 +311,7 @@ export async function getQuickFixesForCommand(
309311
const onDidRunQuickFixEmitter = new Emitter<string>();
310312
const onDidRunQuickFix = onDidRunQuickFixEmitter.event;
311313
const fixes: ITerminalAction[] = [];
312-
const newCommand = terminalCommand.command;
314+
const newCommand = resolveAliases(terminalCommand.command, aliases);
313315
const expectedCommands = [];
314316
for (const options of quickFixOptions.values()) {
315317
for (const option of options) {
@@ -424,3 +426,16 @@ function convertToQuickFixOptions(selectorProvider: ITerminalQuickFixProviderSel
424426
getQuickFixes: selectorProvider.provider.provideTerminalQuickFixes
425427
};
426428
}
429+
430+
function resolveAliases(commandLine: string, aliases?: string[][]): string {
431+
if (!aliases) {
432+
return commandLine;
433+
}
434+
for (const alias of aliases) {
435+
if (alias.length !== 2) {
436+
throw new Error('Not an alias');
437+
}
438+
commandLine.replaceAll(alias[0], alias[1]);
439+
}
440+
return commandLine;
441+
}

src/vs/workbench/contrib/terminal/test/browser/quickFixAddon.test.ts

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ suite('QuickFixAddon', () => {
5353
terminalInstance = {
5454
async freePortKillProcess(port: string): Promise<void> { }
5555
} as Pick<ITerminalInstance, 'freePortKillProcess'>;
56-
quickFixAddon = instantiationService.createInstance(TerminalQuickFixAddon, capabilities);
56+
quickFixAddon = instantiationService.createInstance(TerminalQuickFixAddon, [], capabilities);
5757
terminal.loadAddon(quickFixAddon);
5858
});
5959
suite('registerCommandFinishedListener & getMatchActions', () => {
@@ -79,23 +79,23 @@ suite('QuickFixAddon', () => {
7979
});
8080
suite('returns undefined when', () => {
8181
test('output does not match', async () => {
82-
strictEqual(await (getQuickFixesForCommand(terminal, createCommand(command, `invalid output`, GitSimilarOutputRegex, exitCode), expectedMap, openerService)), undefined);
82+
strictEqual(await (getQuickFixesForCommand([], terminal, createCommand(command, `invalid output`, GitSimilarOutputRegex, exitCode), expectedMap, openerService)), undefined);
8383
});
8484
test('command does not match', async () => {
85-
strictEqual(await (getQuickFixesForCommand(terminal, createCommand(`gt sttatus`, output, GitSimilarOutputRegex, exitCode), expectedMap, openerService)), undefined);
85+
strictEqual(await (getQuickFixesForCommand([], terminal, createCommand(`gt sttatus`, output, GitSimilarOutputRegex, exitCode), expectedMap, openerService)), undefined);
8686
});
8787
});
8888
suite('returns undefined when', () => {
8989
test('expected unix exit code', async () => {
90-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(command, output, GitSimilarOutputRegex, exitCode), expectedMap, openerService))?.fixes, actions);
90+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitSimilarOutputRegex, exitCode), expectedMap, openerService))?.fixes, actions);
9191
});
9292
test('matching exit status', async () => {
93-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(command, output, GitSimilarOutputRegex, 2), expectedMap, openerService))?.fixes, actions);
93+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitSimilarOutputRegex, 2), expectedMap, openerService))?.fixes, actions);
9494
});
9595
});
9696
suite('returns match', () => {
9797
test('returns match', async () => {
98-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(command, output, GitSimilarOutputRegex), expectedMap, openerService))?.fixes, actions);
98+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitSimilarOutputRegex), expectedMap, openerService))?.fixes, actions);
9999
});
100100

101101
test('returns multiple match', async () => {
@@ -117,14 +117,14 @@ suite('QuickFixAddon', () => {
117117
tooltip: 'Run: git push',
118118
command: 'git push'
119119
}];
120-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand('git pu', output, GitSimilarOutputRegex), expectedMap, openerService))?.fixes, actions);
120+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand('git pu', output, GitSimilarOutputRegex), expectedMap, openerService))?.fixes, actions);
121121
});
122122
test('passes any arguments through', async () => {
123123
output = `git: 'checkoutt' is not a git command. See 'git --help'.
124124
125125
The most similar commands are
126126
checkout`;
127-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand('git checkoutt .', output, GitSimilarOutputRegex), expectedMap, openerService))?.fixes, [{
127+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand('git checkoutt .', output, GitSimilarOutputRegex), expectedMap, openerService))?.fixes, [{
128128
id: 'Git Similar',
129129
enabled: true,
130130
label: 'Run: git checkout .',
@@ -153,18 +153,18 @@ suite('QuickFixAddon', () => {
153153
});
154154
suite('returns undefined when', () => {
155155
test('output does not match', async () => {
156-
strictEqual((await getQuickFixesForCommand(terminal, createCommand(command, `invalid output`, GitTwoDashesRegex, exitCode), expectedMap, openerService)), undefined);
156+
strictEqual((await getQuickFixesForCommand([], terminal, createCommand(command, `invalid output`, GitTwoDashesRegex, exitCode), expectedMap, openerService)), undefined);
157157
});
158158
test('command does not match', async () => {
159-
strictEqual((await getQuickFixesForCommand(terminal, createCommand(`gt sttatus`, output, GitTwoDashesRegex, exitCode), expectedMap, openerService)), undefined);
159+
strictEqual((await getQuickFixesForCommand([], terminal, createCommand(`gt sttatus`, output, GitTwoDashesRegex, exitCode), expectedMap, openerService)), undefined);
160160
});
161161
});
162162
suite('returns undefined when', () => {
163163
test('expected unix exit code', async () => {
164-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(command, output, GitTwoDashesRegex, exitCode), expectedMap, openerService))?.fixes, actions);
164+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitTwoDashesRegex, exitCode), expectedMap, openerService))?.fixes, actions);
165165
});
166166
test('matching exit status', async () => {
167-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(command, output, GitTwoDashesRegex, 2), expectedMap, openerService))?.fixes, actions);
167+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitTwoDashesRegex, 2), expectedMap, openerService))?.fixes, actions);
168168
});
169169
});
170170
});
@@ -200,11 +200,11 @@ suite('QuickFixAddon', () => {
200200
});
201201
suite('returns undefined when', () => {
202202
test('output does not match', async () => {
203-
strictEqual((await getQuickFixesForCommand(terminal, createCommand(portCommand, `invalid output`, FreePortOutputRegex), expectedMap, openerService))?.fixes, undefined);
203+
strictEqual((await getQuickFixesForCommand([], terminal, createCommand(portCommand, `invalid output`, FreePortOutputRegex), expectedMap, openerService))?.fixes, undefined);
204204
});
205205
});
206206
test('returns actions', async () => {
207-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(portCommand, output, FreePortOutputRegex), expectedMap, openerService))?.fixes, actionOptions);
207+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(portCommand, output, FreePortOutputRegex), expectedMap, openerService))?.fixes, actionOptions);
208208
});
209209
});
210210
}
@@ -231,18 +231,18 @@ suite('QuickFixAddon', () => {
231231
});
232232
suite('returns undefined when', () => {
233233
test('output does not match', async () => {
234-
strictEqual((await getQuickFixesForCommand(terminal, createCommand(command, `invalid output`, GitPushOutputRegex, exitCode), expectedMap, openerService)), undefined);
234+
strictEqual((await getQuickFixesForCommand([], terminal, createCommand(command, `invalid output`, GitPushOutputRegex, exitCode), expectedMap, openerService)), undefined);
235235
});
236236
test('command does not match', async () => {
237-
strictEqual((await getQuickFixesForCommand(terminal, createCommand(`git status`, output, GitPushOutputRegex, exitCode), expectedMap, openerService)), undefined);
237+
strictEqual((await getQuickFixesForCommand([], terminal, createCommand(`git status`, output, GitPushOutputRegex, exitCode), expectedMap, openerService)), undefined);
238238
});
239239
});
240240
suite('returns actions when', () => {
241241
test('expected unix exit code', async () => {
242-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(command, output, GitPushOutputRegex, exitCode), expectedMap, openerService))?.fixes, actions);
242+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitPushOutputRegex, exitCode), expectedMap, openerService))?.fixes, actions);
243243
});
244244
test('matching exit status', async () => {
245-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(command, output, GitPushOutputRegex, 2), expectedMap, openerService))?.fixes, actions);
245+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitPushOutputRegex, 2), expectedMap, openerService))?.fixes, actions);
246246
});
247247
});
248248
});
@@ -272,18 +272,18 @@ suite('QuickFixAddon', () => {
272272
});
273273
suite('returns undefined when', () => {
274274
test('output does not match', async () => {
275-
strictEqual((await getQuickFixesForCommand(terminal, createCommand(command, `invalid output`, GitCreatePrOutputRegex, exitCode), expectedMap, openerService)), undefined);
275+
strictEqual((await getQuickFixesForCommand([], terminal, createCommand(command, `invalid output`, GitCreatePrOutputRegex, exitCode), expectedMap, openerService)), undefined);
276276
});
277277
test('command does not match', async () => {
278-
strictEqual((await getQuickFixesForCommand(terminal, createCommand(`git status`, output, GitCreatePrOutputRegex, exitCode), expectedMap, openerService)), undefined);
278+
strictEqual((await getQuickFixesForCommand([], terminal, createCommand(`git status`, output, GitCreatePrOutputRegex, exitCode), expectedMap, openerService)), undefined);
279279
});
280280
test('failure exit status', async () => {
281-
strictEqual((await getQuickFixesForCommand(terminal, createCommand(command, output, GitCreatePrOutputRegex, 2), expectedMap, openerService)), undefined);
281+
strictEqual((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitCreatePrOutputRegex, 2), expectedMap, openerService)), undefined);
282282
});
283283
});
284284
suite('returns actions when', () => {
285285
test('expected unix exit code', async () => {
286-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(command, output, GitCreatePrOutputRegex, exitCode), expectedMap, openerService))?.fixes, actions);
286+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitCreatePrOutputRegex, exitCode), expectedMap, openerService))?.fixes, actions);
287287
});
288288
});
289289
});
@@ -311,18 +311,18 @@ suite('QuickFixAddon', () => {
311311
});
312312
suite('returns undefined when', () => {
313313
test('output does not match', async () => {
314-
strictEqual((await getQuickFixesForCommand(terminal, createCommand(command, `invalid output`, GitPushOutputRegex, exitCode), expectedMap, openerService)), undefined);
314+
strictEqual((await getQuickFixesForCommand([], terminal, createCommand(command, `invalid output`, GitPushOutputRegex, exitCode), expectedMap, openerService)), undefined);
315315
});
316316
test('command does not match', async () => {
317-
strictEqual((await getQuickFixesForCommand(terminal, createCommand(`git status`, output, GitPushOutputRegex, exitCode), expectedMap, openerService)), undefined);
317+
strictEqual((await getQuickFixesForCommand([], terminal, createCommand(`git status`, output, GitPushOutputRegex, exitCode), expectedMap, openerService)), undefined);
318318
});
319319
});
320320
suite('returns actions when', () => {
321321
test('expected unix exit code', async () => {
322-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(command, output, GitPushOutputRegex, exitCode), expectedMap, openerService))?.fixes, actions);
322+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitPushOutputRegex, exitCode), expectedMap, openerService))?.fixes, actions);
323323
});
324324
test('matching exit status', async () => {
325-
assertMatchOptions((await getQuickFixesForCommand(terminal, createCommand(command, output, GitPushOutputRegex, 2), expectedMap, openerService))?.fixes, actions);
325+
assertMatchOptions((await getQuickFixesForCommand([], terminal, createCommand(command, output, GitPushOutputRegex, 2), expectedMap, openerService))?.fixes, actions);
326326
});
327327
});
328328
});

0 commit comments

Comments
 (0)