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.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/commands/cd/cd.cjs +66 -0
- package/dist/cjs/src/commands/cd/cd.cjs.map +10 -0
- package/dist/cjs/src/commands/index.cjs +10 -2
- package/dist/cjs/src/commands/index.cjs.map +3 -3
- package/dist/cjs/src/commands/ls/ls.cjs +65 -42
- package/dist/cjs/src/commands/ls/ls.cjs.map +3 -3
- package/dist/cjs/src/commands/sed/sed.cjs +291 -76
- package/dist/cjs/src/commands/sed/sed.cjs.map +3 -3
- package/dist/cjs/src/commands/tr/tr.cjs +223 -0
- package/dist/cjs/src/commands/tr/tr.cjs.map +10 -0
- package/dist/cjs/src/commands/tree/tree.cjs +7 -4
- package/dist/cjs/src/commands/tree/tree.cjs.map +3 -3
- package/dist/cjs/src/interpreter/context.cjs +3 -2
- package/dist/cjs/src/interpreter/context.cjs.map +3 -3
- package/dist/cjs/src/interpreter/interpreter.cjs +4 -2
- package/dist/cjs/src/interpreter/interpreter.cjs.map +3 -3
- package/dist/cjs/src/parser/parser.cjs +11 -2
- package/dist/cjs/src/parser/parser.cjs.map +3 -3
- package/dist/cjs/src/types.cjs.map +2 -2
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/src/commands/cd/cd.mjs +36 -0
- package/dist/mjs/src/commands/cd/cd.mjs.map +10 -0
- package/dist/mjs/src/commands/index.mjs +10 -2
- package/dist/mjs/src/commands/index.mjs.map +3 -3
- package/dist/mjs/src/commands/ls/ls.mjs +65 -42
- package/dist/mjs/src/commands/ls/ls.mjs.map +3 -3
- package/dist/mjs/src/commands/sed/sed.mjs +291 -76
- package/dist/mjs/src/commands/sed/sed.mjs.map +3 -3
- package/dist/mjs/src/commands/tr/tr.mjs +193 -0
- package/dist/mjs/src/commands/tr/tr.mjs.map +10 -0
- package/dist/mjs/src/commands/tree/tree.mjs +7 -4
- package/dist/mjs/src/commands/tree/tree.mjs.map +3 -3
- package/dist/mjs/src/interpreter/context.mjs +3 -2
- package/dist/mjs/src/interpreter/context.mjs.map +3 -3
- package/dist/mjs/src/interpreter/interpreter.mjs +4 -2
- package/dist/mjs/src/interpreter/interpreter.mjs.map +3 -3
- package/dist/mjs/src/parser/parser.mjs +11 -2
- package/dist/mjs/src/parser/parser.mjs.map +3 -3
- package/dist/mjs/src/types.mjs.map +2 -2
- package/dist/types/src/commands/cd/cd.d.ts +2 -0
- package/dist/types/src/commands/index.d.ts +2 -0
- package/dist/types/src/commands/tr/tr.d.ts +2 -0
- package/dist/types/src/interpreter/context.d.ts +1 -0
- package/dist/types/src/types.d.ts +1 -0
- 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
|
-
|
|
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=
|
|
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": "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",
|
|
8
|
-
"debugId": "
|
|
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": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
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
|
}
|
package/dist/mjs/package.json
CHANGED
|
@@ -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=
|
|
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;
|
|
8
|
-
"debugId": "
|
|
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 [-
|
|
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
|
-
|
|
41
|
-
|
|
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=
|
|
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 [-
|
|
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": ";AACA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "C0BF60626A0B8D0564756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|