// 跨平台默认 shell 选择 import { platform } from 'node:process' import { execSync } from 'node:child_process' export interface ShellSpec { file: string args: string[] label: string } function which(bin: string): string | null { try { const cmd = platform === 'win32' ? `where ${bin}` : `command -v ${bin}` const out = execSync(cmd, { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim().split(/\r?\n/)[0] return out || null } catch { return null } } export function defaultShell(): ShellSpec { switch (platform) { case 'win32': { // 优先 PowerShell 7 (pwsh), 否则 Windows PowerShell 5 (powershell) const pwsh = which('pwsh.exe') || which('pwsh') if (pwsh) return { file: pwsh, args: ['-NoLogo'], label: 'PowerShell 7' } const ps5 = which('powershell.exe') || which('powershell') if (ps5) return { file: ps5, args: ['-NoLogo'], label: 'Windows PowerShell' } return { file: 'powershell.exe', args: ['-NoLogo'], label: 'PowerShell' } } case 'darwin': case 'linux': { const envShell = process.env.SHELL if (envShell) { const name = envShell.split('/').pop() || envShell return { file: envShell, args: [], label: name } } if (platform === 'darwin') { const zsh = which('zsh') if (zsh) return { file: zsh, args: [], label: 'zsh' } const bash = which('bash') if (bash) return { file: bash, args: ['-l'], label: 'bash' } } else { const bash = which('bash') if (bash) return { file: bash, args: ['-l'], label: 'bash' } const sh = which('sh') if (sh) return { file: sh, args: [], label: 'sh' } } return { file: '/bin/sh', args: [], label: 'sh' } } default: return { file: '/bin/sh', args: [], label: 'sh' } } } // 终端的初始工作目录 // Windows 上通常没有 HOME, 但装了 Git Bash / MSYS 之后 HOME 可能被设成 POSIX 路径 // (比如 /c/Users/xxx), 那个路径在 Win32 下不存在 -> pty 起不来, 所以 win32 优先 USERPROFILE。 export function defaultCwd(): string { const home = platform === 'win32' ? (process.env.USERPROFILE || process.env.HOME) : (process.env.HOME || process.env.USERPROFILE) return home || process.cwd() }