Skip to content

Commit 1d60909

Browse files
committed
Implement Terminal.creationOptions API
Fixes #63052
1 parent 5d3c599 commit 1d60909

File tree

6 files changed

+87
-9
lines changed

6 files changed

+87
-9
lines changed

extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { window, Pseudoterminal, EventEmitter, TerminalDimensions, workspace, ConfigurationTarget, Disposable } from 'vscode';
7-
import { doesNotThrow, equal, ok, deepEqual } from 'assert';
7+
import { doesNotThrow, equal, ok, deepEqual, throws } from 'assert';
88

99
suite('window namespace tests', () => {
1010
suiteSetup(async () => {
@@ -84,6 +84,30 @@ suite('window namespace tests', () => {
8484
}
8585
});
8686

87+
test('creationOptions should be set and readonly for TerminalOptions terminals', (done) => {
88+
disposables.push(window.onDidOpenTerminal(term => {
89+
try {
90+
equal(terminal, term);
91+
} catch (e) {
92+
done(e);
93+
}
94+
terminal.dispose();
95+
disposables.push(window.onDidCloseTerminal(() => done()));
96+
}));
97+
const options = {
98+
name: 'foo',
99+
hideFromUser: true
100+
};
101+
const terminal = window.createTerminal(options);
102+
try {
103+
equal(terminal.name, 'foo');
104+
deepEqual(terminal.creationOptions, options);
105+
throws(() => (<any>terminal.creationOptions).name = 'bad', 'creationOptions should be readonly at runtime');
106+
} catch (e) {
107+
done(e);
108+
}
109+
});
110+
87111
test('onDidOpenTerminal should fire when a terminal is created', (done) => {
88112
disposables.push(window.onDidOpenTerminal(term => {
89113
try {
@@ -369,6 +393,33 @@ suite('window namespace tests', () => {
369393
};
370394
const terminal = window.createTerminal({ name: 'foo', pty });
371395
});
396+
397+
test('creationOptions should be set and readonly for ExtensionTerminalOptions terminals', (done) => {
398+
disposables.push(window.onDidOpenTerminal(term => {
399+
try {
400+
equal(terminal, term);
401+
} catch (e) {
402+
done(e);
403+
}
404+
terminal.dispose();
405+
disposables.push(window.onDidCloseTerminal(() => done()));
406+
}));
407+
const writeEmitter = new EventEmitter<string>();
408+
const pty: Pseudoterminal = {
409+
onDidWrite: writeEmitter.event,
410+
open: () => { },
411+
close: () => { }
412+
};
413+
const options = { name: 'foo', pty };
414+
const terminal = window.createTerminal(options);
415+
try {
416+
equal(terminal.name, 'foo');
417+
deepEqual(terminal.creationOptions, options);
418+
throws(() => (<any>terminal.creationOptions).name = 'bad', 'creationOptions should be readonly at runtime');
419+
} catch (e) {
420+
done(e);
421+
}
422+
});
372423
});
373424
});
374425
});

src/vs/vscode.proposed.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,13 @@ declare module 'vscode' {
689689
}
690690

691691
export interface Terminal {
692+
/**
693+
* The object used to initialize the terminal, this is useful for things like detecting the
694+
* shell type of shells not launched by the extension or detecting what folder the shell was
695+
* launched in.
696+
*/
697+
readonly creationOptions: Readonly<TerminalOptions | ExtensionTerminalOptions>;
698+
692699
/**
693700
* The current dimensions of the terminal. This will be `undefined` immediately after the
694701
* terminal is created as the dimensions are not known until shortly after the terminal is

src/vs/workbench/api/browser/mainThreadTerminalService.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,18 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
167167
}
168168

169169
private _onTerminalOpened(terminalInstance: ITerminalInstance): void {
170+
const shellLaunchConfigDto: IShellLaunchConfigDto = {
171+
name: terminalInstance.shellLaunchConfig.name,
172+
executable: terminalInstance.shellLaunchConfig.executable,
173+
args: terminalInstance.shellLaunchConfig.args,
174+
cwd: terminalInstance.shellLaunchConfig.cwd,
175+
env: terminalInstance.shellLaunchConfig.env
176+
};
170177
if (terminalInstance.title) {
171-
this._proxy.$acceptTerminalOpened(terminalInstance.id, terminalInstance.title);
178+
this._proxy.$acceptTerminalOpened(terminalInstance.id, terminalInstance.title, shellLaunchConfigDto);
172179
} else {
173180
terminalInstance.waitForTitle().then(title => {
174-
this._proxy.$acceptTerminalOpened(terminalInstance.id, title);
181+
this._proxy.$acceptTerminalOpened(terminalInstance.id, title, shellLaunchConfigDto);
175182
});
176183
}
177184
}

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,7 @@ export interface ITerminalDimensionsDto {
11971197

11981198
export interface ExtHostTerminalServiceShape {
11991199
$acceptTerminalClosed(id: number): void;
1200-
$acceptTerminalOpened(id: number, name: string): void;
1200+
$acceptTerminalOpened(id: number, name: string, shellLaunchConfig: IShellLaunchConfigDto): void;
12011201
$acceptActiveTerminalChanged(id: number | null): void;
12021202
$acceptTerminalProcessId(id: number, processId: number): void;
12031203
$acceptTerminalProcessData(id: number, data: string): void;

src/vs/workbench/api/common/extHostTerminalService.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,12 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
102102

103103
constructor(
104104
proxy: MainThreadTerminalServiceShape,
105+
private readonly _creationOptions: vscode.TerminalOptions | vscode.ExtensionTerminalOptions,
105106
private _name?: string,
106107
id?: number
107108
) {
108109
super(proxy, id);
110+
this._creationOptions = Object.freeze(this._creationOptions);
109111
this._pidPromise = new Promise<number>(c => this._pidPromiseComplete = c);
110112
}
111113

@@ -162,6 +164,10 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
162164
return this._pidPromise;
163165
}
164166

167+
public get creationOptions(): Readonly<vscode.TerminalOptions | vscode.ExtensionTerminalOptions> {
168+
return this._creationOptions;
169+
}
170+
165171
public sendText(text: string, addNewLine: boolean = true): void {
166172
this._checkDisposed();
167173
this._queueApiRequest(this._proxy.$sendText, [text, addNewLine]);
@@ -310,7 +316,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
310316
public abstract $acceptWorkspacePermissionsChanged(isAllowed: boolean): void;
311317

312318
public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal {
313-
const terminal = new ExtHostTerminal(this._proxy, options.name);
319+
const terminal = new ExtHostTerminal(this._proxy, options, options.name);
314320
const p = new ExtHostPseudoterminal(options.pty);
315321
terminal.createExtensionTerminal().then(id => this._setupExtHostProcessListeners(id, p));
316322
this._terminals.push(terminal);
@@ -390,7 +396,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
390396
}
391397
}
392398

393-
public $acceptTerminalOpened(id: number, name: string): void {
399+
public $acceptTerminalOpened(id: number, name: string, shellLaunchConfigDto: IShellLaunchConfigDto): void {
394400
const index = this._getTerminalObjectIndexById(this._terminals, id);
395401
if (index !== null) {
396402
// The terminal has already been created (via createTerminal*), only fire the event
@@ -399,7 +405,14 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
399405
return;
400406
}
401407

402-
const terminal = new ExtHostTerminal(this._proxy, name, id);
408+
const creationOptions: vscode.TerminalOptions = {
409+
name: shellLaunchConfigDto.name,
410+
shellPath: shellLaunchConfigDto.executable,
411+
shellArgs: shellLaunchConfigDto.args,
412+
cwd: typeof shellLaunchConfigDto.cwd === 'string' ? shellLaunchConfigDto.cwd : URI.revive(shellLaunchConfigDto.cwd),
413+
env: shellLaunchConfigDto.env
414+
};
415+
const terminal = new ExtHostTerminal(this._proxy, creationOptions, name, id);
403416
this._terminals.push(terminal);
404417
this._onDidOpenTerminal.fire(terminal);
405418
terminal.isOpen = true;

src/vs/workbench/api/node/extHostTerminalService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
4545
}
4646

4747
public createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal {
48-
const terminal = new ExtHostTerminal(this._proxy, name);
48+
const terminal = new ExtHostTerminal(this._proxy, { name, shellPath, shellArgs }, name);
4949
terminal.create(shellPath, shellArgs);
5050
this._terminals.push(terminal);
5151
return terminal;
5252
}
5353

5454
public createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal {
55-
const terminal = new ExtHostTerminal(this._proxy, options.name);
55+
const terminal = new ExtHostTerminal(this._proxy, options, options.name);
5656
terminal.create(options.shellPath, options.shellArgs, options.cwd, options.env, /*options.waitOnExit*/ undefined, options.strictEnv, options.hideFromUser);
5757
this._terminals.push(terminal);
5858
return terminal;

0 commit comments

Comments
 (0)