shell-dsl 0.0.6 → 0.0.8
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 +3 -1
- package/dist/cjs/index.cjs +14 -4
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/commands/awk/awk.cjs +276 -0
- package/dist/cjs/src/commands/awk/awk.cjs.map +10 -0
- package/dist/cjs/src/commands/break-continue/break-continue.cjs +56 -0
- package/dist/cjs/src/commands/break-continue/break-continue.cjs.map +10 -0
- package/dist/cjs/src/commands/cat/cat.cjs +57 -0
- package/dist/cjs/src/commands/cat/cat.cjs.map +10 -0
- package/dist/cjs/src/commands/cp/cp.cjs +126 -0
- package/dist/cjs/src/commands/cp/cp.cjs.map +10 -0
- package/dist/cjs/src/commands/echo/echo.cjs +50 -0
- package/dist/cjs/src/commands/echo/echo.cjs.map +10 -0
- package/dist/cjs/src/commands/find/find.cjs +251 -0
- package/dist/cjs/src/commands/find/find.cjs.map +10 -0
- package/dist/cjs/src/commands/grep/grep.cjs +510 -0
- package/dist/cjs/src/commands/grep/grep.cjs.map +10 -0
- package/dist/cjs/src/commands/head/head.cjs +95 -0
- package/dist/cjs/src/commands/head/head.cjs.map +10 -0
- package/dist/cjs/src/commands/index.cjs +136 -0
- package/dist/cjs/src/commands/index.cjs.map +10 -0
- package/dist/cjs/src/commands/ls/ls.cjs +119 -0
- package/dist/cjs/src/commands/ls/ls.cjs.map +10 -0
- package/dist/cjs/src/commands/mkdir/mkdir.cjs +64 -0
- package/dist/cjs/src/commands/mkdir/mkdir.cjs.map +10 -0
- package/dist/cjs/src/commands/mv/mv.cjs +118 -0
- package/dist/cjs/src/commands/mv/mv.cjs.map +10 -0
- package/dist/cjs/src/commands/pwd/pwd.cjs +41 -0
- package/dist/cjs/src/commands/pwd/pwd.cjs.map +10 -0
- package/dist/cjs/src/commands/rm/rm.cjs +82 -0
- package/dist/cjs/src/commands/rm/rm.cjs.map +10 -0
- package/dist/cjs/src/commands/sed/sed.cjs +218 -0
- package/dist/cjs/src/commands/sed/sed.cjs.map +10 -0
- package/dist/cjs/src/commands/sort/sort.cjs +105 -0
- package/dist/cjs/src/commands/sort/sort.cjs.map +10 -0
- package/dist/cjs/src/commands/tail/tail.cjs +95 -0
- package/dist/cjs/src/commands/tail/tail.cjs.map +10 -0
- package/dist/cjs/src/commands/tee/tee.cjs +65 -0
- package/dist/cjs/src/commands/tee/tee.cjs.map +10 -0
- package/dist/cjs/src/commands/test/test.cjs +148 -0
- package/dist/cjs/src/commands/test/test.cjs.map +10 -0
- package/dist/cjs/src/commands/touch/touch.cjs +70 -0
- package/dist/cjs/src/commands/touch/touch.cjs.map +10 -0
- package/dist/cjs/src/commands/tree/tree.cjs +161 -0
- package/dist/cjs/src/commands/tree/tree.cjs.map +10 -0
- package/dist/cjs/src/commands/true-false/true-false.cjs +43 -0
- package/dist/cjs/src/commands/true-false/true-false.cjs.map +10 -0
- package/dist/cjs/src/commands/uniq/uniq.cjs +116 -0
- package/dist/cjs/src/commands/uniq/uniq.cjs.map +10 -0
- package/dist/cjs/src/commands/wc/wc.cjs +116 -0
- package/dist/cjs/src/commands/wc/wc.cjs.map +10 -0
- package/dist/cjs/src/index.cjs +10 -2
- package/dist/cjs/src/index.cjs.map +3 -3
- package/dist/cjs/src/interpreter/index.cjs +4 -2
- package/dist/cjs/src/interpreter/index.cjs.map +3 -3
- package/dist/cjs/src/interpreter/interpreter.cjs +390 -2
- package/dist/cjs/src/interpreter/interpreter.cjs.map +3 -3
- package/dist/cjs/src/lexer/index.cjs +3 -2
- package/dist/cjs/src/lexer/index.cjs.map +3 -3
- package/dist/cjs/src/lexer/lexer.cjs +359 -8
- package/dist/cjs/src/lexer/lexer.cjs.map +3 -3
- package/dist/cjs/src/lexer/tokens.cjs +35 -2
- package/dist/cjs/src/lexer/tokens.cjs.map +3 -3
- package/dist/cjs/src/parser/ast.cjs +25 -1
- package/dist/cjs/src/parser/ast.cjs.map +3 -3
- package/dist/cjs/src/parser/index.cjs +7 -1
- package/dist/cjs/src/parser/index.cjs.map +3 -3
- package/dist/cjs/src/parser/parser.cjs +280 -8
- package/dist/cjs/src/parser/parser.cjs.map +3 -3
- package/dist/cjs/src/shell-dsl.cjs +2 -2
- package/dist/cjs/src/shell-dsl.cjs.map +3 -3
- package/dist/mjs/index.mjs +25 -5
- package/dist/mjs/index.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/src/commands/awk/awk.mjs +246 -0
- package/dist/mjs/src/commands/awk/awk.mjs.map +10 -0
- package/dist/mjs/src/commands/break-continue/break-continue.mjs +26 -0
- package/dist/mjs/src/commands/break-continue/break-continue.mjs.map +10 -0
- package/dist/mjs/src/commands/cat/cat.mjs +27 -0
- package/dist/mjs/src/commands/cat/cat.mjs.map +10 -0
- package/dist/mjs/src/commands/cp/cp.mjs +96 -0
- package/dist/mjs/src/commands/cp/cp.mjs.map +10 -0
- package/dist/mjs/src/commands/echo/echo.mjs +20 -0
- package/dist/mjs/src/commands/echo/echo.mjs.map +10 -0
- package/dist/mjs/src/commands/find/find.mjs +221 -0
- package/dist/mjs/src/commands/find/find.mjs.map +10 -0
- package/dist/mjs/src/commands/grep/grep.mjs +480 -0
- package/dist/mjs/src/commands/grep/grep.mjs.map +10 -0
- package/dist/mjs/src/commands/head/head.mjs +65 -0
- package/dist/mjs/src/commands/head/head.mjs.map +10 -0
- package/dist/mjs/src/commands/index.mjs +106 -0
- package/dist/mjs/src/commands/index.mjs.map +10 -0
- package/dist/mjs/src/commands/ls/ls.mjs +89 -0
- package/dist/mjs/src/commands/ls/ls.mjs.map +10 -0
- package/dist/mjs/src/commands/mkdir/mkdir.mjs +34 -0
- package/dist/mjs/src/commands/mkdir/mkdir.mjs.map +10 -0
- package/dist/mjs/src/commands/mv/mv.mjs +88 -0
- package/dist/mjs/src/commands/mv/mv.mjs.map +10 -0
- package/dist/mjs/src/commands/pwd/pwd.mjs +11 -0
- package/dist/mjs/src/commands/pwd/pwd.mjs.map +10 -0
- package/dist/mjs/src/commands/rm/rm.mjs +52 -0
- package/dist/mjs/src/commands/rm/rm.mjs.map +10 -0
- package/dist/mjs/src/commands/sed/sed.mjs +188 -0
- package/dist/mjs/src/commands/sed/sed.mjs.map +10 -0
- package/dist/mjs/src/commands/sort/sort.mjs +75 -0
- package/dist/mjs/src/commands/sort/sort.mjs.map +10 -0
- package/dist/mjs/src/commands/tail/tail.mjs +65 -0
- package/dist/mjs/src/commands/tail/tail.mjs.map +10 -0
- package/dist/mjs/src/commands/tee/tee.mjs +35 -0
- package/dist/mjs/src/commands/tee/tee.mjs.map +10 -0
- package/dist/mjs/src/commands/test/test.mjs +118 -0
- package/dist/mjs/src/commands/test/test.mjs.map +10 -0
- package/dist/mjs/src/commands/touch/touch.mjs +40 -0
- package/dist/mjs/src/commands/touch/touch.mjs.map +10 -0
- package/dist/mjs/src/commands/tree/tree.mjs +131 -0
- package/dist/mjs/src/commands/tree/tree.mjs.map +10 -0
- package/dist/mjs/src/commands/true-false/true-false.mjs +13 -0
- package/dist/mjs/src/commands/true-false/true-false.mjs.map +10 -0
- package/dist/mjs/src/commands/uniq/uniq.mjs +86 -0
- package/dist/mjs/src/commands/uniq/uniq.mjs.map +10 -0
- package/dist/mjs/src/commands/wc/wc.mjs +86 -0
- package/dist/mjs/src/commands/wc/wc.mjs.map +10 -0
- package/dist/mjs/src/index.mjs +18 -4
- package/dist/mjs/src/index.mjs.map +3 -3
- package/dist/mjs/src/interpreter/index.mjs +5 -3
- package/dist/mjs/src/interpreter/index.mjs.map +2 -2
- package/dist/mjs/src/interpreter/interpreter.mjs +390 -2
- package/dist/mjs/src/interpreter/interpreter.mjs.map +3 -3
- package/dist/mjs/src/lexer/index.mjs +4 -3
- package/dist/mjs/src/lexer/index.mjs.map +2 -2
- package/dist/mjs/src/lexer/lexer.mjs +359 -8
- package/dist/mjs/src/lexer/lexer.mjs.map +3 -3
- package/dist/mjs/src/lexer/tokens.mjs +35 -2
- package/dist/mjs/src/lexer/tokens.mjs.map +3 -3
- package/dist/mjs/src/parser/ast.mjs +25 -1
- package/dist/mjs/src/parser/ast.mjs.map +3 -3
- package/dist/mjs/src/parser/index.mjs +14 -2
- package/dist/mjs/src/parser/index.mjs.map +3 -3
- package/dist/mjs/src/parser/parser.mjs +280 -8
- package/dist/mjs/src/parser/parser.mjs.map +3 -3
- package/dist/mjs/src/shell-dsl.mjs +2 -2
- package/dist/mjs/src/shell-dsl.mjs.map +3 -3
- package/dist/types/index.d.ts +2 -2
- package/dist/types/src/commands/awk/awk.d.ts +2 -0
- package/dist/types/src/commands/break-continue/break-continue.d.ts +3 -0
- package/dist/types/src/commands/cat/cat.d.ts +2 -0
- package/dist/types/src/commands/cp/cp.d.ts +2 -0
- package/dist/types/src/commands/echo/echo.d.ts +2 -0
- package/dist/types/src/commands/find/find.d.ts +2 -0
- package/dist/types/src/commands/grep/grep.d.ts +2 -0
- package/dist/types/src/commands/head/head.d.ts +2 -0
- package/dist/types/src/commands/index.d.ts +25 -0
- package/dist/types/src/commands/ls/ls.d.ts +2 -0
- package/dist/types/src/commands/mkdir/mkdir.d.ts +2 -0
- package/dist/types/src/commands/mv/mv.d.ts +2 -0
- package/dist/types/src/commands/pwd/pwd.d.ts +2 -0
- package/dist/types/src/commands/rm/rm.d.ts +2 -0
- package/dist/types/src/commands/sed/sed.d.ts +2 -0
- package/dist/types/src/commands/sort/sort.d.ts +2 -0
- package/dist/types/src/commands/tail/tail.d.ts +2 -0
- package/dist/types/src/commands/tee/tee.d.ts +2 -0
- package/dist/types/{commands → src/commands/test}/test.d.ts +1 -1
- package/dist/types/src/commands/touch/touch.d.ts +2 -0
- package/dist/types/src/commands/tree/tree.d.ts +2 -0
- package/dist/types/{commands → src/commands/true-false}/true-false.d.ts +1 -1
- package/dist/types/src/commands/uniq/uniq.d.ts +2 -0
- package/dist/types/src/commands/wc/wc.d.ts +2 -0
- package/dist/types/src/index.d.ts +3 -3
- package/dist/types/src/interpreter/index.d.ts +1 -1
- package/dist/types/src/interpreter/interpreter.d.ts +18 -0
- package/dist/types/src/lexer/index.d.ts +2 -2
- package/dist/types/src/lexer/lexer.d.ts +16 -2
- package/dist/types/src/lexer/tokens.d.ts +20 -0
- package/dist/types/src/parser/ast.d.ts +47 -1
- package/dist/types/src/parser/index.d.ts +2 -2
- package/dist/types/src/parser/parser.d.ts +15 -0
- package/package.json +1 -1
- package/dist/types/commands/cat.d.ts +0 -2
- package/dist/types/commands/cp.d.ts +0 -2
- package/dist/types/commands/echo.d.ts +0 -2
- package/dist/types/commands/find.d.ts +0 -2
- package/dist/types/commands/grep.d.ts +0 -2
- package/dist/types/commands/head.d.ts +0 -2
- package/dist/types/commands/index.d.ts +0 -22
- package/dist/types/commands/ls.d.ts +0 -2
- package/dist/types/commands/mkdir.d.ts +0 -2
- package/dist/types/commands/mv.d.ts +0 -2
- package/dist/types/commands/pwd.d.ts +0 -2
- package/dist/types/commands/rm.d.ts +0 -2
- package/dist/types/commands/sort.d.ts +0 -2
- package/dist/types/commands/tail.d.ts +0 -2
- package/dist/types/commands/tee.d.ts +0 -2
- package/dist/types/commands/touch.d.ts +0 -2
- package/dist/types/commands/tree.d.ts +0 -2
- package/dist/types/commands/uniq.d.ts +0 -2
- package/dist/types/commands/wc.d.ts +0 -2
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/shell-dsl.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { ShellConfig, Command, VirtualFS, ExecResult, RedirectObjectMap } from \"./types.mjs\";\nimport { isRawValue, isRedirectObject } from \"./types.mjs\";\nimport type { Token } from \"./lexer/tokens.mjs\";\nimport type { ASTNode } from \"./parser/ast.mjs\";\nimport { Lexer } from \"./lexer/lexer.mjs\";\nimport { Parser } from \"./parser/parser.mjs\";\nimport { Interpreter } from \"./interpreter/interpreter.mjs\";\nimport { ShellPromise } from \"./shell-promise.mjs\";\nimport { escape, escapeForInterpolation } from \"./utils/escape.mjs\";\n\nexport interface Program {\n ast: ASTNode;\n source: string;\n}\n\nexport class ShellDSL {\n private fs: VirtualFS;\n private initialCwd: string;\n private initialEnv: Record<string, string>;\n private currentCwd: string;\n private currentEnv: Record<string, string>;\n private commands: Record<string, Command>;\n private shouldThrow: boolean = true;\n\n constructor(config: ShellConfig) {\n this.fs = config.fs;\n this.initialCwd = config.cwd;\n this.initialEnv = { ...config.env };\n this.currentCwd = config.cwd;\n this.currentEnv = { ...config.env };\n this.commands = config.commands;\n }\n\n // Template tag function\n tag(strings: TemplateStringsArray, ...values: unknown[]): ShellPromise {\n // Build the command string with escaped interpolations\n let source = strings[0] ?? \"\";\n const redirectObjects: RedirectObjectMap = {};\n let objIndex = 0;\n\n for (let i = 0; i < values.length; i++) {\n const value = values[i];\n const precedingString = strings[i] ?? \"\";\n\n if (isRawValue(value)) {\n source += value.raw;\n } else if (this.isRedirectTarget(precedingString, value)) {\n // Value appears after a redirect operator - store as redirect object\n const marker = `__REDIR_OBJ_${objIndex++}__`;\n redirectObjects[marker] = value as Buffer | Blob | Response | string;\n source += marker;\n } else {\n source += escapeForInterpolation(value);\n }\n source += strings[i + 1] ?? \"\";\n }\n\n return this.createPromise(source, { redirectObjects });\n }\n\n private isRedirectTarget(precedingString: string, value: unknown): boolean {\n // Check if value is a redirect object type AND appears after redirect operator\n if (!isRedirectObject(value) || isRawValue(value)) {\n return false;\n }\n // Check if preceding string ends with redirect operator\n const trimmed = precedingString.trimEnd();\n const afterRedirectOp = /(<|>|>>|2>|2>>|&>|&>>)\\s*$/.test(trimmed);\n\n if (!afterRedirectOp) {\n return false;\n }\n\n // Buffer, Blob, Response are always treated as redirect objects\n if (Buffer.isBuffer(value) || value instanceof Blob || value instanceof Response) {\n return true;\n }\n\n // For strings after input redirect (<), treat as content per spec\n // For strings after output redirect (>), they must be Buffers\n if (typeof value === \"string\") {\n // Only input redirection supports string content\n return /<\\s*$/.test(trimmed);\n }\n\n return false;\n }\n\n private createPromise(source: string, options?: { cwd?: string; env?: Record<string, string>; shouldThrow?: boolean; redirectObjects?: RedirectObjectMap }): ShellPromise {\n const shell = this;\n\n return new ShellPromise({\n execute: async (overrides) => {\n const cwd = overrides?.cwd ?? options?.cwd ?? shell.currentCwd;\n const env = { ...shell.currentEnv, ...options?.env, ...overrides?.env };\n\n const interpreter = new Interpreter({\n fs: shell.fs,\n cwd,\n env,\n commands: shell.commands,\n redirectObjects: options?.redirectObjects,\n });\n\n const tokens = shell.lex(source);\n const ast = shell.parse(tokens);\n return interpreter.execute(ast);\n },\n cwdOverride: options?.cwd,\n envOverride: options?.env,\n shouldThrow: options?.shouldThrow ?? this.shouldThrow,\n });\n }\n\n // Global defaults\n cwd(path: string): void {\n this.currentCwd = path;\n }\n\n env(vars: Record<string, string>): void {\n Object.assign(this.currentEnv, vars);\n }\n\n throws(enable: boolean): void {\n this.shouldThrow = enable;\n }\n\n resetCwd(): void {\n this.currentCwd = this.initialCwd;\n }\n\n resetEnv(): void {\n this.currentEnv = { ...this.initialEnv };\n }\n\n // Utility\n escape(str: string): string {\n return escape(str);\n }\n\n // Low-level API\n lex(source: string): Token[] {\n return new Lexer(source).tokenize();\n }\n\n parse(tokens: Token[]): ASTNode {\n return new Parser(tokens).parse();\n }\n\n compile(ast: ASTNode): Program {\n // For now, the \"program\" is just the AST with source reconstruction\n return {\n ast,\n source: \"\", // Could reconstruct source from AST if needed\n };\n }\n\n async run(program: Program): Promise<ExecResult> {\n const interpreter = new Interpreter({\n fs: this.fs,\n cwd: this.currentCwd,\n env: this.currentEnv,\n commands: this.commands,\n });\n\n return interpreter.execute(program.ast);\n }\n}\n\n// Factory function that returns a callable template tag\nexport function createShellDSL(config: ShellConfig): ShellDSL & ((strings: TemplateStringsArray, ...values: unknown[]) => ShellPromise) {\n const shell = new ShellDSL(config);\n\n // Create a function that acts as both tag and shell instance\n const tag = (strings: TemplateStringsArray, ...values: unknown[]) => {\n return shell.tag(strings, ...values);\n };\n\n // Copy all properties and methods from shell to tag function\n Object.setPrototypeOf(tag, ShellDSL.prototype);\n Object.assign(tag, {\n fs: (shell as any).fs,\n initialCwd: (shell as any).initialCwd,\n initialEnv: (shell as any).initialEnv,\n currentCwd: (shell as any).currentCwd,\n currentEnv: (shell as any).currentEnv,\n commands: (shell as any).commands,\n shouldThrow: (shell as any).shouldThrow,\n });\n\n // Bind methods\n (tag as any).cwd = shell.cwd.bind(shell);\n (tag as any).env = shell.env.bind(shell);\n (tag as any).throws = shell.throws.bind(shell);\n (tag as any).resetCwd = shell.resetCwd.bind(shell);\n (tag as any).resetEnv = shell.resetEnv.bind(shell);\n (tag as any).escape = shell.escape.bind(shell);\n (tag as any).lex = shell.lex.bind(shell);\n (tag as any).parse = shell.parse.bind(shell);\n (tag as any).compile = shell.compile.bind(shell);\n (tag as any).run = shell.run.bind(shell);\n (tag as any).tag = shell.tag.bind(shell);\n\n return tag as ShellDSL & ((strings: TemplateStringsArray, ...values: unknown[]) => ShellPromise);\n}\n"
|
|
5
|
+
"import type { ShellConfig, Command, VirtualFS, ExecResult, RedirectObjectMap } from \"./types.mjs\";\nimport { isRawValue, isRedirectObject } from \"./types.mjs\";\nimport type { Token } from \"./lexer/tokens.mjs\";\nimport type { ASTNode } from \"./parser/ast.mjs\";\nimport { Lexer } from \"./lexer/lexer.mjs\";\nimport { Parser } from \"./parser/parser.mjs\";\nimport { Interpreter } from \"./interpreter/interpreter.mjs\";\nimport { ShellPromise } from \"./shell-promise.mjs\";\nimport { escape, escapeForInterpolation } from \"./utils/escape.mjs\";\n\nexport interface Program {\n ast: ASTNode;\n source: string;\n}\n\nexport class ShellDSL {\n private fs: VirtualFS;\n private initialCwd: string;\n private initialEnv: Record<string, string>;\n private currentCwd: string;\n private currentEnv: Record<string, string>;\n private commands: Record<string, Command>;\n private shouldThrow: boolean = true;\n\n constructor(config: ShellConfig) {\n this.fs = config.fs;\n this.initialCwd = config.cwd;\n this.initialEnv = { ...config.env };\n this.currentCwd = config.cwd;\n this.currentEnv = { ...config.env };\n this.commands = config.commands;\n }\n\n // Template tag function\n tag(strings: TemplateStringsArray, ...values: unknown[]): ShellPromise {\n // Build the command string with escaped interpolations\n let source = strings[0] ?? \"\";\n const redirectObjects: RedirectObjectMap = {};\n let objIndex = 0;\n\n for (let i = 0; i < values.length; i++) {\n const value = values[i];\n const precedingString = strings[i] ?? \"\";\n\n if (isRawValue(value)) {\n source += value.raw;\n } else if (this.isRedirectTarget(precedingString, value)) {\n // Value appears after a redirect operator - store as redirect object\n const marker = `__REDIR_OBJ_${objIndex++}__`;\n redirectObjects[marker] = value as Buffer | Blob | Response | string;\n source += marker;\n } else {\n source += escapeForInterpolation(value);\n }\n source += strings[i + 1] ?? \"\";\n }\n\n return this.createPromise(source, { redirectObjects });\n }\n\n private isRedirectTarget(precedingString: string, value: unknown): boolean {\n // Check if value is a redirect object type AND appears after redirect operator\n if (!isRedirectObject(value) || isRawValue(value)) {\n return false;\n }\n // Check if preceding string ends with redirect operator\n const trimmed = precedingString.trimEnd();\n const afterRedirectOp = /(<|>|>>|2>|2>>|&>|&>>)\\s*$/.test(trimmed);\n\n if (!afterRedirectOp) {\n return false;\n }\n\n // Buffer, Blob, Response are always treated as redirect objects\n if (Buffer.isBuffer(value) || value instanceof Blob || value instanceof Response) {\n return true;\n }\n\n // For strings after input redirect (<), treat as content per spec\n // For strings after output redirect (>), they must be Buffers\n if (typeof value === \"string\") {\n // Only input redirection supports string content\n return /<\\s*$/.test(trimmed);\n }\n\n return false;\n }\n\n private createPromise(source: string, options?: { cwd?: string; env?: Record<string, string>; shouldThrow?: boolean; redirectObjects?: RedirectObjectMap }): ShellPromise {\n const shell = this;\n\n return new ShellPromise({\n execute: async (overrides) => {\n const cwd = overrides?.cwd ?? options?.cwd ?? shell.currentCwd;\n const env = { ...shell.currentEnv, ...options?.env, ...overrides?.env };\n\n const interpreter = new Interpreter({\n fs: shell.fs,\n cwd,\n env,\n commands: shell.commands,\n redirectObjects: options?.redirectObjects,\n });\n\n const tokens = shell.lex(source);\n const ast = shell.parse(tokens);\n return interpreter.execute(ast);\n },\n cwdOverride: options?.cwd,\n envOverride: options?.env,\n shouldThrow: options?.shouldThrow ?? this.shouldThrow,\n });\n }\n\n // Global defaults\n cwd(path: string): void {\n this.currentCwd = path;\n }\n\n env(vars: Record<string, string>): void {\n Object.assign(this.currentEnv, vars);\n }\n\n throws(enable: boolean): void {\n this.shouldThrow = enable;\n }\n\n resetCwd(): void {\n this.currentCwd = this.initialCwd;\n }\n\n resetEnv(): void {\n this.currentEnv = { ...this.initialEnv };\n }\n\n // Utility\n escape(str: string): string {\n return escape(str);\n }\n\n // Low-level API\n lex(source: string): Token[] {\n return new Lexer(source, { preserveNewlines: true }).tokenize();\n }\n\n parse(tokens: Token[]): ASTNode {\n return new Parser(tokens).parse();\n }\n\n compile(ast: ASTNode): Program {\n // For now, the \"program\" is just the AST with source reconstruction\n return {\n ast,\n source: \"\", // Could reconstruct source from AST if needed\n };\n }\n\n async run(program: Program): Promise<ExecResult> {\n const interpreter = new Interpreter({\n fs: this.fs,\n cwd: this.currentCwd,\n env: this.currentEnv,\n commands: this.commands,\n });\n\n return interpreter.execute(program.ast);\n }\n}\n\n// Factory function that returns a callable template tag\nexport function createShellDSL(config: ShellConfig): ShellDSL & ((strings: TemplateStringsArray, ...values: unknown[]) => ShellPromise) {\n const shell = new ShellDSL(config);\n\n // Create a function that acts as both tag and shell instance\n const tag = (strings: TemplateStringsArray, ...values: unknown[]) => {\n return shell.tag(strings, ...values);\n };\n\n // Copy all properties and methods from shell to tag function\n Object.setPrototypeOf(tag, ShellDSL.prototype);\n Object.assign(tag, {\n fs: (shell as any).fs,\n initialCwd: (shell as any).initialCwd,\n initialEnv: (shell as any).initialEnv,\n currentCwd: (shell as any).currentCwd,\n currentEnv: (shell as any).currentEnv,\n commands: (shell as any).commands,\n shouldThrow: (shell as any).shouldThrow,\n });\n\n // Bind methods\n (tag as any).cwd = shell.cwd.bind(shell);\n (tag as any).env = shell.env.bind(shell);\n (tag as any).throws = shell.throws.bind(shell);\n (tag as any).resetCwd = shell.resetCwd.bind(shell);\n (tag as any).resetEnv = shell.resetEnv.bind(shell);\n (tag as any).escape = shell.escape.bind(shell);\n (tag as any).lex = shell.lex.bind(shell);\n (tag as any).parse = shell.parse.bind(shell);\n (tag as any).compile = shell.compile.bind(shell);\n (tag as any).run = shell.run.bind(shell);\n (tag as any).tag = shell.tag.bind(shell);\n\n return tag as ShellDSL & ((strings: TemplateStringsArray, ...values: unknown[]) => ShellPromise);\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AACA;AAGA;AACA;AACA;AACA;AACA;AAAA;AAOO,MAAM,SAAS;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAuB;AAAA,EAE/B,WAAW,CAAC,QAAqB;AAAA,IAC/B,KAAK,KAAK,OAAO;AAAA,IACjB,KAAK,aAAa,OAAO;AAAA,IACzB,KAAK,aAAa,KAAK,OAAO,IAAI;AAAA,IAClC,KAAK,aAAa,OAAO;AAAA,IACzB,KAAK,aAAa,KAAK,OAAO,IAAI;AAAA,IAClC,KAAK,WAAW,OAAO;AAAA;AAAA,EAIzB,GAAG,CAAC,YAAkC,QAAiC;AAAA,IAErE,IAAI,SAAS,QAAQ,MAAM;AAAA,IAC3B,MAAM,kBAAqC,CAAC;AAAA,IAC5C,IAAI,WAAW;AAAA,IAEf,SAAS,IAAI,EAAG,IAAI,OAAO,QAAQ,KAAK;AAAA,MACtC,MAAM,QAAQ,OAAO;AAAA,MACrB,MAAM,kBAAkB,QAAQ,MAAM;AAAA,MAEtC,IAAI,WAAW,KAAK,GAAG;AAAA,QACrB,UAAU,MAAM;AAAA,MAClB,EAAO,SAAI,KAAK,iBAAiB,iBAAiB,KAAK,GAAG;AAAA,QAExD,MAAM,SAAS,eAAe;AAAA,QAC9B,gBAAgB,UAAU;AAAA,QAC1B,UAAU;AAAA,MACZ,EAAO;AAAA,QACL,UAAU,uBAAuB,KAAK;AAAA;AAAA,MAExC,UAAU,QAAQ,IAAI,MAAM;AAAA,IAC9B;AAAA,IAEA,OAAO,KAAK,cAAc,QAAQ,EAAE,gBAAgB,CAAC;AAAA;AAAA,EAG/C,gBAAgB,CAAC,iBAAyB,OAAyB;AAAA,IAEzE,IAAI,CAAC,iBAAiB,KAAK,KAAK,WAAW,KAAK,GAAG;AAAA,MACjD,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,UAAU,gBAAgB,QAAQ;AAAA,IACxC,MAAM,kBAAkB,6BAA6B,KAAK,OAAO;AAAA,IAEjE,IAAI,CAAC,iBAAiB;AAAA,MACpB,OAAO;AAAA,IACT;AAAA,IAGA,IAAI,OAAO,SAAS,KAAK,KAAK,iBAAiB,QAAQ,iBAAiB,UAAU;AAAA,MAChF,OAAO;AAAA,IACT;AAAA,IAIA,IAAI,OAAO,UAAU,UAAU;AAAA,MAE7B,OAAO,QAAQ,KAAK,OAAO;AAAA,IAC7B;AAAA,IAEA,OAAO;AAAA;AAAA,EAGD,aAAa,CAAC,QAAgB,SAAoI;AAAA,IACxK,MAAM,QAAQ;AAAA,IAEd,OAAO,IAAI,aAAa;AAAA,MACtB,SAAS,OAAO,cAAc;AAAA,QAC5B,MAAM,MAAM,WAAW,OAAO,SAAS,OAAO,MAAM;AAAA,QACpD,MAAM,MAAM,KAAK,MAAM,eAAe,SAAS,QAAQ,WAAW,IAAI;AAAA,QAEtE,MAAM,cAAc,IAAI,YAAY;AAAA,UAClC,IAAI,MAAM;AAAA,UACV;AAAA,UACA;AAAA,UACA,UAAU,MAAM;AAAA,UAChB,iBAAiB,SAAS;AAAA,QAC5B,CAAC;AAAA,QAED,MAAM,SAAS,MAAM,IAAI,MAAM;AAAA,QAC/B,MAAM,MAAM,MAAM,MAAM,MAAM;AAAA,QAC9B,OAAO,YAAY,QAAQ,GAAG;AAAA;AAAA,MAEhC,aAAa,SAAS;AAAA,MACtB,aAAa,SAAS;AAAA,MACtB,aAAa,SAAS,eAAe,KAAK;AAAA,IAC5C,CAAC;AAAA;AAAA,EAIH,GAAG,CAAC,MAAoB;AAAA,IACtB,KAAK,aAAa;AAAA;AAAA,EAGpB,GAAG,CAAC,MAAoC;AAAA,IACtC,OAAO,OAAO,KAAK,YAAY,IAAI;AAAA;AAAA,EAGrC,MAAM,CAAC,QAAuB;AAAA,IAC5B,KAAK,cAAc;AAAA;AAAA,EAGrB,QAAQ,GAAS;AAAA,IACf,KAAK,aAAa,KAAK;AAAA;AAAA,EAGzB,QAAQ,GAAS;AAAA,IACf,KAAK,aAAa,KAAK,KAAK,WAAW;AAAA;AAAA,EAIzC,MAAM,CAAC,KAAqB;AAAA,IAC1B,OAAO,OAAO,GAAG;AAAA;AAAA,EAInB,GAAG,CAAC,QAAyB;AAAA,IAC3B,OAAO,IAAI,MAAM,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "7846EA9AA40AD9AA64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from "./src/index.ts";
|
|
2
|
-
export { builtinCommands } from "./commands/index.ts";
|
|
3
|
-
export { echo, cat, grep, wc, head, tail, sort, uniq, pwd, ls, mkdir, rm, test, bracket, trueCmd, falseCmd, } from "./commands/index.ts";
|
|
2
|
+
export { builtinCommands } from "./src/commands/index.ts";
|
|
3
|
+
export { echo, cat, grep, wc, head, tail, sort, uniq, pwd, ls, mkdir, rm, test, bracket, trueCmd, falseCmd, touch, cp, mv, tee, tree, find, sed, awk, breakCmd, continueCmd, } from "./src/commands/index.ts";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Command } from "../types.ts";
|
|
2
|
+
export { echo } from "./echo/echo.ts";
|
|
3
|
+
export { cat } from "./cat/cat.ts";
|
|
4
|
+
export { grep } from "./grep/grep.ts";
|
|
5
|
+
export { wc } from "./wc/wc.ts";
|
|
6
|
+
export { head } from "./head/head.ts";
|
|
7
|
+
export { tail } from "./tail/tail.ts";
|
|
8
|
+
export { sort } from "./sort/sort.ts";
|
|
9
|
+
export { uniq } from "./uniq/uniq.ts";
|
|
10
|
+
export { pwd } from "./pwd/pwd.ts";
|
|
11
|
+
export { ls } from "./ls/ls.ts";
|
|
12
|
+
export { mkdir } from "./mkdir/mkdir.ts";
|
|
13
|
+
export { rm } from "./rm/rm.ts";
|
|
14
|
+
export { test, bracket } from "./test/test.ts";
|
|
15
|
+
export { trueCmd, falseCmd } from "./true-false/true-false.ts";
|
|
16
|
+
export { touch } from "./touch/touch.ts";
|
|
17
|
+
export { cp } from "./cp/cp.ts";
|
|
18
|
+
export { mv } from "./mv/mv.ts";
|
|
19
|
+
export { tee } from "./tee/tee.ts";
|
|
20
|
+
export { tree } from "./tree/tree.ts";
|
|
21
|
+
export { find } from "./find/find.ts";
|
|
22
|
+
export { sed } from "./sed/sed.ts";
|
|
23
|
+
export { awk } from "./awk/awk.ts";
|
|
24
|
+
export { breakCmd, continueCmd } from "./break-continue/break-continue.ts";
|
|
25
|
+
export declare const builtinCommands: Record<string, Command>;
|
|
@@ -6,9 +6,9 @@ export { ShellError, LexError, ParseError } from "./errors.ts";
|
|
|
6
6
|
export { Lexer, lex, tokenToString } from "./lexer/index.ts";
|
|
7
7
|
export type { Token, RedirectMode } from "./lexer/index.ts";
|
|
8
8
|
export { Parser, parse } from "./parser/index.ts";
|
|
9
|
-
export type { ASTNode, Redirect, CommandNode, PipelineNode, AndNode, OrNode, SequenceNode, LiteralNode, VariableNode, SubstitutionNode, GlobNode, ConcatNode, } from "./parser/index.ts";
|
|
10
|
-
export { isCommandNode, isPipelineNode, isAndNode, isOrNode, isSequenceNode, isLiteralNode, isVariableNode, isSubstitutionNode, isGlobNode, isConcatNode, } from "./parser/index.ts";
|
|
11
|
-
export { Interpreter, type InterpreterOptions } from "./interpreter/index.ts";
|
|
9
|
+
export type { ASTNode, Redirect, CommandNode, PipelineNode, AndNode, OrNode, SequenceNode, LiteralNode, VariableNode, SubstitutionNode, GlobNode, ConcatNode, IfNode, ForNode, WhileNode, UntilNode, CaseNode, CaseClause, ArithmeticNode, } from "./parser/index.ts";
|
|
10
|
+
export { isCommandNode, isPipelineNode, isAndNode, isOrNode, isSequenceNode, isLiteralNode, isVariableNode, isSubstitutionNode, isGlobNode, isConcatNode, isIfNode, isForNode, isWhileNode, isUntilNode, isCaseNode, isArithmeticNode, } from "./parser/index.ts";
|
|
11
|
+
export { Interpreter, type InterpreterOptions, BreakException, ContinueException } from "./interpreter/index.ts";
|
|
12
12
|
export { createVirtualFS } from "./fs/index.ts";
|
|
13
13
|
export { FileSystem, ReadOnlyFileSystem, type Permission, type PermissionRules, type UnderlyingFS, } from "./fs/index.ts";
|
|
14
14
|
export { createStdin, StdinImpl } from "./io/index.ts";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { Interpreter, type InterpreterOptions } from "./interpreter.ts";
|
|
1
|
+
export { Interpreter, type InterpreterOptions, BreakException, ContinueException } from "./interpreter.ts";
|
|
2
2
|
export { createCommandContext, type ContextOptions } from "./context.ts";
|
|
@@ -7,13 +7,23 @@ export interface InterpreterOptions {
|
|
|
7
7
|
commands: Record<string, Command>;
|
|
8
8
|
redirectObjects?: RedirectObjectMap;
|
|
9
9
|
}
|
|
10
|
+
export declare class BreakException extends Error {
|
|
11
|
+
levels: number;
|
|
12
|
+
constructor(levels?: number);
|
|
13
|
+
}
|
|
14
|
+
export declare class ContinueException extends Error {
|
|
15
|
+
levels: number;
|
|
16
|
+
constructor(levels?: number);
|
|
17
|
+
}
|
|
10
18
|
export declare class Interpreter {
|
|
11
19
|
private fs;
|
|
12
20
|
private cwd;
|
|
13
21
|
private env;
|
|
14
22
|
private commands;
|
|
15
23
|
private redirectObjects;
|
|
24
|
+
private loopDepth;
|
|
16
25
|
constructor(options: InterpreterOptions);
|
|
26
|
+
getLoopDepth(): number;
|
|
17
27
|
execute(ast: ASTNode): Promise<ExecResult>;
|
|
18
28
|
private executeNode;
|
|
19
29
|
private executeCommand;
|
|
@@ -24,7 +34,15 @@ export declare class Interpreter {
|
|
|
24
34
|
private executeSequence;
|
|
25
35
|
private executeAnd;
|
|
26
36
|
private executeOr;
|
|
37
|
+
private executeIf;
|
|
38
|
+
private executeFor;
|
|
39
|
+
private executeWhile;
|
|
40
|
+
private executeUntil;
|
|
41
|
+
private executeCase;
|
|
42
|
+
private matchCasePattern;
|
|
27
43
|
private evaluateNode;
|
|
44
|
+
private evaluateArithmetic;
|
|
45
|
+
private parseArithmeticExpr;
|
|
28
46
|
setCwd(cwd: string): void;
|
|
29
47
|
setEnv(vars: Record<string, string>): void;
|
|
30
48
|
getCwd(): string;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Lexer, lex } from "./lexer.ts";
|
|
2
|
-
export type { Token, RedirectMode } from "./tokens.ts";
|
|
3
|
-
export { tokenToString } from "./tokens.ts";
|
|
2
|
+
export type { Token, RedirectMode, KeywordValue } from "./tokens.ts";
|
|
3
|
+
export { tokenToString, KEYWORDS } from "./tokens.ts";
|
|
@@ -4,21 +4,35 @@ export declare class Lexer {
|
|
|
4
4
|
private pos;
|
|
5
5
|
private line;
|
|
6
6
|
private column;
|
|
7
|
-
|
|
7
|
+
private tokenQueue;
|
|
8
|
+
private preserveNewlines;
|
|
9
|
+
constructor(source: string, options?: {
|
|
10
|
+
preserveNewlines?: boolean;
|
|
11
|
+
});
|
|
8
12
|
tokenize(): Token[];
|
|
9
13
|
private nextToken;
|
|
10
14
|
private readVariable;
|
|
15
|
+
private readUntilDoubleCloseParen;
|
|
11
16
|
private readUntilMatchingParen;
|
|
12
17
|
private readSingleQuote;
|
|
13
18
|
private readDoubleQuote;
|
|
14
19
|
private readWord;
|
|
20
|
+
private readAssignmentValueTokens;
|
|
21
|
+
private parseAssignmentValue;
|
|
22
|
+
private readHeredoc;
|
|
23
|
+
private readHeredocDelimiter;
|
|
24
|
+
private tokenizeRestOfLine;
|
|
25
|
+
private readRestOfLineToken;
|
|
15
26
|
private isWordBreak;
|
|
16
27
|
private isVarChar;
|
|
17
28
|
private skipWhitespace;
|
|
29
|
+
private skipWhitespaceExceptNewlines;
|
|
18
30
|
private skipComment;
|
|
19
31
|
private peek;
|
|
20
32
|
private peekAhead;
|
|
21
33
|
private advance;
|
|
22
34
|
private isAtEnd;
|
|
23
35
|
}
|
|
24
|
-
export declare function lex(source: string
|
|
36
|
+
export declare function lex(source: string, options?: {
|
|
37
|
+
preserveNewlines?: boolean;
|
|
38
|
+
}): Token[];
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export type RedirectMode = ">" | ">>" | "<" | "2>" | "2>>" | "&>" | "&>>" | "2>&1" | "1>&2";
|
|
2
|
+
export type KeywordValue = "if" | "then" | "elif" | "else" | "fi" | "for" | "in" | "do" | "done" | "while" | "until" | "case" | "esac";
|
|
3
|
+
export declare const KEYWORDS: Set<string>;
|
|
2
4
|
export type Token = {
|
|
3
5
|
type: "word";
|
|
4
6
|
value: string;
|
|
7
|
+
} | {
|
|
8
|
+
type: "keyword";
|
|
9
|
+
value: KeywordValue;
|
|
5
10
|
} | {
|
|
6
11
|
type: "pipe";
|
|
7
12
|
} | {
|
|
@@ -10,6 +15,8 @@ export type Token = {
|
|
|
10
15
|
type: "or";
|
|
11
16
|
} | {
|
|
12
17
|
type: "semicolon";
|
|
18
|
+
} | {
|
|
19
|
+
type: "newline";
|
|
13
20
|
} | {
|
|
14
21
|
type: "redirect";
|
|
15
22
|
mode: RedirectMode;
|
|
@@ -19,6 +26,9 @@ export type Token = {
|
|
|
19
26
|
} | {
|
|
20
27
|
type: "substitution";
|
|
21
28
|
command: string;
|
|
29
|
+
} | {
|
|
30
|
+
type: "arithmetic";
|
|
31
|
+
expression: string;
|
|
22
32
|
} | {
|
|
23
33
|
type: "glob";
|
|
24
34
|
pattern: string;
|
|
@@ -32,6 +42,16 @@ export type Token = {
|
|
|
32
42
|
type: "assignment";
|
|
33
43
|
name: string;
|
|
34
44
|
value: string | Token[];
|
|
45
|
+
} | {
|
|
46
|
+
type: "heredoc";
|
|
47
|
+
content: string;
|
|
48
|
+
expand: boolean;
|
|
49
|
+
} | {
|
|
50
|
+
type: "openParen";
|
|
51
|
+
} | {
|
|
52
|
+
type: "closeParen";
|
|
53
|
+
} | {
|
|
54
|
+
type: "doubleSemicolon";
|
|
35
55
|
} | {
|
|
36
56
|
type: "eof";
|
|
37
57
|
};
|
|
@@ -2,8 +2,9 @@ export type RedirectMode = ">" | ">>" | "<" | "2>" | "2>>" | "&>" | "&>>" | "2>&
|
|
|
2
2
|
export interface Redirect {
|
|
3
3
|
mode: RedirectMode;
|
|
4
4
|
target: ASTNode;
|
|
5
|
+
heredocContent?: boolean;
|
|
5
6
|
}
|
|
6
|
-
export type ASTNode = CommandNode | PipelineNode | AndNode | OrNode | SequenceNode | LiteralNode | VariableNode | SubstitutionNode | GlobNode | ConcatNode;
|
|
7
|
+
export type ASTNode = CommandNode | PipelineNode | AndNode | OrNode | SequenceNode | LiteralNode | VariableNode | SubstitutionNode | GlobNode | ConcatNode | IfNode | ForNode | WhileNode | UntilNode | CaseNode | ArithmeticNode;
|
|
7
8
|
export interface CommandNode {
|
|
8
9
|
type: "command";
|
|
9
10
|
name: ASTNode;
|
|
@@ -52,6 +53,45 @@ export interface ConcatNode {
|
|
|
52
53
|
type: "concat";
|
|
53
54
|
parts: ASTNode[];
|
|
54
55
|
}
|
|
56
|
+
export interface IfNode {
|
|
57
|
+
type: "if";
|
|
58
|
+
condition: ASTNode;
|
|
59
|
+
thenBranch: ASTNode;
|
|
60
|
+
elifBranches: Array<{
|
|
61
|
+
condition: ASTNode;
|
|
62
|
+
body: ASTNode;
|
|
63
|
+
}>;
|
|
64
|
+
elseBranch?: ASTNode;
|
|
65
|
+
}
|
|
66
|
+
export interface ForNode {
|
|
67
|
+
type: "for";
|
|
68
|
+
variable: string;
|
|
69
|
+
items: ASTNode[];
|
|
70
|
+
body: ASTNode;
|
|
71
|
+
}
|
|
72
|
+
export interface WhileNode {
|
|
73
|
+
type: "while";
|
|
74
|
+
condition: ASTNode;
|
|
75
|
+
body: ASTNode;
|
|
76
|
+
}
|
|
77
|
+
export interface UntilNode {
|
|
78
|
+
type: "until";
|
|
79
|
+
condition: ASTNode;
|
|
80
|
+
body: ASTNode;
|
|
81
|
+
}
|
|
82
|
+
export interface CaseClause {
|
|
83
|
+
patterns: ASTNode[];
|
|
84
|
+
body: ASTNode;
|
|
85
|
+
}
|
|
86
|
+
export interface CaseNode {
|
|
87
|
+
type: "case";
|
|
88
|
+
word: ASTNode;
|
|
89
|
+
clauses: CaseClause[];
|
|
90
|
+
}
|
|
91
|
+
export interface ArithmeticNode {
|
|
92
|
+
type: "arithmetic";
|
|
93
|
+
expression: string;
|
|
94
|
+
}
|
|
55
95
|
export declare function isCommandNode(node: ASTNode): node is CommandNode;
|
|
56
96
|
export declare function isPipelineNode(node: ASTNode): node is PipelineNode;
|
|
57
97
|
export declare function isAndNode(node: ASTNode): node is AndNode;
|
|
@@ -62,3 +102,9 @@ export declare function isVariableNode(node: ASTNode): node is VariableNode;
|
|
|
62
102
|
export declare function isSubstitutionNode(node: ASTNode): node is SubstitutionNode;
|
|
63
103
|
export declare function isGlobNode(node: ASTNode): node is GlobNode;
|
|
64
104
|
export declare function isConcatNode(node: ASTNode): node is ConcatNode;
|
|
105
|
+
export declare function isIfNode(node: ASTNode): node is IfNode;
|
|
106
|
+
export declare function isForNode(node: ASTNode): node is ForNode;
|
|
107
|
+
export declare function isWhileNode(node: ASTNode): node is WhileNode;
|
|
108
|
+
export declare function isUntilNode(node: ASTNode): node is UntilNode;
|
|
109
|
+
export declare function isCaseNode(node: ASTNode): node is CaseNode;
|
|
110
|
+
export declare function isArithmeticNode(node: ASTNode): node is ArithmeticNode;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Parser, parse } from "./parser.ts";
|
|
2
|
-
export type { ASTNode, Redirect, RedirectMode, CommandNode, PipelineNode, AndNode, OrNode, SequenceNode, LiteralNode, VariableNode, SubstitutionNode, GlobNode, ConcatNode, } from "./ast.ts";
|
|
3
|
-
export { isCommandNode, isPipelineNode, isAndNode, isOrNode, isSequenceNode, isLiteralNode, isVariableNode, isSubstitutionNode, isGlobNode, isConcatNode, } from "./ast.ts";
|
|
2
|
+
export type { ASTNode, Redirect, RedirectMode, CommandNode, PipelineNode, AndNode, OrNode, SequenceNode, LiteralNode, VariableNode, SubstitutionNode, GlobNode, ConcatNode, IfNode, ForNode, WhileNode, UntilNode, CaseNode, CaseClause, ArithmeticNode, } from "./ast.ts";
|
|
3
|
+
export { isCommandNode, isPipelineNode, isAndNode, isOrNode, isSequenceNode, isLiteralNode, isVariableNode, isSubstitutionNode, isGlobNode, isConcatNode, isIfNode, isForNode, isWhileNode, isUntilNode, isCaseNode, isArithmeticNode, } from "./ast.ts";
|
|
@@ -6,12 +6,27 @@ export declare class Parser {
|
|
|
6
6
|
constructor(tokens: Token[]);
|
|
7
7
|
parse(): ASTNode;
|
|
8
8
|
private parseSequence;
|
|
9
|
+
private skipNewlines;
|
|
10
|
+
private isTerminatingKeyword;
|
|
9
11
|
private parseAndOr;
|
|
10
12
|
private parsePipeline;
|
|
13
|
+
private parseCompoundOrCommand;
|
|
14
|
+
private parseIf;
|
|
15
|
+
private parseFor;
|
|
16
|
+
private parseWhile;
|
|
17
|
+
private parseUntil;
|
|
18
|
+
private parseCase;
|
|
19
|
+
private parseCasePattern;
|
|
20
|
+
private parseCaseBody;
|
|
21
|
+
private parseCompoundList;
|
|
22
|
+
private isCompoundListTerminator;
|
|
23
|
+
private checkKeyword;
|
|
24
|
+
private expectKeyword;
|
|
11
25
|
private parseCommand;
|
|
12
26
|
private parseWordArg;
|
|
13
27
|
private tokenToNode;
|
|
14
28
|
private parseDoubleQuoteParts;
|
|
29
|
+
private parseHeredocContent;
|
|
15
30
|
private parseRedirect;
|
|
16
31
|
private isWordToken;
|
|
17
32
|
private check;
|
package/package.json
CHANGED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { Command } from "../src/types.ts";
|
|
2
|
-
export { echo } from "./echo.ts";
|
|
3
|
-
export { cat } from "./cat.ts";
|
|
4
|
-
export { grep } from "./grep.ts";
|
|
5
|
-
export { wc } from "./wc.ts";
|
|
6
|
-
export { head } from "./head.ts";
|
|
7
|
-
export { tail } from "./tail.ts";
|
|
8
|
-
export { sort } from "./sort.ts";
|
|
9
|
-
export { uniq } from "./uniq.ts";
|
|
10
|
-
export { pwd } from "./pwd.ts";
|
|
11
|
-
export { ls } from "./ls.ts";
|
|
12
|
-
export { mkdir } from "./mkdir.ts";
|
|
13
|
-
export { rm } from "./rm.ts";
|
|
14
|
-
export { test, bracket } from "./test.ts";
|
|
15
|
-
export { trueCmd, falseCmd } from "./true-false.ts";
|
|
16
|
-
export { touch } from "./touch.ts";
|
|
17
|
-
export { cp } from "./cp.ts";
|
|
18
|
-
export { mv } from "./mv.ts";
|
|
19
|
-
export { tee } from "./tee.ts";
|
|
20
|
-
export { tree } from "./tree.ts";
|
|
21
|
-
export { find } from "./find.ts";
|
|
22
|
-
export declare const builtinCommands: Record<string, Command>;
|