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