Skip to content

Commit c3ba479

Browse files
authored
fix(windows): quote editor launch paths
Ensure Windows editor launches quote workspace paths containing spaces. PR: #622
1 parent 31e0f7a commit c3ba479

2 files changed

Lines changed: 47 additions & 2 deletions

File tree

packages/workshop-utils/src/launch-editor.server.test.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { expect, test } from 'vitest'
2-
import { parseEditorCommand } from './launch-editor.server.ts'
2+
import {
3+
getWindowsEditorCommandArgs,
4+
parseEditorCommand,
5+
} from './launch-editor.server.ts'
36

47
test('preserves unquoted Windows editor paths', () => {
58
const editor = String.raw`C:\Users\James\AppData\Local\Programs\cursor\Cursor.exe`
@@ -22,3 +25,29 @@ test('keeps shell parsing for non-Windows editor commands', () => {
2225
'--reuse-window',
2326
])
2427
})
28+
29+
test('quotes Windows editor command arguments with spaces (aha)', () => {
30+
const editor = 'code'
31+
const workshopPath = String.raw`C:\Users\Campbell L Mitchell\Campbell - Ensign College\epicshop-tutorial`
32+
33+
expect(getWindowsEditorCommandArgs(editor, [workshopPath])).toEqual([
34+
'/D',
35+
'/S',
36+
'/C',
37+
String.raw`"code" "C:\Users\Campbell L Mitchell\Campbell - Ensign College\epicshop-tutorial"`,
38+
])
39+
})
40+
41+
test('quotes Windows editor paths with spaces and preserves editor args', () => {
42+
const editor = String.raw`C:\Program Files\Microsoft VS Code\bin\code.cmd`
43+
const workshopPath = String.raw`C:\Users\Campbell L Mitchell\epicshop-tutorial`
44+
45+
expect(
46+
getWindowsEditorCommandArgs(editor, ['--reuse-window', workshopPath]),
47+
).toEqual([
48+
'/D',
49+
'/S',
50+
'/C',
51+
String.raw`"C:\Program Files\Microsoft VS Code\bin\code.cmd" "--reuse-window" "C:\Users\Campbell L Mitchell\epicshop-tutorial"`,
52+
])
53+
})

packages/workshop-utils/src/launch-editor.server.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,22 @@ export function parseEditorCommand(
259259
return shellQuote.parse(trimmedEditor).map((arg) => String(arg))
260260
}
261261

262+
function quoteWindowsCmdArg(arg: string): string {
263+
return `"${arg.replaceAll('"', '\\"')}"`
264+
}
265+
266+
export function getWindowsEditorCommandArgs(
267+
editor: string,
268+
args: Array<string>,
269+
): Array<string> {
270+
return [
271+
'/D',
272+
'/S',
273+
'/C',
274+
[quoteWindowsCmdArg(editor), ...args.map(quoteWindowsCmdArg)].join(' '),
275+
]
276+
}
277+
262278
function getWindowsProcessPaths(): string[] {
263279
const systemRoot = process.env.SystemRoot ?? process.env.WINDIR
264280
const wmicPath = systemRoot
@@ -604,7 +620,7 @@ export async function launchEditor(
604620
// launch .exe files.
605621
_childProcess = child_process.spawn(
606622
'cmd.exe',
607-
['/C', editor].concat(args).filter(Boolean),
623+
getWindowsEditorCommandArgs(editor, args),
608624
{ stdio: ['inherit', 'inherit', 'pipe'] },
609625
)
610626
} else {

0 commit comments

Comments
 (0)