Skip to content

Commit c054e7a

Browse files
authored
Adopt Terminal Shell Type API from VSCode with legacy fallback (#153)
@anthonykim1 The VSCode shell type is missing following types: `tcshell`, `wsl`, `xonsh`
1 parent 455d430 commit c054e7a

File tree

3 files changed

+91
-20
lines changed

3 files changed

+91
-20
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@
519519
"enabledApiProposals": [
520520
"chatParticipantPrivate",
521521
"chatParticipantAdditions",
522-
"chatVariableResolver"
522+
"chatVariableResolver",
523+
"terminalShellType"
523524
]
524-
}
525+
}

src/features/common/shellDetector.ts

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Terminal } from 'vscode';
1+
import { Terminal, TerminalShellType as TerminalShellTypeVscode } from 'vscode';
22
import { isWindows } from '../../managers/common/utils';
33
import * as os from 'os';
44
import { vscodeShell } from '../../common/vscodeEnv.apis';
@@ -32,22 +32,24 @@ const IS_NUSHELL = /(nu$)/i;
3232
const IS_XONSH = /(xonsh$)/i;
3333

3434
type KnownShellType = Exclude<TerminalShellType, TerminalShellType.unknown>;
35-
const detectableShells = new Map<KnownShellType, RegExp>(unsafeEntries({
36-
[TerminalShellType.powershell]: IS_POWERSHELL,
37-
[TerminalShellType.gitbash]: IS_GITBASH,
38-
[TerminalShellType.bash]: IS_BASH,
39-
[TerminalShellType.wsl]: IS_WSL,
40-
[TerminalShellType.zsh]: IS_ZSH,
41-
[TerminalShellType.ksh]: IS_KSH,
42-
[TerminalShellType.commandPrompt]: IS_COMMAND,
43-
[TerminalShellType.fish]: IS_FISH,
44-
[TerminalShellType.tcshell]: IS_TCSHELL,
45-
[TerminalShellType.cshell]: IS_CSHELL,
46-
[TerminalShellType.nushell]: IS_NUSHELL,
47-
[TerminalShellType.powershellCore]: IS_POWERSHELL_CORE,
48-
[TerminalShellType.xonsh]: IS_XONSH,
49-
// This `satisfies` makes sure all shells are covered
50-
} satisfies Record<KnownShellType, RegExp>));
35+
const detectableShells = new Map<KnownShellType, RegExp>(
36+
unsafeEntries({
37+
[TerminalShellType.powershell]: IS_POWERSHELL,
38+
[TerminalShellType.gitbash]: IS_GITBASH,
39+
[TerminalShellType.bash]: IS_BASH,
40+
[TerminalShellType.wsl]: IS_WSL,
41+
[TerminalShellType.zsh]: IS_ZSH,
42+
[TerminalShellType.ksh]: IS_KSH,
43+
[TerminalShellType.commandPrompt]: IS_COMMAND,
44+
[TerminalShellType.fish]: IS_FISH,
45+
[TerminalShellType.tcshell]: IS_TCSHELL,
46+
[TerminalShellType.cshell]: IS_CSHELL,
47+
[TerminalShellType.nushell]: IS_NUSHELL,
48+
[TerminalShellType.powershellCore]: IS_POWERSHELL_CORE,
49+
[TerminalShellType.xonsh]: IS_XONSH,
50+
// This `satisfies` makes sure all shells are covered
51+
} satisfies Record<KnownShellType, RegExp>),
52+
);
5153

5254
function identifyShellFromShellPath(shellPath: string): TerminalShellType {
5355
// Remove .exe extension so shells can be more consistently detected
@@ -122,8 +124,38 @@ function identifyShellFromSettings(): TerminalShellType {
122124
return shellPath ? identifyShellFromShellPath(shellPath) : TerminalShellType.unknown;
123125
}
124126

127+
function fromShellTypeApi(terminal: Terminal): TerminalShellType {
128+
switch (terminal.state.shellType) {
129+
case TerminalShellTypeVscode.Sh:
130+
case TerminalShellTypeVscode.Bash:
131+
return TerminalShellType.bash;
132+
case TerminalShellTypeVscode.Fish:
133+
return TerminalShellType.fish;
134+
case TerminalShellTypeVscode.Csh:
135+
return TerminalShellType.cshell;
136+
case TerminalShellTypeVscode.Ksh:
137+
return TerminalShellType.ksh;
138+
case TerminalShellTypeVscode.Zsh:
139+
return TerminalShellType.zsh;
140+
case TerminalShellTypeVscode.CommandPrompt:
141+
return TerminalShellType.commandPrompt;
142+
case TerminalShellTypeVscode.GitBash:
143+
return TerminalShellType.gitbash;
144+
case TerminalShellTypeVscode.PowerShell:
145+
return TerminalShellType.powershellCore;
146+
case TerminalShellTypeVscode.NuShell:
147+
return TerminalShellType.nushell;
148+
default:
149+
return TerminalShellType.unknown;
150+
}
151+
}
152+
125153
export function identifyTerminalShell(terminal: Terminal): TerminalShellType {
126-
let shellType = identifyShellFromTerminalName(terminal);
154+
let shellType = fromShellTypeApi(terminal);
155+
156+
if (shellType === TerminalShellType.unknown) {
157+
shellType = identifyShellFromTerminalName(terminal);
158+
}
127159

128160
if (shellType === TerminalShellType.unknown) {
129161
shellType = identifyShellFromSettings();
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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+
declare module 'vscode' {
7+
// https://github.com/microsoft/vscode/issues/230165
8+
9+
/**
10+
* Known terminal shell types.
11+
*/
12+
export enum TerminalShellType {
13+
Sh = 1,
14+
Bash = 2,
15+
Fish = 3,
16+
Csh = 4,
17+
Ksh = 5,
18+
Zsh = 6,
19+
CommandPrompt = 7,
20+
GitBash = 8,
21+
PowerShell = 9,
22+
Python = 10,
23+
Julia = 11,
24+
NuShell = 12,
25+
Node = 13,
26+
}
27+
28+
// Part of TerminalState since the shellType can change multiple times and this comes with an event.
29+
export interface TerminalState {
30+
/**
31+
* The current detected shell type of the terminal. New shell types may be added in the
32+
* future in which case they will be returned as a number that is not part of
33+
* {@link TerminalShellType}.
34+
* Includes number type to prevent the breaking change when new enum members are added?
35+
*/
36+
readonly shellType?: TerminalShellType | number | undefined;
37+
}
38+
}

0 commit comments

Comments
 (0)