Skip to content

Commit 2b4f18e

Browse files
committed
fix: shell type API
1 parent 6b56432 commit 2b4f18e

7 files changed

Lines changed: 46 additions & 82 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"publisher": "ms-python",
77
"preview": true,
88
"engines": {
9-
"vscode": "^1.98.0-20250221"
9+
"vscode": "^1.99.0-20250317"
1010
},
1111
"categories": [
1212
"Other"

src/extension.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ import { AutoFindProjects } from './features/creators/autoFindProjects';
5656
import { registerTools } from './common/lm.apis';
5757
import { GetPackagesTool } from './features/copilotTools';
5858
import { TerminalActivationImpl } from './features/terminal/terminalActivationState';
59-
import { getEnvironmentForTerminal } from './features/terminal/utils';
59+
import { getEnvironmentForTerminal, normalizeShellPath } from './features/terminal/utils';
6060
import { PowershellStartupProvider } from './features/terminal/startup/powershellStartup';
6161
import { ShellStartupActivationManagerImpl } from './features/terminal/startup/activateUsingShellStartup';
6262
import { BashStartupProvider, GitBashStartupProvider } from './features/terminal/startup/bashStartup';
@@ -251,7 +251,8 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
251251
const envVar = shellEnv.value;
252252
if (envVar) {
253253
if (envVar['VIRTUAL_ENV']) {
254-
const env = await api.resolveEnvironment(Uri.file(envVar['VIRTUAL_ENV']));
254+
const envPath = normalizeShellPath(envVar['VIRTUAL_ENV'], e.terminal.state.shell);
255+
const env = await api.resolveEnvironment(Uri.file(envPath));
255256
if (env) {
256257
monitoredTerminals.set(e.terminal, env);
257258
terminalActivation.updateActivationState(e.terminal, env, true);

src/features/common/shellDetector.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as os from 'os';
2-
import { Terminal, TerminalShellType as TerminalShellTypeVscode } from 'vscode';
2+
import { Terminal } from 'vscode';
33
import { vscodeShell } from '../../common/vscodeEnv.apis';
44
import { getConfiguration } from '../../common/workspace.apis';
55
import { TerminalShellType } from '../../api';
@@ -135,25 +135,26 @@ function identifyShellFromSettings(): TerminalShellType {
135135

136136
function fromShellTypeApi(terminal: Terminal): TerminalShellType {
137137
try {
138-
switch (terminal.state.shellType) {
139-
case TerminalShellTypeVscode.Sh:
140-
case TerminalShellTypeVscode.Bash:
138+
switch (terminal.state.shell) {
139+
case 'sh':
140+
case 'bash':
141141
return TerminalShellType.bash;
142-
case TerminalShellTypeVscode.Fish:
142+
case 'fish':
143143
return TerminalShellType.fish;
144-
case TerminalShellTypeVscode.Csh:
144+
case 'csh':
145145
return TerminalShellType.cshell;
146-
case TerminalShellTypeVscode.Ksh:
146+
case 'ksh':
147147
return TerminalShellType.ksh;
148-
case TerminalShellTypeVscode.Zsh:
148+
case 'zsh':
149149
return TerminalShellType.zsh;
150-
case TerminalShellTypeVscode.CommandPrompt:
150+
case 'cmd':
151151
return TerminalShellType.commandPrompt;
152-
case TerminalShellTypeVscode.GitBash:
152+
case 'gitbash':
153153
return TerminalShellType.gitbash;
154-
case TerminalShellTypeVscode.PowerShell:
154+
case 'powershell':
155+
case 'pwsh':
155156
return TerminalShellType.powershellCore;
156-
case TerminalShellTypeVscode.NuShell:
157+
case 'nu':
157158
return TerminalShellType.nushell;
158159
default:
159160
return TerminalShellType.unknown;

src/features/terminal/startup/bashStartup.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ async function getZshProfiles(): Promise<string[]> {
5252
return result.map((p) => p.profilePath);
5353
}
5454

55-
const regionStart = '# vscode python environment activation begin';
56-
const regionEnd = '# vscode python environment activation end';
55+
const regionStart = '# >>> vscode python';
56+
const regionEnd = '# <<< vscode python';
5757

5858
function getActivationContent(): string {
5959
const lineSep = '\n';

src/features/terminal/utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Terminal, TerminalOptions, Uri } from 'vscode';
33
import { sleep } from '../../common/utils/asyncUtils';
44
import { PythonEnvironment, PythonProject, PythonProjectEnvironmentApi, PythonProjectGetterApi } from '../../api';
55
import { getConfiguration, getWorkspaceFolders } from '../../common/workspace.apis';
6+
import { isWindows } from '../../common/utils/platformUtils';
67

78
const SHELL_INTEGRATION_TIMEOUT = 500; // 0.5 seconds
89
const SHELL_INTEGRATION_POLL_INTERVAL = 20; // 0.02 seconds
@@ -125,3 +126,12 @@ export async function getAllDistinctProjectEnvironments(
125126

126127
return envs.length > 0 ? envs : undefined;
127128
}
129+
130+
export function normalizeShellPath(filePath: string, shellType?: string): string {
131+
if (isWindows() && shellType) {
132+
if (shellType.toLowerCase() === 'gitbash' || shellType.toLowerCase() === 'git-bash') {
133+
return filePath.replace(/\\/g, '/').replace(/^\/([a-zA-Z])/, '$1:');
134+
}
135+
}
136+
return filePath;
137+
}

src/test/features/common/shellDetector.unit.test.ts

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { TerminalShellType } from '../../../api';
2-
import { Terminal, TerminalShellType as VSCTerminalShellType } from 'vscode';
2+
import { Terminal } from 'vscode';
33
import { identifyTerminalShell } from '../../../features/common/shellDetector';
44
import assert from 'assert';
55
import { isWindows } from '../../../common/utils/platformUtils';
@@ -26,38 +26,6 @@ function getNameByShellType(shellType: string): string {
2626
return shellType === 'unknown' ? '' : shellType;
2727
}
2828

29-
function getVSCShellType(shellType: string): VSCTerminalShellType | undefined {
30-
try {
31-
switch (shellType) {
32-
case 'sh':
33-
return VSCTerminalShellType.Sh;
34-
case 'bash':
35-
return VSCTerminalShellType.Bash;
36-
case 'powershell':
37-
case 'pwsh':
38-
return VSCTerminalShellType.PowerShell;
39-
case 'cmd':
40-
return VSCTerminalShellType.CommandPrompt;
41-
case 'gitbash':
42-
return VSCTerminalShellType.GitBash;
43-
case 'zsh':
44-
return VSCTerminalShellType.Zsh;
45-
case 'ksh':
46-
return VSCTerminalShellType.Ksh;
47-
case 'fish':
48-
return VSCTerminalShellType.Fish;
49-
case 'cshell':
50-
return VSCTerminalShellType.Csh;
51-
case 'nushell':
52-
return VSCTerminalShellType.NuShell;
53-
default:
54-
return undefined;
55-
}
56-
} catch {
57-
return undefined;
58-
}
59-
}
60-
6129
function getShellPath(shellType: string): string | undefined {
6230
switch (shellType) {
6331
case 'sh':
@@ -129,23 +97,22 @@ function expectedShellType(shellType: string): TerminalShellType {
12997
}
13098

13199
suite('Shell Detector', () => {
132-
testShellTypes.forEach((shellType) => {
133-
if (shellType === TerminalShellType.unknown) {
100+
testShellTypes.forEach((shell) => {
101+
if (shell === TerminalShellType.unknown) {
134102
return;
135103
}
136104

137-
const name = getNameByShellType(shellType);
138-
const vscShellType = getVSCShellType(shellType);
139-
test(`Detect ${shellType}`, () => {
105+
const name = getNameByShellType(shell);
106+
test(`Detect ${shell}`, () => {
140107
const terminal = {
141108
name,
142-
state: { shellType: vscShellType },
109+
state: { shell },
143110
creationOptions: {
144-
shellPath: getShellPath(shellType),
111+
shellPath: getShellPath(shell),
145112
},
146113
} as Terminal;
147114
const detected = identifyTerminalShell(terminal);
148-
const expected = expectedShellType(shellType);
115+
const expected = expectedShellType(shell);
149116
assert.strictEqual(detected, expected);
150117
});
151118
});

src/vscode.proposed.terminalShellType.d.ts

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,18 @@
66
declare module 'vscode' {
77
// https://github.com/microsoft/vscode/issues/230165
88

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-
289
// Part of TerminalState since the shellType can change multiple times and this comes with an event.
2910
export interface TerminalState {
3011
/**
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?
12+
* The detected shell type of the {@link Terminal}. This will be `undefined` when there is
13+
* not a clear signal as to what the shell is, or the shell is not supported yet. This
14+
* value should change to the shell type of a sub-shell when launched (for example, running
15+
* `bash` inside `zsh`).
16+
*
17+
* Note that the possible values are currently defined as any of the following:
18+
* 'bash', 'cmd', 'csh', 'fish', 'gitbash', 'julia', 'ksh', 'node', 'nu', 'pwsh', 'python',
19+
* 'sh', 'wsl', 'zsh'.
3520
*/
36-
readonly shellType?: TerminalShellType | number | undefined;
21+
readonly shell: string | undefined;
3722
}
3823
}

0 commit comments

Comments
 (0)