Skip to content

Commit 9d470ba

Browse files
fix(shell): prefer PowerShell 7 over legacy when no Windows profile is set (#82)
1 parent 02b2f42 commit 9d470ba

2 files changed

Lines changed: 28 additions & 11 deletions

File tree

src/utils/__tests__/shell.spec.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"
22
import * as vscode from "vscode"
3+
import { existsSync } from "fs"
34
import { userInfo } from "os"
45
import { getShell } from "../shell"
56

@@ -15,6 +16,11 @@ vi.mock("os", () => ({
1516
userInfo: vi.fn(() => ({ shell: null })),
1617
}))
1718

19+
// Mock the fs module — getWindowsShellFromVSCode probes for PowerShell 7 (pwsh.exe).
20+
vi.mock("fs", () => ({
21+
existsSync: vi.fn(() => false),
22+
}))
23+
1824
// Mock path module for testing
1925
vi.mock("path", async () => {
2026
const actual = await vi.importActual("path")
@@ -57,6 +63,8 @@ describe("Shell Detection Tests", () => {
5763

5864
// Reset userInfo mock to default
5965
vi.mocked(userInfo).mockReturnValue({ shell: null } as any)
66+
// Default: PowerShell 7 is not installed, so the probe falls back to legacy.
67+
vi.mocked(existsSync).mockReturnValue(false)
6068
})
6169

6270
afterEach(() => {
@@ -173,11 +181,20 @@ describe("Shell Detection Tests", () => {
173181
expect(getShell()).toBe("C:\\Windows\\System32\\cmd.exe")
174182
})
175183

176-
it("defaults to Windows PowerShell when VS Code has no configured profile", () => {
177-
// Modern VS Code launches PowerShell by default on Windows (issue #82), so
178-
// getShell() should report PowerShell rather than falling through to cmd.exe.
184+
it("defaults to PowerShell 7 when no profile is configured and pwsh.exe is installed", () => {
185+
// Modern VS Code launches PowerShell by default on Windows (issue #82) and
186+
// prefers PS7 when present, so getShell() should report pwsh.exe.
187+
vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
188+
vi.mocked(existsSync).mockReturnValue(true)
189+
190+
expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe")
191+
})
192+
193+
it("falls back to Windows PowerShell 5.1 when no profile is configured and PS7 is absent", () => {
194+
// Without PS7 installed, the probe falls back to the always-present legacy
195+
// PowerShell rather than cmd.exe.
179196
vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
180-
vi.mocked(userInfo).mockReturnValue({ shell: "C:\\Program Files\\PowerShell\\7\\pwsh.exe" } as any)
197+
vi.mocked(existsSync).mockReturnValue(false)
181198

182199
expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe")
183200
})

src/utils/shell.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as vscode from "vscode"
2+
import { existsSync } from "fs"
23
import { userInfo } from "os"
34
import * as path from "path"
45

@@ -188,13 +189,12 @@ function normalizeShellPath(path: string | string[] | undefined): string | null
188189
function getWindowsShellFromVSCode(): string | null {
189190
const { defaultProfileName, profiles } = getWindowsTerminalConfig()
190191
if (!defaultProfileName) {
191-
// No explicit Windows terminal profile is configured. VS Code's built-in
192-
// default on modern Windows is PowerShell (not cmd.exe), and that is the
193-
// shell the integrated terminal actually launches. Mirror it here so the
194-
// system prompt advertises the real shell instead of falling through to
195-
// COMSPEC (cmd.exe). Windows PowerShell is always present, so it is a safe
196-
// allowlisted default. See issue #82.
197-
return SHELL_PATHS.POWERSHELL_LEGACY
192+
// No explicit Windows terminal profile is configured. VS Code auto-detects
193+
// the default on modern Windows and prefers PowerShell 7 (pwsh.exe) when it
194+
// is installed, otherwise the always-present Windows PowerShell 5.1. Mirror
195+
// that here so the system prompt advertises the real shell instead of falling
196+
// through to COMSPEC (cmd.exe). See issue #82.
197+
return existsSync(SHELL_PATHS.POWERSHELL_7) ? SHELL_PATHS.POWERSHELL_7 : SHELL_PATHS.POWERSHELL_LEGACY
198198
}
199199

200200
const profile = profiles[defaultProfileName]

0 commit comments

Comments
 (0)