shell-dsl 0.0.14 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/commands/cd/cd.cjs +66 -0
  3. package/dist/cjs/src/commands/cd/cd.cjs.map +10 -0
  4. package/dist/cjs/src/commands/index.cjs +10 -2
  5. package/dist/cjs/src/commands/index.cjs.map +3 -3
  6. package/dist/cjs/src/commands/ls/ls.cjs +65 -42
  7. package/dist/cjs/src/commands/ls/ls.cjs.map +3 -3
  8. package/dist/cjs/src/commands/sed/sed.cjs +291 -76
  9. package/dist/cjs/src/commands/sed/sed.cjs.map +3 -3
  10. package/dist/cjs/src/commands/tr/tr.cjs +223 -0
  11. package/dist/cjs/src/commands/tr/tr.cjs.map +10 -0
  12. package/dist/cjs/src/commands/tree/tree.cjs +7 -4
  13. package/dist/cjs/src/commands/tree/tree.cjs.map +3 -3
  14. package/dist/cjs/src/interpreter/context.cjs +3 -2
  15. package/dist/cjs/src/interpreter/context.cjs.map +3 -3
  16. package/dist/cjs/src/interpreter/interpreter.cjs +4 -2
  17. package/dist/cjs/src/interpreter/interpreter.cjs.map +3 -3
  18. package/dist/cjs/src/parser/parser.cjs +11 -2
  19. package/dist/cjs/src/parser/parser.cjs.map +3 -3
  20. package/dist/cjs/src/types.cjs.map +2 -2
  21. package/dist/mjs/package.json +1 -1
  22. package/dist/mjs/src/commands/cd/cd.mjs +36 -0
  23. package/dist/mjs/src/commands/cd/cd.mjs.map +10 -0
  24. package/dist/mjs/src/commands/index.mjs +10 -2
  25. package/dist/mjs/src/commands/index.mjs.map +3 -3
  26. package/dist/mjs/src/commands/ls/ls.mjs +65 -42
  27. package/dist/mjs/src/commands/ls/ls.mjs.map +3 -3
  28. package/dist/mjs/src/commands/sed/sed.mjs +291 -76
  29. package/dist/mjs/src/commands/sed/sed.mjs.map +3 -3
  30. package/dist/mjs/src/commands/tr/tr.mjs +193 -0
  31. package/dist/mjs/src/commands/tr/tr.mjs.map +10 -0
  32. package/dist/mjs/src/commands/tree/tree.mjs +7 -4
  33. package/dist/mjs/src/commands/tree/tree.mjs.map +3 -3
  34. package/dist/mjs/src/interpreter/context.mjs +3 -2
  35. package/dist/mjs/src/interpreter/context.mjs.map +3 -3
  36. package/dist/mjs/src/interpreter/interpreter.mjs +4 -2
  37. package/dist/mjs/src/interpreter/interpreter.mjs.map +3 -3
  38. package/dist/mjs/src/parser/parser.mjs +11 -2
  39. package/dist/mjs/src/parser/parser.mjs.map +3 -3
  40. package/dist/mjs/src/types.mjs.map +2 -2
  41. package/dist/types/src/commands/cd/cd.d.ts +2 -0
  42. package/dist/types/src/commands/index.d.ts +2 -0
  43. package/dist/types/src/commands/tr/tr.d.ts +2 -0
  44. package/dist/types/src/interpreter/context.d.ts +1 -0
  45. package/dist/types/src/types.d.ts +1 -0
  46. package/package.json +1 -1
@@ -314,7 +314,16 @@ class Parser {
314
314
  const redirect = this.parseRedirect();
315
315
  redirects.push(redirect);
316
316
  while (this.isWordToken()) {
317
- args.push(this.parseWordArg());
317
+ if (this.peek().type === "heredoc") {
318
+ const heredocToken = this.advance();
319
+ redirects.push({
320
+ mode: "<",
321
+ target: this.tokenToNode(heredocToken),
322
+ heredocContent: true
323
+ });
324
+ } else {
325
+ args.push(this.parseWordArg());
326
+ }
318
327
  }
319
328
  }
320
329
  if (args.length === 0 && assignments.length === 0 && redirects.length === 0) {
@@ -485,4 +494,4 @@ function parse(tokens) {
485
494
  return new Parser(tokens).parse();
486
495
  }
487
496
 
488
- //# debugId=A85F8476E4AB0C2264756E2164756E21
497
+ //# debugId=8C083E4DFB31F65664756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parser/parser.ts"],
4
4
  "sourcesContent": [
5
- "import { ParseError } from \"../errors.cjs\";\nimport type { Token, KeywordValue } from \"../lexer/tokens.cjs\";\nimport type { ASTNode, Redirect, RedirectMode, CommandNode, IfNode, ForNode, WhileNode, UntilNode, CaseNode, CaseClause } from \"./ast.cjs\";\n\nexport class Parser {\n private tokens: Token[];\n private pos: number = 0;\n\n constructor(tokens: Token[]) {\n this.tokens = tokens;\n }\n\n parse(): ASTNode {\n const result = this.parseSequence();\n if (!this.isAtEnd()) {\n throw new ParseError(`Unexpected token: ${JSON.stringify(this.peek())}`);\n }\n return result;\n }\n\n // sequence := and_or ((';'|'\\n') and_or)*\n private parseSequence(): ASTNode {\n this.skipNewlines();\n const commands: ASTNode[] = [];\n commands.push(this.parseAndOr());\n\n while (this.match(\"semicolon\") || this.match(\"newline\")) {\n this.skipNewlines();\n // Skip empty commands after separator, or stop at terminating keywords\n if (this.isAtEnd() || this.check(\"semicolon\") || this.check(\"newline\") || this.isTerminatingKeyword()) continue;\n commands.push(this.parseAndOr());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"sequence\", commands };\n }\n\n private skipNewlines(): void {\n while (this.match(\"newline\")) {\n // keep consuming newlines\n }\n }\n\n private isTerminatingKeyword(): boolean {\n const token = this.peek();\n if (token.type !== \"keyword\") return false;\n return [\"then\", \"elif\", \"else\", \"fi\", \"do\", \"done\", \"esac\"].includes(token.value);\n }\n\n // and_or := pipeline (('&&'|'||') pipeline)*\n private parseAndOr(): ASTNode {\n let left = this.parsePipeline();\n\n while (this.check(\"and\") || this.check(\"or\")) {\n if (this.match(\"and\")) {\n const right = this.parsePipeline();\n left = { type: \"and\", left, right };\n } else if (this.match(\"or\")) {\n const right = this.parsePipeline();\n left = { type: \"or\", left, right };\n }\n }\n\n return left;\n }\n\n // pipeline := command ('|' command)*\n private parsePipeline(): ASTNode {\n const commands: ASTNode[] = [];\n commands.push(this.parseCompoundOrCommand());\n\n while (this.match(\"pipe\")) {\n this.skipNewlines();\n commands.push(this.parseCompoundOrCommand());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"pipeline\", commands };\n }\n\n // compound_or_command := compound_command | simple_command\n private parseCompoundOrCommand(): ASTNode {\n this.skipNewlines();\n const token = this.peek();\n\n if (token.type === \"keyword\") {\n switch (token.value) {\n case \"if\":\n return this.parseIf();\n case \"for\":\n return this.parseFor();\n case \"while\":\n return this.parseWhile();\n case \"until\":\n return this.parseUntil();\n case \"case\":\n return this.parseCase();\n }\n }\n\n return this.parseCommand();\n }\n\n // if := 'if' compound_list 'then' compound_list ('elif' compound_list 'then' compound_list)* ['else' compound_list] 'fi'\n private parseIf(): IfNode {\n this.expectKeyword(\"if\");\n const condition = this.parseCompoundList([\"then\"]);\n this.expectKeyword(\"then\");\n const thenBranch = this.parseCompoundList([\"elif\", \"else\", \"fi\"]);\n\n const elifBranches: Array<{ condition: ASTNode; body: ASTNode }> = [];\n while (this.checkKeyword(\"elif\")) {\n this.expectKeyword(\"elif\");\n const elifCondition = this.parseCompoundList([\"then\"]);\n this.expectKeyword(\"then\");\n const elifBody = this.parseCompoundList([\"elif\", \"else\", \"fi\"]);\n elifBranches.push({ condition: elifCondition, body: elifBody });\n }\n\n let elseBranch: ASTNode | undefined;\n if (this.checkKeyword(\"else\")) {\n this.expectKeyword(\"else\");\n elseBranch = this.parseCompoundList([\"fi\"]);\n }\n\n this.expectKeyword(\"fi\");\n\n return {\n type: \"if\",\n condition,\n thenBranch,\n elifBranches,\n elseBranch,\n };\n }\n\n // for := 'for' NAME ['in' word*] (';'|'\\n') 'do' compound_list 'done'\n private parseFor(): ForNode {\n this.expectKeyword(\"for\");\n\n // Get variable name\n const varToken = this.peek();\n if (varToken.type !== \"word\") {\n throw new ParseError(\"Expected variable name after 'for'\");\n }\n this.advance();\n const variable = varToken.value;\n\n // Parse optional 'in' clause\n const items: ASTNode[] = [];\n if (this.checkKeyword(\"in\")) {\n this.expectKeyword(\"in\");\n // Read items until semicolon, newline, or 'do'\n while (!this.isAtEnd() && !this.check(\"semicolon\") && !this.check(\"newline\") && !this.checkKeyword(\"do\")) {\n items.push(this.parseWordArg());\n }\n }\n\n // Consume separator (semicolon or newline)\n if (!this.match(\"semicolon\")) {\n this.match(\"newline\");\n }\n this.skipNewlines();\n\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"for\",\n variable,\n items,\n body,\n };\n }\n\n // while := 'while' compound_list 'do' compound_list 'done'\n private parseWhile(): WhileNode {\n this.expectKeyword(\"while\");\n const condition = this.parseCompoundList([\"do\"]);\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"while\",\n condition,\n body,\n };\n }\n\n // until := 'until' compound_list 'do' compound_list 'done'\n private parseUntil(): UntilNode {\n this.expectKeyword(\"until\");\n const condition = this.parseCompoundList([\"do\"]);\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"until\",\n condition,\n body,\n };\n }\n\n // case := 'case' word 'in' (pattern ('|' pattern)* ')' compound_list ';;')* 'esac'\n private parseCase(): CaseNode {\n this.expectKeyword(\"case\");\n const word = this.parseWordArg();\n this.expectKeyword(\"in\");\n this.skipNewlines();\n\n const clauses: CaseClause[] = [];\n\n while (!this.isAtEnd() && !this.checkKeyword(\"esac\")) {\n // Parse patterns separated by '|'\n // Skip leading '(' if present\n this.match(\"openParen\");\n\n const patterns: ASTNode[] = [];\n patterns.push(this.parseCasePattern());\n\n while (this.match(\"pipe\")) {\n patterns.push(this.parseCasePattern());\n }\n\n // Expect ')'\n if (!this.match(\"closeParen\")) {\n throw new ParseError(\"Expected ')' after case pattern\");\n }\n\n // Parse body until ';;' or 'esac'\n const body = this.parseCaseBody();\n\n clauses.push({ patterns, body });\n\n // ';;' is optional for the last clause\n this.match(\"doubleSemicolon\");\n this.skipNewlines();\n }\n\n this.expectKeyword(\"esac\");\n\n return {\n type: \"case\",\n word,\n clauses,\n };\n }\n\n private parseCasePattern(): ASTNode {\n const token = this.peek();\n\n // Handle glob patterns and words\n if (token.type === \"word\" || token.type === \"glob\" || token.type === \"singleQuote\" || token.type === \"doubleQuote\") {\n return this.parseWordArg();\n }\n\n throw new ParseError(`Expected pattern in case clause, got ${token.type}`);\n }\n\n private parseCaseBody(): ASTNode {\n const commands: ASTNode[] = [];\n this.skipNewlines();\n\n // Parse until ';;' or 'esac'\n while (!this.isAtEnd() && !this.check(\"doubleSemicolon\") && !this.checkKeyword(\"esac\")) {\n commands.push(this.parseAndOr());\n // Consume separator\n if (!this.match(\"semicolon\") && !this.match(\"newline\")) {\n break;\n }\n this.skipNewlines();\n // Check for terminators after consuming separators\n if (this.check(\"doubleSemicolon\") || this.checkKeyword(\"esac\")) {\n break;\n }\n }\n\n if (commands.length === 0) {\n return { type: \"command\", name: { type: \"literal\", value: \"true\" }, args: [], redirects: [], assignments: [] };\n }\n if (commands.length === 1) {\n return commands[0]!;\n }\n return { type: \"sequence\", commands };\n }\n\n // compound_list := and_or ((';'|'\\n') and_or)* [';'|'\\n']\n private parseCompoundList(terminators: KeywordValue[]): ASTNode {\n this.skipNewlines();\n const commands: ASTNode[] = [];\n\n // Check for empty list\n if (this.isCompoundListTerminator(terminators)) {\n // Return a no-op command for empty list\n return { type: \"command\", name: { type: \"literal\", value: \"true\" }, args: [], redirects: [], assignments: [] };\n }\n\n commands.push(this.parseAndOr());\n\n while ((this.match(\"semicolon\") || this.match(\"newline\")) && !this.isAtEnd()) {\n this.skipNewlines();\n // Check for terminators\n if (this.isCompoundListTerminator(terminators)) {\n break;\n }\n commands.push(this.parseAndOr());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"sequence\", commands };\n }\n\n private isCompoundListTerminator(terminators: KeywordValue[]): boolean {\n const token = this.peek();\n if (token.type !== \"keyword\") return false;\n return terminators.includes(token.value);\n }\n\n private checkKeyword(value: KeywordValue): boolean {\n const token = this.peek();\n return token.type === \"keyword\" && token.value === value;\n }\n\n private expectKeyword(value: KeywordValue): void {\n if (!this.checkKeyword(value)) {\n throw new ParseError(`Expected '${value}'`);\n }\n this.advance();\n // Don't skip newlines here - let the caller handle them\n // Newlines are significant as command separators in compound lists\n }\n\n // command := assignment* word+ redirect*\n private parseCommand(): CommandNode {\n const assignments: Array<{ name: string; value: ASTNode }> = [];\n const args: ASTNode[] = [];\n const redirects: Redirect[] = [];\n\n // Collect leading assignments\n while (this.check(\"assignment\")) {\n const token = this.advance() as Token & { type: \"assignment\" };\n assignments.push({\n name: token.name,\n value: this.tokenToNode(token.value),\n });\n }\n\n // Collect command name and arguments\n while (this.isWordToken()) {\n // Check if it's a heredoc token - convert to input redirect\n if (this.peek().type === \"heredoc\") {\n const heredocToken = this.advance() as Token & { type: \"heredoc\" };\n redirects.push({\n mode: \"<\",\n target: this.tokenToNode(heredocToken),\n heredocContent: true,\n });\n } else {\n args.push(this.parseWordArg());\n }\n }\n\n // Collect redirects\n while (this.check(\"redirect\")) {\n const redirect = this.parseRedirect();\n redirects.push(redirect);\n // After a redirect, there might be more words\n while (this.isWordToken()) {\n args.push(this.parseWordArg());\n }\n }\n\n if (args.length === 0 && assignments.length === 0 && redirects.length === 0) {\n throw new ParseError(\"Expected command\");\n }\n\n const name = args.shift() ?? { type: \"literal\" as const, value: redirects.length > 0 ? \":\" : \"\" };\n\n return {\n type: \"command\",\n name,\n args,\n redirects,\n assignments,\n };\n }\n\n private parseWordArg(): ASTNode {\n const token = this.advance();\n return this.tokenToNode(token);\n }\n\n private tokenToNode(token: Token | string | Token[]): ASTNode {\n if (typeof token === \"string\") {\n return { type: \"literal\", value: token };\n }\n\n if (Array.isArray(token)) {\n const parts = token.map((t) => this.tokenToNode(t));\n if (parts.length === 1) return parts[0]!;\n return { type: \"concat\", parts };\n }\n\n switch (token.type) {\n case \"word\":\n return { type: \"literal\", value: token.value };\n case \"singleQuote\":\n return { type: \"literal\", value: token.value };\n case \"doubleQuote\":\n return this.parseDoubleQuoteParts(token.parts);\n case \"variable\":\n return { type: \"variable\", name: token.name };\n case \"substitution\":\n // Parse the inner command\n const innerParser = new Parser(\n new (require(\"../lexer/lexer.ts\").Lexer)(token.command, { preserveNewlines: true }).tokenize()\n );\n return { type: \"substitution\", command: innerParser.parse() };\n case \"arithmetic\":\n return { type: \"arithmetic\", expression: token.expression };\n case \"glob\":\n return { type: \"glob\", pattern: token.pattern };\n case \"assignment\":\n return this.tokenToNode(token.value);\n case \"heredoc\":\n if (token.expand) {\n return this.parseHeredocContent(token.content);\n }\n return { type: \"literal\", value: token.content };\n default:\n throw new ParseError(`Unexpected token type: ${(token as Token).type}`);\n }\n }\n\n private parseDoubleQuoteParts(parts: Array<string | Token>): ASTNode {\n if (parts.length === 0) {\n return { type: \"literal\", value: \"\" };\n }\n\n if (parts.length === 1) {\n const part = parts[0]!;\n if (typeof part === \"string\") {\n return { type: \"literal\", value: part };\n }\n return this.tokenToNode(part);\n }\n\n const nodes: ASTNode[] = parts.map((part) => {\n if (typeof part === \"string\") {\n return { type: \"literal\" as const, value: part };\n }\n return this.tokenToNode(part);\n });\n\n return { type: \"concat\", parts: nodes };\n }\n\n private parseHeredocContent(content: string): ASTNode {\n // Parse content looking for $VAR and ${VAR} patterns\n const parts: ASTNode[] = [];\n let currentLiteral = \"\";\n let i = 0;\n\n while (i < content.length) {\n if (content[i] === \"$\") {\n // Flush current literal\n if (currentLiteral) {\n parts.push({ type: \"literal\", value: currentLiteral });\n currentLiteral = \"\";\n }\n\n i++; // consume $\n if (i >= content.length) {\n currentLiteral += \"$\";\n break;\n }\n\n if (content[i] === \"{\") {\n // ${VAR} syntax\n i++; // consume {\n let varName = \"\";\n while (i < content.length && content[i] !== \"}\") {\n varName += content[i];\n i++;\n }\n if (i < content.length && content[i] === \"}\") {\n i++; // consume }\n }\n if (varName) {\n parts.push({ type: \"variable\", name: varName });\n }\n } else if (/[a-zA-Z_]/.test(content[i] ?? \"\")) {\n // $VAR syntax\n let varName = \"\";\n while (i < content.length && /[a-zA-Z0-9_]/.test(content[i] ?? \"\")) {\n varName += content[i];\n i++;\n }\n parts.push({ type: \"variable\", name: varName });\n } else {\n // Not a variable, keep the $\n currentLiteral += \"$\";\n }\n } else {\n currentLiteral += content[i];\n i++;\n }\n }\n\n // Flush remaining literal\n if (currentLiteral) {\n parts.push({ type: \"literal\", value: currentLiteral });\n }\n\n if (parts.length === 0) {\n return { type: \"literal\", value: \"\" };\n }\n if (parts.length === 1) {\n return parts[0]!;\n }\n return { type: \"concat\", parts };\n }\n\n private parseRedirect(): Redirect {\n const token = this.advance() as Token & { type: \"redirect\" };\n const mode = token.mode as RedirectMode;\n\n // 2>&1 and 1>&2 don't have a target\n if (mode === \"2>&1\" || mode === \"1>&2\") {\n return { mode, target: { type: \"literal\", value: \"\" } };\n }\n\n if (!this.isWordToken()) {\n throw new ParseError(`Expected redirect target after ${mode}`);\n }\n\n const target = this.parseWordArg();\n return { mode, target };\n }\n\n private isWordToken(): boolean {\n const token = this.peek();\n return (\n token.type === \"word\" ||\n token.type === \"singleQuote\" ||\n token.type === \"doubleQuote\" ||\n token.type === \"variable\" ||\n token.type === \"substitution\" ||\n token.type === \"arithmetic\" ||\n token.type === \"glob\" ||\n token.type === \"heredoc\"\n );\n }\n\n private check(type: Token[\"type\"]): boolean {\n return this.peek().type === type;\n }\n\n private match(type: Token[\"type\"]): boolean {\n if (this.check(type)) {\n this.advance();\n return true;\n }\n return false;\n }\n\n private peek(): Token {\n return this.tokens[this.pos] ?? { type: \"eof\" };\n }\n\n private advance(): Token {\n const token = this.peek();\n this.pos++;\n return token;\n }\n\n private isAtEnd(): boolean {\n return this.peek().type === \"eof\";\n }\n}\n\nexport function parse(tokens: Token[]): ASTNode {\n return new Parser(tokens).parse();\n}\n"
5
+ "import { ParseError } from \"../errors.cjs\";\nimport type { Token, KeywordValue } from \"../lexer/tokens.cjs\";\nimport type { ASTNode, Redirect, RedirectMode, CommandNode, IfNode, ForNode, WhileNode, UntilNode, CaseNode, CaseClause } from \"./ast.cjs\";\n\nexport class Parser {\n private tokens: Token[];\n private pos: number = 0;\n\n constructor(tokens: Token[]) {\n this.tokens = tokens;\n }\n\n parse(): ASTNode {\n const result = this.parseSequence();\n if (!this.isAtEnd()) {\n throw new ParseError(`Unexpected token: ${JSON.stringify(this.peek())}`);\n }\n return result;\n }\n\n // sequence := and_or ((';'|'\\n') and_or)*\n private parseSequence(): ASTNode {\n this.skipNewlines();\n const commands: ASTNode[] = [];\n commands.push(this.parseAndOr());\n\n while (this.match(\"semicolon\") || this.match(\"newline\")) {\n this.skipNewlines();\n // Skip empty commands after separator, or stop at terminating keywords\n if (this.isAtEnd() || this.check(\"semicolon\") || this.check(\"newline\") || this.isTerminatingKeyword()) continue;\n commands.push(this.parseAndOr());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"sequence\", commands };\n }\n\n private skipNewlines(): void {\n while (this.match(\"newline\")) {\n // keep consuming newlines\n }\n }\n\n private isTerminatingKeyword(): boolean {\n const token = this.peek();\n if (token.type !== \"keyword\") return false;\n return [\"then\", \"elif\", \"else\", \"fi\", \"do\", \"done\", \"esac\"].includes(token.value);\n }\n\n // and_or := pipeline (('&&'|'||') pipeline)*\n private parseAndOr(): ASTNode {\n let left = this.parsePipeline();\n\n while (this.check(\"and\") || this.check(\"or\")) {\n if (this.match(\"and\")) {\n const right = this.parsePipeline();\n left = { type: \"and\", left, right };\n } else if (this.match(\"or\")) {\n const right = this.parsePipeline();\n left = { type: \"or\", left, right };\n }\n }\n\n return left;\n }\n\n // pipeline := command ('|' command)*\n private parsePipeline(): ASTNode {\n const commands: ASTNode[] = [];\n commands.push(this.parseCompoundOrCommand());\n\n while (this.match(\"pipe\")) {\n this.skipNewlines();\n commands.push(this.parseCompoundOrCommand());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"pipeline\", commands };\n }\n\n // compound_or_command := compound_command | simple_command\n private parseCompoundOrCommand(): ASTNode {\n this.skipNewlines();\n const token = this.peek();\n\n if (token.type === \"keyword\") {\n switch (token.value) {\n case \"if\":\n return this.parseIf();\n case \"for\":\n return this.parseFor();\n case \"while\":\n return this.parseWhile();\n case \"until\":\n return this.parseUntil();\n case \"case\":\n return this.parseCase();\n }\n }\n\n return this.parseCommand();\n }\n\n // if := 'if' compound_list 'then' compound_list ('elif' compound_list 'then' compound_list)* ['else' compound_list] 'fi'\n private parseIf(): IfNode {\n this.expectKeyword(\"if\");\n const condition = this.parseCompoundList([\"then\"]);\n this.expectKeyword(\"then\");\n const thenBranch = this.parseCompoundList([\"elif\", \"else\", \"fi\"]);\n\n const elifBranches: Array<{ condition: ASTNode; body: ASTNode }> = [];\n while (this.checkKeyword(\"elif\")) {\n this.expectKeyword(\"elif\");\n const elifCondition = this.parseCompoundList([\"then\"]);\n this.expectKeyword(\"then\");\n const elifBody = this.parseCompoundList([\"elif\", \"else\", \"fi\"]);\n elifBranches.push({ condition: elifCondition, body: elifBody });\n }\n\n let elseBranch: ASTNode | undefined;\n if (this.checkKeyword(\"else\")) {\n this.expectKeyword(\"else\");\n elseBranch = this.parseCompoundList([\"fi\"]);\n }\n\n this.expectKeyword(\"fi\");\n\n return {\n type: \"if\",\n condition,\n thenBranch,\n elifBranches,\n elseBranch,\n };\n }\n\n // for := 'for' NAME ['in' word*] (';'|'\\n') 'do' compound_list 'done'\n private parseFor(): ForNode {\n this.expectKeyword(\"for\");\n\n // Get variable name\n const varToken = this.peek();\n if (varToken.type !== \"word\") {\n throw new ParseError(\"Expected variable name after 'for'\");\n }\n this.advance();\n const variable = varToken.value;\n\n // Parse optional 'in' clause\n const items: ASTNode[] = [];\n if (this.checkKeyword(\"in\")) {\n this.expectKeyword(\"in\");\n // Read items until semicolon, newline, or 'do'\n while (!this.isAtEnd() && !this.check(\"semicolon\") && !this.check(\"newline\") && !this.checkKeyword(\"do\")) {\n items.push(this.parseWordArg());\n }\n }\n\n // Consume separator (semicolon or newline)\n if (!this.match(\"semicolon\")) {\n this.match(\"newline\");\n }\n this.skipNewlines();\n\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"for\",\n variable,\n items,\n body,\n };\n }\n\n // while := 'while' compound_list 'do' compound_list 'done'\n private parseWhile(): WhileNode {\n this.expectKeyword(\"while\");\n const condition = this.parseCompoundList([\"do\"]);\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"while\",\n condition,\n body,\n };\n }\n\n // until := 'until' compound_list 'do' compound_list 'done'\n private parseUntil(): UntilNode {\n this.expectKeyword(\"until\");\n const condition = this.parseCompoundList([\"do\"]);\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"until\",\n condition,\n body,\n };\n }\n\n // case := 'case' word 'in' (pattern ('|' pattern)* ')' compound_list ';;')* 'esac'\n private parseCase(): CaseNode {\n this.expectKeyword(\"case\");\n const word = this.parseWordArg();\n this.expectKeyword(\"in\");\n this.skipNewlines();\n\n const clauses: CaseClause[] = [];\n\n while (!this.isAtEnd() && !this.checkKeyword(\"esac\")) {\n // Parse patterns separated by '|'\n // Skip leading '(' if present\n this.match(\"openParen\");\n\n const patterns: ASTNode[] = [];\n patterns.push(this.parseCasePattern());\n\n while (this.match(\"pipe\")) {\n patterns.push(this.parseCasePattern());\n }\n\n // Expect ')'\n if (!this.match(\"closeParen\")) {\n throw new ParseError(\"Expected ')' after case pattern\");\n }\n\n // Parse body until ';;' or 'esac'\n const body = this.parseCaseBody();\n\n clauses.push({ patterns, body });\n\n // ';;' is optional for the last clause\n this.match(\"doubleSemicolon\");\n this.skipNewlines();\n }\n\n this.expectKeyword(\"esac\");\n\n return {\n type: \"case\",\n word,\n clauses,\n };\n }\n\n private parseCasePattern(): ASTNode {\n const token = this.peek();\n\n // Handle glob patterns and words\n if (token.type === \"word\" || token.type === \"glob\" || token.type === \"singleQuote\" || token.type === \"doubleQuote\") {\n return this.parseWordArg();\n }\n\n throw new ParseError(`Expected pattern in case clause, got ${token.type}`);\n }\n\n private parseCaseBody(): ASTNode {\n const commands: ASTNode[] = [];\n this.skipNewlines();\n\n // Parse until ';;' or 'esac'\n while (!this.isAtEnd() && !this.check(\"doubleSemicolon\") && !this.checkKeyword(\"esac\")) {\n commands.push(this.parseAndOr());\n // Consume separator\n if (!this.match(\"semicolon\") && !this.match(\"newline\")) {\n break;\n }\n this.skipNewlines();\n // Check for terminators after consuming separators\n if (this.check(\"doubleSemicolon\") || this.checkKeyword(\"esac\")) {\n break;\n }\n }\n\n if (commands.length === 0) {\n return { type: \"command\", name: { type: \"literal\", value: \"true\" }, args: [], redirects: [], assignments: [] };\n }\n if (commands.length === 1) {\n return commands[0]!;\n }\n return { type: \"sequence\", commands };\n }\n\n // compound_list := and_or ((';'|'\\n') and_or)* [';'|'\\n']\n private parseCompoundList(terminators: KeywordValue[]): ASTNode {\n this.skipNewlines();\n const commands: ASTNode[] = [];\n\n // Check for empty list\n if (this.isCompoundListTerminator(terminators)) {\n // Return a no-op command for empty list\n return { type: \"command\", name: { type: \"literal\", value: \"true\" }, args: [], redirects: [], assignments: [] };\n }\n\n commands.push(this.parseAndOr());\n\n while ((this.match(\"semicolon\") || this.match(\"newline\")) && !this.isAtEnd()) {\n this.skipNewlines();\n // Check for terminators\n if (this.isCompoundListTerminator(terminators)) {\n break;\n }\n commands.push(this.parseAndOr());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"sequence\", commands };\n }\n\n private isCompoundListTerminator(terminators: KeywordValue[]): boolean {\n const token = this.peek();\n if (token.type !== \"keyword\") return false;\n return terminators.includes(token.value);\n }\n\n private checkKeyword(value: KeywordValue): boolean {\n const token = this.peek();\n return token.type === \"keyword\" && token.value === value;\n }\n\n private expectKeyword(value: KeywordValue): void {\n if (!this.checkKeyword(value)) {\n throw new ParseError(`Expected '${value}'`);\n }\n this.advance();\n // Don't skip newlines here - let the caller handle them\n // Newlines are significant as command separators in compound lists\n }\n\n // command := assignment* word+ redirect*\n private parseCommand(): CommandNode {\n const assignments: Array<{ name: string; value: ASTNode }> = [];\n const args: ASTNode[] = [];\n const redirects: Redirect[] = [];\n\n // Collect leading assignments\n while (this.check(\"assignment\")) {\n const token = this.advance() as Token & { type: \"assignment\" };\n assignments.push({\n name: token.name,\n value: this.tokenToNode(token.value),\n });\n }\n\n // Collect command name and arguments\n while (this.isWordToken()) {\n // Check if it's a heredoc token - convert to input redirect\n if (this.peek().type === \"heredoc\") {\n const heredocToken = this.advance() as Token & { type: \"heredoc\" };\n redirects.push({\n mode: \"<\",\n target: this.tokenToNode(heredocToken),\n heredocContent: true,\n });\n } else {\n args.push(this.parseWordArg());\n }\n }\n\n // Collect redirects\n while (this.check(\"redirect\")) {\n const redirect = this.parseRedirect();\n redirects.push(redirect);\n // After a redirect, there might be more words\n while (this.isWordToken()) {\n if (this.peek().type === \"heredoc\") {\n const heredocToken = this.advance() as Token & { type: \"heredoc\" };\n redirects.push({\n mode: \"<\",\n target: this.tokenToNode(heredocToken),\n heredocContent: true,\n });\n } else {\n args.push(this.parseWordArg());\n }\n }\n }\n\n if (args.length === 0 && assignments.length === 0 && redirects.length === 0) {\n throw new ParseError(\"Expected command\");\n }\n\n const name = args.shift() ?? { type: \"literal\" as const, value: redirects.length > 0 ? \":\" : \"\" };\n\n return {\n type: \"command\",\n name,\n args,\n redirects,\n assignments,\n };\n }\n\n private parseWordArg(): ASTNode {\n const token = this.advance();\n return this.tokenToNode(token);\n }\n\n private tokenToNode(token: Token | string | Token[]): ASTNode {\n if (typeof token === \"string\") {\n return { type: \"literal\", value: token };\n }\n\n if (Array.isArray(token)) {\n const parts = token.map((t) => this.tokenToNode(t));\n if (parts.length === 1) return parts[0]!;\n return { type: \"concat\", parts };\n }\n\n switch (token.type) {\n case \"word\":\n return { type: \"literal\", value: token.value };\n case \"singleQuote\":\n return { type: \"literal\", value: token.value };\n case \"doubleQuote\":\n return this.parseDoubleQuoteParts(token.parts);\n case \"variable\":\n return { type: \"variable\", name: token.name };\n case \"substitution\":\n // Parse the inner command\n const innerParser = new Parser(\n new (require(\"../lexer/lexer.ts\").Lexer)(token.command, { preserveNewlines: true }).tokenize()\n );\n return { type: \"substitution\", command: innerParser.parse() };\n case \"arithmetic\":\n return { type: \"arithmetic\", expression: token.expression };\n case \"glob\":\n return { type: \"glob\", pattern: token.pattern };\n case \"assignment\":\n return this.tokenToNode(token.value);\n case \"heredoc\":\n if (token.expand) {\n return this.parseHeredocContent(token.content);\n }\n return { type: \"literal\", value: token.content };\n default:\n throw new ParseError(`Unexpected token type: ${(token as Token).type}`);\n }\n }\n\n private parseDoubleQuoteParts(parts: Array<string | Token>): ASTNode {\n if (parts.length === 0) {\n return { type: \"literal\", value: \"\" };\n }\n\n if (parts.length === 1) {\n const part = parts[0]!;\n if (typeof part === \"string\") {\n return { type: \"literal\", value: part };\n }\n return this.tokenToNode(part);\n }\n\n const nodes: ASTNode[] = parts.map((part) => {\n if (typeof part === \"string\") {\n return { type: \"literal\" as const, value: part };\n }\n return this.tokenToNode(part);\n });\n\n return { type: \"concat\", parts: nodes };\n }\n\n private parseHeredocContent(content: string): ASTNode {\n // Parse content looking for $VAR and ${VAR} patterns\n const parts: ASTNode[] = [];\n let currentLiteral = \"\";\n let i = 0;\n\n while (i < content.length) {\n if (content[i] === \"$\") {\n // Flush current literal\n if (currentLiteral) {\n parts.push({ type: \"literal\", value: currentLiteral });\n currentLiteral = \"\";\n }\n\n i++; // consume $\n if (i >= content.length) {\n currentLiteral += \"$\";\n break;\n }\n\n if (content[i] === \"{\") {\n // ${VAR} syntax\n i++; // consume {\n let varName = \"\";\n while (i < content.length && content[i] !== \"}\") {\n varName += content[i];\n i++;\n }\n if (i < content.length && content[i] === \"}\") {\n i++; // consume }\n }\n if (varName) {\n parts.push({ type: \"variable\", name: varName });\n }\n } else if (/[a-zA-Z_]/.test(content[i] ?? \"\")) {\n // $VAR syntax\n let varName = \"\";\n while (i < content.length && /[a-zA-Z0-9_]/.test(content[i] ?? \"\")) {\n varName += content[i];\n i++;\n }\n parts.push({ type: \"variable\", name: varName });\n } else {\n // Not a variable, keep the $\n currentLiteral += \"$\";\n }\n } else {\n currentLiteral += content[i];\n i++;\n }\n }\n\n // Flush remaining literal\n if (currentLiteral) {\n parts.push({ type: \"literal\", value: currentLiteral });\n }\n\n if (parts.length === 0) {\n return { type: \"literal\", value: \"\" };\n }\n if (parts.length === 1) {\n return parts[0]!;\n }\n return { type: \"concat\", parts };\n }\n\n private parseRedirect(): Redirect {\n const token = this.advance() as Token & { type: \"redirect\" };\n const mode = token.mode as RedirectMode;\n\n // 2>&1 and 1>&2 don't have a target\n if (mode === \"2>&1\" || mode === \"1>&2\") {\n return { mode, target: { type: \"literal\", value: \"\" } };\n }\n\n if (!this.isWordToken()) {\n throw new ParseError(`Expected redirect target after ${mode}`);\n }\n\n const target = this.parseWordArg();\n return { mode, target };\n }\n\n private isWordToken(): boolean {\n const token = this.peek();\n return (\n token.type === \"word\" ||\n token.type === \"singleQuote\" ||\n token.type === \"doubleQuote\" ||\n token.type === \"variable\" ||\n token.type === \"substitution\" ||\n token.type === \"arithmetic\" ||\n token.type === \"glob\" ||\n token.type === \"heredoc\"\n );\n }\n\n private check(type: Token[\"type\"]): boolean {\n return this.peek().type === type;\n }\n\n private match(type: Token[\"type\"]): boolean {\n if (this.check(type)) {\n this.advance();\n return true;\n }\n return false;\n }\n\n private peek(): Token {\n return this.tokens[this.pos] ?? { type: \"eof\" };\n }\n\n private advance(): Token {\n const token = this.peek();\n this.pos++;\n return token;\n }\n\n private isAtEnd(): boolean {\n return this.peek().type === \"eof\";\n }\n}\n\nexport function parse(tokens: Token[]): ASTNode {\n return new Parser(tokens).parse();\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAA2B,IAA3B;AAAA;AAIO,MAAM,OAAO;AAAA,EACV;AAAA,EACA,MAAc;AAAA,EAEtB,WAAW,CAAC,QAAiB;AAAA,IAC3B,KAAK,SAAS;AAAA;AAAA,EAGhB,KAAK,GAAY;AAAA,IACf,MAAM,SAAS,KAAK,cAAc;AAAA,IAClC,IAAI,CAAC,KAAK,QAAQ,GAAG;AAAA,MACnB,MAAM,IAAI,yBAAW,qBAAqB,KAAK,UAAU,KAAK,KAAK,CAAC,GAAG;AAAA,IACzE;AAAA,IACA,OAAO;AAAA;AAAA,EAID,aAAa,GAAY;AAAA,IAC/B,KAAK,aAAa;AAAA,IAClB,MAAM,WAAsB,CAAC;AAAA,IAC7B,SAAS,KAAK,KAAK,WAAW,CAAC;AAAA,IAE/B,OAAO,KAAK,MAAM,WAAW,KAAK,KAAK,MAAM,SAAS,GAAG;AAAA,MACvD,KAAK,aAAa;AAAA,MAElB,IAAI,KAAK,QAAQ,KAAK,KAAK,MAAM,WAAW,KAAK,KAAK,MAAM,SAAS,KAAK,KAAK,qBAAqB;AAAA,QAAG;AAAA,MACvG,SAAS,KAAK,KAAK,WAAW,CAAC;AAAA,IACjC;AAAA,IAEA,IAAI,SAAS,WAAW,GAAG;AAAA,MACzB,OAAO,SAAS;AAAA,IAClB;AAAA,IAEA,OAAO,EAAE,MAAM,YAAY,SAAS;AAAA;AAAA,EAG9B,YAAY,GAAS;AAAA,IAC3B,OAAO,KAAK,MAAM,SAAS,GAAG,CAE9B;AAAA;AAAA,EAGM,oBAAoB,GAAY;AAAA,IACtC,MAAM,QAAQ,KAAK,KAAK;AAAA,IACxB,IAAI,MAAM,SAAS;AAAA,MAAW,OAAO;AAAA,IACrC,OAAO,CAAC,QAAQ,QAAQ,QAAQ,MAAM,MAAM,QAAQ,MAAM,EAAE,SAAS,MAAM,KAAK;AAAA;AAAA,EAI1E,UAAU,GAAY;AAAA,IAC5B,IAAI,OAAO,KAAK,cAAc;AAAA,IAE9B,OAAO,KAAK,MAAM,KAAK,KAAK,KAAK,MAAM,IAAI,GAAG;AAAA,MAC5C,IAAI,KAAK,MAAM,KAAK,GAAG;AAAA,QACrB,MAAM,QAAQ,KAAK,cAAc;AAAA,QACjC,OAAO,EAAE,MAAM,OAAO,MAAM,MAAM;AAAA,MACpC,EAAO,SAAI,KAAK,MAAM,IAAI,GAAG;AAAA,QAC3B,MAAM,QAAQ,KAAK,cAAc;AAAA,QACjC,OAAO,EAAE,MAAM,MAAM,MAAM,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA,EAID,aAAa,GAAY;AAAA,IAC/B,MAAM,WAAsB,CAAC;AAAA,IAC7B,SAAS,KAAK,KAAK,uBAAuB,CAAC;AAAA,IAE3C,OAAO,KAAK,MAAM,MAAM,GAAG;AAAA,MACzB,KAAK,aAAa;AAAA,MAClB,SAAS,KAAK,KAAK,uBAAuB,CAAC;AAAA,IAC7C;AAAA,IAEA,IAAI,SAAS,WAAW,GAAG;AAAA,MACzB,OAAO,SAAS;AAAA,IAClB;AAAA,IAEA,OAAO,EAAE,MAAM,YAAY,SAAS;AAAA;AAAA,EAI9B,sBAAsB,GAAY;AAAA,IACxC,KAAK,aAAa;AAAA,IAClB,MAAM,QAAQ,KAAK,KAAK;AAAA,IAExB,IAAI,MAAM,SAAS,WAAW;AAAA,MAC5B,QAAQ,MAAM;AAAA,aACP;AAAA,UACH,OAAO,KAAK,QAAQ;AAAA,aACjB;AAAA,UACH,OAAO,KAAK,SAAS;AAAA,aAClB;AAAA,UACH,OAAO,KAAK,WAAW;AAAA,aACpB;AAAA,UACH,OAAO,KAAK,WAAW;AAAA,aACpB;AAAA,UACH,OAAO,KAAK,UAAU;AAAA;AAAA,IAE5B;AAAA,IAEA,OAAO,KAAK,aAAa;AAAA;AAAA,EAInB,OAAO,GAAW;AAAA,IACxB,KAAK,cAAc,IAAI;AAAA,IACvB,MAAM,YAAY,KAAK,kBAAkB,CAAC,MAAM,CAAC;AAAA,IACjD,KAAK,cAAc,MAAM;AAAA,IACzB,MAAM,aAAa,KAAK,kBAAkB,CAAC,QAAQ,QAAQ,IAAI,CAAC;AAAA,IAEhE,MAAM,eAA6D,CAAC;AAAA,IACpE,OAAO,KAAK,aAAa,MAAM,GAAG;AAAA,MAChC,KAAK,cAAc,MAAM;AAAA,MACzB,MAAM,gBAAgB,KAAK,kBAAkB,CAAC,MAAM,CAAC;AAAA,MACrD,KAAK,cAAc,MAAM;AAAA,MACzB,MAAM,WAAW,KAAK,kBAAkB,CAAC,QAAQ,QAAQ,IAAI,CAAC;AAAA,MAC9D,aAAa,KAAK,EAAE,WAAW,eAAe,MAAM,SAAS,CAAC;AAAA,IAChE;AAAA,IAEA,IAAI;AAAA,IACJ,IAAI,KAAK,aAAa,MAAM,GAAG;AAAA,MAC7B,KAAK,cAAc,MAAM;AAAA,MACzB,aAAa,KAAK,kBAAkB,CAAC,IAAI,CAAC;AAAA,IAC5C;AAAA,IAEA,KAAK,cAAc,IAAI;AAAA,IAEvB,OAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA,EAIM,QAAQ,GAAY;AAAA,IAC1B,KAAK,cAAc,KAAK;AAAA,IAGxB,MAAM,WAAW,KAAK,KAAK;AAAA,IAC3B,IAAI,SAAS,SAAS,QAAQ;AAAA,MAC5B,MAAM,IAAI,yBAAW,oCAAoC;AAAA,IAC3D;AAAA,IACA,KAAK,QAAQ;AAAA,IACb,MAAM,WAAW,SAAS;AAAA,IAG1B,MAAM,QAAmB,CAAC;AAAA,IAC1B,IAAI,KAAK,aAAa,IAAI,GAAG;AAAA,MAC3B,KAAK,cAAc,IAAI;AAAA,MAEvB,OAAO,CAAC,KAAK,QAAQ,KAAK,CAAC,KAAK,MAAM,WAAW,KAAK,CAAC,KAAK,MAAM,SAAS,KAAK,CAAC,KAAK,aAAa,IAAI,GAAG;AAAA,QACxG,MAAM,KAAK,KAAK,aAAa,CAAC;AAAA,MAChC;AAAA,IACF;AAAA,IAGA,IAAI,CAAC,KAAK,MAAM,WAAW,GAAG;AAAA,MAC5B,KAAK,MAAM,SAAS;AAAA,IACtB;AAAA,IACA,KAAK,aAAa;AAAA,IAElB,KAAK,cAAc,IAAI;AAAA,IACvB,MAAM,OAAO,KAAK,kBAAkB,CAAC,MAAM,CAAC;AAAA,IAC5C,KAAK,cAAc,MAAM;AAAA,IAEzB,OAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA,EAIM,UAAU,GAAc;AAAA,IAC9B,KAAK,cAAc,OAAO;AAAA,IAC1B,MAAM,YAAY,KAAK,kBAAkB,CAAC,IAAI,CAAC;AAAA,IAC/C,KAAK,cAAc,IAAI;AAAA,IACvB,MAAM,OAAO,KAAK,kBAAkB,CAAC,MAAM,CAAC;AAAA,IAC5C,KAAK,cAAc,MAAM;AAAA,IAEzB,OAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA;AAAA,EAIM,UAAU,GAAc;AAAA,IAC9B,KAAK,cAAc,OAAO;AAAA,IAC1B,MAAM,YAAY,KAAK,kBAAkB,CAAC,IAAI,CAAC;AAAA,IAC/C,KAAK,cAAc,IAAI;AAAA,IACvB,MAAM,OAAO,KAAK,kBAAkB,CAAC,MAAM,CAAC;AAAA,IAC5C,KAAK,cAAc,MAAM;AAAA,IAEzB,OAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA;AAAA,EAIM,SAAS,GAAa;AAAA,IAC5B,KAAK,cAAc,MAAM;AAAA,IACzB,MAAM,OAAO,KAAK,aAAa;AAAA,IAC/B,KAAK,cAAc,IAAI;AAAA,IACvB,KAAK,aAAa;AAAA,IAElB,MAAM,UAAwB,CAAC;AAAA,IAE/B,OAAO,CAAC,KAAK,QAAQ,KAAK,CAAC,KAAK,aAAa,MAAM,GAAG;AAAA,MAGpD,KAAK,MAAM,WAAW;AAAA,MAEtB,MAAM,WAAsB,CAAC;AAAA,MAC7B,SAAS,KAAK,KAAK,iBAAiB,CAAC;AAAA,MAErC,OAAO,KAAK,MAAM,MAAM,GAAG;AAAA,QACzB,SAAS,KAAK,KAAK,iBAAiB,CAAC;AAAA,MACvC;AAAA,MAGA,IAAI,CAAC,KAAK,MAAM,YAAY,GAAG;AAAA,QAC7B,MAAM,IAAI,yBAAW,iCAAiC;AAAA,MACxD;AAAA,MAGA,MAAM,OAAO,KAAK,cAAc;AAAA,MAEhC,QAAQ,KAAK,EAAE,UAAU,KAAK,CAAC;AAAA,MAG/B,KAAK,MAAM,iBAAiB;AAAA,MAC5B,KAAK,aAAa;AAAA,IACpB;AAAA,IAEA,KAAK,cAAc,MAAM;AAAA,IAEzB,OAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA;AAAA,EAGM,gBAAgB,GAAY;AAAA,IAClC,MAAM,QAAQ,KAAK,KAAK;AAAA,IAGxB,IAAI,MAAM,SAAS,UAAU,MAAM,SAAS,UAAU,MAAM,SAAS,iBAAiB,MAAM,SAAS,eAAe;AAAA,MAClH,OAAO,KAAK,aAAa;AAAA,IAC3B;AAAA,IAEA,MAAM,IAAI,yBAAW,wCAAwC,MAAM,MAAM;AAAA;AAAA,EAGnE,aAAa,GAAY;AAAA,IAC/B,MAAM,WAAsB,CAAC;AAAA,IAC7B,KAAK,aAAa;AAAA,IAGlB,OAAO,CAAC,KAAK,QAAQ,KAAK,CAAC,KAAK,MAAM,iBAAiB,KAAK,CAAC,KAAK,aAAa,MAAM,GAAG;AAAA,MACtF,SAAS,KAAK,KAAK,WAAW,CAAC;AAAA,MAE/B,IAAI,CAAC,KAAK,MAAM,WAAW,KAAK,CAAC,KAAK,MAAM,SAAS,GAAG;AAAA,QACtD;AAAA,MACF;AAAA,MACA,KAAK,aAAa;AAAA,MAElB,IAAI,KAAK,MAAM,iBAAiB,KAAK,KAAK,aAAa,MAAM,GAAG;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,IAEA,IAAI,SAAS,WAAW,GAAG;AAAA,MACzB,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,MAAM,WAAW,OAAO,OAAO,GAAG,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,aAAa,CAAC,EAAE;AAAA,IAC/G;AAAA,IACA,IAAI,SAAS,WAAW,GAAG;AAAA,MACzB,OAAO,SAAS;AAAA,IAClB;AAAA,IACA,OAAO,EAAE,MAAM,YAAY,SAAS;AAAA;AAAA,EAI9B,iBAAiB,CAAC,aAAsC;AAAA,IAC9D,KAAK,aAAa;AAAA,IAClB,MAAM,WAAsB,CAAC;AAAA,IAG7B,IAAI,KAAK,yBAAyB,WAAW,GAAG;AAAA,MAE9C,OAAO,EAAE,MAAM,WAAW,MAAM,EAAE,MAAM,WAAW,OAAO,OAAO,GAAG,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,aAAa,CAAC,EAAE;AAAA,IAC/G;AAAA,IAEA,SAAS,KAAK,KAAK,WAAW,CAAC;AAAA,IAE/B,QAAQ,KAAK,MAAM,WAAW,KAAK,KAAK,MAAM,SAAS,MAAM,CAAC,KAAK,QAAQ,GAAG;AAAA,MAC5E,KAAK,aAAa;AAAA,MAElB,IAAI,KAAK,yBAAyB,WAAW,GAAG;AAAA,QAC9C;AAAA,MACF;AAAA,MACA,SAAS,KAAK,KAAK,WAAW,CAAC;AAAA,IACjC;AAAA,IAEA,IAAI,SAAS,WAAW,GAAG;AAAA,MACzB,OAAO,SAAS;AAAA,IAClB;AAAA,IAEA,OAAO,EAAE,MAAM,YAAY,SAAS;AAAA;AAAA,EAG9B,wBAAwB,CAAC,aAAsC;AAAA,IACrE,MAAM,QAAQ,KAAK,KAAK;AAAA,IACxB,IAAI,MAAM,SAAS;AAAA,MAAW,OAAO;AAAA,IACrC,OAAO,YAAY,SAAS,MAAM,KAAK;AAAA;AAAA,EAGjC,YAAY,CAAC,OAA8B;AAAA,IACjD,MAAM,QAAQ,KAAK,KAAK;AAAA,IACxB,OAAO,MAAM,SAAS,aAAa,MAAM,UAAU;AAAA;AAAA,EAG7C,aAAa,CAAC,OAA2B;AAAA,IAC/C,IAAI,CAAC,KAAK,aAAa,KAAK,GAAG;AAAA,MAC7B,MAAM,IAAI,yBAAW,aAAa,QAAQ;AAAA,IAC5C;AAAA,IACA,KAAK,QAAQ;AAAA;AAAA,EAMP,YAAY,GAAgB;AAAA,IAClC,MAAM,cAAuD,CAAC;AAAA,IAC9D,MAAM,OAAkB,CAAC;AAAA,IACzB,MAAM,YAAwB,CAAC;AAAA,IAG/B,OAAO,KAAK,MAAM,YAAY,GAAG;AAAA,MAC/B,MAAM,QAAQ,KAAK,QAAQ;AAAA,MAC3B,YAAY,KAAK;AAAA,QACf,MAAM,MAAM;AAAA,QACZ,OAAO,KAAK,YAAY,MAAM,KAAK;AAAA,MACrC,CAAC;AAAA,IACH;AAAA,IAGA,OAAO,KAAK,YAAY,GAAG;AAAA,MAEzB,IAAI,KAAK,KAAK,EAAE,SAAS,WAAW;AAAA,QAClC,MAAM,eAAe,KAAK,QAAQ;AAAA,QAClC,UAAU,KAAK;AAAA,UACb,MAAM;AAAA,UACN,QAAQ,KAAK,YAAY,YAAY;AAAA,UACrC,gBAAgB;AAAA,QAClB,CAAC;AAAA,MACH,EAAO;AAAA,QACL,KAAK,KAAK,KAAK,aAAa,CAAC;AAAA;AAAA,IAEjC;AAAA,IAGA,OAAO,KAAK,MAAM,UAAU,GAAG;AAAA,MAC7B,MAAM,WAAW,KAAK,cAAc;AAAA,MACpC,UAAU,KAAK,QAAQ;AAAA,MAEvB,OAAO,KAAK,YAAY,GAAG;AAAA,QACzB,KAAK,KAAK,KAAK,aAAa,CAAC;AAAA,MAC/B;AAAA,IACF;AAAA,IAEA,IAAI,KAAK,WAAW,KAAK,YAAY,WAAW,KAAK,UAAU,WAAW,GAAG;AAAA,MAC3E,MAAM,IAAI,yBAAW,kBAAkB;AAAA,IACzC;AAAA,IAEA,MAAM,OAAO,KAAK,MAAM,KAAK,EAAE,MAAM,WAAoB,OAAO,UAAU,SAAS,IAAI,MAAM,GAAG;AAAA,IAEhG,OAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA,EAGM,YAAY,GAAY;AAAA,IAC9B,MAAM,QAAQ,KAAK,QAAQ;AAAA,IAC3B,OAAO,KAAK,YAAY,KAAK;AAAA;AAAA,EAGvB,WAAW,CAAC,OAA0C;AAAA,IAC5D,IAAI,OAAO,UAAU,UAAU;AAAA,MAC7B,OAAO,EAAE,MAAM,WAAW,OAAO,MAAM;AAAA,IACzC;AAAA,IAEA,IAAI,MAAM,QAAQ,KAAK,GAAG;AAAA,MACxB,MAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC;AAAA,MAClD,IAAI,MAAM,WAAW;AAAA,QAAG,OAAO,MAAM;AAAA,MACrC,OAAO,EAAE,MAAM,UAAU,MAAM;AAAA,IACjC;AAAA,IAEA,QAAQ,MAAM;AAAA,WACP;AAAA,QACH,OAAO,EAAE,MAAM,WAAW,OAAO,MAAM,MAAM;AAAA,WAC1C;AAAA,QACH,OAAO,EAAE,MAAM,WAAW,OAAO,MAAM,MAAM;AAAA,WAC1C;AAAA,QACH,OAAO,KAAK,sBAAsB,MAAM,KAAK;AAAA,WAC1C;AAAA,QACH,OAAO,EAAE,MAAM,YAAY,MAAM,MAAM,KAAK;AAAA,WACzC;AAAA,QAEH,MAAM,cAAc,IAAI,OACtB,mCAAkC,MAAO,MAAM,SAAS,EAAE,kBAAkB,KAAK,CAAC,EAAE,SAAS,CAC/F;AAAA,QACA,OAAO,EAAE,MAAM,gBAAgB,SAAS,YAAY,MAAM,EAAE;AAAA,WACzD;AAAA,QACH,OAAO,EAAE,MAAM,cAAc,YAAY,MAAM,WAAW;AAAA,WACvD;AAAA,QACH,OAAO,EAAE,MAAM,QAAQ,SAAS,MAAM,QAAQ;AAAA,WAC3C;AAAA,QACH,OAAO,KAAK,YAAY,MAAM,KAAK;AAAA,WAChC;AAAA,QACH,IAAI,MAAM,QAAQ;AAAA,UAChB,OAAO,KAAK,oBAAoB,MAAM,OAAO;AAAA,QAC/C;AAAA,QACA,OAAO,EAAE,MAAM,WAAW,OAAO,MAAM,QAAQ;AAAA;AAAA,QAE/C,MAAM,IAAI,yBAAW,0BAA2B,MAAgB,MAAM;AAAA;AAAA;AAAA,EAIpE,qBAAqB,CAAC,OAAuC;AAAA,IACnE,IAAI,MAAM,WAAW,GAAG;AAAA,MACtB,OAAO,EAAE,MAAM,WAAW,OAAO,GAAG;AAAA,IACtC;AAAA,IAEA,IAAI,MAAM,WAAW,GAAG;AAAA,MACtB,MAAM,OAAO,MAAM;AAAA,MACnB,IAAI,OAAO,SAAS,UAAU;AAAA,QAC5B,OAAO,EAAE,MAAM,WAAW,OAAO,KAAK;AAAA,MACxC;AAAA,MACA,OAAO,KAAK,YAAY,IAAI;AAAA,IAC9B;AAAA,IAEA,MAAM,QAAmB,MAAM,IAAI,CAAC,SAAS;AAAA,MAC3C,IAAI,OAAO,SAAS,UAAU;AAAA,QAC5B,OAAO,EAAE,MAAM,WAAoB,OAAO,KAAK;AAAA,MACjD;AAAA,MACA,OAAO,KAAK,YAAY,IAAI;AAAA,KAC7B;AAAA,IAED,OAAO,EAAE,MAAM,UAAU,OAAO,MAAM;AAAA;AAAA,EAGhC,mBAAmB,CAAC,SAA0B;AAAA,IAEpD,MAAM,QAAmB,CAAC;AAAA,IAC1B,IAAI,iBAAiB;AAAA,IACrB,IAAI,IAAI;AAAA,IAER,OAAO,IAAI,QAAQ,QAAQ;AAAA,MACzB,IAAI,QAAQ,OAAO,KAAK;AAAA,QAEtB,IAAI,gBAAgB;AAAA,UAClB,MAAM,KAAK,EAAE,MAAM,WAAW,OAAO,eAAe,CAAC;AAAA,UACrD,iBAAiB;AAAA,QACnB;AAAA,QAEA;AAAA,QACA,IAAI,KAAK,QAAQ,QAAQ;AAAA,UACvB,kBAAkB;AAAA,UAClB;AAAA,QACF;AAAA,QAEA,IAAI,QAAQ,OAAO,KAAK;AAAA,UAEtB;AAAA,UACA,IAAI,UAAU;AAAA,UACd,OAAO,IAAI,QAAQ,UAAU,QAAQ,OAAO,KAAK;AAAA,YAC/C,WAAW,QAAQ;AAAA,YACnB;AAAA,UACF;AAAA,UACA,IAAI,IAAI,QAAQ,UAAU,QAAQ,OAAO,KAAK;AAAA,YAC5C;AAAA,UACF;AAAA,UACA,IAAI,SAAS;AAAA,YACX,MAAM,KAAK,EAAE,MAAM,YAAY,MAAM,QAAQ,CAAC;AAAA,UAChD;AAAA,QACF,EAAO,SAAI,YAAY,KAAK,QAAQ,MAAM,EAAE,GAAG;AAAA,UAE7C,IAAI,UAAU;AAAA,UACd,OAAO,IAAI,QAAQ,UAAU,eAAe,KAAK,QAAQ,MAAM,EAAE,GAAG;AAAA,YAClE,WAAW,QAAQ;AAAA,YACnB;AAAA,UACF;AAAA,UACA,MAAM,KAAK,EAAE,MAAM,YAAY,MAAM,QAAQ,CAAC;AAAA,QAChD,EAAO;AAAA,UAEL,kBAAkB;AAAA;AAAA,MAEtB,EAAO;AAAA,QACL,kBAAkB,QAAQ;AAAA,QAC1B;AAAA;AAAA,IAEJ;AAAA,IAGA,IAAI,gBAAgB;AAAA,MAClB,MAAM,KAAK,EAAE,MAAM,WAAW,OAAO,eAAe,CAAC;AAAA,IACvD;AAAA,IAEA,IAAI,MAAM,WAAW,GAAG;AAAA,MACtB,OAAO,EAAE,MAAM,WAAW,OAAO,GAAG;AAAA,IACtC;AAAA,IACA,IAAI,MAAM,WAAW,GAAG;AAAA,MACtB,OAAO,MAAM;AAAA,IACf;AAAA,IACA,OAAO,EAAE,MAAM,UAAU,MAAM;AAAA;AAAA,EAGzB,aAAa,GAAa;AAAA,IAChC,MAAM,QAAQ,KAAK,QAAQ;AAAA,IAC3B,MAAM,OAAO,MAAM;AAAA,IAGnB,IAAI,SAAS,UAAU,SAAS,QAAQ;AAAA,MACtC,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,WAAW,OAAO,GAAG,EAAE;AAAA,IACxD;AAAA,IAEA,IAAI,CAAC,KAAK,YAAY,GAAG;AAAA,MACvB,MAAM,IAAI,yBAAW,kCAAkC,MAAM;AAAA,IAC/D;AAAA,IAEA,MAAM,SAAS,KAAK,aAAa;AAAA,IACjC,OAAO,EAAE,MAAM,OAAO;AAAA;AAAA,EAGhB,WAAW,GAAY;AAAA,IAC7B,MAAM,QAAQ,KAAK,KAAK;AAAA,IACxB,OACE,MAAM,SAAS,UACf,MAAM,SAAS,iBACf,MAAM,SAAS,iBACf,MAAM,SAAS,cACf,MAAM,SAAS,kBACf,MAAM,SAAS,gBACf,MAAM,SAAS,UACf,MAAM,SAAS;AAAA;AAAA,EAIX,KAAK,CAAC,MAA8B;AAAA,IAC1C,OAAO,KAAK,KAAK,EAAE,SAAS;AAAA;AAAA,EAGtB,KAAK,CAAC,MAA8B;AAAA,IAC1C,IAAI,KAAK,MAAM,IAAI,GAAG;AAAA,MACpB,KAAK,QAAQ;AAAA,MACb,OAAO;AAAA,IACT;AAAA,IACA,OAAO;AAAA;AAAA,EAGD,IAAI,GAAU;AAAA,IACpB,OAAO,KAAK,OAAO,KAAK,QAAQ,EAAE,MAAM,MAAM;AAAA;AAAA,EAGxC,OAAO,GAAU;AAAA,IACvB,MAAM,QAAQ,KAAK,KAAK;AAAA,IACxB,KAAK;AAAA,IACL,OAAO;AAAA;AAAA,EAGD,OAAO,GAAY;AAAA,IACzB,OAAO,KAAK,KAAK,EAAE,SAAS;AAAA;AAEhC;AAEO,SAAS,KAAK,CAAC,QAA0B;AAAA,EAC9C,OAAO,IAAI,OAAO,MAAM,EAAE,MAAM;AAAA;",
8
- "debugId": "A85F8476E4AB0C2264756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "8C083E4DFB31F65664756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../src/types.ts"],
4
4
  "sourcesContent": [
5
- "// Virtual Filesystem Interface\nexport interface VirtualFS {\n readFile(path: string): Promise<Buffer>;\n readdir(path: string): Promise<string[]>;\n stat(path: string): Promise<FileStat>;\n exists(path: string): Promise<boolean>;\n\n writeFile(path: string, data: Buffer | string): Promise<void>;\n appendFile(path: string, data: Buffer | string): Promise<void>;\n mkdir(path: string, opts?: { recursive?: boolean }): Promise<void>;\n\n rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void>;\n\n resolve(...paths: string[]): string;\n dirname(path: string): string;\n basename(path: string): string;\n glob(pattern: string, opts?: { cwd?: string }): Promise<string[]>;\n}\n\nexport interface FileStat {\n isFile(): boolean;\n isDirectory(): boolean;\n size: number;\n mtime: Date;\n}\n\n// Command Interfaces\nexport type Command = (ctx: CommandContext) => Promise<number>;\n\nexport interface CommandContext {\n args: string[];\n stdin: Stdin;\n stdout: Stdout;\n stderr: Stderr;\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n}\n\nexport interface Stdin {\n stream(): AsyncIterable<Uint8Array>;\n buffer(): Promise<Buffer>;\n text(): Promise<string>;\n lines(): AsyncIterable<string>;\n}\n\nexport interface Stdout {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n}\n\nexport interface Stderr {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n}\n\nexport interface OutputCollector extends Stdout {\n close(): void;\n collect(): Promise<Buffer>;\n getReadableStream(): AsyncIterable<Uint8Array>;\n}\n\n// Execution Result\nexport interface ExecResult {\n stdout: Buffer;\n stderr: Buffer;\n exitCode: number;\n}\n\n// Shell Configuration\nexport interface ShellConfig {\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n commands: Record<string, Command>;\n}\n\n// Raw escape hatch type\nexport interface RawValue {\n raw: string;\n}\n\nexport function isRawValue(value: unknown): value is RawValue {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"raw\" in value &&\n typeof (value as RawValue).raw === \"string\"\n );\n}\n\n// JS Object Redirection types\nexport type RedirectObject = Buffer | Blob | Response | string;\n\nexport interface RedirectObjectMap {\n [marker: string]: RedirectObject;\n}\n\nexport function isRedirectObject(value: unknown): value is RedirectObject {\n return (\n Buffer.isBuffer(value) ||\n value instanceof Blob ||\n value instanceof Response ||\n typeof value === \"string\"\n );\n}\n"
5
+ "// Virtual Filesystem Interface\nexport interface VirtualFS {\n readFile(path: string): Promise<Buffer>;\n readdir(path: string): Promise<string[]>;\n stat(path: string): Promise<FileStat>;\n exists(path: string): Promise<boolean>;\n\n writeFile(path: string, data: Buffer | string): Promise<void>;\n appendFile(path: string, data: Buffer | string): Promise<void>;\n mkdir(path: string, opts?: { recursive?: boolean }): Promise<void>;\n\n rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void>;\n\n resolve(...paths: string[]): string;\n dirname(path: string): string;\n basename(path: string): string;\n glob(pattern: string, opts?: { cwd?: string }): Promise<string[]>;\n}\n\nexport interface FileStat {\n isFile(): boolean;\n isDirectory(): boolean;\n size: number;\n mtime: Date;\n}\n\n// Command Interfaces\nexport type Command = (ctx: CommandContext) => Promise<number>;\n\nexport interface CommandContext {\n args: string[];\n stdin: Stdin;\n stdout: Stdout;\n stderr: Stderr;\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n setCwd: (path: string) => void;\n}\n\nexport interface Stdin {\n stream(): AsyncIterable<Uint8Array>;\n buffer(): Promise<Buffer>;\n text(): Promise<string>;\n lines(): AsyncIterable<string>;\n}\n\nexport interface Stdout {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n}\n\nexport interface Stderr {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n}\n\nexport interface OutputCollector extends Stdout {\n close(): void;\n collect(): Promise<Buffer>;\n getReadableStream(): AsyncIterable<Uint8Array>;\n}\n\n// Execution Result\nexport interface ExecResult {\n stdout: Buffer;\n stderr: Buffer;\n exitCode: number;\n}\n\n// Shell Configuration\nexport interface ShellConfig {\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n commands: Record<string, Command>;\n}\n\n// Raw escape hatch type\nexport interface RawValue {\n raw: string;\n}\n\nexport function isRawValue(value: unknown): value is RawValue {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"raw\" in value &&\n typeof (value as RawValue).raw === \"string\"\n );\n}\n\n// JS Object Redirection types\nexport type RedirectObject = Buffer | Blob | Response | string;\n\nexport interface RedirectObjectMap {\n [marker: string]: RedirectObject;\n}\n\nexport function isRedirectObject(value: unknown): value is RedirectObject {\n return (\n Buffer.isBuffer(value) ||\n value instanceof Blob ||\n value instanceof Response ||\n typeof value === \"string\"\n );\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkFO,SAAS,UAAU,CAAC,OAAmC;AAAA,EAC5D,OACE,OAAO,UAAU,YACjB,UAAU,QACV,SAAS,SACT,OAAQ,MAAmB,QAAQ;AAAA;AAWhC,SAAS,gBAAgB,CAAC,OAAyC;AAAA,EACxE,OACE,OAAO,SAAS,KAAK,KACrB,iBAAiB,QACjB,iBAAiB,YACjB,OAAO,UAAU;AAAA;",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmFO,SAAS,UAAU,CAAC,OAAmC;AAAA,EAC5D,OACE,OAAO,UAAU,YACjB,UAAU,QACV,SAAS,SACT,OAAQ,MAAmB,QAAQ;AAAA;AAWhC,SAAS,gBAAgB,CAAC,OAAyC;AAAA,EACxE,OACE,OAAO,SAAS,KAAK,KACrB,iBAAiB,QACjB,iBAAiB,YACjB,OAAO,UAAU;AAAA;",
8
8
  "debugId": "A099C0F37A42BA3264756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "shell-dsl",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "type": "module"
5
5
  }
@@ -0,0 +1,36 @@
1
+ // src/commands/cd/cd.ts
2
+ var cd = async (ctx) => {
3
+ if (ctx.args.length === 0) {
4
+ return 0;
5
+ }
6
+ let target = ctx.args[0];
7
+ if (target === "-") {
8
+ const oldpwd = ctx.env.OLDPWD;
9
+ if (!oldpwd) {
10
+ await ctx.stderr.writeText(`cd: OLDPWD not set
11
+ `);
12
+ return 1;
13
+ }
14
+ target = oldpwd;
15
+ }
16
+ const resolved = ctx.fs.resolve(ctx.cwd, target);
17
+ try {
18
+ const stat = await ctx.fs.stat(resolved);
19
+ if (!stat.isDirectory()) {
20
+ await ctx.stderr.writeText(`cd: not a directory: ${target}
21
+ `);
22
+ return 1;
23
+ }
24
+ } catch {
25
+ await ctx.stderr.writeText(`cd: not a directory: ${target}
26
+ `);
27
+ return 1;
28
+ }
29
+ ctx.setCwd(resolved);
30
+ return 0;
31
+ };
32
+ export {
33
+ cd
34
+ };
35
+
36
+ //# debugId=3C0FC29F2AE9154464756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/commands/cd/cd.ts"],
4
+ "sourcesContent": [
5
+ "import type { Command } from \"../../types.mjs\";\n\nexport const cd: Command = async (ctx) => {\n if (ctx.args.length === 0) {\n return 0;\n }\n\n let target = ctx.args[0]!;\n\n if (target === \"-\") {\n const oldpwd = ctx.env.OLDPWD;\n if (!oldpwd) {\n await ctx.stderr.writeText(\"cd: OLDPWD not set\\n\");\n return 1;\n }\n target = oldpwd;\n }\n\n const resolved = ctx.fs.resolve(ctx.cwd, target);\n\n try {\n const stat = await ctx.fs.stat(resolved);\n if (!stat.isDirectory()) {\n await ctx.stderr.writeText(`cd: not a directory: ${target}\\n`);\n return 1;\n }\n } catch {\n await ctx.stderr.writeText(`cd: not a directory: ${target}\\n`);\n return 1;\n }\n\n ctx.setCwd(resolved);\n\n return 0;\n};\n"
6
+ ],
7
+ "mappings": ";AAEO,IAAM,KAAc,OAAO,QAAQ;AAAA,EACxC,IAAI,IAAI,KAAK,WAAW,GAAG;AAAA,IACzB,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,SAAS,IAAI,KAAK;AAAA,EAEtB,IAAI,WAAW,KAAK;AAAA,IAClB,MAAM,SAAS,IAAI,IAAI;AAAA,IACvB,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,OAAO,UAAU;AAAA,CAAsB;AAAA,MACjD,OAAO;AAAA,IACT;AAAA,IACA,SAAS;AAAA,EACX;AAAA,EAEA,MAAM,WAAW,IAAI,GAAG,QAAQ,IAAI,KAAK,MAAM;AAAA,EAE/C,IAAI;AAAA,IACF,MAAM,OAAO,MAAM,IAAI,GAAG,KAAK,QAAQ;AAAA,IACvC,IAAI,CAAC,KAAK,YAAY,GAAG;AAAA,MACvB,MAAM,IAAI,OAAO,UAAU,wBAAwB;AAAA,CAAU;AAAA,MAC7D,OAAO;AAAA,IACT;AAAA,IACA,MAAM;AAAA,IACN,MAAM,IAAI,OAAO,UAAU,wBAAwB;AAAA,CAAU;AAAA,IAC7D,OAAO;AAAA;AAAA,EAGT,IAAI,OAAO,QAAQ;AAAA,EAEnB,OAAO;AAAA;",
8
+ "debugId": "3C0FC29F2AE9154464756E2164756E21",
9
+ "names": []
10
+ }
@@ -23,6 +23,8 @@ import { sed } from "./sed/sed.mjs";
23
23
  import { awk } from "./awk/awk.mjs";
24
24
  import { breakCmd, continueCmd } from "./break-continue/break-continue.mjs";
25
25
  import { colon } from "./colon/colon.mjs";
26
+ import { cd } from "./cd/cd.mjs";
27
+ import { tr } from "./tr/tr.mjs";
26
28
  import { echo as echo2 } from "./echo/echo.mjs";
27
29
  import { cat as cat2 } from "./cat/cat.mjs";
28
30
  import { grep as grep2 } from "./grep/grep.mjs";
@@ -47,6 +49,8 @@ import { sed as sed2 } from "./sed/sed.mjs";
47
49
  import { awk as awk2 } from "./awk/awk.mjs";
48
50
  import { breakCmd as breakCmd2, continueCmd as continueCmd2 } from "./break-continue/break-continue.mjs";
49
51
  import { colon as colon2 } from "./colon/colon.mjs";
52
+ import { cd as cd2 } from "./cd/cd.mjs";
53
+ import { tr as tr2 } from "./tr/tr.mjs";
50
54
  var builtinCommands = {
51
55
  echo: echo2,
52
56
  cat: cat2,
@@ -74,13 +78,16 @@ var builtinCommands = {
74
78
  awk: awk2,
75
79
  break: breakCmd2,
76
80
  continue: continueCmd2,
77
- ":": colon2
81
+ ":": colon2,
82
+ cd: cd2,
83
+ tr: tr2
78
84
  };
79
85
  export {
80
86
  wc,
81
87
  uniq,
82
88
  trueCmd,
83
89
  tree,
90
+ tr,
84
91
  touch,
85
92
  test,
86
93
  tee,
@@ -100,6 +107,7 @@ export {
100
107
  cp,
101
108
  continueCmd,
102
109
  colon,
110
+ cd,
103
111
  cat,
104
112
  builtinCommands,
105
113
  breakCmd,
@@ -107,4 +115,4 @@ export {
107
115
  awk
108
116
  };
109
117
 
110
- //# debugId=EB08C754C93B4E2664756E2164756E21
118
+ //# debugId=D1FD821D9116613964756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/commands/index.ts"],
4
4
  "sourcesContent": [
5
- "import type { Command } from \"../types.mjs\";\n\nexport { echo } from \"./echo/echo.mjs\";\nexport { cat } from \"./cat/cat.mjs\";\nexport { grep } from \"./grep/grep.mjs\";\nexport { wc } from \"./wc/wc.mjs\";\nexport { head } from \"./head/head.mjs\";\nexport { tail } from \"./tail/tail.mjs\";\nexport { sort } from \"./sort/sort.mjs\";\nexport { uniq } from \"./uniq/uniq.mjs\";\nexport { pwd } from \"./pwd/pwd.mjs\";\nexport { ls } from \"./ls/ls.mjs\";\nexport { mkdir } from \"./mkdir/mkdir.mjs\";\nexport { rm } from \"./rm/rm.mjs\";\nexport { test, bracket } from \"./test/test.mjs\";\nexport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nexport { touch } from \"./touch/touch.mjs\";\nexport { cp } from \"./cp/cp.mjs\";\nexport { mv } from \"./mv/mv.mjs\";\nexport { tee } from \"./tee/tee.mjs\";\nexport { tree } from \"./tree/tree.mjs\";\nexport { find } from \"./find/find.mjs\";\nexport { sed } from \"./sed/sed.mjs\";\nexport { awk } from \"./awk/awk.mjs\";\nexport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nexport { colon } from \"./colon/colon.mjs\";\n\n// Re-export all commands as a bundle\nimport { echo } from \"./echo/echo.mjs\";\nimport { cat } from \"./cat/cat.mjs\";\nimport { grep } from \"./grep/grep.mjs\";\nimport { wc } from \"./wc/wc.mjs\";\nimport { head } from \"./head/head.mjs\";\nimport { tail } from \"./tail/tail.mjs\";\nimport { sort } from \"./sort/sort.mjs\";\nimport { uniq } from \"./uniq/uniq.mjs\";\nimport { pwd } from \"./pwd/pwd.mjs\";\nimport { ls } from \"./ls/ls.mjs\";\nimport { mkdir } from \"./mkdir/mkdir.mjs\";\nimport { rm } from \"./rm/rm.mjs\";\nimport { test, bracket } from \"./test/test.mjs\";\nimport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nimport { touch } from \"./touch/touch.mjs\";\nimport { cp } from \"./cp/cp.mjs\";\nimport { mv } from \"./mv/mv.mjs\";\nimport { tee } from \"./tee/tee.mjs\";\nimport { tree } from \"./tree/tree.mjs\";\nimport { find } from \"./find/find.mjs\";\nimport { sed } from \"./sed/sed.mjs\";\nimport { awk } from \"./awk/awk.mjs\";\nimport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nimport { colon } from \"./colon/colon.mjs\";\n\nexport const builtinCommands: Record<string, Command> = {\n echo,\n cat,\n grep,\n wc,\n head,\n tail,\n sort,\n uniq,\n pwd,\n ls,\n mkdir,\n rm,\n test,\n \"[\": bracket,\n true: trueCmd,\n false: falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n break: breakCmd,\n continue: continueCmd,\n \":\": colon,\n};\n"
5
+ "import type { Command } from \"../types.mjs\";\n\nexport { echo } from \"./echo/echo.mjs\";\nexport { cat } from \"./cat/cat.mjs\";\nexport { grep } from \"./grep/grep.mjs\";\nexport { wc } from \"./wc/wc.mjs\";\nexport { head } from \"./head/head.mjs\";\nexport { tail } from \"./tail/tail.mjs\";\nexport { sort } from \"./sort/sort.mjs\";\nexport { uniq } from \"./uniq/uniq.mjs\";\nexport { pwd } from \"./pwd/pwd.mjs\";\nexport { ls } from \"./ls/ls.mjs\";\nexport { mkdir } from \"./mkdir/mkdir.mjs\";\nexport { rm } from \"./rm/rm.mjs\";\nexport { test, bracket } from \"./test/test.mjs\";\nexport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nexport { touch } from \"./touch/touch.mjs\";\nexport { cp } from \"./cp/cp.mjs\";\nexport { mv } from \"./mv/mv.mjs\";\nexport { tee } from \"./tee/tee.mjs\";\nexport { tree } from \"./tree/tree.mjs\";\nexport { find } from \"./find/find.mjs\";\nexport { sed } from \"./sed/sed.mjs\";\nexport { awk } from \"./awk/awk.mjs\";\nexport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nexport { colon } from \"./colon/colon.mjs\";\nexport { cd } from \"./cd/cd.mjs\";\nexport { tr } from \"./tr/tr.mjs\";\n\n// Re-export all commands as a bundle\nimport { echo } from \"./echo/echo.mjs\";\nimport { cat } from \"./cat/cat.mjs\";\nimport { grep } from \"./grep/grep.mjs\";\nimport { wc } from \"./wc/wc.mjs\";\nimport { head } from \"./head/head.mjs\";\nimport { tail } from \"./tail/tail.mjs\";\nimport { sort } from \"./sort/sort.mjs\";\nimport { uniq } from \"./uniq/uniq.mjs\";\nimport { pwd } from \"./pwd/pwd.mjs\";\nimport { ls } from \"./ls/ls.mjs\";\nimport { mkdir } from \"./mkdir/mkdir.mjs\";\nimport { rm } from \"./rm/rm.mjs\";\nimport { test, bracket } from \"./test/test.mjs\";\nimport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nimport { touch } from \"./touch/touch.mjs\";\nimport { cp } from \"./cp/cp.mjs\";\nimport { mv } from \"./mv/mv.mjs\";\nimport { tee } from \"./tee/tee.mjs\";\nimport { tree } from \"./tree/tree.mjs\";\nimport { find } from \"./find/find.mjs\";\nimport { sed } from \"./sed/sed.mjs\";\nimport { awk } from \"./awk/awk.mjs\";\nimport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nimport { colon } from \"./colon/colon.mjs\";\nimport { cd } from \"./cd/cd.mjs\";\nimport { tr } from \"./tr/tr.mjs\";\n\nexport const builtinCommands: Record<string, Command> = {\n echo,\n cat,\n grep,\n wc,\n head,\n tail,\n sort,\n uniq,\n pwd,\n ls,\n mkdir,\n rm,\n test,\n \"[\": bracket,\n true: trueCmd,\n false: falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n break: breakCmd,\n continue: continueCmd,\n \":\": colon,\n cd,\n tr,\n};\n"
6
6
  ],
7
- "mappings": ";AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA,iBAAS;AACT,gBAAS;AACT,iBAAS;AACT,eAAS;AACT,iBAAS;AACT,iBAAS;AACT,iBAAS;AACT,iBAAS;AACT,gBAAS;AACT,eAAS;AACT,kBAAS;AACT,eAAS;AACT,iBAAS,kBAAM;AACf,oBAAS,sBAAS;AAClB,kBAAS;AACT,eAAS;AACT,eAAS;AACT,gBAAS;AACT,iBAAS;AACT,iBAAS;AACT,gBAAS;AACT,gBAAS;AACT,qBAAS,0BAAU;AACnB,kBAAS;AAEF,IAAM,kBAA2C;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,UAAU;AAAA,EACV,KAAK;AACP;",
8
- "debugId": "EB08C754C93B4E2664756E2164756E21",
7
+ "mappings": ";AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA,iBAAS;AACT,gBAAS;AACT,iBAAS;AACT,eAAS;AACT,iBAAS;AACT,iBAAS;AACT,iBAAS;AACT,iBAAS;AACT,gBAAS;AACT,eAAS;AACT,kBAAS;AACT,eAAS;AACT,iBAAS,kBAAM;AACf,oBAAS,sBAAS;AAClB,kBAAS;AACT,eAAS;AACT,eAAS;AACT,gBAAS;AACT,iBAAS;AACT,iBAAS;AACT,gBAAS;AACT,gBAAS;AACT,qBAAS,0BAAU;AACnB,kBAAS;AACT,eAAS;AACT,eAAS;AAEF,IAAM,kBAA2C;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,UAAU;AAAA,EACV,KAAK;AAAA,EACL;AAAA,EACA;AACF;",
8
+ "debugId": "D1FD821D9116613964756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -5,11 +5,12 @@ var spec = {
5
5
  flags: [
6
6
  { short: "a", long: "all" },
7
7
  { short: "l" },
8
- { short: "1" }
8
+ { short: "1" },
9
+ { short: "R" }
9
10
  ],
10
- usage: "ls [-al1] [file ...]"
11
+ usage: "ls [-alR1] [file ...]"
11
12
  };
12
- var defaults = { all: false, long: false, onePerLine: false };
13
+ var defaults = { all: false, long: false, onePerLine: false, recursive: false };
13
14
  var handler = (flags, flag) => {
14
15
  if (flag.short === "a")
15
16
  flags.all = true;
@@ -17,6 +18,8 @@ var handler = (flags, flag) => {
17
18
  flags.long = true;
18
19
  if (flag.short === "1")
19
20
  flags.onePerLine = true;
21
+ if (flag.short === "R")
22
+ flags.recursive = true;
20
23
  };
21
24
  var parser = createFlagParser(spec, defaults, handler);
22
25
  var ls = async (ctx) => {
@@ -25,8 +28,63 @@ var ls = async (ctx) => {
25
28
  await parser.writeError(result.error, ctx.stderr);
26
29
  return 1;
27
30
  }
28
- const { all: showAll, long: longFormat, onePerLine } = result.flags;
31
+ const { all: showAll, long: longFormat, onePerLine, recursive } = result.flags;
29
32
  const paths = result.args.length === 0 ? ["."] : result.args;
33
+ let needsBlankLine = false;
34
+ const listDir = async (dirPath, displayPath, showHeader) => {
35
+ if (needsBlankLine)
36
+ await ctx.stdout.writeText(`
37
+ `);
38
+ needsBlankLine = true;
39
+ if (showHeader) {
40
+ await ctx.stdout.writeText(`${displayPath}:
41
+ `);
42
+ }
43
+ let entries = await ctx.fs.readdir(dirPath);
44
+ if (!showAll) {
45
+ entries = entries.filter((e) => !e.startsWith("."));
46
+ }
47
+ entries.sort();
48
+ if (longFormat) {
49
+ for (const entry of entries) {
50
+ const entryPath = ctx.fs.resolve(dirPath, entry);
51
+ try {
52
+ const entryStat = await ctx.fs.stat(entryPath);
53
+ const type = entryStat.isDirectory() ? "d" : "-";
54
+ const perms = "rwxr-xr-x";
55
+ const size = String(entryStat.size).padStart(8);
56
+ const date = entryStat.mtime.toISOString().slice(0, 10);
57
+ await ctx.stdout.writeText(`${type}${perms} ${size} ${date} ${entry}
58
+ `);
59
+ } catch {
60
+ await ctx.stdout.writeText(`?????????? ${entry}
61
+ `);
62
+ }
63
+ }
64
+ } else if (onePerLine) {
65
+ for (const entry of entries) {
66
+ await ctx.stdout.writeText(entry + `
67
+ `);
68
+ }
69
+ } else {
70
+ if (entries.length > 0) {
71
+ await ctx.stdout.writeText(entries.join(" ") + `
72
+ `);
73
+ }
74
+ }
75
+ if (recursive) {
76
+ for (const entry of entries) {
77
+ const entryPath = ctx.fs.resolve(dirPath, entry);
78
+ try {
79
+ const entryStat = await ctx.fs.stat(entryPath);
80
+ if (entryStat.isDirectory()) {
81
+ const subDisplay = displayPath === "." ? entry : `${displayPath}/${entry}`;
82
+ await listDir(entryPath, subDisplay, true);
83
+ }
84
+ } catch {}
85
+ }
86
+ }
87
+ };
30
88
  for (let i = 0;i < paths.length; i++) {
31
89
  const pathArg = paths[i];
32
90
  const path = ctx.fs.resolve(ctx.cwd, pathArg);
@@ -37,43 +95,8 @@ var ls = async (ctx) => {
37
95
  `);
38
96
  continue;
39
97
  }
40
- if (paths.length > 1) {
41
- if (i > 0)
42
- await ctx.stdout.writeText(`
43
- `);
44
- await ctx.stdout.writeText(`${pathArg}:
45
- `);
46
- }
47
- let entries = await ctx.fs.readdir(path);
48
- if (!showAll) {
49
- entries = entries.filter((e) => !e.startsWith("."));
50
- }
51
- entries.sort();
52
- if (longFormat) {
53
- for (const entry of entries) {
54
- const entryPath = ctx.fs.resolve(path, entry);
55
- try {
56
- const entryStat = await ctx.fs.stat(entryPath);
57
- const type = entryStat.isDirectory() ? "d" : "-";
58
- const perms = "rwxr-xr-x";
59
- const size = String(entryStat.size).padStart(8);
60
- const date = entryStat.mtime.toISOString().slice(0, 10);
61
- await ctx.stdout.writeText(`${type}${perms} ${size} ${date} ${entry}
62
- `);
63
- } catch {
64
- await ctx.stdout.writeText(`?????????? ${entry}
65
- `);
66
- }
67
- }
68
- } else if (onePerLine) {
69
- for (const entry of entries) {
70
- await ctx.stdout.writeText(entry + `
71
- `);
72
- }
73
- } else {
74
- await ctx.stdout.writeText(entries.join(" ") + `
75
- `);
76
- }
98
+ const showHeader = recursive || paths.length > 1;
99
+ await listDir(path, pathArg, showHeader);
77
100
  } catch (err) {
78
101
  await ctx.stderr.writeText(`ls: cannot access '${pathArg}': No such file or directory
79
102
  `);
@@ -86,4 +109,4 @@ export {
86
109
  ls
87
110
  };
88
111
 
89
- //# debugId=CEDE14395BFC6B1E64756E2164756E21
112
+ //# debugId=C0BF60626A0B8D0564756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/commands/ls/ls.ts"],
4
4
  "sourcesContent": [
5
- "import type { Command } from \"../../types.mjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.mjs\";\n\ninterface LsFlags {\n all: boolean;\n long: boolean;\n onePerLine: boolean;\n}\n\nconst spec = {\n name: \"ls\",\n flags: [\n { short: \"a\", long: \"all\" },\n { short: \"l\" },\n { short: \"1\" },\n ] as FlagDefinition[],\n usage: \"ls [-al1] [file ...]\",\n};\n\nconst defaults: LsFlags = { all: false, long: false, onePerLine: false };\n\nconst handler = (flags: LsFlags, flag: FlagDefinition) => {\n if (flag.short === \"a\") flags.all = true;\n if (flag.short === \"l\") flags.long = true;\n if (flag.short === \"1\") flags.onePerLine = true;\n};\n\nconst parser = createFlagParser(spec, defaults, handler);\n\nexport const ls: Command = async (ctx) => {\n const result = parser.parse(ctx.args);\n\n if (result.error) {\n await parser.writeError(result.error, ctx.stderr);\n return 1;\n }\n\n const { all: showAll, long: longFormat, onePerLine } = result.flags;\n const paths = result.args.length === 0 ? [\".\"] : result.args;\n\n for (let i = 0; i < paths.length; i++) {\n const pathArg = paths[i]!;\n const path = ctx.fs.resolve(ctx.cwd, pathArg);\n\n try {\n const stat = await ctx.fs.stat(path);\n\n if (stat.isFile()) {\n // It's a file, just print the name\n await ctx.stdout.writeText(ctx.fs.basename(path) + \"\\n\");\n continue;\n }\n\n // It's a directory\n if (paths.length > 1) {\n if (i > 0) await ctx.stdout.writeText(\"\\n\");\n await ctx.stdout.writeText(`${pathArg}:\\n`);\n }\n\n let entries = await ctx.fs.readdir(path);\n\n if (!showAll) {\n entries = entries.filter((e) => !e.startsWith(\".\"));\n }\n\n entries.sort();\n\n if (longFormat) {\n for (const entry of entries) {\n const entryPath = ctx.fs.resolve(path, entry);\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n const type = entryStat.isDirectory() ? \"d\" : \"-\";\n const perms = \"rwxr-xr-x\"; // Simplified permissions\n const size = String(entryStat.size).padStart(8);\n const date = entryStat.mtime.toISOString().slice(0, 10);\n await ctx.stdout.writeText(`${type}${perms} ${size} ${date} ${entry}\\n`);\n } catch {\n await ctx.stdout.writeText(`?????????? ${entry}\\n`);\n }\n }\n } else if (onePerLine) {\n for (const entry of entries) {\n await ctx.stdout.writeText(entry + \"\\n\");\n }\n } else {\n // Default: space-separated\n await ctx.stdout.writeText(entries.join(\" \") + \"\\n\");\n }\n } catch (err) {\n await ctx.stderr.writeText(`ls: cannot access '${pathArg}': No such file or directory\\n`);\n return 1;\n }\n }\n\n return 0;\n};\n"
5
+ "import type { Command } from \"../../types.mjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.mjs\";\n\ninterface LsFlags {\n all: boolean;\n long: boolean;\n onePerLine: boolean;\n recursive: boolean;\n}\n\nconst spec = {\n name: \"ls\",\n flags: [\n { short: \"a\", long: \"all\" },\n { short: \"l\" },\n { short: \"1\" },\n { short: \"R\" },\n ] as FlagDefinition[],\n usage: \"ls [-alR1] [file ...]\",\n};\n\nconst defaults: LsFlags = { all: false, long: false, onePerLine: false, recursive: false };\n\nconst handler = (flags: LsFlags, flag: FlagDefinition) => {\n if (flag.short === \"a\") flags.all = true;\n if (flag.short === \"l\") flags.long = true;\n if (flag.short === \"1\") flags.onePerLine = true;\n if (flag.short === \"R\") flags.recursive = true;\n};\n\nconst parser = createFlagParser(spec, defaults, handler);\n\nexport const ls: Command = async (ctx) => {\n const result = parser.parse(ctx.args);\n\n if (result.error) {\n await parser.writeError(result.error, ctx.stderr);\n return 1;\n }\n\n const { all: showAll, long: longFormat, onePerLine, recursive } = result.flags;\n const paths = result.args.length === 0 ? [\".\"] : result.args;\n let needsBlankLine = false;\n\n const listDir = async (dirPath: string, displayPath: string, showHeader: boolean) => {\n if (needsBlankLine) await ctx.stdout.writeText(\"\\n\");\n needsBlankLine = true;\n\n if (showHeader) {\n await ctx.stdout.writeText(`${displayPath}:\\n`);\n }\n\n let entries = await ctx.fs.readdir(dirPath);\n\n if (!showAll) {\n entries = entries.filter((e) => !e.startsWith(\".\"));\n }\n\n entries.sort();\n\n if (longFormat) {\n for (const entry of entries) {\n const entryPath = ctx.fs.resolve(dirPath, entry);\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n const type = entryStat.isDirectory() ? \"d\" : \"-\";\n const perms = \"rwxr-xr-x\";\n const size = String(entryStat.size).padStart(8);\n const date = entryStat.mtime.toISOString().slice(0, 10);\n await ctx.stdout.writeText(`${type}${perms} ${size} ${date} ${entry}\\n`);\n } catch {\n await ctx.stdout.writeText(`?????????? ${entry}\\n`);\n }\n }\n } else if (onePerLine) {\n for (const entry of entries) {\n await ctx.stdout.writeText(entry + \"\\n\");\n }\n } else {\n if (entries.length > 0) {\n await ctx.stdout.writeText(entries.join(\" \") + \"\\n\");\n }\n }\n\n if (recursive) {\n for (const entry of entries) {\n const entryPath = ctx.fs.resolve(dirPath, entry);\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n if (entryStat.isDirectory()) {\n const subDisplay = displayPath === \".\" ? entry : `${displayPath}/${entry}`;\n await listDir(entryPath, subDisplay, true);\n }\n } catch {\n // skip entries we can't stat\n }\n }\n }\n };\n\n for (let i = 0; i < paths.length; i++) {\n const pathArg = paths[i]!;\n const path = ctx.fs.resolve(ctx.cwd, pathArg);\n\n try {\n const stat = await ctx.fs.stat(path);\n\n if (stat.isFile()) {\n await ctx.stdout.writeText(ctx.fs.basename(path) + \"\\n\");\n continue;\n }\n\n const showHeader = recursive || paths.length > 1;\n await listDir(path, pathArg, showHeader);\n } catch (err) {\n await ctx.stderr.writeText(`ls: cannot access '${pathArg}': No such file or directory\\n`);\n return 1;\n }\n }\n\n return 0;\n};\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "CEDE14395BFC6B1E64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "C0BF60626A0B8D0564756E2164756E21",
9
9
  "names": []
10
10
  }