summaryrefslogtreecommitdiff
path: root/packages/core/src/utils/paths.ts
diff options
context:
space:
mode:
authorSandy Tao <[email protected]>2025-08-04 10:49:15 -0700
committerGitHub <[email protected]>2025-08-04 17:49:15 +0000
commitb9fe4fc263340c7a614e3e36462284b865e641c7 (patch)
tree30676821ed0ba9378af060c68197dfc2a268252e /packages/core/src/utils/paths.ts
parente506b40c271da0e05a361f5299c37976a9e1f1f3 (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.ts38
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',
+ );
}
/**