b2bbc80ee8
- Migrated AuthCredentialStore and AuthStorage to shared modules, standardizing credential management and soft deletion. - Consolidated Anthropic authentication and various other formatting/utility helpers into shared modules. - Improved unicode normalization in patch logic with regex for efficiency and correctness. - Enhanced JTD type guards for robust schema validation.
77 lines
2.1 KiB
TypeScript
77 lines
2.1 KiB
TypeScript
export function parseCommandArgs(argsString: string): string[] {
|
|
const args: string[] = [];
|
|
let current = "";
|
|
let inQuote: string | null = null;
|
|
|
|
for (let i = 0; i < argsString.length; i++) {
|
|
const char = argsString[i];
|
|
|
|
if (inQuote) {
|
|
if (char === inQuote) {
|
|
inQuote = null;
|
|
} else {
|
|
current += char;
|
|
}
|
|
} else if (char === '"' || char === "'") {
|
|
inQuote = char;
|
|
} else if (char === " " || char === "\t") {
|
|
if (current) {
|
|
args.push(current);
|
|
current = "";
|
|
}
|
|
} else {
|
|
current += char;
|
|
}
|
|
}
|
|
|
|
if (current) {
|
|
args.push(current);
|
|
}
|
|
|
|
return args;
|
|
}
|
|
|
|
/**
|
|
* Substitute argument placeholders in template content
|
|
* Supports $1, $2, ... for positional args, $@ and $ARGUMENTS for all args
|
|
*
|
|
* Note: Replacement happens on the template string only. Argument values
|
|
* containing patterns like $1, $@, or $ARGUMENTS are NOT recursively substituted.
|
|
*/
|
|
export function substituteArgs(content: string, args: string[]): string {
|
|
let result = content;
|
|
|
|
// Replace $1, $2, etc. with positional args FIRST (before wildcards)
|
|
// This prevents wildcard replacement values containing $<digit> patterns from being re-substituted
|
|
result = result.replace(/\$(\d+)/g, (_, num) => {
|
|
const index = parseInt(num, 10) - 1;
|
|
return args[index] ?? "";
|
|
});
|
|
|
|
result = result.replace(/\$@\[(\d+)(?::(\d*)?)?\]/g, (_, startRaw: string, lengthRaw?: string) => {
|
|
const start = Number.parseInt(startRaw, 10);
|
|
if (!Number.isFinite(start) || start < 1) return "";
|
|
const startIndex = start - 1;
|
|
if (startIndex >= args.length) return "";
|
|
|
|
if (lengthRaw === undefined || lengthRaw === "") {
|
|
return args.slice(startIndex).join(" ");
|
|
}
|
|
|
|
const length = Number.parseInt(lengthRaw, 10);
|
|
if (!Number.isFinite(length) || length <= 0) return "";
|
|
return args.slice(startIndex, startIndex + length).join(" ");
|
|
});
|
|
|
|
// Pre-compute all args joined (optimization)
|
|
const allArgs = args.join(" ");
|
|
|
|
// Replace $ARGUMENTS with all args joined (new syntax, aligns with Claude, Codex, OpenCode)
|
|
result = result.replaceAll("$ARGUMENTS", allArgs);
|
|
|
|
// Replace $@ with all args joined (existing syntax)
|
|
result = result.replaceAll("$@", allArgs);
|
|
|
|
return result;
|
|
}
|