MCPcopy Create free account
hub / github.com/Zoo-Code-Org/Zoo-Code / parseCommandLine

Function parseCommandLine

src/shared/parse-command.ts:542–727  ·  view source on GitHub ↗

* Parse a single line of commands.

(command: string)

Source from the content-addressed store, hash-verified

540 * Parse a single line of commands.
541 */
542function parseCommandLine(command: string): string[] {
543 if (!command?.trim()) return []
544
545 // Storage for replaced content
546 const redirections: string[] = []
547 const subshells: string[] = []
548 const quotes: string[] = []
549 const singleQuotes: string[] = []
550 const arithmeticExpressions: string[] = []
551 const variables: string[] = []
552 const parameterExpansions: string[] = []
553
554 // First handle PowerShell redirections by temporarily replacing them
555 let processedCommand = command.replace(/\d*>&\d*/g, (match) => {
556 redirections.push(match)
557 return `__REDIR_${redirections.length - 1}__`
558 })
559
560 // Handle arithmetic expressions: $((...)) pattern
561 // Match the entire arithmetic expression including nested parentheses
562 processedCommand = processedCommand.replace(/\$\(\([^)]*(?:\)[^)]*)*\)\)/g, (match) => {
563 arithmeticExpressions.push(match)
564 return `__ARITH_${arithmeticExpressions.length - 1}__`
565 })
566
567 // Handle $[...] arithmetic expressions (alternative syntax)
568 processedCommand = processedCommand.replace(/\$\[[^\]]*\]/g, (match) => {
569 arithmeticExpressions.push(match)
570 return `__ARITH_${arithmeticExpressions.length - 1}__`
571 })
572
573 // Handle parameter expansions: ${...} patterns (including array indexing)
574 // This covers ${var}, ${var:-default}, ${var:+alt}, ${#var}, ${var%pattern}, etc.
575 processedCommand = processedCommand.replace(/\$\{[^}]+\}/g, (match) => {
576 parameterExpansions.push(match)
577 return `__PARAM_${parameterExpansions.length - 1}__`
578 })
579
580 // Handle process substitutions: <(...) and >(...)
581 processedCommand = processedCommand.replace(/[<>]\(([^)]+)\)/g, (_, inner) => {
582 subshells.push(inner.trim())
583 return `__SUBSH_${subshells.length - 1}__`
584 })
585
586 // Handle locale quoting: $"...". This must run before variable masking for
587 // the same reason as ANSI-C: without it the generic double-quote masker would
588 // strip the outer quotes leaving a bare $ that the variable regex absorbs,
589 // corrupting the placeholder. The whole token (including $") is stored in the
590 // double-quote bucket so it is restored verbatim.
591 processedCommand = processedCommand.replace(/\$"(?:[^"\\]|\\.)*"/g, (match) => {
592 quotes.push(match)
593 return `__QUOTE_${quotes.length - 1}__`
594 })
595
596 // Handle ANSI-C quoting: $'...'. This must run before variable masking so the
597 // leading $ is captured as part of the quoted unit rather than being treated
598 // as a variable expansion (which would corrupt a following placeholder).
599 // ANSI-C strings interpret backslash escapes, so the pattern is escape-aware.

Callers 1

parseCommandFunction · 0.85

Calls 3

restorePlaceholdersFunction · 0.85
replaceMethod · 0.65
warnMethod · 0.65

Tested by

no test coverage detected