shell-dsl 0.0.5 → 0.0.7

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/README.md CHANGED
@@ -441,7 +441,7 @@ import { builtinCommands } from "shell-dsl/commands";
441
441
  Or import individually:
442
442
 
443
443
  ```ts
444
- import { echo, cat, grep, wc, cp, mv, touch, tee, tree } from "shell-dsl/commands";
444
+ import { echo, cat, grep, wc, cp, mv, touch, tee, tree, find } from "shell-dsl/commands";
445
445
  ```
446
446
 
447
447
  | Command | Description |
@@ -463,6 +463,7 @@ import { echo, cat, grep, wc, cp, mv, touch, tee, tree } from "shell-dsl/command
463
463
  | `touch` | Create empty files or update timestamps (`-c` no-create) |
464
464
  | `tee` | Duplicate stdin to stdout and files (`-a` append) |
465
465
  | `tree` | Display directory structure as tree (`-a` all, `-d` dirs only, `-L <n>` depth) |
466
+ | `find` | Search for files (`-name`, `-iname`, `-type f\|d`, `-maxdepth`, `-mindepth`) |
466
467
  | `test` / `[` | File and string tests (`-f`, `-d`, `-e`, `-z`, `-n`, `=`, `!=`) |
467
468
  | `true` | Exit with code 0 |
468
469
  | `false` | Exit with code 1 |
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "shell-dsl",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "type": "commonjs"
5
5
  }
@@ -166,6 +166,15 @@ class Interpreter {
166
166
  }
167
167
  switch (redirect.mode) {
168
168
  case "<": {
169
+ if (redirect.heredocContent) {
170
+ return {
171
+ stdin: async function* () {
172
+ yield new TextEncoder().encode(target);
173
+ }(),
174
+ stdout,
175
+ stderr
176
+ };
177
+ }
169
178
  const path = this.fs.resolve(this.cwd, target);
170
179
  const content = await this.fs.readFile(path);
171
180
  return {
@@ -378,4 +387,4 @@ class Interpreter {
378
387
  }
379
388
  }
380
389
 
381
- //# debugId=672068A850D821FB64756E2164756E21
390
+ //# debugId=5AFD9CE7FC1DFBCF64756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/interpreter/interpreter.ts"],
4
4
  "sourcesContent": [
5
- "import type { ASTNode, CommandNode, Redirect } from \"../parser/ast.cjs\";\nimport type { Command, VirtualFS, ExecResult, OutputCollector, RedirectObjectMap } from \"../types.cjs\";\nimport { createCommandContext } from \"./context.cjs\";\nimport { createStdin } from \"../io/stdin.cjs\";\nimport { createStdout, createStderr, createPipe, PipeBuffer, createBufferTargetCollector } from \"../io/stdout.cjs\";\nimport { Lexer } from \"../lexer/lexer.cjs\";\nimport { Parser } from \"../parser/parser.cjs\";\n\nexport interface InterpreterOptions {\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n commands: Record<string, Command>;\n redirectObjects?: RedirectObjectMap;\n}\n\nexport class Interpreter {\n private fs: VirtualFS;\n private cwd: string;\n private env: Record<string, string>;\n private commands: Record<string, Command>;\n private redirectObjects: RedirectObjectMap;\n\n constructor(options: InterpreterOptions) {\n this.fs = options.fs;\n this.cwd = options.cwd;\n this.env = { ...options.env };\n this.commands = options.commands;\n this.redirectObjects = options.redirectObjects ?? {};\n }\n\n async execute(ast: ASTNode): Promise<ExecResult> {\n const stdout = createStdout();\n const stderr = createStderr();\n\n const exitCode = await this.executeNode(ast, null, stdout, stderr);\n\n stdout.close();\n stderr.close();\n\n return {\n stdout: await stdout.collect(),\n stderr: await stderr.collect(),\n exitCode,\n };\n }\n\n private async executeNode(\n node: ASTNode,\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n switch (node.type) {\n case \"command\":\n return this.executeCommand(node, stdinSource, stdout, stderr);\n case \"pipeline\":\n return this.executePipeline(node.commands, stdinSource, stdout, stderr);\n case \"sequence\":\n return this.executeSequence(node.commands, stdinSource, stdout, stderr);\n case \"and\":\n return this.executeAnd(node.left, node.right, stdinSource, stdout, stderr);\n case \"or\":\n return this.executeOr(node.left, node.right, stdinSource, stdout, stderr);\n default:\n throw new Error(`Cannot execute node type: ${node.type}`);\n }\n }\n\n private async executeCommand(\n node: CommandNode,\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n // Create local env with assignments\n const localEnv = { ...this.env };\n for (const assignment of node.assignments) {\n localEnv[assignment.name] = await this.evaluateNode(assignment.value);\n }\n\n // If there's no command name but there are assignments, just update env\n const name = await this.evaluateNode(node.name);\n if (name === \"\" && node.assignments.length > 0) {\n for (const assignment of node.assignments) {\n this.env[assignment.name] = await this.evaluateNode(assignment.value);\n }\n return 0;\n }\n\n // Evaluate arguments using localEnv for scoped variable expansion\n const args: string[] = [];\n for (const arg of node.args) {\n const evaluated = await this.evaluateNode(arg, localEnv);\n // Glob expansion returns multiple values\n if (arg.type === \"glob\") {\n const matches = await this.fs.glob(evaluated, { cwd: this.cwd });\n if (matches.length > 0) {\n args.push(...matches);\n } else {\n // No matches - use pattern as-is\n args.push(evaluated);\n }\n } else {\n args.push(evaluated);\n }\n }\n\n // Handle redirects\n let actualStdin = stdinSource;\n let actualStdout: OutputCollector = stdout;\n let actualStderr: OutputCollector = stderr;\n let stderrToStdout = false;\n let stdoutToStderr = false;\n const fileWritePromises: Promise<void>[] = [];\n\n for (const redirect of node.redirects) {\n const result = await this.handleRedirect(\n redirect,\n actualStdin,\n actualStdout,\n actualStderr\n );\n actualStdin = result.stdin;\n actualStdout = result.stdout;\n actualStderr = result.stderr;\n stderrToStdout = result.stderrToStdout || stderrToStdout;\n stdoutToStderr = result.stdoutToStderr || stdoutToStderr;\n if (result.fileWritePromise) {\n fileWritePromises.push(result.fileWritePromise);\n }\n }\n\n // Handle stderr->stdout redirect\n if (stderrToStdout) {\n actualStderr = actualStdout;\n }\n if (stdoutToStderr) {\n actualStdout = actualStderr;\n }\n\n // Look up command\n const command = this.commands[name];\n if (!command) {\n await stderr.writeText(`${name}: command not found\\n`);\n return 127;\n }\n\n // Create context and execute\n const ctx = createCommandContext({\n args,\n stdin: createStdin(actualStdin),\n stdout: actualStdout,\n stderr: actualStderr,\n fs: this.fs,\n cwd: this.cwd,\n env: localEnv,\n });\n\n let exitCode: number;\n try {\n exitCode = await command(ctx);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await stderr.writeText(`${name}: ${message}\\n`);\n exitCode = 1;\n }\n\n // Close redirect collectors and wait for file writes\n if (actualStdout !== stdout) {\n actualStdout.close();\n }\n if (actualStderr !== stderr && actualStderr !== actualStdout) {\n actualStderr.close();\n }\n\n // Wait for all file write operations to complete\n await Promise.all(fileWritePromises);\n\n return exitCode;\n }\n\n private async handleRedirect(\n redirect: Redirect,\n stdin: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<{\n stdin: AsyncIterable<Uint8Array> | null;\n stdout: OutputCollector;\n stderr: OutputCollector;\n stderrToStdout?: boolean;\n stdoutToStderr?: boolean;\n fileWritePromise?: Promise<void>;\n }> {\n const target = await this.evaluateNode(redirect.target);\n\n // Check if target is a redirect object marker\n if (target in this.redirectObjects) {\n return this.handleObjectRedirect(redirect.mode, this.redirectObjects[target]!, stdin, stdout, stderr);\n }\n\n switch (redirect.mode) {\n case \"<\": {\n // Input redirect\n const path = this.fs.resolve(this.cwd, target);\n const content = await this.fs.readFile(path);\n return {\n stdin: (async function* () {\n yield new Uint8Array(content);\n })(),\n stdout,\n stderr,\n };\n }\n case \">\": {\n // Output redirect (overwrite)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStdout();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.writeFile(path, data);\n })();\n return { stdin, stdout: collector, stderr, fileWritePromise };\n }\n case \">>\": {\n // Output redirect (append)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStdout();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.appendFile(path, data);\n })();\n return { stdin, stdout: collector, stderr, fileWritePromise };\n }\n case \"2>\": {\n // Stderr redirect (overwrite)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStderr();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.writeFile(path, data);\n })();\n return { stdin, stdout, stderr: collector, fileWritePromise };\n }\n case \"2>>\": {\n // Stderr redirect (append)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStderr();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.appendFile(path, data);\n })();\n return { stdin, stdout, stderr: collector, fileWritePromise };\n }\n case \"&>\": {\n // Both to file (overwrite)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStdout();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.writeFile(path, data);\n })();\n return { stdin, stdout: collector, stderr: collector, fileWritePromise };\n }\n case \"&>>\": {\n // Both to file (append)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStdout();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.appendFile(path, data);\n })();\n return { stdin, stdout: collector, stderr: collector, fileWritePromise };\n }\n case \"2>&1\":\n return { stdin, stdout, stderr, stderrToStdout: true };\n case \"1>&2\":\n return { stdin, stdout, stderr, stdoutToStderr: true };\n default:\n return { stdin, stdout, stderr };\n }\n }\n\n private async handleObjectRedirect(\n mode: string,\n obj: Buffer | Blob | Response | string,\n stdin: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<{\n stdin: AsyncIterable<Uint8Array> | null;\n stdout: OutputCollector;\n stderr: OutputCollector;\n stderrToStdout?: boolean;\n stdoutToStderr?: boolean;\n fileWritePromise?: Promise<void>;\n }> {\n switch (mode) {\n case \"<\": {\n // Input from object\n const data = await this.readFromObject(obj);\n return {\n stdin: (async function* () {\n yield data;\n })(),\n stdout,\n stderr,\n };\n }\n case \">\":\n case \">>\": {\n // Output to object (only Buffer supported)\n if (!Buffer.isBuffer(obj)) {\n throw new Error(\"Output redirection only supports Buffer targets\");\n }\n const collector = createBufferTargetCollector(obj);\n return { stdin, stdout: collector, stderr };\n }\n case \"2>\":\n case \"2>>\": {\n // Stderr to object (only Buffer supported)\n if (!Buffer.isBuffer(obj)) {\n throw new Error(\"Stderr redirection only supports Buffer targets\");\n }\n const collector = createBufferTargetCollector(obj);\n return { stdin, stdout, stderr: collector };\n }\n case \"&>\":\n case \"&>>\": {\n // Both to object (only Buffer supported)\n if (!Buffer.isBuffer(obj)) {\n throw new Error(\"Combined redirection only supports Buffer targets\");\n }\n const collector = createBufferTargetCollector(obj);\n return { stdin, stdout: collector, stderr: collector };\n }\n default:\n return { stdin, stdout, stderr };\n }\n }\n\n private async readFromObject(obj: Buffer | Blob | Response | string): Promise<Uint8Array> {\n if (Buffer.isBuffer(obj)) {\n return new Uint8Array(obj);\n }\n if (obj instanceof Blob) {\n return new Uint8Array(await obj.arrayBuffer());\n }\n if (obj instanceof Response) {\n return new Uint8Array(await obj.arrayBuffer());\n }\n if (typeof obj === \"string\") {\n return new TextEncoder().encode(obj);\n }\n throw new Error(\"Unsupported redirect object type\");\n }\n\n private async executePipeline(\n commands: ASTNode[],\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n if (commands.length === 0) return 0;\n if (commands.length === 1) {\n return this.executeNode(commands[0]!, stdinSource, stdout, stderr);\n }\n\n // Create pipes between commands\n const pipes: PipeBuffer[] = [];\n for (let i = 0; i < commands.length - 1; i++) {\n pipes.push(createPipe());\n }\n\n // Execute all commands concurrently\n const promises: Promise<number>[] = [];\n\n for (let i = 0; i < commands.length; i++) {\n const command = commands[i]!;\n const cmdStdin = i === 0 ? stdinSource : pipes[i - 1]!.getReadableStream();\n const cmdStdout = i === commands.length - 1 ? stdout : pipes[i]!;\n\n promises.push(\n this.executeNode(command, cmdStdin, cmdStdout, stderr).then((code) => {\n // Close pipe when command finishes\n if (i < commands.length - 1) {\n pipes[i]!.close();\n }\n return code;\n })\n );\n }\n\n // Wait for all commands and return last exit code\n const results = await Promise.all(promises);\n return results[results.length - 1]!;\n }\n\n private async executeSequence(\n commands: ASTNode[],\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n let lastExitCode = 0;\n\n for (const command of commands) {\n lastExitCode = await this.executeNode(command, stdinSource, stdout, stderr);\n }\n\n return lastExitCode;\n }\n\n private async executeAnd(\n left: ASTNode,\n right: ASTNode,\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n const leftCode = await this.executeNode(left, stdinSource, stdout, stderr);\n if (leftCode !== 0) {\n return leftCode;\n }\n return this.executeNode(right, stdinSource, stdout, stderr);\n }\n\n private async executeOr(\n left: ASTNode,\n right: ASTNode,\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n const leftCode = await this.executeNode(left, stdinSource, stdout, stderr);\n if (leftCode === 0) {\n return 0;\n }\n return this.executeNode(right, stdinSource, stdout, stderr);\n }\n\n private async evaluateNode(node: ASTNode, localEnv?: Record<string, string>): Promise<string> {\n const env = localEnv ?? this.env;\n switch (node.type) {\n case \"literal\":\n return node.value;\n case \"variable\":\n return env[node.name] ?? \"\";\n case \"glob\":\n return node.pattern;\n case \"concat\": {\n const parts = await Promise.all(node.parts.map((p) => this.evaluateNode(p, localEnv)));\n return parts.join(\"\");\n }\n case \"substitution\": {\n // Execute the command and capture output\n const subStdout = createStdout();\n const subStderr = createStderr();\n await this.executeNode(node.command, null, subStdout, subStderr);\n subStdout.close();\n const output = await subStdout.collect();\n // Trim trailing newlines\n return output.toString(\"utf-8\").replace(/\\n+$/, \"\");\n }\n default:\n throw new Error(`Cannot evaluate node type: ${node.type}`);\n }\n }\n\n setCwd(cwd: string): void {\n this.cwd = cwd;\n }\n\n setEnv(vars: Record<string, string>): void {\n Object.assign(this.env, vars);\n }\n\n getCwd(): string {\n return this.cwd;\n }\n\n getEnv(): Record<string, string> {\n return { ...this.env };\n }\n}\n"
5
+ "import type { ASTNode, CommandNode, Redirect } from \"../parser/ast.cjs\";\nimport type { Command, VirtualFS, ExecResult, OutputCollector, RedirectObjectMap } from \"../types.cjs\";\nimport { createCommandContext } from \"./context.cjs\";\nimport { createStdin } from \"../io/stdin.cjs\";\nimport { createStdout, createStderr, createPipe, PipeBuffer, createBufferTargetCollector } from \"../io/stdout.cjs\";\nimport { Lexer } from \"../lexer/lexer.cjs\";\nimport { Parser } from \"../parser/parser.cjs\";\n\nexport interface InterpreterOptions {\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n commands: Record<string, Command>;\n redirectObjects?: RedirectObjectMap;\n}\n\nexport class Interpreter {\n private fs: VirtualFS;\n private cwd: string;\n private env: Record<string, string>;\n private commands: Record<string, Command>;\n private redirectObjects: RedirectObjectMap;\n\n constructor(options: InterpreterOptions) {\n this.fs = options.fs;\n this.cwd = options.cwd;\n this.env = { ...options.env };\n this.commands = options.commands;\n this.redirectObjects = options.redirectObjects ?? {};\n }\n\n async execute(ast: ASTNode): Promise<ExecResult> {\n const stdout = createStdout();\n const stderr = createStderr();\n\n const exitCode = await this.executeNode(ast, null, stdout, stderr);\n\n stdout.close();\n stderr.close();\n\n return {\n stdout: await stdout.collect(),\n stderr: await stderr.collect(),\n exitCode,\n };\n }\n\n private async executeNode(\n node: ASTNode,\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n switch (node.type) {\n case \"command\":\n return this.executeCommand(node, stdinSource, stdout, stderr);\n case \"pipeline\":\n return this.executePipeline(node.commands, stdinSource, stdout, stderr);\n case \"sequence\":\n return this.executeSequence(node.commands, stdinSource, stdout, stderr);\n case \"and\":\n return this.executeAnd(node.left, node.right, stdinSource, stdout, stderr);\n case \"or\":\n return this.executeOr(node.left, node.right, stdinSource, stdout, stderr);\n default:\n throw new Error(`Cannot execute node type: ${node.type}`);\n }\n }\n\n private async executeCommand(\n node: CommandNode,\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n // Create local env with assignments\n const localEnv = { ...this.env };\n for (const assignment of node.assignments) {\n localEnv[assignment.name] = await this.evaluateNode(assignment.value);\n }\n\n // If there's no command name but there are assignments, just update env\n const name = await this.evaluateNode(node.name);\n if (name === \"\" && node.assignments.length > 0) {\n for (const assignment of node.assignments) {\n this.env[assignment.name] = await this.evaluateNode(assignment.value);\n }\n return 0;\n }\n\n // Evaluate arguments using localEnv for scoped variable expansion\n const args: string[] = [];\n for (const arg of node.args) {\n const evaluated = await this.evaluateNode(arg, localEnv);\n // Glob expansion returns multiple values\n if (arg.type === \"glob\") {\n const matches = await this.fs.glob(evaluated, { cwd: this.cwd });\n if (matches.length > 0) {\n args.push(...matches);\n } else {\n // No matches - use pattern as-is\n args.push(evaluated);\n }\n } else {\n args.push(evaluated);\n }\n }\n\n // Handle redirects\n let actualStdin = stdinSource;\n let actualStdout: OutputCollector = stdout;\n let actualStderr: OutputCollector = stderr;\n let stderrToStdout = false;\n let stdoutToStderr = false;\n const fileWritePromises: Promise<void>[] = [];\n\n for (const redirect of node.redirects) {\n const result = await this.handleRedirect(\n redirect,\n actualStdin,\n actualStdout,\n actualStderr\n );\n actualStdin = result.stdin;\n actualStdout = result.stdout;\n actualStderr = result.stderr;\n stderrToStdout = result.stderrToStdout || stderrToStdout;\n stdoutToStderr = result.stdoutToStderr || stdoutToStderr;\n if (result.fileWritePromise) {\n fileWritePromises.push(result.fileWritePromise);\n }\n }\n\n // Handle stderr->stdout redirect\n if (stderrToStdout) {\n actualStderr = actualStdout;\n }\n if (stdoutToStderr) {\n actualStdout = actualStderr;\n }\n\n // Look up command\n const command = this.commands[name];\n if (!command) {\n await stderr.writeText(`${name}: command not found\\n`);\n return 127;\n }\n\n // Create context and execute\n const ctx = createCommandContext({\n args,\n stdin: createStdin(actualStdin),\n stdout: actualStdout,\n stderr: actualStderr,\n fs: this.fs,\n cwd: this.cwd,\n env: localEnv,\n });\n\n let exitCode: number;\n try {\n exitCode = await command(ctx);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await stderr.writeText(`${name}: ${message}\\n`);\n exitCode = 1;\n }\n\n // Close redirect collectors and wait for file writes\n if (actualStdout !== stdout) {\n actualStdout.close();\n }\n if (actualStderr !== stderr && actualStderr !== actualStdout) {\n actualStderr.close();\n }\n\n // Wait for all file write operations to complete\n await Promise.all(fileWritePromises);\n\n return exitCode;\n }\n\n private async handleRedirect(\n redirect: Redirect,\n stdin: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<{\n stdin: AsyncIterable<Uint8Array> | null;\n stdout: OutputCollector;\n stderr: OutputCollector;\n stderrToStdout?: boolean;\n stdoutToStderr?: boolean;\n fileWritePromise?: Promise<void>;\n }> {\n const target = await this.evaluateNode(redirect.target);\n\n // Check if target is a redirect object marker\n if (target in this.redirectObjects) {\n return this.handleObjectRedirect(redirect.mode, this.redirectObjects[target]!, stdin, stdout, stderr);\n }\n\n switch (redirect.mode) {\n case \"<\": {\n if (redirect.heredocContent) {\n // Heredoc: target is already the content\n return {\n stdin: (async function* () {\n yield new TextEncoder().encode(target);\n })(),\n stdout,\n stderr,\n };\n }\n // Input redirect from file\n const path = this.fs.resolve(this.cwd, target);\n const content = await this.fs.readFile(path);\n return {\n stdin: (async function* () {\n yield new Uint8Array(content);\n })(),\n stdout,\n stderr,\n };\n }\n case \">\": {\n // Output redirect (overwrite)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStdout();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.writeFile(path, data);\n })();\n return { stdin, stdout: collector, stderr, fileWritePromise };\n }\n case \">>\": {\n // Output redirect (append)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStdout();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.appendFile(path, data);\n })();\n return { stdin, stdout: collector, stderr, fileWritePromise };\n }\n case \"2>\": {\n // Stderr redirect (overwrite)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStderr();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.writeFile(path, data);\n })();\n return { stdin, stdout, stderr: collector, fileWritePromise };\n }\n case \"2>>\": {\n // Stderr redirect (append)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStderr();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.appendFile(path, data);\n })();\n return { stdin, stdout, stderr: collector, fileWritePromise };\n }\n case \"&>\": {\n // Both to file (overwrite)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStdout();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.writeFile(path, data);\n })();\n return { stdin, stdout: collector, stderr: collector, fileWritePromise };\n }\n case \"&>>\": {\n // Both to file (append)\n const path = this.fs.resolve(this.cwd, target);\n const collector = createStdout();\n const fileWritePromise = (async () => {\n const data = await collector.collect();\n await this.fs.appendFile(path, data);\n })();\n return { stdin, stdout: collector, stderr: collector, fileWritePromise };\n }\n case \"2>&1\":\n return { stdin, stdout, stderr, stderrToStdout: true };\n case \"1>&2\":\n return { stdin, stdout, stderr, stdoutToStderr: true };\n default:\n return { stdin, stdout, stderr };\n }\n }\n\n private async handleObjectRedirect(\n mode: string,\n obj: Buffer | Blob | Response | string,\n stdin: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<{\n stdin: AsyncIterable<Uint8Array> | null;\n stdout: OutputCollector;\n stderr: OutputCollector;\n stderrToStdout?: boolean;\n stdoutToStderr?: boolean;\n fileWritePromise?: Promise<void>;\n }> {\n switch (mode) {\n case \"<\": {\n // Input from object\n const data = await this.readFromObject(obj);\n return {\n stdin: (async function* () {\n yield data;\n })(),\n stdout,\n stderr,\n };\n }\n case \">\":\n case \">>\": {\n // Output to object (only Buffer supported)\n if (!Buffer.isBuffer(obj)) {\n throw new Error(\"Output redirection only supports Buffer targets\");\n }\n const collector = createBufferTargetCollector(obj);\n return { stdin, stdout: collector, stderr };\n }\n case \"2>\":\n case \"2>>\": {\n // Stderr to object (only Buffer supported)\n if (!Buffer.isBuffer(obj)) {\n throw new Error(\"Stderr redirection only supports Buffer targets\");\n }\n const collector = createBufferTargetCollector(obj);\n return { stdin, stdout, stderr: collector };\n }\n case \"&>\":\n case \"&>>\": {\n // Both to object (only Buffer supported)\n if (!Buffer.isBuffer(obj)) {\n throw new Error(\"Combined redirection only supports Buffer targets\");\n }\n const collector = createBufferTargetCollector(obj);\n return { stdin, stdout: collector, stderr: collector };\n }\n default:\n return { stdin, stdout, stderr };\n }\n }\n\n private async readFromObject(obj: Buffer | Blob | Response | string): Promise<Uint8Array> {\n if (Buffer.isBuffer(obj)) {\n return new Uint8Array(obj);\n }\n if (obj instanceof Blob) {\n return new Uint8Array(await obj.arrayBuffer());\n }\n if (obj instanceof Response) {\n return new Uint8Array(await obj.arrayBuffer());\n }\n if (typeof obj === \"string\") {\n return new TextEncoder().encode(obj);\n }\n throw new Error(\"Unsupported redirect object type\");\n }\n\n private async executePipeline(\n commands: ASTNode[],\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n if (commands.length === 0) return 0;\n if (commands.length === 1) {\n return this.executeNode(commands[0]!, stdinSource, stdout, stderr);\n }\n\n // Create pipes between commands\n const pipes: PipeBuffer[] = [];\n for (let i = 0; i < commands.length - 1; i++) {\n pipes.push(createPipe());\n }\n\n // Execute all commands concurrently\n const promises: Promise<number>[] = [];\n\n for (let i = 0; i < commands.length; i++) {\n const command = commands[i]!;\n const cmdStdin = i === 0 ? stdinSource : pipes[i - 1]!.getReadableStream();\n const cmdStdout = i === commands.length - 1 ? stdout : pipes[i]!;\n\n promises.push(\n this.executeNode(command, cmdStdin, cmdStdout, stderr).then((code) => {\n // Close pipe when command finishes\n if (i < commands.length - 1) {\n pipes[i]!.close();\n }\n return code;\n })\n );\n }\n\n // Wait for all commands and return last exit code\n const results = await Promise.all(promises);\n return results[results.length - 1]!;\n }\n\n private async executeSequence(\n commands: ASTNode[],\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n let lastExitCode = 0;\n\n for (const command of commands) {\n lastExitCode = await this.executeNode(command, stdinSource, stdout, stderr);\n }\n\n return lastExitCode;\n }\n\n private async executeAnd(\n left: ASTNode,\n right: ASTNode,\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n const leftCode = await this.executeNode(left, stdinSource, stdout, stderr);\n if (leftCode !== 0) {\n return leftCode;\n }\n return this.executeNode(right, stdinSource, stdout, stderr);\n }\n\n private async executeOr(\n left: ASTNode,\n right: ASTNode,\n stdinSource: AsyncIterable<Uint8Array> | null,\n stdout: OutputCollector,\n stderr: OutputCollector\n ): Promise<number> {\n const leftCode = await this.executeNode(left, stdinSource, stdout, stderr);\n if (leftCode === 0) {\n return 0;\n }\n return this.executeNode(right, stdinSource, stdout, stderr);\n }\n\n private async evaluateNode(node: ASTNode, localEnv?: Record<string, string>): Promise<string> {\n const env = localEnv ?? this.env;\n switch (node.type) {\n case \"literal\":\n return node.value;\n case \"variable\":\n return env[node.name] ?? \"\";\n case \"glob\":\n return node.pattern;\n case \"concat\": {\n const parts = await Promise.all(node.parts.map((p) => this.evaluateNode(p, localEnv)));\n return parts.join(\"\");\n }\n case \"substitution\": {\n // Execute the command and capture output\n const subStdout = createStdout();\n const subStderr = createStderr();\n await this.executeNode(node.command, null, subStdout, subStderr);\n subStdout.close();\n const output = await subStdout.collect();\n // Trim trailing newlines\n return output.toString(\"utf-8\").replace(/\\n+$/, \"\");\n }\n default:\n throw new Error(`Cannot evaluate node type: ${node.type}`);\n }\n }\n\n setCwd(cwd: string): void {\n this.cwd = cwd;\n }\n\n setEnv(vars: Record<string, string>): void {\n Object.assign(this.env, vars);\n }\n\n getCwd(): string {\n return this.cwd;\n }\n\n getEnv(): Record<string, string> {\n return { ...this.env };\n }\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "672068A850D821FB64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "5AFD9CE7FC1DFBCF64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -59,12 +59,17 @@ class Lexer {
59
59
  pos = 0;
60
60
  line = 1;
61
61
  column = 1;
62
+ tokenQueue = [];
62
63
  constructor(source) {
63
64
  this.source = source;
64
65
  }
65
66
  tokenize() {
66
67
  const tokens = [];
67
- while (!this.isAtEnd()) {
68
+ while (!this.isAtEnd() || this.tokenQueue.length > 0) {
69
+ if (this.tokenQueue.length > 0) {
70
+ tokens.push(this.tokenQueue.shift());
71
+ continue;
72
+ }
68
73
  this.skipWhitespace();
69
74
  if (this.isAtEnd())
70
75
  break;
@@ -77,6 +82,9 @@ class Lexer {
77
82
  return tokens;
78
83
  }
79
84
  nextToken() {
85
+ if (this.tokenQueue.length > 0) {
86
+ return this.tokenQueue.shift();
87
+ }
80
88
  const char = this.peek();
81
89
  if (char === "#") {
82
90
  this.skipComment();
@@ -120,6 +128,10 @@ class Lexer {
120
128
  }
121
129
  if (char === "<") {
122
130
  this.advance();
131
+ if (this.peek() === "<") {
132
+ this.advance();
133
+ return this.readHeredoc();
134
+ }
123
135
  return { type: "redirect", mode: "<" };
124
136
  }
125
137
  if (char === "1" || char === "2") {
@@ -289,6 +301,150 @@ class Lexer {
289
301
  }
290
302
  return { type: "word", value };
291
303
  }
304
+ readHeredoc() {
305
+ const stripTabs = this.peek() === "-";
306
+ if (stripTabs) {
307
+ this.advance();
308
+ }
309
+ while (this.peek() === " " || this.peek() === "\t") {
310
+ this.advance();
311
+ }
312
+ const { delimiter, expand } = this.readHeredocDelimiter();
313
+ this.tokenizeRestOfLine();
314
+ if (this.peek() === `
315
+ `) {
316
+ this.advance();
317
+ }
318
+ let content = "";
319
+ while (!this.isAtEnd()) {
320
+ const lineStart = this.pos;
321
+ let line = "";
322
+ while (!this.isAtEnd() && this.peek() !== `
323
+ `) {
324
+ line += this.advance();
325
+ }
326
+ const strippedLine = stripTabs ? line.replace(/^\t+/, "") : line;
327
+ if (strippedLine === delimiter) {
328
+ if (this.peek() === `
329
+ `) {
330
+ this.advance();
331
+ }
332
+ break;
333
+ }
334
+ if (stripTabs) {
335
+ content += line.replace(/^\t+/, "");
336
+ } else {
337
+ content += line;
338
+ }
339
+ if (this.peek() === `
340
+ `) {
341
+ content += this.advance();
342
+ }
343
+ }
344
+ return { type: "heredoc", content, expand };
345
+ }
346
+ readHeredocDelimiter() {
347
+ const quoteChar = this.peek();
348
+ if (quoteChar === "'" || quoteChar === '"') {
349
+ this.advance();
350
+ let delimiter2 = "";
351
+ while (!this.isAtEnd() && this.peek() !== quoteChar && this.peek() !== `
352
+ `) {
353
+ delimiter2 += this.advance();
354
+ }
355
+ if (this.peek() === quoteChar) {
356
+ this.advance();
357
+ }
358
+ return { delimiter: delimiter2, expand: false };
359
+ }
360
+ let delimiter = "";
361
+ while (!this.isAtEnd() && !this.isWordBreak(this.peek()) && this.peek() !== `
362
+ `) {
363
+ if (this.peek() === "\\") {
364
+ this.advance();
365
+ if (!this.isAtEnd()) {
366
+ delimiter += this.advance();
367
+ }
368
+ } else {
369
+ delimiter += this.advance();
370
+ }
371
+ }
372
+ return { delimiter, expand: true };
373
+ }
374
+ tokenizeRestOfLine() {
375
+ while (!this.isAtEnd() && this.peek() !== `
376
+ `) {
377
+ while (this.peek() === " " || this.peek() === "\t") {
378
+ this.advance();
379
+ }
380
+ if (this.isAtEnd() || this.peek() === `
381
+ `)
382
+ break;
383
+ const token = this.readRestOfLineToken();
384
+ if (token) {
385
+ this.tokenQueue.push(token);
386
+ }
387
+ }
388
+ }
389
+ readRestOfLineToken() {
390
+ const char = this.peek();
391
+ if (char === "|") {
392
+ this.advance();
393
+ if (this.peek() === "|") {
394
+ this.advance();
395
+ return { type: "or" };
396
+ }
397
+ return { type: "pipe" };
398
+ }
399
+ if (char === "&") {
400
+ this.advance();
401
+ if (this.peek() === "&") {
402
+ this.advance();
403
+ return { type: "and" };
404
+ }
405
+ return { type: "word", value: "&" };
406
+ }
407
+ if (char === ";") {
408
+ this.advance();
409
+ return { type: "semicolon" };
410
+ }
411
+ if (char === ">") {
412
+ this.advance();
413
+ if (this.peek() === ">") {
414
+ this.advance();
415
+ return { type: "redirect", mode: ">>" };
416
+ }
417
+ return { type: "redirect", mode: ">" };
418
+ }
419
+ if (char === "<") {
420
+ this.advance();
421
+ return { type: "redirect", mode: "<" };
422
+ }
423
+ if (char === "$") {
424
+ return this.readVariable();
425
+ }
426
+ if (char === "'") {
427
+ return this.readSingleQuote();
428
+ }
429
+ if (char === '"') {
430
+ return this.readDoubleQuote();
431
+ }
432
+ let value = "";
433
+ while (!this.isAtEnd() && !this.isWordBreak(this.peek()) && this.peek() !== `
434
+ `) {
435
+ if (this.peek() === "\\") {
436
+ this.advance();
437
+ if (!this.isAtEnd()) {
438
+ value += this.advance();
439
+ }
440
+ } else {
441
+ value += this.advance();
442
+ }
443
+ }
444
+ if (value === "")
445
+ return null;
446
+ return { type: "word", value };
447
+ }
292
448
  isWordBreak(char) {
293
449
  return WORD_BREAK_CHARS.has(char);
294
450
  }
@@ -332,4 +488,4 @@ function lex(source) {
332
488
  return new Lexer(source).tokenize();
333
489
  }
334
490
 
335
- //# debugId=860EEAF9CC49FB9A64756E2164756E21
491
+ //# debugId=768674A138D6E11564756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lexer/lexer.ts"],
4
4
  "sourcesContent": [
5
- "import { LexError } from \"../errors.cjs\";\nimport type { Token, RedirectMode } from \"./tokens.cjs\";\n\nconst GLOB_CHARS = new Set([\"*\", \"?\", \"[\", \"{\", \"}\"]);\nconst WORD_BREAK_CHARS = new Set([\n \" \",\n \"\\t\",\n \"\\n\",\n \"\\r\",\n \"|\",\n \"&\",\n \";\",\n \">\",\n \"<\",\n \"(\",\n \")\",\n \"$\",\n \"'\",\n '\"',\n \"`\",\n]);\n\nexport class Lexer {\n private source: string;\n private pos: number = 0;\n private line: number = 1;\n private column: number = 1;\n\n constructor(source: string) {\n this.source = source;\n }\n\n tokenize(): Token[] {\n const tokens: Token[] = [];\n\n while (!this.isAtEnd()) {\n this.skipWhitespace();\n if (this.isAtEnd()) break;\n\n const token = this.nextToken();\n if (token) {\n tokens.push(token);\n }\n }\n\n tokens.push({ type: \"eof\" });\n return tokens;\n }\n\n private nextToken(): Token | null {\n const char = this.peek();\n\n // Comments\n if (char === \"#\") {\n this.skipComment();\n return null;\n }\n\n // Operators and redirects\n if (char === \"|\") {\n this.advance();\n if (this.peek() === \"|\") {\n this.advance();\n return { type: \"or\" };\n }\n return { type: \"pipe\" };\n }\n\n if (char === \"&\") {\n this.advance();\n if (this.peek() === \"&\") {\n this.advance();\n return { type: \"and\" };\n }\n if (this.peek() === \">\") {\n this.advance();\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \"&>>\" };\n }\n return { type: \"redirect\", mode: \"&>\" };\n }\n // Background execution (&) - treat as word for now\n return { type: \"word\", value: \"&\" };\n }\n\n if (char === \";\") {\n this.advance();\n return { type: \"semicolon\" };\n }\n\n // Redirects\n if (char === \">\") {\n this.advance();\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \">>\" };\n }\n return { type: \"redirect\", mode: \">\" };\n }\n\n if (char === \"<\") {\n this.advance();\n return { type: \"redirect\", mode: \"<\" };\n }\n\n // File descriptor redirects (2>, 2>>, 2>&1, 1>&2)\n if (char === \"1\" || char === \"2\") {\n const fd = char;\n const nextChar = this.peekAhead(1);\n if (nextChar === \">\") {\n this.advance(); // consume fd\n this.advance(); // consume >\n if (fd === \"2\") {\n if (this.peek() === \"&\" && this.peekAhead(1) === \"1\") {\n this.advance(); // consume &\n this.advance(); // consume 1\n return { type: \"redirect\", mode: \"2>&1\" };\n }\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \"2>>\" };\n }\n return { type: \"redirect\", mode: \"2>\" };\n } else {\n // 1>&2\n if (this.peek() === \"&\" && this.peekAhead(1) === \"2\") {\n this.advance(); // consume &\n this.advance(); // consume 2\n return { type: \"redirect\", mode: \"1>&2\" };\n }\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \">>\" };\n }\n return { type: \"redirect\", mode: \">\" };\n }\n }\n }\n\n // Variables and substitutions\n if (char === \"$\") {\n return this.readVariable();\n }\n\n // Single quotes\n if (char === \"'\") {\n return this.readSingleQuote();\n }\n\n // Double quotes\n if (char === '\"') {\n return this.readDoubleQuote();\n }\n\n // Word (including potential globs and assignments)\n return this.readWord();\n }\n\n private readVariable(): Token {\n this.advance(); // consume $\n\n // Command substitution $(...)\n if (this.peek() === \"(\") {\n this.advance(); // consume (\n const command = this.readUntilMatchingParen();\n return { type: \"substitution\", command };\n }\n\n // ${VAR} syntax\n if (this.peek() === \"{\") {\n this.advance(); // consume {\n let name = \"\";\n while (!this.isAtEnd() && this.peek() !== \"}\") {\n name += this.advance();\n }\n if (this.peek() === \"}\") {\n this.advance(); // consume }\n }\n return { type: \"variable\", name };\n }\n\n // $VAR syntax\n let name = \"\";\n while (!this.isAtEnd() && this.isVarChar(this.peek())) {\n name += this.advance();\n }\n\n if (name === \"\") {\n return { type: \"word\", value: \"$\" };\n }\n\n return { type: \"variable\", name };\n }\n\n private readUntilMatchingParen(): string {\n let depth = 1;\n let result = \"\";\n\n while (!this.isAtEnd() && depth > 0) {\n const char = this.peek();\n if (char === \"(\") {\n depth++;\n } else if (char === \")\") {\n depth--;\n if (depth === 0) {\n this.advance(); // consume closing )\n break;\n }\n }\n result += this.advance();\n }\n\n return result;\n }\n\n private readSingleQuote(): Token {\n this.advance(); // consume opening '\n let value = \"\";\n\n while (!this.isAtEnd() && this.peek() !== \"'\") {\n value += this.advance();\n }\n\n if (this.peek() === \"'\") {\n this.advance(); // consume closing '\n } else {\n throw new LexError(\"Unterminated single quote\", this.pos, this.line, this.column);\n }\n\n return { type: \"singleQuote\", value };\n }\n\n private readDoubleQuote(): Token {\n this.advance(); // consume opening \"\n const parts: Array<string | Token> = [];\n let currentString = \"\";\n\n while (!this.isAtEnd() && this.peek() !== '\"') {\n const char = this.peek();\n\n if (char === \"\\\\\") {\n this.advance();\n if (!this.isAtEnd()) {\n const escaped = this.advance();\n // In double quotes, only certain chars are special\n if ([\"$\", '\"', \"\\\\\", \"`\", \"\\n\"].includes(escaped)) {\n currentString += escaped;\n } else {\n currentString += \"\\\\\" + escaped;\n }\n }\n } else if (char === \"$\") {\n if (currentString) {\n parts.push(currentString);\n currentString = \"\";\n }\n parts.push(this.readVariable());\n } else {\n currentString += this.advance();\n }\n }\n\n if (currentString) {\n parts.push(currentString);\n }\n\n if (this.peek() === '\"') {\n this.advance(); // consume closing \"\n } else {\n throw new LexError(\"Unterminated double quote\", this.pos, this.line, this.column);\n }\n\n return { type: \"doubleQuote\", parts };\n }\n\n private readWord(): Token {\n let value = \"\";\n let hasGlobChars = false;\n\n while (!this.isAtEnd() && !this.isWordBreak(this.peek())) {\n const char = this.peek();\n\n if (char === \"\\\\\") {\n this.advance();\n if (!this.isAtEnd()) {\n value += this.advance();\n }\n } else {\n if (GLOB_CHARS.has(char)) {\n hasGlobChars = true;\n }\n value += this.advance();\n }\n }\n\n // Check if this is an assignment (VAR=value)\n const assignmentMatch = value.match(/^([a-zA-Z_][a-zA-Z0-9_]*)=(.*)$/);\n if (assignmentMatch) {\n return {\n type: \"assignment\",\n name: assignmentMatch[1]!,\n value: assignmentMatch[2]!,\n };\n }\n\n if (hasGlobChars) {\n return { type: \"glob\", pattern: value };\n }\n\n return { type: \"word\", value };\n }\n\n private isWordBreak(char: string): boolean {\n return WORD_BREAK_CHARS.has(char);\n }\n\n private isVarChar(char: string): boolean {\n return /[a-zA-Z0-9_]/.test(char);\n }\n\n private skipWhitespace(): void {\n while (!this.isAtEnd() && /\\s/.test(this.peek())) {\n this.advance();\n }\n }\n\n private skipComment(): void {\n while (!this.isAtEnd() && this.peek() !== \"\\n\") {\n this.advance();\n }\n }\n\n private peek(): string {\n return this.source[this.pos] ?? \"\";\n }\n\n private peekAhead(n: number): string {\n return this.source[this.pos + n] ?? \"\";\n }\n\n private advance(): string {\n const char = this.source[this.pos]!;\n this.pos++;\n if (char === \"\\n\") {\n this.line++;\n this.column = 1;\n } else {\n this.column++;\n }\n return char;\n }\n\n private isAtEnd(): boolean {\n return this.pos >= this.source.length;\n }\n}\n\nexport function lex(source: string): Token[] {\n return new Lexer(source).tokenize();\n}\n"
5
+ "import { LexError } from \"../errors.cjs\";\nimport type { Token, RedirectMode } from \"./tokens.cjs\";\n\nconst GLOB_CHARS = new Set([\"*\", \"?\", \"[\", \"{\", \"}\"]);\nconst WORD_BREAK_CHARS = new Set([\n \" \",\n \"\\t\",\n \"\\n\",\n \"\\r\",\n \"|\",\n \"&\",\n \";\",\n \">\",\n \"<\",\n \"(\",\n \")\",\n \"$\",\n \"'\",\n '\"',\n \"`\",\n]);\n\nexport class Lexer {\n private source: string;\n private pos: number = 0;\n private line: number = 1;\n private column: number = 1;\n private tokenQueue: Token[] = [];\n\n constructor(source: string) {\n this.source = source;\n }\n\n tokenize(): Token[] {\n const tokens: Token[] = [];\n\n while (!this.isAtEnd() || this.tokenQueue.length > 0) {\n // Drain token queue first (for heredoc handling)\n if (this.tokenQueue.length > 0) {\n tokens.push(this.tokenQueue.shift()!);\n continue;\n }\n\n this.skipWhitespace();\n if (this.isAtEnd()) break;\n\n const token = this.nextToken();\n if (token) {\n tokens.push(token);\n }\n }\n\n tokens.push({ type: \"eof\" });\n return tokens;\n }\n\n private nextToken(): Token | null {\n // Check token queue first (used for heredoc handling)\n if (this.tokenQueue.length > 0) {\n return this.tokenQueue.shift()!;\n }\n\n const char = this.peek();\n\n // Comments\n if (char === \"#\") {\n this.skipComment();\n return null;\n }\n\n // Operators and redirects\n if (char === \"|\") {\n this.advance();\n if (this.peek() === \"|\") {\n this.advance();\n return { type: \"or\" };\n }\n return { type: \"pipe\" };\n }\n\n if (char === \"&\") {\n this.advance();\n if (this.peek() === \"&\") {\n this.advance();\n return { type: \"and\" };\n }\n if (this.peek() === \">\") {\n this.advance();\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \"&>>\" };\n }\n return { type: \"redirect\", mode: \"&>\" };\n }\n // Background execution (&) - treat as word for now\n return { type: \"word\", value: \"&\" };\n }\n\n if (char === \";\") {\n this.advance();\n return { type: \"semicolon\" };\n }\n\n // Redirects\n if (char === \">\") {\n this.advance();\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \">>\" };\n }\n return { type: \"redirect\", mode: \">\" };\n }\n\n if (char === \"<\") {\n this.advance();\n if (this.peek() === \"<\") {\n this.advance();\n return this.readHeredoc();\n }\n return { type: \"redirect\", mode: \"<\" };\n }\n\n // File descriptor redirects (2>, 2>>, 2>&1, 1>&2)\n if (char === \"1\" || char === \"2\") {\n const fd = char;\n const nextChar = this.peekAhead(1);\n if (nextChar === \">\") {\n this.advance(); // consume fd\n this.advance(); // consume >\n if (fd === \"2\") {\n if (this.peek() === \"&\" && this.peekAhead(1) === \"1\") {\n this.advance(); // consume &\n this.advance(); // consume 1\n return { type: \"redirect\", mode: \"2>&1\" };\n }\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \"2>>\" };\n }\n return { type: \"redirect\", mode: \"2>\" };\n } else {\n // 1>&2\n if (this.peek() === \"&\" && this.peekAhead(1) === \"2\") {\n this.advance(); // consume &\n this.advance(); // consume 2\n return { type: \"redirect\", mode: \"1>&2\" };\n }\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \">>\" };\n }\n return { type: \"redirect\", mode: \">\" };\n }\n }\n }\n\n // Variables and substitutions\n if (char === \"$\") {\n return this.readVariable();\n }\n\n // Single quotes\n if (char === \"'\") {\n return this.readSingleQuote();\n }\n\n // Double quotes\n if (char === '\"') {\n return this.readDoubleQuote();\n }\n\n // Word (including potential globs and assignments)\n return this.readWord();\n }\n\n private readVariable(): Token {\n this.advance(); // consume $\n\n // Command substitution $(...)\n if (this.peek() === \"(\") {\n this.advance(); // consume (\n const command = this.readUntilMatchingParen();\n return { type: \"substitution\", command };\n }\n\n // ${VAR} syntax\n if (this.peek() === \"{\") {\n this.advance(); // consume {\n let name = \"\";\n while (!this.isAtEnd() && this.peek() !== \"}\") {\n name += this.advance();\n }\n if (this.peek() === \"}\") {\n this.advance(); // consume }\n }\n return { type: \"variable\", name };\n }\n\n // $VAR syntax\n let name = \"\";\n while (!this.isAtEnd() && this.isVarChar(this.peek())) {\n name += this.advance();\n }\n\n if (name === \"\") {\n return { type: \"word\", value: \"$\" };\n }\n\n return { type: \"variable\", name };\n }\n\n private readUntilMatchingParen(): string {\n let depth = 1;\n let result = \"\";\n\n while (!this.isAtEnd() && depth > 0) {\n const char = this.peek();\n if (char === \"(\") {\n depth++;\n } else if (char === \")\") {\n depth--;\n if (depth === 0) {\n this.advance(); // consume closing )\n break;\n }\n }\n result += this.advance();\n }\n\n return result;\n }\n\n private readSingleQuote(): Token {\n this.advance(); // consume opening '\n let value = \"\";\n\n while (!this.isAtEnd() && this.peek() !== \"'\") {\n value += this.advance();\n }\n\n if (this.peek() === \"'\") {\n this.advance(); // consume closing '\n } else {\n throw new LexError(\"Unterminated single quote\", this.pos, this.line, this.column);\n }\n\n return { type: \"singleQuote\", value };\n }\n\n private readDoubleQuote(): Token {\n this.advance(); // consume opening \"\n const parts: Array<string | Token> = [];\n let currentString = \"\";\n\n while (!this.isAtEnd() && this.peek() !== '\"') {\n const char = this.peek();\n\n if (char === \"\\\\\") {\n this.advance();\n if (!this.isAtEnd()) {\n const escaped = this.advance();\n // In double quotes, only certain chars are special\n if ([\"$\", '\"', \"\\\\\", \"`\", \"\\n\"].includes(escaped)) {\n currentString += escaped;\n } else {\n currentString += \"\\\\\" + escaped;\n }\n }\n } else if (char === \"$\") {\n if (currentString) {\n parts.push(currentString);\n currentString = \"\";\n }\n parts.push(this.readVariable());\n } else {\n currentString += this.advance();\n }\n }\n\n if (currentString) {\n parts.push(currentString);\n }\n\n if (this.peek() === '\"') {\n this.advance(); // consume closing \"\n } else {\n throw new LexError(\"Unterminated double quote\", this.pos, this.line, this.column);\n }\n\n return { type: \"doubleQuote\", parts };\n }\n\n private readWord(): Token {\n let value = \"\";\n let hasGlobChars = false;\n\n while (!this.isAtEnd() && !this.isWordBreak(this.peek())) {\n const char = this.peek();\n\n if (char === \"\\\\\") {\n this.advance();\n if (!this.isAtEnd()) {\n value += this.advance();\n }\n } else {\n if (GLOB_CHARS.has(char)) {\n hasGlobChars = true;\n }\n value += this.advance();\n }\n }\n\n // Check if this is an assignment (VAR=value)\n const assignmentMatch = value.match(/^([a-zA-Z_][a-zA-Z0-9_]*)=(.*)$/);\n if (assignmentMatch) {\n return {\n type: \"assignment\",\n name: assignmentMatch[1]!,\n value: assignmentMatch[2]!,\n };\n }\n\n if (hasGlobChars) {\n return { type: \"glob\", pattern: value };\n }\n\n return { type: \"word\", value };\n }\n\n private readHeredoc(): Token {\n // Check for tab-stripping variant (<<-)\n const stripTabs = this.peek() === \"-\";\n if (stripTabs) {\n this.advance();\n }\n\n // Skip whitespace before delimiter\n while (this.peek() === \" \" || this.peek() === \"\\t\") {\n this.advance();\n }\n\n // Read delimiter and determine if expansion is enabled\n const { delimiter, expand } = this.readHeredocDelimiter();\n\n // Tokenize the rest of the current line and queue those tokens\n this.tokenizeRestOfLine();\n\n // Skip the newline that starts the heredoc content\n if (this.peek() === \"\\n\") {\n this.advance();\n }\n\n // Read content until closing delimiter\n let content = \"\";\n while (!this.isAtEnd()) {\n const lineStart = this.pos;\n let line = \"\";\n\n // Read until end of line or end of input\n while (!this.isAtEnd() && this.peek() !== \"\\n\") {\n line += this.advance();\n }\n\n // Check if this line is the delimiter (after stripping leading tabs if <<-)\n const strippedLine = stripTabs ? line.replace(/^\\t+/, \"\") : line;\n if (strippedLine === delimiter) {\n // Found closing delimiter, consume newline if present\n if (this.peek() === \"\\n\") {\n this.advance();\n }\n break;\n }\n\n // Add the line to content\n if (stripTabs) {\n content += line.replace(/^\\t+/, \"\");\n } else {\n content += line;\n }\n\n // Add newline if present\n if (this.peek() === \"\\n\") {\n content += this.advance();\n }\n }\n\n return { type: \"heredoc\", content, expand };\n }\n\n private readHeredocDelimiter(): { delimiter: string; expand: boolean } {\n const quoteChar = this.peek();\n\n // Quoted delimiter - no expansion\n if (quoteChar === \"'\" || quoteChar === '\"') {\n this.advance(); // consume opening quote\n let delimiter = \"\";\n while (!this.isAtEnd() && this.peek() !== quoteChar && this.peek() !== \"\\n\") {\n delimiter += this.advance();\n }\n if (this.peek() === quoteChar) {\n this.advance(); // consume closing quote\n }\n return { delimiter, expand: false };\n }\n\n // Unquoted delimiter - expansion enabled\n let delimiter = \"\";\n while (!this.isAtEnd() && !this.isWordBreak(this.peek()) && this.peek() !== \"\\n\") {\n if (this.peek() === \"\\\\\") {\n this.advance();\n if (!this.isAtEnd()) {\n delimiter += this.advance();\n }\n } else {\n delimiter += this.advance();\n }\n }\n\n return { delimiter, expand: true };\n }\n\n private tokenizeRestOfLine(): void {\n // Tokenize the rest of the line (until newline or end)\n while (!this.isAtEnd() && this.peek() !== \"\\n\") {\n // Skip only spaces and tabs, not newlines\n while (this.peek() === \" \" || this.peek() === \"\\t\") {\n this.advance();\n }\n if (this.isAtEnd() || this.peek() === \"\\n\") break;\n\n const token = this.readRestOfLineToken();\n if (token) {\n this.tokenQueue.push(token);\n }\n }\n }\n\n private readRestOfLineToken(): Token | null {\n const char = this.peek();\n\n if (char === \"|\") {\n this.advance();\n if (this.peek() === \"|\") {\n this.advance();\n return { type: \"or\" };\n }\n return { type: \"pipe\" };\n }\n\n if (char === \"&\") {\n this.advance();\n if (this.peek() === \"&\") {\n this.advance();\n return { type: \"and\" };\n }\n return { type: \"word\", value: \"&\" };\n }\n\n if (char === \";\") {\n this.advance();\n return { type: \"semicolon\" };\n }\n\n if (char === \">\") {\n this.advance();\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \">>\" };\n }\n return { type: \"redirect\", mode: \">\" };\n }\n\n if (char === \"<\") {\n this.advance();\n return { type: \"redirect\", mode: \"<\" };\n }\n\n if (char === \"$\") {\n return this.readVariable();\n }\n\n if (char === \"'\") {\n return this.readSingleQuote();\n }\n\n if (char === '\"') {\n return this.readDoubleQuote();\n }\n\n // Read a word but stop at newline\n let value = \"\";\n while (!this.isAtEnd() && !this.isWordBreak(this.peek()) && this.peek() !== \"\\n\") {\n if (this.peek() === \"\\\\\") {\n this.advance();\n if (!this.isAtEnd()) {\n value += this.advance();\n }\n } else {\n value += this.advance();\n }\n }\n\n if (value === \"\") return null;\n return { type: \"word\", value };\n }\n\n private isWordBreak(char: string): boolean {\n return WORD_BREAK_CHARS.has(char);\n }\n\n private isVarChar(char: string): boolean {\n return /[a-zA-Z0-9_]/.test(char);\n }\n\n private skipWhitespace(): void {\n while (!this.isAtEnd() && /\\s/.test(this.peek())) {\n this.advance();\n }\n }\n\n private skipComment(): void {\n while (!this.isAtEnd() && this.peek() !== \"\\n\") {\n this.advance();\n }\n }\n\n private peek(): string {\n return this.source[this.pos] ?? \"\";\n }\n\n private peekAhead(n: number): string {\n return this.source[this.pos + n] ?? \"\";\n }\n\n private advance(): string {\n const char = this.source[this.pos]!;\n this.pos++;\n if (char === \"\\n\") {\n this.line++;\n this.column = 1;\n } else {\n this.column++;\n }\n return char;\n }\n\n private isAtEnd(): boolean {\n return this.pos >= this.source.length;\n }\n}\n\nexport function lex(source: string): Token[] {\n return new Lexer(source).tokenize();\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "860EEAF9CC49FB9A64756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAyB,IAAzB;AAGA,IAAM,aAAa,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG,CAAC;AACpD,IAAM,mBAAmB,IAAI,IAAI;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAAA;AAEM,MAAM,MAAM;AAAA,EACT;AAAA,EACA,MAAc;AAAA,EACd,OAAe;AAAA,EACf,SAAiB;AAAA,EACjB,aAAsB,CAAC;AAAA,EAE/B,WAAW,CAAC,QAAgB;AAAA,IAC1B,KAAK,SAAS;AAAA;AAAA,EAGhB,QAAQ,GAAY;AAAA,IAClB,MAAM,SAAkB,CAAC;AAAA,IAEzB,OAAO,CAAC,KAAK,QAAQ,KAAK,KAAK,WAAW,SAAS,GAAG;AAAA,MAEpD,IAAI,KAAK,WAAW,SAAS,GAAG;AAAA,QAC9B,OAAO,KAAK,KAAK,WAAW,MAAM,CAAE;AAAA,QACpC;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAAA,MACpB,IAAI,KAAK,QAAQ;AAAA,QAAG;AAAA,MAEpB,MAAM,QAAQ,KAAK,UAAU;AAAA,MAC7B,IAAI,OAAO;AAAA,QACT,OAAO,KAAK,KAAK;AAAA,MACnB;AAAA,IACF;AAAA,IAEA,OAAO,KAAK,EAAE,MAAM,MAAM,CAAC;AAAA,IAC3B,OAAO;AAAA;AAAA,EAGD,SAAS,GAAiB;AAAA,IAEhC,IAAI,KAAK,WAAW,SAAS,GAAG;AAAA,MAC9B,OAAO,KAAK,WAAW,MAAM;AAAA,IAC/B;AAAA,IAEA,MAAM,OAAO,KAAK,KAAK;AAAA,IAGvB,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,YAAY;AAAA,MACjB,OAAO;AAAA,IACT;AAAA,IAGA,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QACvB,KAAK,QAAQ;AAAA,QACb,OAAO,EAAE,MAAM,KAAK;AAAA,MACtB;AAAA,MACA,OAAO,EAAE,MAAM,OAAO;AAAA,IACxB;AAAA,IAEA,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QACvB,KAAK,QAAQ;AAAA,QACb,OAAO,EAAE,MAAM,MAAM;AAAA,MACvB;AAAA,MACA,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QACvB,KAAK,QAAQ;AAAA,QACb,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,UACvB,KAAK,QAAQ;AAAA,UACb,OAAO,EAAE,MAAM,YAAY,MAAM,MAAM;AAAA,QACzC;AAAA,QACA,OAAO,EAAE,MAAM,YAAY,MAAM,KAAK;AAAA,MACxC;AAAA,MAEA,OAAO,EAAE,MAAM,QAAQ,OAAO,IAAI;AAAA,IACpC;AAAA,IAEA,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,OAAO,EAAE,MAAM,YAAY;AAAA,IAC7B;AAAA,IAGA,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QACvB,KAAK,QAAQ;AAAA,QACb,OAAO,EAAE,MAAM,YAAY,MAAM,KAAK;AAAA,MACxC;AAAA,MACA,OAAO,EAAE,MAAM,YAAY,MAAM,IAAI;AAAA,IACvC;AAAA,IAEA,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QACvB,KAAK,QAAQ;AAAA,QACb,OAAO,KAAK,YAAY;AAAA,MAC1B;AAAA,MACA,OAAO,EAAE,MAAM,YAAY,MAAM,IAAI;AAAA,IACvC;AAAA,IAGA,IAAI,SAAS,OAAO,SAAS,KAAK;AAAA,MAChC,MAAM,KAAK;AAAA,MACX,MAAM,WAAW,KAAK,UAAU,CAAC;AAAA,MACjC,IAAI,aAAa,KAAK;AAAA,QACpB,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,IAAI,OAAO,KAAK;AAAA,UACd,IAAI,KAAK,KAAK,MAAM,OAAO,KAAK,UAAU,CAAC,MAAM,KAAK;AAAA,YACpD,KAAK,QAAQ;AAAA,YACb,KAAK,QAAQ;AAAA,YACb,OAAO,EAAE,MAAM,YAAY,MAAM,OAAO;AAAA,UAC1C;AAAA,UACA,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,YACvB,KAAK,QAAQ;AAAA,YACb,OAAO,EAAE,MAAM,YAAY,MAAM,MAAM;AAAA,UACzC;AAAA,UACA,OAAO,EAAE,MAAM,YAAY,MAAM,KAAK;AAAA,QACxC,EAAO;AAAA,UAEL,IAAI,KAAK,KAAK,MAAM,OAAO,KAAK,UAAU,CAAC,MAAM,KAAK;AAAA,YACpD,KAAK,QAAQ;AAAA,YACb,KAAK,QAAQ;AAAA,YACb,OAAO,EAAE,MAAM,YAAY,MAAM,OAAO;AAAA,UAC1C;AAAA,UACA,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,YACvB,KAAK,QAAQ;AAAA,YACb,OAAO,EAAE,MAAM,YAAY,MAAM,KAAK;AAAA,UACxC;AAAA,UACA,OAAO,EAAE,MAAM,YAAY,MAAM,IAAI;AAAA;AAAA,MAEzC;AAAA,IACF;AAAA,IAGA,IAAI,SAAS,KAAK;AAAA,MAChB,OAAO,KAAK,aAAa;AAAA,IAC3B;AAAA,IAGA,IAAI,SAAS,KAAK;AAAA,MAChB,OAAO,KAAK,gBAAgB;AAAA,IAC9B;AAAA,IAGA,IAAI,SAAS,KAAK;AAAA,MAChB,OAAO,KAAK,gBAAgB;AAAA,IAC9B;AAAA,IAGA,OAAO,KAAK,SAAS;AAAA;AAAA,EAGf,YAAY,GAAU;AAAA,IAC5B,KAAK,QAAQ;AAAA,IAGb,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,MACvB,KAAK,QAAQ;AAAA,MACb,MAAM,UAAU,KAAK,uBAAuB;AAAA,MAC5C,OAAO,EAAE,MAAM,gBAAgB,QAAQ;AAAA,IACzC;AAAA,IAGA,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,MACvB,KAAK,QAAQ;AAAA,MACb,IAAI,QAAO;AAAA,MACX,OAAO,CAAC,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM,KAAK;AAAA,QAC7C,SAAQ,KAAK,QAAQ;AAAA,MACvB;AAAA,MACA,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QACvB,KAAK,QAAQ;AAAA,MACf;AAAA,MACA,OAAO,EAAE,MAAM,YAAY,YAAK;AAAA,IAClC;AAAA,IAGA,IAAI,OAAO;AAAA,IACX,OAAO,CAAC,KAAK,QAAQ,KAAK,KAAK,UAAU,KAAK,KAAK,CAAC,GAAG;AAAA,MACrD,QAAQ,KAAK,QAAQ;AAAA,IACvB;AAAA,IAEA,IAAI,SAAS,IAAI;AAAA,MACf,OAAO,EAAE,MAAM,QAAQ,OAAO,IAAI;AAAA,IACpC;AAAA,IAEA,OAAO,EAAE,MAAM,YAAY,KAAK;AAAA;AAAA,EAG1B,sBAAsB,GAAW;AAAA,IACvC,IAAI,QAAQ;AAAA,IACZ,IAAI,SAAS;AAAA,IAEb,OAAO,CAAC,KAAK,QAAQ,KAAK,QAAQ,GAAG;AAAA,MACnC,MAAM,OAAO,KAAK,KAAK;AAAA,MACvB,IAAI,SAAS,KAAK;AAAA,QAChB;AAAA,MACF,EAAO,SAAI,SAAS,KAAK;AAAA,QACvB;AAAA,QACA,IAAI,UAAU,GAAG;AAAA,UACf,KAAK,QAAQ;AAAA,UACb;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU,KAAK,QAAQ;AAAA,IACzB;AAAA,IAEA,OAAO;AAAA;AAAA,EAGD,eAAe,GAAU;AAAA,IAC/B,KAAK,QAAQ;AAAA,IACb,IAAI,QAAQ;AAAA,IAEZ,OAAO,CAAC,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM,KAAK;AAAA,MAC7C,SAAS,KAAK,QAAQ;AAAA,IACxB;AAAA,IAEA,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,MACvB,KAAK,QAAQ;AAAA,IACf,EAAO;AAAA,MACL,MAAM,IAAI,uBAAS,6BAA6B,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM;AAAA;AAAA,IAGlF,OAAO,EAAE,MAAM,eAAe,MAAM;AAAA;AAAA,EAG9B,eAAe,GAAU;AAAA,IAC/B,KAAK,QAAQ;AAAA,IACb,MAAM,QAA+B,CAAC;AAAA,IACtC,IAAI,gBAAgB;AAAA,IAEpB,OAAO,CAAC,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM,KAAK;AAAA,MAC7C,MAAM,OAAO,KAAK,KAAK;AAAA,MAEvB,IAAI,SAAS,MAAM;AAAA,QACjB,KAAK,QAAQ;AAAA,QACb,IAAI,CAAC,KAAK,QAAQ,GAAG;AAAA,UACnB,MAAM,UAAU,KAAK,QAAQ;AAAA,UAE7B,IAAI,CAAC,KAAK,KAAK,MAAM,KAAK;AAAA,CAAI,EAAE,SAAS,OAAO,GAAG;AAAA,YACjD,iBAAiB;AAAA,UACnB,EAAO;AAAA,YACL,iBAAiB,OAAO;AAAA;AAAA,QAE5B;AAAA,MACF,EAAO,SAAI,SAAS,KAAK;AAAA,QACvB,IAAI,eAAe;AAAA,UACjB,MAAM,KAAK,aAAa;AAAA,UACxB,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,KAAK,aAAa,CAAC;AAAA,MAChC,EAAO;AAAA,QACL,iBAAiB,KAAK,QAAQ;AAAA;AAAA,IAElC;AAAA,IAEA,IAAI,eAAe;AAAA,MACjB,MAAM,KAAK,aAAa;AAAA,IAC1B;AAAA,IAEA,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,MACvB,KAAK,QAAQ;AAAA,IACf,EAAO;AAAA,MACL,MAAM,IAAI,uBAAS,6BAA6B,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM;AAAA;AAAA,IAGlF,OAAO,EAAE,MAAM,eAAe,MAAM;AAAA;AAAA,EAG9B,QAAQ,GAAU;AAAA,IACxB,IAAI,QAAQ;AAAA,IACZ,IAAI,eAAe;AAAA,IAEnB,OAAO,CAAC,KAAK,QAAQ,KAAK,CAAC,KAAK,YAAY,KAAK,KAAK,CAAC,GAAG;AAAA,MACxD,MAAM,OAAO,KAAK,KAAK;AAAA,MAEvB,IAAI,SAAS,MAAM;AAAA,QACjB,KAAK,QAAQ;AAAA,QACb,IAAI,CAAC,KAAK,QAAQ,GAAG;AAAA,UACnB,SAAS,KAAK,QAAQ;AAAA,QACxB;AAAA,MACF,EAAO;AAAA,QACL,IAAI,WAAW,IAAI,IAAI,GAAG;AAAA,UACxB,eAAe;AAAA,QACjB;AAAA,QACA,SAAS,KAAK,QAAQ;AAAA;AAAA,IAE1B;AAAA,IAGA,MAAM,kBAAkB,MAAM,MAAM,iCAAiC;AAAA,IACrE,IAAI,iBAAiB;AAAA,MACnB,OAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAM,gBAAgB;AAAA,QACtB,OAAO,gBAAgB;AAAA,MACzB;AAAA,IACF;AAAA,IAEA,IAAI,cAAc;AAAA,MAChB,OAAO,EAAE,MAAM,QAAQ,SAAS,MAAM;AAAA,IACxC;AAAA,IAEA,OAAO,EAAE,MAAM,QAAQ,MAAM;AAAA;AAAA,EAGvB,WAAW,GAAU;AAAA,IAE3B,MAAM,YAAY,KAAK,KAAK,MAAM;AAAA,IAClC,IAAI,WAAW;AAAA,MACb,KAAK,QAAQ;AAAA,IACf;AAAA,IAGA,OAAO,KAAK,KAAK,MAAM,OAAO,KAAK,KAAK,MAAM,MAAM;AAAA,MAClD,KAAK,QAAQ;AAAA,IACf;AAAA,IAGA,QAAQ,WAAW,WAAW,KAAK,qBAAqB;AAAA,IAGxD,KAAK,mBAAmB;AAAA,IAGxB,IAAI,KAAK,KAAK,MAAM;AAAA,GAAM;AAAA,MACxB,KAAK,QAAQ;AAAA,IACf;AAAA,IAGA,IAAI,UAAU;AAAA,IACd,OAAO,CAAC,KAAK,QAAQ,GAAG;AAAA,MACtB,MAAM,YAAY,KAAK;AAAA,MACvB,IAAI,OAAO;AAAA,MAGX,OAAO,CAAC,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM;AAAA,GAAM;AAAA,QAC9C,QAAQ,KAAK,QAAQ;AAAA,MACvB;AAAA,MAGA,MAAM,eAAe,YAAY,KAAK,QAAQ,QAAQ,EAAE,IAAI;AAAA,MAC5D,IAAI,iBAAiB,WAAW;AAAA,QAE9B,IAAI,KAAK,KAAK,MAAM;AAAA,GAAM;AAAA,UACxB,KAAK,QAAQ;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAAA,MAGA,IAAI,WAAW;AAAA,QACb,WAAW,KAAK,QAAQ,QAAQ,EAAE;AAAA,MACpC,EAAO;AAAA,QACL,WAAW;AAAA;AAAA,MAIb,IAAI,KAAK,KAAK,MAAM;AAAA,GAAM;AAAA,QACxB,WAAW,KAAK,QAAQ;AAAA,MAC1B;AAAA,IACF;AAAA,IAEA,OAAO,EAAE,MAAM,WAAW,SAAS,OAAO;AAAA;AAAA,EAGpC,oBAAoB,GAA2C;AAAA,IACrE,MAAM,YAAY,KAAK,KAAK;AAAA,IAG5B,IAAI,cAAc,OAAO,cAAc,KAAK;AAAA,MAC1C,KAAK,QAAQ;AAAA,MACb,IAAI,aAAY;AAAA,MAChB,OAAO,CAAC,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM,aAAa,KAAK,KAAK,MAAM;AAAA,GAAM;AAAA,QAC3E,cAAa,KAAK,QAAQ;AAAA,MAC5B;AAAA,MACA,IAAI,KAAK,KAAK,MAAM,WAAW;AAAA,QAC7B,KAAK,QAAQ;AAAA,MACf;AAAA,MACA,OAAO,EAAE,uBAAW,QAAQ,MAAM;AAAA,IACpC;AAAA,IAGA,IAAI,YAAY;AAAA,IAChB,OAAO,CAAC,KAAK,QAAQ,KAAK,CAAC,KAAK,YAAY,KAAK,KAAK,CAAC,KAAK,KAAK,KAAK,MAAM;AAAA,GAAM;AAAA,MAChF,IAAI,KAAK,KAAK,MAAM,MAAM;AAAA,QACxB,KAAK,QAAQ;AAAA,QACb,IAAI,CAAC,KAAK,QAAQ,GAAG;AAAA,UACnB,aAAa,KAAK,QAAQ;AAAA,QAC5B;AAAA,MACF,EAAO;AAAA,QACL,aAAa,KAAK,QAAQ;AAAA;AAAA,IAE9B;AAAA,IAEA,OAAO,EAAE,WAAW,QAAQ,KAAK;AAAA;AAAA,EAG3B,kBAAkB,GAAS;AAAA,IAEjC,OAAO,CAAC,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM;AAAA,GAAM;AAAA,MAE9C,OAAO,KAAK,KAAK,MAAM,OAAO,KAAK,KAAK,MAAM,MAAM;AAAA,QAClD,KAAK,QAAQ;AAAA,MACf;AAAA,MACA,IAAI,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM;AAAA;AAAA,QAAM;AAAA,MAE5C,MAAM,QAAQ,KAAK,oBAAoB;AAAA,MACvC,IAAI,OAAO;AAAA,QACT,KAAK,WAAW,KAAK,KAAK;AAAA,MAC5B;AAAA,IACF;AAAA;AAAA,EAGM,mBAAmB,GAAiB;AAAA,IAC1C,MAAM,OAAO,KAAK,KAAK;AAAA,IAEvB,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QACvB,KAAK,QAAQ;AAAA,QACb,OAAO,EAAE,MAAM,KAAK;AAAA,MACtB;AAAA,MACA,OAAO,EAAE,MAAM,OAAO;AAAA,IACxB;AAAA,IAEA,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QACvB,KAAK,QAAQ;AAAA,QACb,OAAO,EAAE,MAAM,MAAM;AAAA,MACvB;AAAA,MACA,OAAO,EAAE,MAAM,QAAQ,OAAO,IAAI;AAAA,IACpC;AAAA,IAEA,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,OAAO,EAAE,MAAM,YAAY;AAAA,IAC7B;AAAA,IAEA,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QACvB,KAAK,QAAQ;AAAA,QACb,OAAO,EAAE,MAAM,YAAY,MAAM,KAAK;AAAA,MACxC;AAAA,MACA,OAAO,EAAE,MAAM,YAAY,MAAM,IAAI;AAAA,IACvC;AAAA,IAEA,IAAI,SAAS,KAAK;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,OAAO,EAAE,MAAM,YAAY,MAAM,IAAI;AAAA,IACvC;AAAA,IAEA,IAAI,SAAS,KAAK;AAAA,MAChB,OAAO,KAAK,aAAa;AAAA,IAC3B;AAAA,IAEA,IAAI,SAAS,KAAK;AAAA,MAChB,OAAO,KAAK,gBAAgB;AAAA,IAC9B;AAAA,IAEA,IAAI,SAAS,KAAK;AAAA,MAChB,OAAO,KAAK,gBAAgB;AAAA,IAC9B;AAAA,IAGA,IAAI,QAAQ;AAAA,IACZ,OAAO,CAAC,KAAK,QAAQ,KAAK,CAAC,KAAK,YAAY,KAAK,KAAK,CAAC,KAAK,KAAK,KAAK,MAAM;AAAA,GAAM;AAAA,MAChF,IAAI,KAAK,KAAK,MAAM,MAAM;AAAA,QACxB,KAAK,QAAQ;AAAA,QACb,IAAI,CAAC,KAAK,QAAQ,GAAG;AAAA,UACnB,SAAS,KAAK,QAAQ;AAAA,QACxB;AAAA,MACF,EAAO;AAAA,QACL,SAAS,KAAK,QAAQ;AAAA;AAAA,IAE1B;AAAA,IAEA,IAAI,UAAU;AAAA,MAAI,OAAO;AAAA,IACzB,OAAO,EAAE,MAAM,QAAQ,MAAM;AAAA;AAAA,EAGvB,WAAW,CAAC,MAAuB;AAAA,IACzC,OAAO,iBAAiB,IAAI,IAAI;AAAA;AAAA,EAG1B,SAAS,CAAC,MAAuB;AAAA,IACvC,OAAO,eAAe,KAAK,IAAI;AAAA;AAAA,EAGzB,cAAc,GAAS;AAAA,IAC7B,OAAO,CAAC,KAAK,QAAQ,KAAK,KAAK,KAAK,KAAK,KAAK,CAAC,GAAG;AAAA,MAChD,KAAK,QAAQ;AAAA,IACf;AAAA;AAAA,EAGM,WAAW,GAAS;AAAA,IAC1B,OAAO,CAAC,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM;AAAA,GAAM;AAAA,MAC9C,KAAK,QAAQ;AAAA,IACf;AAAA;AAAA,EAGM,IAAI,GAAW;AAAA,IACrB,OAAO,KAAK,OAAO,KAAK,QAAQ;AAAA;AAAA,EAG1B,SAAS,CAAC,GAAmB;AAAA,IACnC,OAAO,KAAK,OAAO,KAAK,MAAM,MAAM;AAAA;AAAA,EAG9B,OAAO,GAAW;AAAA,IACxB,MAAM,OAAO,KAAK,OAAO,KAAK;AAAA,IAC9B,KAAK;AAAA,IACL,IAAI,SAAS;AAAA,GAAM;AAAA,MACjB,KAAK;AAAA,MACL,KAAK,SAAS;AAAA,IAChB,EAAO;AAAA,MACL,KAAK;AAAA;AAAA,IAEP,OAAO;AAAA;AAAA,EAGD,OAAO,GAAY;AAAA,IACzB,OAAO,KAAK,OAAO,KAAK,OAAO;AAAA;AAEnC;AAEO,SAAS,GAAG,CAAC,QAAyB;AAAA,EAC3C,OAAO,IAAI,MAAM,MAAM,EAAE,SAAS;AAAA;",
8
+ "debugId": "768674A138D6E11564756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -58,9 +58,13 @@ function tokenToString(token) {
58
58
  return `"${token.parts.map((p) => typeof p === "string" ? p : tokenToString(p)).join("")}"`;
59
59
  case "assignment":
60
60
  return `${token.name}=${typeof token.value === "string" ? token.value : token.value.map(tokenToString).join("")}`;
61
+ case "heredoc":
62
+ return `<<${token.expand ? "EOF" : "'EOF'"}
63
+ ${token.content}
64
+ EOF`;
61
65
  case "eof":
62
66
  return "<EOF>";
63
67
  }
64
68
  }
65
69
 
66
- //# debugId=96D73CDE1FEDB90164756E2164756E21
70
+ //# debugId=CCBBA4DA0434D7BA64756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lexer/tokens.ts"],
4
4
  "sourcesContent": [
5
- "export type RedirectMode =\n | \">\"\n | \">>\"\n | \"<\"\n | \"2>\"\n | \"2>>\"\n | \"&>\"\n | \"&>>\"\n | \"2>&1\"\n | \"1>&2\";\n\nexport type Token =\n | { type: \"word\"; value: string }\n | { type: \"pipe\" }\n | { type: \"and\" }\n | { type: \"or\" }\n | { type: \"semicolon\" }\n | { type: \"redirect\"; mode: RedirectMode }\n | { type: \"variable\"; name: string }\n | { type: \"substitution\"; command: string }\n | { type: \"glob\"; pattern: string }\n | { type: \"singleQuote\"; value: string }\n | { type: \"doubleQuote\"; parts: Array<string | Token> }\n | { type: \"assignment\"; name: string; value: string | Token[] }\n | { type: \"eof\" };\n\nexport function tokenToString(token: Token): string {\n switch (token.type) {\n case \"word\":\n return token.value;\n case \"pipe\":\n return \"|\";\n case \"and\":\n return \"&&\";\n case \"or\":\n return \"||\";\n case \"semicolon\":\n return \";\";\n case \"redirect\":\n return token.mode;\n case \"variable\":\n return `$${token.name}`;\n case \"substitution\":\n return `$(${token.command})`;\n case \"glob\":\n return token.pattern;\n case \"singleQuote\":\n return `'${token.value}'`;\n case \"doubleQuote\":\n return `\"${token.parts.map((p) => (typeof p === \"string\" ? p : tokenToString(p))).join(\"\")}\"`;\n case \"assignment\":\n return `${token.name}=${typeof token.value === \"string\" ? token.value : token.value.map(tokenToString).join(\"\")}`;\n case \"eof\":\n return \"<EOF>\";\n }\n}\n"
5
+ "export type RedirectMode =\n | \">\"\n | \">>\"\n | \"<\"\n | \"2>\"\n | \"2>>\"\n | \"&>\"\n | \"&>>\"\n | \"2>&1\"\n | \"1>&2\";\n\nexport type Token =\n | { type: \"word\"; value: string }\n | { type: \"pipe\" }\n | { type: \"and\" }\n | { type: \"or\" }\n | { type: \"semicolon\" }\n | { type: \"redirect\"; mode: RedirectMode }\n | { type: \"variable\"; name: string }\n | { type: \"substitution\"; command: string }\n | { type: \"glob\"; pattern: string }\n | { type: \"singleQuote\"; value: string }\n | { type: \"doubleQuote\"; parts: Array<string | Token> }\n | { type: \"assignment\"; name: string; value: string | Token[] }\n | { type: \"heredoc\"; content: string; expand: boolean }\n | { type: \"eof\" };\n\nexport function tokenToString(token: Token): string {\n switch (token.type) {\n case \"word\":\n return token.value;\n case \"pipe\":\n return \"|\";\n case \"and\":\n return \"&&\";\n case \"or\":\n return \"||\";\n case \"semicolon\":\n return \";\";\n case \"redirect\":\n return token.mode;\n case \"variable\":\n return `$${token.name}`;\n case \"substitution\":\n return `$(${token.command})`;\n case \"glob\":\n return token.pattern;\n case \"singleQuote\":\n return `'${token.value}'`;\n case \"doubleQuote\":\n return `\"${token.parts.map((p) => (typeof p === \"string\" ? p : tokenToString(p))).join(\"\")}\"`;\n case \"assignment\":\n return `${token.name}=${typeof token.value === \"string\" ? token.value : token.value.map(tokenToString).join(\"\")}`;\n case \"heredoc\":\n return `<<${token.expand ? \"EOF\" : \"'EOF'\"}\\n${token.content}\\nEOF`;\n case \"eof\":\n return \"<EOF>\";\n }\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BO,SAAS,aAAa,CAAC,OAAsB;AAAA,EAClD,QAAQ,MAAM;AAAA,SACP;AAAA,MACH,OAAO,MAAM;AAAA,SACV;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO,MAAM;AAAA,SACV;AAAA,MACH,OAAO,IAAI,MAAM;AAAA,SACd;AAAA,MACH,OAAO,KAAK,MAAM;AAAA,SACf;AAAA,MACH,OAAO,MAAM;AAAA,SACV;AAAA,MACH,OAAO,IAAI,MAAM;AAAA,SACd;AAAA,MACH,OAAO,IAAI,MAAM,MAAM,IAAI,CAAC,MAAO,OAAO,MAAM,WAAW,IAAI,cAAc,CAAC,CAAE,EAAE,KAAK,EAAE;AAAA,SACtF;AAAA,MACH,OAAO,GAAG,MAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ,MAAM,MAAM,IAAI,aAAa,EAAE,KAAK,EAAE;AAAA,SAC3G;AAAA,MACH,OAAO;AAAA;AAAA;",
8
- "debugId": "96D73CDE1FEDB90164756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BO,SAAS,aAAa,CAAC,OAAsB;AAAA,EAClD,QAAQ,MAAM;AAAA,SACP;AAAA,MACH,OAAO,MAAM;AAAA,SACV;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO,MAAM;AAAA,SACV;AAAA,MACH,OAAO,IAAI,MAAM;AAAA,SACd;AAAA,MACH,OAAO,KAAK,MAAM;AAAA,SACf;AAAA,MACH,OAAO,MAAM;AAAA,SACV;AAAA,MACH,OAAO,IAAI,MAAM;AAAA,SACd;AAAA,MACH,OAAO,IAAI,MAAM,MAAM,IAAI,CAAC,MAAO,OAAO,MAAM,WAAW,IAAI,cAAc,CAAC,CAAE,EAAE,KAAK,EAAE;AAAA,SACtF;AAAA,MACH,OAAO,GAAG,MAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ,MAAM,MAAM,IAAI,aAAa,EAAE,KAAK,EAAE;AAAA,SAC3G;AAAA,MACH,OAAO,KAAK,MAAM,SAAS,QAAQ;AAAA,EAAY,MAAM;AAAA;AAAA,SAClD;AAAA,MACH,OAAO;AAAA;AAAA;",
8
+ "debugId": "CCBBA4DA0434D7BA64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parser/ast.ts"],
4
4
  "sourcesContent": [
5
- "export type RedirectMode =\n | \">\"\n | \">>\"\n | \"<\"\n | \"2>\"\n | \"2>>\"\n | \"&>\"\n | \"&>>\"\n | \"2>&1\"\n | \"1>&2\";\n\nexport interface Redirect {\n mode: RedirectMode;\n target: ASTNode;\n}\n\nexport type ASTNode =\n | CommandNode\n | PipelineNode\n | AndNode\n | OrNode\n | SequenceNode\n | LiteralNode\n | VariableNode\n | SubstitutionNode\n | GlobNode\n | ConcatNode;\n\nexport interface CommandNode {\n type: \"command\";\n name: ASTNode;\n args: ASTNode[];\n redirects: Redirect[];\n assignments: Array<{ name: string; value: ASTNode }>;\n}\n\nexport interface PipelineNode {\n type: \"pipeline\";\n commands: ASTNode[];\n}\n\nexport interface AndNode {\n type: \"and\";\n left: ASTNode;\n right: ASTNode;\n}\n\nexport interface OrNode {\n type: \"or\";\n left: ASTNode;\n right: ASTNode;\n}\n\nexport interface SequenceNode {\n type: \"sequence\";\n commands: ASTNode[];\n}\n\nexport interface LiteralNode {\n type: \"literal\";\n value: string;\n}\n\nexport interface VariableNode {\n type: \"variable\";\n name: string;\n}\n\nexport interface SubstitutionNode {\n type: \"substitution\";\n command: ASTNode;\n}\n\nexport interface GlobNode {\n type: \"glob\";\n pattern: string;\n}\n\nexport interface ConcatNode {\n type: \"concat\";\n parts: ASTNode[];\n}\n\n// Type guards\nexport function isCommandNode(node: ASTNode): node is CommandNode {\n return node.type === \"command\";\n}\n\nexport function isPipelineNode(node: ASTNode): node is PipelineNode {\n return node.type === \"pipeline\";\n}\n\nexport function isAndNode(node: ASTNode): node is AndNode {\n return node.type === \"and\";\n}\n\nexport function isOrNode(node: ASTNode): node is OrNode {\n return node.type === \"or\";\n}\n\nexport function isSequenceNode(node: ASTNode): node is SequenceNode {\n return node.type === \"sequence\";\n}\n\nexport function isLiteralNode(node: ASTNode): node is LiteralNode {\n return node.type === \"literal\";\n}\n\nexport function isVariableNode(node: ASTNode): node is VariableNode {\n return node.type === \"variable\";\n}\n\nexport function isSubstitutionNode(node: ASTNode): node is SubstitutionNode {\n return node.type === \"substitution\";\n}\n\nexport function isGlobNode(node: ASTNode): node is GlobNode {\n return node.type === \"glob\";\n}\n\nexport function isConcatNode(node: ASTNode): node is ConcatNode {\n return node.type === \"concat\";\n}\n"
5
+ "export type RedirectMode =\n | \">\"\n | \">>\"\n | \"<\"\n | \"2>\"\n | \"2>>\"\n | \"&>\"\n | \"&>>\"\n | \"2>&1\"\n | \"1>&2\";\n\nexport interface Redirect {\n mode: RedirectMode;\n target: ASTNode;\n heredocContent?: boolean;\n}\n\nexport type ASTNode =\n | CommandNode\n | PipelineNode\n | AndNode\n | OrNode\n | SequenceNode\n | LiteralNode\n | VariableNode\n | SubstitutionNode\n | GlobNode\n | ConcatNode;\n\nexport interface CommandNode {\n type: \"command\";\n name: ASTNode;\n args: ASTNode[];\n redirects: Redirect[];\n assignments: Array<{ name: string; value: ASTNode }>;\n}\n\nexport interface PipelineNode {\n type: \"pipeline\";\n commands: ASTNode[];\n}\n\nexport interface AndNode {\n type: \"and\";\n left: ASTNode;\n right: ASTNode;\n}\n\nexport interface OrNode {\n type: \"or\";\n left: ASTNode;\n right: ASTNode;\n}\n\nexport interface SequenceNode {\n type: \"sequence\";\n commands: ASTNode[];\n}\n\nexport interface LiteralNode {\n type: \"literal\";\n value: string;\n}\n\nexport interface VariableNode {\n type: \"variable\";\n name: string;\n}\n\nexport interface SubstitutionNode {\n type: \"substitution\";\n command: ASTNode;\n}\n\nexport interface GlobNode {\n type: \"glob\";\n pattern: string;\n}\n\nexport interface ConcatNode {\n type: \"concat\";\n parts: ASTNode[];\n}\n\n// Type guards\nexport function isCommandNode(node: ASTNode): node is CommandNode {\n return node.type === \"command\";\n}\n\nexport function isPipelineNode(node: ASTNode): node is PipelineNode {\n return node.type === \"pipeline\";\n}\n\nexport function isAndNode(node: ASTNode): node is AndNode {\n return node.type === \"and\";\n}\n\nexport function isOrNode(node: ASTNode): node is OrNode {\n return node.type === \"or\";\n}\n\nexport function isSequenceNode(node: ASTNode): node is SequenceNode {\n return node.type === \"sequence\";\n}\n\nexport function isLiteralNode(node: ASTNode): node is LiteralNode {\n return node.type === \"literal\";\n}\n\nexport function isVariableNode(node: ASTNode): node is VariableNode {\n return node.type === \"variable\";\n}\n\nexport function isSubstitutionNode(node: ASTNode): node is SubstitutionNode {\n return node.type === \"substitution\";\n}\n\nexport function isGlobNode(node: ASTNode): node is GlobNode {\n return node.type === \"glob\";\n}\n\nexport function isConcatNode(node: ASTNode): node is ConcatNode {\n return node.type === \"concat\";\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFO,SAAS,aAAa,CAAC,MAAoC;AAAA,EAChE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,cAAc,CAAC,MAAqC;AAAA,EAClE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,SAAS,CAAC,MAAgC;AAAA,EACxD,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,QAAQ,CAAC,MAA+B;AAAA,EACtD,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,cAAc,CAAC,MAAqC;AAAA,EAClE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,aAAa,CAAC,MAAoC;AAAA,EAChE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,cAAc,CAAC,MAAqC;AAAA,EAClE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,kBAAkB,CAAC,MAAyC;AAAA,EAC1E,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,UAAU,CAAC,MAAiC;AAAA,EAC1D,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,YAAY,CAAC,MAAmC;AAAA,EAC9D,OAAO,KAAK,SAAS;AAAA;",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqFO,SAAS,aAAa,CAAC,MAAoC;AAAA,EAChE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,cAAc,CAAC,MAAqC;AAAA,EAClE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,SAAS,CAAC,MAAgC;AAAA,EACxD,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,QAAQ,CAAC,MAA+B;AAAA,EACtD,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,cAAc,CAAC,MAAqC;AAAA,EAClE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,aAAa,CAAC,MAAoC;AAAA,EAChE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,cAAc,CAAC,MAAqC;AAAA,EAClE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,kBAAkB,CAAC,MAAyC;AAAA,EAC1E,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,UAAU,CAAC,MAAiC;AAAA,EAC1D,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,YAAY,CAAC,MAAmC;AAAA,EAC9D,OAAO,KAAK,SAAS;AAAA;",
8
8
  "debugId": "3FCA1CA4C008614B64756E2164756E21",
9
9
  "names": []
10
10
  }