Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add terminal location API #131028

Merged
merged 29 commits into from
Aug 20, 2021
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a869f86
start #45407
meganrogge Aug 16, 2021
feb96c2
add editorOptions
meganrogge Aug 16, 2021
dc03c75
works for the basic case
meganrogge Aug 16, 2021
d52b5f3
parentTerminal is a real terminal instance
meganrogge Aug 16, 2021
cf10cde
very ugly, but it works
meganrogge Aug 16, 2021
aa458e0
clean up
meganrogge Aug 17, 2021
0142818
get rid of target
meganrogge Aug 17, 2021
1ce1f73
clean up
meganrogge Aug 17, 2021
b48448d
clean up
meganrogge Aug 17, 2021
fdc5cc2
remove some lines
meganrogge Aug 17, 2021
29276e8
Merge branch 'main' into merogge/split-api
meganrogge Aug 17, 2021
d79f5be
Merge branch 'main' into merogge/split-api
meganrogge Aug 17, 2021
0bc2f1f
Update src/vs/workbench/api/common/extHostTerminalService.ts
meganrogge Aug 17, 2021
0e36ae1
Update src/vs/workbench/api/browser/mainThreadTerminalService.ts
meganrogge Aug 17, 2021
f46876b
get rid of isSplitTerminal and forceSplit
meganrogge Aug 17, 2021
6593e3a
remove isSplitTerminal and target from profile ocreation options
meganrogge Aug 18, 2021
e4f9a07
bring back defaultLocation setting strings
meganrogge Aug 18, 2021
b6046df
splitting is broken with parentTerminal unable to be resolved in main…
meganrogge Aug 18, 2021
8dce8c2
delete console.logs
meganrogge Aug 18, 2021
d28dffd
clean up
meganrogge Aug 18, 2021
163bfe6
add todo
meganrogge Aug 18, 2021
dfa3fee
Merge branch 'main' into merogge/split-api
meganrogge Aug 19, 2021
b62b4de
use ExtHostTerminalIdentifier instead of ExtHostTerminal
meganrogge Aug 19, 2021
1e2febc
Update src/vs/workbench/contrib/terminal/browser/terminalService.ts
meganrogge Aug 19, 2021
00f6275
clean up
meganrogge Aug 19, 2021
d55713e
use instance id for terminal profiles
meganrogge Aug 19, 2021
3cee073
Merge branch 'main' into merogge/split-api
meganrogge Aug 19, 2021
21fd2ae
Merge branch 'main' into merogge/split-api
meganrogge Aug 20, 2021
25692e4
get profiles to work with splits
meganrogge Aug 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/vs/platform/terminal/common/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,9 @@ export interface ICreateContributedTerminalProfileOptions {
isSplitTerminal?: boolean;
}

export const enum TerminalLocation {
TerminalView = 'view',
Editor = 'editor'
export enum TerminalLocation {
Panel = 0,
Editor = 1
}

export type TerminalIcon = ThemeIcon | URI | { light: URI; dark: URI };
Expand Down
36 changes: 36 additions & 0 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,42 @@ declare module 'vscode' {
readonly state: TerminalState;
}

export interface TerminalOptions {
location?: TerminalLocation | TerminalEditorLocationOptions | TerminalSplitLocationOptions;
}

export interface ExtensionTerminalOptions {
location?: TerminalLocation | TerminalEditorLocationOptions | TerminalSplitLocationOptions;
}

export enum TerminalLocation {
Panel = 0,
Editor = 1,
}

export interface TerminalEditorLocationOptions {
/**
* A view column in which the {@link Terminal terminal} should be shown in the editor area.
* Use {@link ViewColumn.Active active} to open in the active editor group, other values are
* adjusted to be `Min(column, columnCount + 1)`, the
* {@link ViewColumn.Active active}-column is not adjusted. Use
* {@linkcode ViewColumn.Beside} to open the editor to the side of the currently active one.
*/
viewColumn: ViewColumn;
/**
* An optional flag that when `true` will stop the {@link Terminal} from taking focus.
*/
preserveFocus?: boolean;
}

export interface TerminalSplitLocationOptions {
/**
* The parent terminal to split this terminal beside. This works whether the parent terminal
* is in the panel or the editor area.
*/
parentTerminal: Terminal;
}

/**
* An event representing a change in a {@link Terminal.state terminal's state}.
*/
Expand Down
12 changes: 11 additions & 1 deletion src/vs/workbench/api/browser/mainThreadTerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy, ITerminal
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { withNullAsUndefined } from 'vs/base/common/types';
import { OperatingSystem, OS } from 'vs/base/common/platform';
import { TerminalEditorLocationOptions } from 'vscode';
import { ExtHostTerminal } from 'vs/workbench/api/common/extHostTerminalService';

@extHostNamedCustomer(MainContext.MainThreadTerminalService)
export class MainThreadTerminalService implements MainThreadTerminalServiceShape {
Expand Down Expand Up @@ -150,13 +152,21 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
if (!terminal) {
terminal = await this._terminalService.createTerminal({
config: shellLaunchConfig,
target: launchConfig.target
location: !launchConfig.location ? undefined : await this._getLocation(launchConfig.location)
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
});
}
r(terminal);
}));
}

private async _getLocation(location: TerminalLocation | TerminalEditorLocationOptions | { parentTerminal: ExtHostTerminal }): Promise<TerminalLocation | TerminalEditorLocationOptions | { parentTerminal: ITerminalInstance } | undefined> {
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
if (typeof location === 'object' && 'parentTerminal' in location) {
const parentTerminal = await this._extHostTerminals.get(location.parentTerminal._id.toString());
return parentTerminal ? { parentTerminal } : undefined;
}
return location;
}

public async $show(id: TerminalIdentifier, preserveFocus: boolean): Promise<void> {
const terminalInstance = await this._getTerminalInstance(id);
if (terminalInstance) {
Expand Down
4 changes: 4 additions & 0 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
},
createTerminal(nameOrOptions?: vscode.TerminalOptions | vscode.ExtensionTerminalOptions | string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal {
if (typeof nameOrOptions === 'object') {
if ('location' in nameOrOptions) {
checkProposedApiEnabled(extension);
}
if ('pty' in nameOrOptions) {
return extHostTerminalService.createExtensionTerminal(nameOrOptions);
}
Expand Down Expand Up @@ -1234,6 +1237,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
TaskRevealKind: extHostTypes.TaskRevealKind,
TaskScope: extHostTypes.TaskScope,
TerminalLink: extHostTypes.TerminalLink,
TerminalLocation: extHostTypes.TerminalLocation,
TerminalProfile: extHostTypes.TerminalProfile,
TextDocumentSaveReason: extHostTypes.TextDocumentSaveReason,
TextEdit: extHostTypes.TextEdit,
Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { IExtensionIdWithVersion } from 'vs/platform/userDataSync/common/extensi
import { WorkspaceTrustRequestOptions } from 'vs/platform/workspace/common/workspaceTrust';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
import { ExtHostInteractive } from 'vs/workbench/api/common/extHostInteractive';
import { ExtHostTerminal } from 'vs/workbench/api/common/extHostTerminalService';
import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/extHostTypes';
import * as tasks from 'vs/workbench/api/common/shared/tasks';
Expand Down Expand Up @@ -487,6 +488,7 @@ export interface TerminalLaunchConfig {
useShellEnvironment?: boolean;
isSplitTerminal?: boolean;
target?: TerminalLocation;
location?: TerminalLocation | { viewColumn: number, preserveFocus?: boolean } | { parentTerminal: ExtHostTerminal };
}

export interface MainThreadTerminalServiceShape extends IDisposable {
Expand Down
19 changes: 13 additions & 6 deletions src/vs/workbench/api/common/extHostTerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export interface ITerminalInternalOptions {
isFeatureTerminal?: boolean;
useShellEnvironment?: boolean;
isSplitTerminal?: boolean;
target?: TerminalLocation;
parentTerminal?: ExtHostTerminal;
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
}

export const IExtHostTerminalService = createDecorator<IExtHostTerminalService>('IExtHostTerminalService');
Expand Down Expand Up @@ -148,11 +148,19 @@ export class ExtHostTerminal {
isExtensionOwnedTerminal: true,
useShellEnvironment: withNullAsUndefined(internalOptions?.useShellEnvironment),
isSplitTerminal: internalOptions?.isSplitTerminal,
target: internalOptions?.target
location: !options.location ? undefined : this._getLocation(options.location, internalOptions?.parentTerminal)
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
});
}

public async createExtensionTerminal(isSplitTerminal?: boolean, target?: TerminalLocation, iconPath?: TerminalIcon, color?: ThemeColor): Promise<number> {
private _getLocation(location: TerminalLocation | vscode.TerminalEditorLocationOptions | vscode.TerminalSplitLocationOptions, parentTerminal?: ExtHostTerminal): TerminalLocation | vscode.TerminalEditorLocationOptions | { parentTerminal: ExtHostTerminal } | undefined {
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
if (typeof location === 'object' && 'parentTerminal' in location) {
// use the ExtHostTerminal with value = to the parentTerminal
return parentTerminal ? { parentTerminal } : undefined;
}
return location;
}

public async createExtensionTerminal(isSplitTerminal?: boolean, iconPath?: TerminalIcon, color?: ThemeColor): Promise<number> {
if (typeof this._id !== 'string') {
throw new Error('Terminal has already been created');
}
Expand All @@ -161,8 +169,7 @@ export class ExtHostTerminal {
isExtensionCustomPtyTerminal: true,
icon: iconPath,
color: ThemeColor.isThemeColor(color) ? color.id : undefined,
isSplitTerminal,
target
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
isSplitTerminal
});
// At this point, the id has been set via `$acceptTerminalOpened`
if (typeof this._id === 'string') {
Expand Down Expand Up @@ -393,7 +400,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I
public createExtensionTerminal(options: vscode.ExtensionTerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal {
const terminal = new ExtHostTerminal(this._proxy, generateUuid(), options, options.name);
const p = new ExtHostPseudoterminal(options.pty);
terminal.createExtensionTerminal(internalOptions?.isSplitTerminal, internalOptions?.target, asTerminalIcon(options.iconPath), asTerminalColor(options.color)).then(id => {
terminal.createExtensionTerminal(internalOptions?.isSplitTerminal, asTerminalIcon(options.iconPath), asTerminalColor(options.color)).then(id => {
const disposable = this._setupExtHostProcessListeners(id, p);
this._terminalProcessDisposables[id] = disposable;
});
Expand Down
5 changes: 5 additions & 0 deletions src/vs/workbench/api/common/extHostTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,11 @@ export class TerminalLink implements vscode.TerminalLink {
}
}

export enum TerminalLocation {
Panel = 0,
Editor = 1,
}

export class TerminalProfile implements vscode.TerminalProfile {
constructor(
public options: vscode.TerminalOptions | vscode.ExtensionTerminalOptions
Expand Down
8 changes: 8 additions & 0 deletions src/vs/workbench/api/node/extHostTerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
public createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal {
const terminal = new ExtHostTerminal(this._proxy, generateUuid(), options, options.name);
this._terminals.push(terminal);
if (options.location && typeof options.location === 'object' && 'parentTerminal' in options.location) {
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
const parentTerminal = options.location.parentTerminal;
if (parentTerminal) {
const parentExtHostTerminal = this._terminals.find(t => t.value === parentTerminal);
internalOptions = internalOptions ? internalOptions : {};
internalOptions.parentTerminal = parentExtHostTerminal;
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
}
}
terminal.create(options, internalOptions);
return terminal.value;
}
Expand Down
17 changes: 12 additions & 5 deletions src/vs/workbench/contrib/terminal/browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Orientation } from 'vs/base/browser/ui/splitview/splitview';
import { IEditableData } from 'vs/workbench/common/views';
import { DeserializedTerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorSerializer';
import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput';
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';

export const ITerminalService = createDecorator<ITerminalService>('terminalService');
export const ITerminalEditorService = createDecorator<ITerminalEditorService>('terminalEditorService');
Expand Down Expand Up @@ -198,7 +199,7 @@ export interface ITerminalEditorService extends ITerminalInstanceHost, ITerminal
/** Gets all _terminal editor_ instances. */
readonly instances: readonly ITerminalInstance[];

openEditor(instance: ITerminalInstance, sideGroup?: boolean): Promise<void>;
openEditor(instance: ITerminalInstance, sideGroup?: boolean, editorOptions?: TerminalEditorLocation): Promise<void>;
detachActiveEditorInstance(): ITerminalInstance;
detachInstance(instance: ITerminalInstance): void;
splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfig?: IShellLaunchConfig): ITerminalInstance;
Expand All @@ -219,10 +220,6 @@ export interface ICreateTerminalOptions {
* specified.
*/
cwd?: string | URI;
/**
* Where to create the terminal, when not specified the default target will be used.
*/
target?: TerminalLocation;
/**
* Creates a split terminal without requiring a terminal instance to split, for example when splitting
* a terminal editor
Expand All @@ -236,6 +233,16 @@ export interface ICreateTerminalOptions {
* The terminal instance to split
*/
instanceToSplit?: ITerminalInstance;

meganrogge marked this conversation as resolved.
Show resolved Hide resolved
/**
* The location at which to create the terminal
*/
location?: TerminalLocation | TerminalEditorLocation | { parentTerminal: ITerminalInstance };
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
}

export interface TerminalEditorLocation {
viewColumn: EditorGroupColumn,
preserveFocus?: boolean
}

/**
Expand Down
14 changes: 7 additions & 7 deletions src/vs/workbench/contrib/terminal/browser/terminalActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export function registerTerminalActions() {
const terminalService = accessor.get(ITerminalService);
const terminalGroupService = accessor.get(ITerminalGroupService);
if (terminalService.isProcessSupportRegistered) {
const instance = await terminalService.createTerminal({ target: terminalService.configHelper.config.defaultLocation });
const instance = await terminalService.createTerminal({ location: terminalService.configHelper.config.defaultLocation });
if (!instance) {
return;
}
Expand All @@ -148,7 +148,7 @@ export function registerTerminalActions() {
async run(accessor: ServicesAccessor) {
const terminalService = accessor.get(ITerminalService);
const instance = await terminalService.createTerminal({
target: TerminalLocation.Editor
location: TerminalLocation.Editor
});
instance.focusWhenReady();
}
Expand All @@ -167,7 +167,7 @@ export function registerTerminalActions() {
async run(accessor: ServicesAccessor) {
const terminalService = accessor.get(ITerminalService);
const instance = await terminalService.createTerminal({
target: TerminalLocation.Editor,
location: TerminalLocation.Editor,
forceSplit: true
});
instance.focusWhenReady();
Expand Down Expand Up @@ -386,7 +386,7 @@ export function registerTerminalActions() {
async run(accessor: ServicesAccessor) {
const terminalService = accessor.get(ITerminalService);
const terminalGroupService = accessor.get(ITerminalGroupService);
const instance = terminalService.activeInstance || await terminalService.createTerminal({ target: TerminalLocation.TerminalView });
const instance = terminalService.activeInstance || await terminalService.createTerminal({ location: TerminalLocation.Panel });
if (!instance) {
return;
}
Expand Down Expand Up @@ -1425,15 +1425,15 @@ export function registerTerminalActions() {
const terminalService = accessor.get(ITerminalService);
const workspaceContextService = accessor.get(IWorkspaceContextService);
const options = convertOptionsOrProfileToOptions(optionsOrProfile);
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
const activeInstance = terminalService.getInstanceHost(options?.target).activeInstance;
const activeInstance = terminalService.getInstanceHost(options?.location === TerminalLocation.Editor ? TerminalLocation.Editor : TerminalLocation.Panel).activeInstance;
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
if (!activeInstance) {
return;
}
const cwd = await getCwdForSplit(terminalService.configHelper, activeInstance, workspaceContextService.getWorkspace().folders, commandService);
if (cwd === undefined) {
return undefined;
}
const instance = await terminalService.createTerminal({ instanceToSplit: activeInstance, config: options?.config, cwd, target: activeInstance.target });
const instance = await terminalService.createTerminal({ instanceToSplit: activeInstance, config: options?.config, cwd, location: activeInstance.target });
if (instance) {
if (instance.target === TerminalLocation.Editor) {
instance.focusWhenReady();
Expand Down Expand Up @@ -1620,7 +1620,7 @@ export function registerTerminalActions() {

if (terminalService.isProcessSupportRegistered) {
eventOrOptions = !eventOrOptions || eventOrOptions instanceof MouseEvent ? {} : eventOrOptions;
eventOrOptions.target = eventOrOptions.target || terminalService.configHelper.config.defaultLocation;
eventOrOptions.location = eventOrOptions.location || terminalService.configHelper.config.defaultLocation;
let instance: ITerminalInstance | undefined;
if (folders.length <= 1) {
// Allow terminal service to handle the path when there is only a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { IEditorOptions } from 'vs/platform/editor/common/editor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { TerminalLocation } from 'vs/platform/terminal/common/terminal';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { IEditorOpenContext } from 'vs/workbench/common/editor';
Expand All @@ -32,6 +31,7 @@ import { BrowserFeatures } from 'vs/base/browser/canIUse';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { openContextMenu } from 'vs/workbench/contrib/terminal/browser/terminalContextMenu';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { TerminalLocation } from 'vs/platform/terminal/common/terminal';

const findWidgetSelector = '.simple-find-part-wrapper';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { EditorActivation } from 'vs/platform/editor/common/editor';
import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation';
import { IShellLaunchConfig, TerminalLocation } from 'vs/platform/terminal/common/terminal';
import { IEditorInput } from 'vs/workbench/common/editor';
import { IRemoteTerminalService, ITerminalEditorService, ITerminalInstance, ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { IRemoteTerminalService, ITerminalEditorService, ITerminalInstance, ITerminalInstanceService, TerminalEditorLocation } from 'vs/workbench/contrib/terminal/browser/terminal';
import { TerminalEditor } from 'vs/workbench/contrib/terminal/browser/terminalEditor';
import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput';
import { DeserializedTerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorSerializer';
Expand Down Expand Up @@ -158,18 +158,19 @@ export class TerminalEditorService extends Disposable implements ITerminalEditor
this._onDidChangeActiveInstance.fire(this.activeInstance);
}

async openEditor(instance: ITerminalInstance, sideGroup: boolean = false): Promise<void> {
async openEditor(instance: ITerminalInstance, sideGroup: boolean = false, editorOptions?: TerminalEditorLocation): Promise<void> {
const resource = this.resolveResource(instance);
if (resource) {
await this._editorService.openEditor({
resource,
options:
{
pinned: true,
forceReload: true
forceReload: true,
preserveFocus: editorOptions?.preserveFocus
}
},
sideGroup ? SIDE_GROUP : undefined);
editorOptions?.viewColumn || sideGroup ? SIDE_GROUP : undefined);
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
Loading