Path: blob/main/src/vs/workbench/contrib/externalTerminal/electron-browser/externalTerminal.contribution.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as nls from '../../../../nls.js';6import * as paths from '../../../../base/common/path.js';7import { DEFAULT_TERMINAL_OSX, IExternalTerminalSettings } from '../../../../platform/externalTerminal/common/externalTerminal.js';8import { MenuId, MenuRegistry } from '../../../../platform/actions/common/actions.js';9import { KeyMod, KeyCode } from '../../../../base/common/keyCodes.js';10import { IHistoryService } from '../../../services/history/common/history.js';11import { KeybindingsRegistry, KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';12import { Schemas } from '../../../../base/common/network.js';13import { IConfigurationRegistry, Extensions, ConfigurationScope, type IConfigurationPropertySchema } from '../../../../platform/configuration/common/configurationRegistry.js';14import { Registry } from '../../../../platform/registry/common/platform.js';15import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from '../../../common/contributions.js';16import { IExternalTerminalService } from '../../../../platform/externalTerminal/electron-browser/externalTerminalService.js';17import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';18import { TerminalContextKeys } from '../../terminal/common/terminalContextKey.js';19import { IRemoteAuthorityResolverService } from '../../../../platform/remote/common/remoteAuthorityResolver.js';20import { LifecyclePhase } from '../../../services/lifecycle/common/lifecycle.js';2122const OPEN_NATIVE_CONSOLE_COMMAND_ID = 'workbench.action.terminal.openNativeConsole';23KeybindingsRegistry.registerCommandAndKeybindingRule({24id: OPEN_NATIVE_CONSOLE_COMMAND_ID,25primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyC,26when: TerminalContextKeys.notFocus,27weight: KeybindingWeight.WorkbenchContrib,28handler: async (accessor) => {29const historyService = accessor.get(IHistoryService);30// Open external terminal in local workspaces31const terminalService = accessor.get(IExternalTerminalService);32const configurationService = accessor.get(IConfigurationService);33const remoteAuthorityResolverService = accessor.get(IRemoteAuthorityResolverService);34const root = historyService.getLastActiveWorkspaceRoot();35const config = configurationService.getValue<IExternalTerminalSettings>('terminal.external');3637// It's a local workspace, open the root38if (root?.scheme === Schemas.file) {39terminalService.openTerminal(config, root.fsPath);40return;41}4243// If it's a remote workspace, open the canonical URI if it is a local folder44try {45if (root?.scheme === Schemas.vscodeRemote) {46const canonicalUri = await remoteAuthorityResolverService.getCanonicalURI(root);47if (canonicalUri.scheme === Schemas.file) {48terminalService.openTerminal(config, canonicalUri.fsPath);49return;50}51}52} catch { }5354// Open the current file's folder if it's local or its canonical URI is local55// Opens current file's folder, if no folder is open in editor56const activeFile = historyService.getLastActiveFile(Schemas.file);57if (activeFile?.scheme === Schemas.file) {58terminalService.openTerminal(config, paths.dirname(activeFile.fsPath));59return;60}61try {62if (activeFile?.scheme === Schemas.vscodeRemote) {63const canonicalUri = await remoteAuthorityResolverService.getCanonicalURI(activeFile);64if (canonicalUri.scheme === Schemas.file) {65terminalService.openTerminal(config, canonicalUri.fsPath);66return;67}68}69} catch { }7071// Fallback to opening without a cwd which will end up using the local home path72terminalService.openTerminal(config, undefined);73}74});7576MenuRegistry.appendMenuItem(MenuId.CommandPalette, {77command: {78id: OPEN_NATIVE_CONSOLE_COMMAND_ID,79title: nls.localize2('globalConsoleAction', "Open New External Terminal")80}81});8283export class ExternalTerminalContribution implements IWorkbenchContribution {8485public _serviceBrand: undefined;86constructor(@IExternalTerminalService private readonly _externalTerminalService: IExternalTerminalService) {87this._updateConfiguration();88}8990private async _updateConfiguration(): Promise<void> {91const terminals = await this._externalTerminalService.getDefaultTerminalForPlatforms();92const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);93const terminalKindProperties: Partial<IConfigurationPropertySchema> = {94type: 'string',95enum: [96'integrated',97'external',98'both'99],100enumDescriptions: [101nls.localize('terminal.kind.integrated', "Show the integrated terminal action."),102nls.localize('terminal.kind.external', "Show the external terminal action."),103nls.localize('terminal.kind.both', "Show both integrated and external terminal actions.")104],105default: 'integrated'106};107configurationRegistry.registerConfiguration({108id: 'externalTerminal',109order: 100,110title: nls.localize('terminalConfigurationTitle', "External Terminal"),111type: 'object',112properties: {113'terminal.explorerKind': {114...terminalKindProperties,115description: nls.localize('explorer.openInTerminalKind', "When opening a file from the Explorer in a terminal, determines what kind of terminal will be launched"),116},117'terminal.sourceControlRepositoriesKind': {118...terminalKindProperties,119description: nls.localize('sourceControlRepositories.openInTerminalKind', "When opening a repository from the Source Control Repositories view in a terminal, determines what kind of terminal will be launched"),120},121'terminal.external.windowsExec': {122type: 'string',123description: nls.localize('terminal.external.windowsExec', "Customizes which terminal to run on Windows."),124default: terminals.windows,125scope: ConfigurationScope.APPLICATION126},127'terminal.external.osxExec': {128type: 'string',129description: nls.localize('terminal.external.osxExec', "Customizes which terminal application to run on macOS."),130default: DEFAULT_TERMINAL_OSX,131scope: ConfigurationScope.APPLICATION132},133'terminal.external.linuxExec': {134type: 'string',135description: nls.localize('terminal.external.linuxExec', "Customizes which terminal to run on Linux."),136default: terminals.linux,137scope: ConfigurationScope.APPLICATION138}139}140});141}142}143144// Register workbench contributions145const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);146workbenchRegistry.registerWorkbenchContribution(ExternalTerminalContribution, LifecyclePhase.Restored);147148149