Provide intellisense for newWithProfile command

Fixes #129140
This commit is contained in:
Daniel Imms 2021-07-21 18:02:48 -07:00
parent 2ff75e163d
commit f831c8d3cb
4 changed files with 168 additions and 50 deletions

View file

@ -3,14 +3,14 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ConfigurationScope, Extensions, IConfigurationNode, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { localize } from 'vs/nls';
import { ITerminalProfile, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
import { iconRegistry } from 'vs/base/common/codicons';
import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
import { Registry } from 'vs/platform/registry/common/platform';
import { Codicon, iconRegistry } from 'vs/base/common/codicons';
import { OperatingSystem } from 'vs/base/common/platform';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { localize } from 'vs/nls';
import { ConfigurationScope, Extensions, IConfigurationNode, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITerminalProfile, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
import { createProfileSchemaEnums } from 'vs/platform/terminal/common/terminalProfiles';
const terminalProfileBaseProperties: IJSONSchemaMap = {
args: {
@ -326,17 +326,9 @@ export function registerTerminalDefaultProfileConfiguration(detectedProfiles?: {
if (lastDefaultProfilesConfiguration) {
registry.deregisterConfigurations([lastDefaultProfilesConfiguration]);
}
let enumValues: string[] | undefined = undefined;
let enumDescriptions: string[] | undefined = undefined;
let profileEnum;
if (detectedProfiles) {
const result = detectedProfiles.profiles.map(e => {
return {
name: e.profileName,
description: createProfileDescription(e)
};
});
enumValues = result.map(e => e.name);
enumDescriptions = result.map(e => e.description);
profileEnum = createProfileSchemaEnums(detectedProfiles?.profiles);
}
lastDefaultProfilesConfiguration = {
id: 'terminal',
@ -349,47 +341,26 @@ export function registerTerminalDefaultProfileConfiguration(detectedProfiles?: {
markdownDescription: localize('terminal.integrated.defaultProfile.linux', "The default profile used on Linux. This setting will currently be ignored if either {0} or {1} are set.", '`terminal.integrated.shell.linux`', '`terminal.integrated.shellArgs.linux`'),
type: ['string', 'null'],
default: null,
enum: detectedProfiles?.os === OperatingSystem.Linux ? enumValues : undefined,
markdownEnumDescriptions: detectedProfiles?.os === OperatingSystem.Linux ? enumDescriptions : undefined
enum: detectedProfiles?.os === OperatingSystem.Linux ? profileEnum?.values : undefined,
markdownEnumDescriptions: detectedProfiles?.os === OperatingSystem.Linux ? profileEnum?.markdownDescriptions : undefined
},
[TerminalSettingId.DefaultProfileMacOs]: {
restricted: true,
markdownDescription: localize('terminal.integrated.defaultProfile.osx', "The default profile used on macOS. This setting will currently be ignored if either {0} or {1} are set.", '`terminal.integrated.shell.osx`', '`terminal.integrated.shellArgs.osx`'),
type: ['string', 'null'],
default: null,
enum: detectedProfiles?.os === OperatingSystem.Macintosh ? enumValues : undefined,
markdownEnumDescriptions: detectedProfiles?.os === OperatingSystem.Macintosh ? enumDescriptions : undefined
enum: detectedProfiles?.os === OperatingSystem.Macintosh ? profileEnum?.values : undefined,
markdownEnumDescriptions: detectedProfiles?.os === OperatingSystem.Macintosh ? profileEnum?.markdownDescriptions : undefined
},
[TerminalSettingId.DefaultProfileWindows]: {
restricted: true,
markdownDescription: localize('terminal.integrated.defaultProfile.windows', "The default profile used on Windows. This setting will currently be ignored if either {0} or {1} are set.", '`terminal.integrated.shell.windows`', '`terminal.integrated.shellArgs.windows`'),
type: ['string', 'null'],
default: null,
enum: detectedProfiles?.os === OperatingSystem.Windows ? enumValues : undefined,
markdownEnumDescriptions: detectedProfiles?.os === OperatingSystem.Windows ? enumDescriptions : undefined
enum: detectedProfiles?.os === OperatingSystem.Windows ? profileEnum?.values : undefined,
markdownEnumDescriptions: detectedProfiles?.os === OperatingSystem.Windows ? profileEnum?.markdownDescriptions : undefined
},
}
};
registry.registerConfiguration(lastDefaultProfilesConfiguration);
}
function createProfileDescription(profile: ITerminalProfile): string {
let description = `$(${ThemeIcon.isThemeIcon(profile.icon) ? profile.icon.id : profile.icon ? profile.icon : Codicon.terminal.id}) ${profile.profileName}\n- path: ${profile.path}`;
if (profile.args) {
if (typeof profile.args === 'string') {
description += `\n- args: "${profile.args}"`;
} else {
description += `\n- args: [${profile.args.length === 0 ? '' : profile.args.join(`','`)}]`;
}
}
if (profile.overrideName !== undefined) {
description += `\n- overrideName: ${profile.overrideName}`;
}
if (profile.color) {
description += `\n- color: ${profile.color}`;
}
if (profile.env) {
description += `\n- env: ${JSON.stringify(profile.env)}`;
}
return description;
}

View file

@ -0,0 +1,48 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Codicon } from 'vs/base/common/codicons';
import { ITerminalProfile } from 'vs/platform/terminal/common/terminal';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
export function createProfileSchemaEnums(detectedProfiles: ITerminalProfile[]): {
values: string[] | undefined,
markdownDescriptions: string[] | undefined
} {
let values: string[] | undefined = undefined;
let markdownDescriptions: string[] | undefined = undefined;
if (detectedProfiles) {
const result = detectedProfiles.map(e => {
return {
name: e.profileName,
description: createProfileDescription(e)
};
});
values = result.map(e => e.name);
markdownDescriptions = result.map(e => e.description);
}
return { values, markdownDescriptions };
}
function createProfileDescription(profile: ITerminalProfile): string {
let description = `$(${ThemeIcon.isThemeIcon(profile.icon) ? profile.icon.id : profile.icon ? profile.icon : Codicon.terminal.id}) ${profile.profileName}\n- path: ${profile.path}`;
if (profile.args) {
if (typeof profile.args === 'string') {
description += `\n- args: "${profile.args}"`;
} else {
description += `\n- args: [${profile.args.length === 0 ? '' : profile.args.join(`','`)}]`;
}
}
if (profile.overrideName !== undefined) {
description += `\n- overrideName: ${profile.overrideName}`;
}
if (profile.color) {
description += `\n- color: ${profile.color}`;
}
if (profile.env) {
description += `\n- env: ${JSON.stringify(profile.env)}`;
}
return description;
}

View file

@ -36,6 +36,7 @@ import { Direction, IRemoteTerminalService, ITerminalGroupService, ITerminalInst
import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess';
import { ILocalTerminalService, IRemoteTerminalAttachTarget, ITerminalConfigHelper, TerminalCommandId, TERMINAL_ACTION_CATEGORY } from 'vs/workbench/contrib/terminal/common/terminal';
import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey';
import { createProfileSchemaEnums } from 'vs/platform/terminal/common/terminalProfiles';
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
@ -128,6 +129,7 @@ export function registerTerminalActions() {
await accessor.get(ITerminalGroupService).showPanel(true);
}
});
registerAction2(class extends Action2 {
constructor() {
super({
@ -166,7 +168,7 @@ export function registerTerminalActions() {
if (typeof eventOrOptionsOrProfile === 'object' && eventOrOptionsOrProfile && 'profileName' in eventOrOptionsOrProfile) {
const config = terminalService.availableProfiles.find(profile => profile.profileName === eventOrOptionsOrProfile.profileName);
if (!config) {
throw new Error(`Could not find terminal profile ${eventOrOptionsOrProfile.profileName}`);
throw new Error(`Could not find terminal profile "${eventOrOptionsOrProfile.profileName}"`);
}
options = { config };
} else if (eventOrOptionsOrProfile instanceof MouseEvent || eventOrOptionsOrProfile instanceof PointerEvent || eventOrOptionsOrProfile instanceof KeyboardEvent) {
@ -2031,3 +2033,101 @@ function convertOptionsOrProfileToOptions(optionsOrProfile?: ICreateTerminalOpti
}
return optionsOrProfile;
}
export function refreshTerminalActions(detectedProfiles: ITerminalProfile[]) {
const profileEnum = createProfileSchemaEnums(detectedProfiles);
const category: ILocalizedString = { value: TERMINAL_ACTION_CATEGORY, original: 'Terminal' };
registerAction2(class extends Action2 {
constructor() {
super({
id: TerminalCommandId.NewWithProfile,
title: { value: localize('workbench.action.terminal.newWithProfile', "Create New Integrated Terminal (With Profile)"), original: 'Create New Integrated Terminal (With Profile)' },
f1: true,
category,
precondition: TerminalContextKeys.processSupported,
description: {
description: 'workbench.action.terminal.newWithProfile',
args: [{
name: 'args',
schema: {
type: 'object',
required: ['profileName'],
properties: {
profileName: {
description: localize('workbench.action.terminal.newWithProfile.profileName', "The name of the profile to create"),
type: 'string',
enum: profileEnum.values,
markdownEnumDescriptions: profileEnum.markdownDescriptions
}
}
}
}]
},
});
}
async run(accessor: ServicesAccessor, eventOrOptionsOrProfile: MouseEvent | ICreateTerminalOptions | ITerminalProfile | { profileName: string } | undefined, profile?: ITerminalProfile) {
const terminalService = accessor.get(ITerminalService);
const terminalGroupService = accessor.get(ITerminalGroupService);
const workspaceContextService = accessor.get(IWorkspaceContextService);
const commandService = accessor.get(ICommandService);
let event: MouseEvent | PointerEvent | KeyboardEvent | undefined;
let options: ICreateTerminalOptions | undefined;
if (typeof eventOrOptionsOrProfile === 'object' && eventOrOptionsOrProfile && 'profileName' in eventOrOptionsOrProfile) {
const config = terminalService.availableProfiles.find(profile => profile.profileName === eventOrOptionsOrProfile.profileName);
if (!config) {
throw new Error(`Could not find terminal profile "${eventOrOptionsOrProfile.profileName}"`);
}
options = { config };
} else if (eventOrOptionsOrProfile instanceof MouseEvent || eventOrOptionsOrProfile instanceof PointerEvent || eventOrOptionsOrProfile instanceof KeyboardEvent) {
event = eventOrOptionsOrProfile;
options = profile ? { config: profile } : undefined;
} else {
options = convertOptionsOrProfileToOptions(eventOrOptionsOrProfile);
}
const folders = workspaceContextService.getWorkspace().folders;
if (event && (event.altKey || event.ctrlKey)) {
const activeInstance = terminalService.activeInstance;
if (activeInstance) {
const cwd = await getCwdForSplit(terminalService.configHelper, activeInstance);
terminalService.splitInstance(activeInstance, options?.config, cwd);
return;
}
}
if (terminalService.isProcessSupportRegistered) {
let instance: ITerminalInstance | undefined;
let cwd: string | URI | undefined;
if (folders.length > 1) {
// multi-root workspace, create root picker
const options: IPickOptions<IQuickPickItem> = {
placeHolder: localize('workbench.action.terminal.newWorkspacePlaceholder', "Select current working directory for new terminal")
};
const workspace = await commandService.executeCommand(PICK_WORKSPACE_FOLDER_COMMAND_ID, [options]);
if (!workspace) {
// Don't create the instance if the workspace picker was canceled
return;
}
cwd = workspace.uri;
}
if (options) {
instance = terminalService.createTerminal(options);
} else {
instance = await terminalService.showProfileQuickPick('createInstance', cwd);
}
if (instance) {
terminalService.setActiveInstance(instance);
if (instance.target === TerminalLocation.Editor) {
await instance.focusWhenReady(true);
} else {
await terminalGroupService.showPanel(true);
}
}
}
}
});
}

View file

@ -32,6 +32,7 @@ import { IThemeService, Themable, ThemeIcon } from 'vs/platform/theme/common/the
import { VirtualWorkspaceContext } from 'vs/workbench/browser/contextkeys';
import { IEditableData, IViewsService } from 'vs/workbench/common/views';
import { IRemoteTerminalService, IRequestAddInstanceToGroupEvent, ITerminalEditorService, ITerminalExternalLinkProvider, ITerminalFindHost, ITerminalGroup, ITerminalGroupService, ITerminalInstance, ITerminalInstanceHost, ITerminalInstanceService, ITerminalProfileProvider, ITerminalService, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal';
import { refreshTerminalActions } from 'vs/workbench/contrib/terminal/browser/terminalActions';
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
import { TerminalEditor } from 'vs/workbench/contrib/terminal/browser/terminalEditor';
import { getColorClass, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
@ -478,16 +479,14 @@ export class TerminalService implements ITerminalService {
this._availableProfiles = result;
this._onDidChangeAvailableProfiles.fire(this._availableProfiles);
this._profilesReadyBarrier.open();
await this._refreshPlatformConfig();
await this._refreshPlatformConfig(result);
}
}
private async _refreshPlatformConfig() {
private async _refreshPlatformConfig(profiles: ITerminalProfile[]) {
const env = await this._remoteAgentService.getEnvironment();
registerTerminalDefaultProfileConfiguration({
os: env?.os || OS,
profiles: this._availableProfiles!
});
registerTerminalDefaultProfileConfiguration({ os: env?.os || OS, profiles });
refreshTerminalActions(profiles);
}
private async _detectProfiles(includeDetectedProfiles?: boolean): Promise<ITerminalProfile[]> {