Files
orca/src/main/editor-launcher-name.ts
T
Jinjing 786d7048a1 fix(win32): suppress Command Prompt window on IDE launches (#11907)
* fix(win32): suppress Command Prompt window on IDE launches

- Prefer JetBrains GUI executables (`*64.exe`) over `.cmd` shims to avoid
  console allocation (STA-3040).
- Use `start "" /B` when launching GUI apps via batch scripts; shims chain
  through console helpers that allocate a visible prompt even with
  `windowsHide`. `start /B` returns immediately, preventing the lingering window.

* fix(win32): suppress Command Prompt window on IDE launches

Prevent lingering Command Prompt windows when launching JetBrains IDEs
on Windows. Use `start "" /B cmd /d /c` so the nested shell exits with
the batch script, but only for JetBrains shims—VS Code and Cursor keep
the waiting form because `start` re-parses arguments and breaks remote
paths with spaces. Prefer colocated `*64.exe` executables beside the
resolved `.cmd` shim over PATH lookups to avoid stale installations.

* fix(win32): extend IDE launcher console suppression to direct paths

Support IDE paths stored directly in settings (e.g., idea.exe,
webstorm.cmd). Detect console idea.exe stubs alongside batch shims
for upgrade to GUI *64.exe. Fix start command title escaping: use
empty string instead of '""' to prevent libuv re-quoting.
2026-08-01 13:38:45 -07:00

45 lines
1.4 KiB
TypeScript

import { basename, win32 } from 'node:path'
export function stripMatchingQuotes(value: string): string {
const trimmed = value.trim()
const quote = trimmed[0]
if ((quote === '"' || quote === "'") && trimmed.endsWith(quote)) {
return trimmed.slice(1, -1)
}
return trimmed
}
export function hasMatchingOuterQuotes(value: string): boolean {
const trimmed = value.trim()
const quote = trimmed[0]
return (quote === '"' || quote === "'") && trimmed.endsWith(quote)
}
function getLeadingShellCommandToken(command: string): string {
const trimmed = command.trim()
const quote = trimmed[0]
if (quote === '"' || quote === "'") {
const closingIndex = trimmed.indexOf(quote, 1)
if (closingIndex > 0) {
return trimmed.slice(1, closingIndex)
}
}
return trimmed.split(/\s+/, 1)[0] ?? ''
}
/** Lowercased launcher name without directory or Windows executable extension. */
export function getLauncherBaseName(
command: string,
options: { shellCommand?: boolean } = {}
): string {
const normalized = options.shellCommand
? getLeadingShellCommandToken(command)
: stripMatchingQuotes(command)
const name = normalized.includes('\\') ? win32.basename(normalized) : basename(normalized)
return name.replace(/\.(?:cmd|exe|bat)$/i, '').toLowerCase()
}
export function isWindowsBatchLauncher(command: string): boolean {
return /\.(?:cmd|bat)$/i.test(stripMatchingQuotes(command))
}