diff options
| author | Sandy Tao <[email protected]> | 2025-08-04 10:49:15 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-08-04 17:49:15 +0000 |
| commit | b9fe4fc263340c7a614e3e36462284b865e641c7 (patch) | |
| tree | 30676821ed0ba9378af060c68197dfc2a268252e /packages/core/src/utils/paths.ts | |
| parent | e506b40c271da0e05a361f5299c37976a9e1f1f3 (diff) | |
feat(cli): Handle Punctuation in @ Command Parsing (#5482)
Diffstat (limited to 'packages/core/src/utils/paths.ts')
| -rw-r--r-- | packages/core/src/utils/paths.ts | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/packages/core/src/utils/paths.ts b/packages/core/src/utils/paths.ts index 5370a7cb..7bab888e 100644 --- a/packages/core/src/utils/paths.ts +++ b/packages/core/src/utils/paths.ts @@ -14,6 +14,13 @@ const TMP_DIR_NAME = 'tmp'; const COMMANDS_DIR_NAME = 'commands'; /** + * Special characters that need to be escaped in file paths for shell compatibility. + * Includes: spaces, parentheses, brackets, braces, semicolons, ampersands, pipes, + * asterisks, question marks, dollar signs, backticks, quotes, hash, and other shell metacharacters. + */ +export const SHELL_SPECIAL_CHARS = /[ \t()[\]{};|*?$`'"#&<>!~]/; + +/** * Replaces the home directory with a tilde. * @param path - The path to tildeify. * @returns The tildeified path. @@ -119,26 +126,43 @@ export function makeRelative( } /** - * Escapes spaces in a file path. + * Escapes special characters in a file path like macOS terminal does. + * Escapes: spaces, parentheses, brackets, braces, semicolons, ampersands, pipes, + * asterisks, question marks, dollar signs, backticks, quotes, hash, and other shell metacharacters. */ export function escapePath(filePath: string): string { let result = ''; for (let i = 0; i < filePath.length; i++) { - // Only escape spaces that are not already escaped. - if (filePath[i] === ' ' && (i === 0 || filePath[i - 1] !== '\\')) { - result += '\\ '; + const char = filePath[i]; + + // Count consecutive backslashes before this character + let backslashCount = 0; + for (let j = i - 1; j >= 0 && filePath[j] === '\\'; j--) { + backslashCount++; + } + + // Character is already escaped if there's an odd number of backslashes before it + const isAlreadyEscaped = backslashCount % 2 === 1; + + // Only escape if not already escaped + if (!isAlreadyEscaped && SHELL_SPECIAL_CHARS.test(char)) { + result += '\\' + char; } else { - result += filePath[i]; + result += char; } } return result; } /** - * Unescapes spaces in a file path. + * Unescapes special characters in a file path. + * Removes backslash escaping from shell metacharacters. */ export function unescapePath(filePath: string): string { - return filePath.replace(/\\ /g, ' '); + return filePath.replace( + new RegExp(`\\\\([${SHELL_SPECIAL_CHARS.source.slice(1, -1)}])`, 'g'), + '$1', + ); } /** |
