shell-dsl 0.0.39 → 0.0.41
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 +183 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/commands/exit/exit.cjs +84 -0
- package/dist/cjs/src/commands/exit/exit.cjs.map +10 -0
- package/dist/cjs/src/commands/index.cjs +18 -2
- package/dist/cjs/src/commands/index.cjs.map +3 -3
- package/dist/cjs/src/commands/sh/sh.cjs +134 -0
- package/dist/cjs/src/commands/sh/sh.cjs.map +10 -0
- package/dist/cjs/src/index.cjs +9 -1
- package/dist/cjs/src/index.cjs.map +3 -3
- package/dist/cjs/src/input-analysis.cjs +154 -0
- package/dist/cjs/src/input-analysis.cjs.map +10 -0
- package/dist/cjs/src/interpreter/context.cjs +6 -1
- package/dist/cjs/src/interpreter/context.cjs.map +3 -3
- package/dist/cjs/src/interpreter/index.cjs +2 -1
- package/dist/cjs/src/interpreter/index.cjs.map +3 -3
- package/dist/cjs/src/interpreter/interpreter.cjs +434 -82
- package/dist/cjs/src/interpreter/interpreter.cjs.map +3 -3
- package/dist/cjs/src/io/async-queue.cjs +105 -0
- package/dist/cjs/src/io/async-queue.cjs.map +10 -0
- package/dist/cjs/src/io/index.cjs +4 -1
- package/dist/cjs/src/io/index.cjs.map +3 -3
- package/dist/cjs/src/io/input-controller.cjs +113 -0
- package/dist/cjs/src/io/input-controller.cjs.map +10 -0
- package/dist/cjs/src/io/stdout.cjs +9 -6
- package/dist/cjs/src/io/stdout.cjs.map +3 -3
- package/dist/cjs/src/lexer/lexer.cjs +13 -1
- package/dist/cjs/src/lexer/lexer.cjs.map +3 -3
- package/dist/cjs/src/parser/parser.cjs +11 -1
- package/dist/cjs/src/parser/parser.cjs.map +3 -3
- package/dist/cjs/src/shell-dsl.cjs +13 -5
- package/dist/cjs/src/shell-dsl.cjs.map +3 -3
- package/dist/cjs/src/shell-session.cjs +128 -0
- package/dist/cjs/src/shell-session.cjs.map +10 -0
- package/dist/cjs/src/types.cjs.map +2 -2
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/src/commands/exit/exit.mjs +44 -0
- package/dist/mjs/src/commands/exit/exit.mjs.map +10 -0
- package/dist/mjs/src/commands/index.mjs +18 -2
- package/dist/mjs/src/commands/index.mjs.map +3 -3
- package/dist/mjs/src/commands/sh/sh.mjs +94 -0
- package/dist/mjs/src/commands/sh/sh.mjs.map +10 -0
- package/dist/mjs/src/index.mjs +19 -3
- package/dist/mjs/src/index.mjs.map +3 -3
- package/dist/mjs/src/input-analysis.mjs +114 -0
- package/dist/mjs/src/input-analysis.mjs.map +10 -0
- package/dist/mjs/src/interpreter/context.mjs +6 -1
- package/dist/mjs/src/interpreter/context.mjs.map +3 -3
- package/dist/mjs/src/interpreter/index.mjs +3 -2
- package/dist/mjs/src/interpreter/index.mjs.map +2 -2
- package/dist/mjs/src/interpreter/interpreter.mjs +434 -82
- package/dist/mjs/src/interpreter/interpreter.mjs.map +3 -3
- package/dist/mjs/src/io/async-queue.mjs +64 -0
- package/dist/mjs/src/io/async-queue.mjs.map +10 -0
- package/dist/mjs/src/io/index.mjs +4 -1
- package/dist/mjs/src/io/index.mjs.map +3 -3
- package/dist/mjs/src/io/input-controller.mjs +72 -0
- package/dist/mjs/src/io/input-controller.mjs.map +10 -0
- package/dist/mjs/src/io/stdout.mjs +9 -6
- package/dist/mjs/src/io/stdout.mjs.map +3 -3
- package/dist/mjs/src/lexer/lexer.mjs +13 -1
- package/dist/mjs/src/lexer/lexer.mjs.map +3 -3
- package/dist/mjs/src/parser/parser.mjs +11 -1
- package/dist/mjs/src/parser/parser.mjs.map +3 -3
- package/dist/mjs/src/shell-dsl.mjs +13 -5
- package/dist/mjs/src/shell-dsl.mjs.map +3 -3
- package/dist/mjs/src/shell-session.mjs +88 -0
- package/dist/mjs/src/shell-session.mjs.map +10 -0
- package/dist/mjs/src/types.mjs.map +2 -2
- package/dist/types/src/commands/exit/exit.d.ts +2 -0
- package/dist/types/src/commands/index.d.ts +2 -0
- package/dist/types/src/commands/sh/sh.d.ts +5 -0
- package/dist/types/src/index.d.ts +6 -3
- package/dist/types/src/input-analysis.d.ts +14 -0
- package/dist/types/src/interpreter/context.d.ts +4 -1
- package/dist/types/src/interpreter/index.d.ts +1 -1
- package/dist/types/src/interpreter/interpreter.d.ts +36 -1
- package/dist/types/src/io/async-queue.d.ts +12 -0
- package/dist/types/src/io/index.d.ts +1 -0
- package/dist/types/src/io/input-controller.d.ts +15 -0
- package/dist/types/src/io/stdout.d.ts +4 -3
- package/dist/types/src/shell-dsl.d.ts +2 -0
- package/dist/types/src/shell-session.d.ts +23 -0
- package/dist/types/src/types.d.ts +52 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ bun add shell-dsl memfs
|
|
|
33
33
|
- **Virtual filesystem** — Uses memfs for complete isolation from the real filesystem
|
|
34
34
|
- **Real filesystem** — Optional sandboxed access to real files with path containment and permissions
|
|
35
35
|
- **Explicit command registry** — Only registered commands can execute
|
|
36
|
+
- **Executable scripts** — Run virtual-filesystem scripts with `./script`, `sh`, `source`, and shebang dispatch
|
|
36
37
|
- **Automatic escaping** — Interpolated values are escaped by default for safety
|
|
37
38
|
- **POSIX-inspired syntax** — Pipes, redirects, control flow operators, and more
|
|
38
39
|
- **Streaming pipelines** — Commands communicate via async iteration
|
|
@@ -234,6 +235,15 @@ await sh`echo $USER`.text(); // "alice\n"
|
|
|
234
235
|
await sh`echo "Home: $HOME"`.text(); // "Home: /home/alice\n"
|
|
235
236
|
```
|
|
236
237
|
|
|
238
|
+
`$?` expands to the previous command's exit code:
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
await sh`false; echo exit:$?; true; echo ok:$?`.text();
|
|
242
|
+
// "exit:1\nok:0\n"
|
|
243
|
+
|
|
244
|
+
await sh`logs clear backend; restart-backend; echo exit:$?; logs backend 100`;
|
|
245
|
+
```
|
|
246
|
+
|
|
237
247
|
### Quoting Semantics
|
|
238
248
|
|
|
239
249
|
| Quote | Behavior |
|
|
@@ -329,6 +339,72 @@ const myls: Command = async (ctx) => {
|
|
|
329
339
|
};
|
|
330
340
|
```
|
|
331
341
|
|
|
342
|
+
## Streaming Sessions
|
|
343
|
+
|
|
344
|
+
Use `createShellSession()` when you want a stateful, streaming shell runtime for a terminal, agent console, or other UI. A session preserves shell state across runs, including `cwd`, environment changes, and `$?`:
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
import { createShellInput, createShellSession, createVirtualFS } from "shell-dsl";
|
|
348
|
+
import { builtinCommands } from "shell-dsl/commands";
|
|
349
|
+
|
|
350
|
+
const session = createShellSession({
|
|
351
|
+
fs,
|
|
352
|
+
cwd: "/",
|
|
353
|
+
env: {},
|
|
354
|
+
commands: builtinCommands,
|
|
355
|
+
terminal: { isTTY: true, columns: 100, rows: 30 },
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
await session.run("cd /work").exit;
|
|
359
|
+
|
|
360
|
+
const execution = session.run("pwd; echo hello");
|
|
361
|
+
for await (const event of execution.output) {
|
|
362
|
+
const stream = event.fd === 1 ? process.stdout : process.stderr;
|
|
363
|
+
stream.write(event.chunk);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const result = await execution.exit;
|
|
367
|
+
console.log(result.exitCode);
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
For interactive input, create a writable async stdin source:
|
|
371
|
+
|
|
372
|
+
```ts
|
|
373
|
+
const stdin = createShellInput();
|
|
374
|
+
const execution = session.run("cat", { stdin });
|
|
375
|
+
|
|
376
|
+
await stdin.write("hello\n");
|
|
377
|
+
stdin.close();
|
|
378
|
+
await execution.exit;
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Unknown commands can be delegated to a runtime-specific adapter without making shell-dsl spawn processes itself:
|
|
382
|
+
|
|
383
|
+
```ts
|
|
384
|
+
const session = createShellSession({
|
|
385
|
+
fs,
|
|
386
|
+
cwd: "/",
|
|
387
|
+
env: {},
|
|
388
|
+
commands: builtinCommands,
|
|
389
|
+
externalCommand: async (ctx) => {
|
|
390
|
+
await ctx.stderr.writeText(`${ctx.name}: not implemented by this host\n`);
|
|
391
|
+
return 127;
|
|
392
|
+
},
|
|
393
|
+
});
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Use `analyzeInput(source)` before running user-entered text to distinguish complete commands from multiline input such as unclosed quotes, heredocs, trailing pipes, and compound statements.
|
|
397
|
+
|
|
398
|
+
## Terminal Demo
|
|
399
|
+
|
|
400
|
+
This repository includes a Bun-powered terminal demo:
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
bun examples/terminal/shell-cli.ts
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
The CLI process uses `node:readline/promises`, so normal prompt editing such as Ctrl+A, Ctrl+E, arrow-key movement, and history are handled by your terminal/readline layer. Tab completion is served by the executor process and includes registered shell-dsl command names plus paths in the virtual filesystem. The demo spawns `shell-executor.ts` with Bun and exchanges JSON-lines messages over stdio. Full raw PTY behavior for interactive child programs is intentionally left to demo or host runtime code rather than shell-dsl core.
|
|
407
|
+
|
|
332
408
|
## Field Splitting
|
|
333
409
|
|
|
334
410
|
Unquoted parameter, command, and arithmetic expansions follow shell-style word expansion:
|
|
@@ -374,6 +450,101 @@ Nested substitution is supported:
|
|
|
374
450
|
await sh`echo "Files: $(ls $(pwd))"`.text();
|
|
375
451
|
```
|
|
376
452
|
|
|
453
|
+
## Executable Scripts
|
|
454
|
+
|
|
455
|
+
Command names containing `/` are treated as virtual-filesystem script paths when no registered command matches. Scripts run inside shell-dsl, not through the host OS:
|
|
456
|
+
|
|
457
|
+
```ts
|
|
458
|
+
await fs.writeFile("/hello", `
|
|
459
|
+
echo "script: $0"
|
|
460
|
+
echo "args: $1 / $#"
|
|
461
|
+
`.trimStart());
|
|
462
|
+
|
|
463
|
+
await sh`./hello Alice`.text();
|
|
464
|
+
// "script: ./hello\nargs: Alice / 1\n"
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Scripts without a shebang run as shell-dsl scripts. `#!/bin/sh` and `#!/usr/bin/env sh` do the same thing:
|
|
468
|
+
|
|
469
|
+
```ts
|
|
470
|
+
await fs.writeFile("/greet", `
|
|
471
|
+
#!/bin/sh
|
|
472
|
+
echo "Hello, $1"
|
|
473
|
+
`.trimStart());
|
|
474
|
+
|
|
475
|
+
await sh`./greet Alice`.text(); // "Hello, Alice\n"
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
Script execution is subprocess-like: variables and `cd` inside `./script` do not leak back to the caller. Use `source` or `.` when you want the script to mutate the current shell state:
|
|
479
|
+
|
|
480
|
+
```ts
|
|
481
|
+
await fs.writeFile("/env", "NAME=Alice\ncd /work\n");
|
|
482
|
+
|
|
483
|
+
await sh`source ./env; echo "$NAME"; pwd`.text();
|
|
484
|
+
// "Alice\n/work\n"
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### Positional Parameters
|
|
488
|
+
|
|
489
|
+
Scripts and `sh -c` support common shell parameters:
|
|
490
|
+
|
|
491
|
+
| Parameter | Meaning |
|
|
492
|
+
|-----------|---------|
|
|
493
|
+
| `$0` | Script name or `sh -c` argv0 |
|
|
494
|
+
| `$1`, `$2`, ... | Positional arguments |
|
|
495
|
+
| `$#` | Number of positional arguments |
|
|
496
|
+
| `$*` | Positional arguments joined with spaces |
|
|
497
|
+
| `$@` | Positional arguments; quoted `"$@"` expands as separate fields |
|
|
498
|
+
| `$?` | Previous command's exit code |
|
|
499
|
+
|
|
500
|
+
```ts
|
|
501
|
+
await sh`sh -c 'echo "$0:$1:$#"' name value`.text();
|
|
502
|
+
// "name:value:1\n"
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
Scripts can stop with an explicit status via `exit`:
|
|
506
|
+
|
|
507
|
+
```ts
|
|
508
|
+
await fs.writeFile("/restart", "restart-backend\nexit $?\n");
|
|
509
|
+
|
|
510
|
+
const result = await sh`./restart`.nothrow();
|
|
511
|
+
result.exitCode; // restart-backend's exit code
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### Shebang Dispatch
|
|
515
|
+
|
|
516
|
+
Non-`sh` shebangs dispatch to registered commands by interpreter basename. For example, `#!/bin/cat` runs the registered `cat` command with the script path as its first argument:
|
|
517
|
+
|
|
518
|
+
```ts
|
|
519
|
+
await fs.writeFile("/show", "#!/bin/cat\nhello\n");
|
|
520
|
+
await sh`./show`.text(); // "#!/bin/cat\nhello\n"
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
Custom shebangs work the same way:
|
|
524
|
+
|
|
525
|
+
```ts
|
|
526
|
+
const customCommand: Command = async (ctx) => {
|
|
527
|
+
await ctx.stdout.writeText(JSON.stringify(ctx.args) + "\n");
|
|
528
|
+
return 0;
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
const sh = createShellDSL({
|
|
532
|
+
fs,
|
|
533
|
+
cwd: "/",
|
|
534
|
+
env: {},
|
|
535
|
+
commands: { ...builtinCommands, custom_command: customCommand },
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
await fs.writeFile("/run", "#!/bin/custom_command\n");
|
|
539
|
+
await sh`./run arg`.text(); // "[\"./run\",\"arg\"]\n"
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
`#!/bin/bash` is not enabled by default. If you intentionally want that alias, register one explicitly:
|
|
543
|
+
|
|
544
|
+
```ts
|
|
545
|
+
commands: { ...builtinCommands, bash: builtinCommands.sh }
|
|
546
|
+
```
|
|
547
|
+
|
|
377
548
|
## Defining Custom Commands
|
|
378
549
|
|
|
379
550
|
Commands are async functions that receive a `CommandContext` and return an exit code (0 = success):
|
|
@@ -406,6 +577,9 @@ interface CommandContext {
|
|
|
406
577
|
fs: VirtualFS; // Virtual filesystem
|
|
407
578
|
cwd: string; // Current working directory
|
|
408
579
|
env: Record<string, string>; // Environment variables
|
|
580
|
+
setCwd(path: string): void; // Change current working directory
|
|
581
|
+
exec?: (name: string, args: string[]) => Promise<ExecResult>;
|
|
582
|
+
shell?: ShellCommandApi; // Evaluate shell-dsl source from commands
|
|
409
583
|
}
|
|
410
584
|
```
|
|
411
585
|
|
|
@@ -567,7 +741,7 @@ import { builtinCommands } from "shell-dsl/commands";
|
|
|
567
741
|
Or import individually:
|
|
568
742
|
|
|
569
743
|
```ts
|
|
570
|
-
import { echo, printf, cat, grep, wc, cp, mv, touch, tee, tree, find, sed, awk, cut, od } from "shell-dsl/commands";
|
|
744
|
+
import { echo, printf, cat, grep, wc, cp, mv, touch, tee, tree, find, sed, awk, cut, od, sh, evalCmd, source, dot, exitCmd } from "shell-dsl/commands";
|
|
571
745
|
```
|
|
572
746
|
|
|
573
747
|
| Command | Description |
|
|
@@ -595,6 +769,10 @@ import { echo, printf, cat, grep, wc, cp, mv, touch, tee, tree, find, sed, awk,
|
|
|
595
769
|
| `awk` | Pattern scanning (`{print $1}`, `-F`, `NF`, `NR`) |
|
|
596
770
|
| `cut` | Select fields/characters (`-f`, `-d`, `-c`, `-b`, `-s`, `--complement`) |
|
|
597
771
|
| `od` | Dump binary/text data (`-A`, `-t x1/x2/o1/o2/c`, `-j`, `-N`, `-v`) |
|
|
772
|
+
| `sh` | Run shell-dsl source from a file, stdin, or `-c` string |
|
|
773
|
+
| `eval` | Evaluate arguments as shell-dsl source in the current shell state |
|
|
774
|
+
| `source` / `.` | Execute a script in the current shell state |
|
|
775
|
+
| `exit` | Stop the current shell with an optional exit code |
|
|
598
776
|
| `test` / `[` | File and string tests (`-f`, `-d`, `-e`, `-z`, `-n`, `=`, `!=`) |
|
|
599
777
|
| `true` | Exit with code 0 |
|
|
600
778
|
| `false` | Exit with code 1 |
|
|
@@ -948,8 +1126,8 @@ await sh`echo ${{ raw: "$(date)" }}`.text();
|
|
|
948
1126
|
|
|
949
1127
|
1. **No host access** — All commands run in-process against a virtual filesystem
|
|
950
1128
|
2. **Automatic escaping** — Interpolated values are escaped by default
|
|
951
|
-
3. **Explicit command registry** — Only registered commands can execute
|
|
952
|
-
4. **No shell spawning** — Never invokes `/bin/sh` or similar
|
|
1129
|
+
3. **Explicit command registry** — Only registered commands can execute, including shebang-dispatched interpreters
|
|
1130
|
+
4. **No shell spawning** — Never invokes `/bin/sh` or similar; `#!/bin/sh` maps to shell-dsl's in-process `sh`
|
|
953
1131
|
|
|
954
1132
|
The `{ raw: ... }` escape hatch exists for advanced use cases but should be used with extreme caution.
|
|
955
1133
|
|
|
@@ -968,6 +1146,8 @@ import type {
|
|
|
968
1146
|
FileStat,
|
|
969
1147
|
ExecResult,
|
|
970
1148
|
ShellConfig,
|
|
1149
|
+
ShellCommandApi,
|
|
1150
|
+
ShellRunOptions,
|
|
971
1151
|
RawValue,
|
|
972
1152
|
Permission,
|
|
973
1153
|
PermissionRules,
|
package/dist/cjs/package.json
CHANGED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
8
|
+
var __toCommonJS = (from) => {
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
+
if (entry)
|
|
11
|
+
return entry;
|
|
12
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
__moduleCache.set(from, entry);
|
|
22
|
+
return entry;
|
|
23
|
+
};
|
|
24
|
+
var __moduleCache;
|
|
25
|
+
var __returnValue = (v) => v;
|
|
26
|
+
function __exportSetter(name, newValue) {
|
|
27
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
+
}
|
|
29
|
+
var __export = (target, all) => {
|
|
30
|
+
for (var name in all)
|
|
31
|
+
__defProp(target, name, {
|
|
32
|
+
get: all[name],
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
set: __exportSetter.bind(all, name)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/commands/exit/exit.ts
|
|
40
|
+
var exports_exit = {};
|
|
41
|
+
__export(exports_exit, {
|
|
42
|
+
exitCmd: () => exitCmd
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(exports_exit);
|
|
45
|
+
function parseExitCode(value) {
|
|
46
|
+
if (!/^[+-]?\d+$/.test(value)) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return Number(value);
|
|
50
|
+
}
|
|
51
|
+
var exitCmd = async (ctx) => {
|
|
52
|
+
if (!ctx.shell) {
|
|
53
|
+
await ctx.stderr.writeText(`exit: shell control not supported
|
|
54
|
+
`);
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
if (ctx.args.length === 0) {
|
|
58
|
+
ctx.shell.exit(ctx.shell.getLastExitCode());
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
const rawExitCode = ctx.args[0];
|
|
62
|
+
const exitCode = parseExitCode(rawExitCode);
|
|
63
|
+
if (exitCode === null) {
|
|
64
|
+
await ctx.stderr.writeText(`exit: ${rawExitCode}: numeric argument required
|
|
65
|
+
`);
|
|
66
|
+
ctx.shell.exit(2);
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
if (!Number.isFinite(exitCode)) {
|
|
70
|
+
await ctx.stderr.writeText(`exit: ${rawExitCode}: numeric argument required
|
|
71
|
+
`);
|
|
72
|
+
ctx.shell.exit(2);
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
if (ctx.args.length > 1) {
|
|
76
|
+
await ctx.stderr.writeText(`exit: too many arguments
|
|
77
|
+
`);
|
|
78
|
+
return 1;
|
|
79
|
+
}
|
|
80
|
+
ctx.shell.exit(exitCode);
|
|
81
|
+
return 0;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
//# debugId=03868A825C7B459964756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/commands/exit/exit.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Command } from \"../../types.cjs\";\n\nfunction parseExitCode(value: string): number | null {\n if (!/^[+-]?\\d+$/.test(value)) {\n return null;\n }\n return Number(value);\n}\n\nexport const exitCmd: Command = async (ctx) => {\n if (!ctx.shell) {\n await ctx.stderr.writeText(\"exit: shell control not supported\\n\");\n return 1;\n }\n\n if (ctx.args.length === 0) {\n ctx.shell.exit(ctx.shell.getLastExitCode());\n return 0;\n }\n\n const rawExitCode = ctx.args[0]!;\n const exitCode = parseExitCode(rawExitCode);\n if (exitCode === null) {\n await ctx.stderr.writeText(`exit: ${rawExitCode}: numeric argument required\\n`);\n ctx.shell.exit(2);\n return 0;\n }\n\n if (!Number.isFinite(exitCode)) {\n await ctx.stderr.writeText(`exit: ${rawExitCode}: numeric argument required\\n`);\n ctx.shell.exit(2);\n return 0;\n }\n\n if (ctx.args.length > 1) {\n await ctx.stderr.writeText(\"exit: too many arguments\\n\");\n return 1;\n }\n\n ctx.shell.exit(exitCode);\n return 0;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,aAAa,CAAC,OAA8B;AAAA,EACnD,IAAI,CAAC,aAAa,KAAK,KAAK,GAAG;AAAA,IAC7B,OAAO;AAAA,EACT;AAAA,EACA,OAAO,OAAO,KAAK;AAAA;AAGd,IAAM,UAAmB,OAAO,QAAQ;AAAA,EAC7C,IAAI,CAAC,IAAI,OAAO;AAAA,IACd,MAAM,IAAI,OAAO,UAAU;AAAA,CAAqC;AAAA,IAChE,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,IAAI,KAAK,WAAW,GAAG;AAAA,IACzB,IAAI,MAAM,KAAK,IAAI,MAAM,gBAAgB,CAAC;AAAA,IAC1C,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,IAAI,KAAK;AAAA,EAC7B,MAAM,WAAW,cAAc,WAAW;AAAA,EAC1C,IAAI,aAAa,MAAM;AAAA,IACrB,MAAM,IAAI,OAAO,UAAU,SAAS;AAAA,CAA0C;AAAA,IAC9E,IAAI,MAAM,KAAK,CAAC;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,CAAC,OAAO,SAAS,QAAQ,GAAG;AAAA,IAC9B,MAAM,IAAI,OAAO,UAAU,SAAS;AAAA,CAA0C;AAAA,IAC9E,IAAI,MAAM,KAAK,CAAC;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,IAAI,KAAK,SAAS,GAAG;AAAA,IACvB,MAAM,IAAI,OAAO,UAAU;AAAA,CAA4B;AAAA,IACvD,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,MAAM,KAAK,QAAQ;AAAA,EACvB,OAAO;AAAA;",
|
|
8
|
+
"debugId": "03868A825C7B459964756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -48,7 +48,9 @@ __export(exports_commands, {
|
|
|
48
48
|
test: () => import_test.test,
|
|
49
49
|
tee: () => import_tee.tee,
|
|
50
50
|
tail: () => import_tail.tail,
|
|
51
|
+
source: () => import_sh.source,
|
|
51
52
|
sort: () => import_sort.sort,
|
|
53
|
+
sh: () => import_sh.sh,
|
|
52
54
|
sed: () => import_sed.sed,
|
|
53
55
|
rm: () => import_rm.rm,
|
|
54
56
|
pwd: () => import_pwd.pwd,
|
|
@@ -61,7 +63,12 @@ __export(exports_commands, {
|
|
|
61
63
|
grep: () => import_grep.grep,
|
|
62
64
|
find: () => import_find.find,
|
|
63
65
|
falseCmd: () => import_true_false.falseCmd,
|
|
66
|
+
exitCmd: () => import_exit.exitCmd,
|
|
67
|
+
exit: () => import_exit.exitCmd,
|
|
68
|
+
evalCmd: () => import_sh.evalCmd,
|
|
69
|
+
eval: () => import_sh.evalCmd,
|
|
64
70
|
echo: () => import_echo.echo,
|
|
71
|
+
dot: () => import_sh.dot,
|
|
65
72
|
cut: () => import_cut.cut,
|
|
66
73
|
cp: () => import_cp.cp,
|
|
67
74
|
continueCmd: () => import_break_continue.continueCmd,
|
|
@@ -103,6 +110,8 @@ var import_cd = require("./cd/cd.cjs");
|
|
|
103
110
|
var import_tr = require("./tr/tr.cjs");
|
|
104
111
|
var import_cut = require("./cut/cut.cjs");
|
|
105
112
|
var import_od = require("./od/od.cjs");
|
|
113
|
+
var import_sh = require("./sh/sh.cjs");
|
|
114
|
+
var import_exit = require("./exit/exit.cjs");
|
|
106
115
|
var import_echo2 = require("./echo/echo.cjs");
|
|
107
116
|
var import_printf2 = require("./printf/printf.cjs");
|
|
108
117
|
var import_cat2 = require("./cat/cat.cjs");
|
|
@@ -132,6 +141,8 @@ var import_cd2 = require("./cd/cd.cjs");
|
|
|
132
141
|
var import_tr2 = require("./tr/tr.cjs");
|
|
133
142
|
var import_cut2 = require("./cut/cut.cjs");
|
|
134
143
|
var import_od2 = require("./od/od.cjs");
|
|
144
|
+
var import_sh2 = require("./sh/sh.cjs");
|
|
145
|
+
var import_exit2 = require("./exit/exit.cjs");
|
|
135
146
|
var builtinCommands = {
|
|
136
147
|
echo: import_echo2.echo,
|
|
137
148
|
printf: import_printf2.printf,
|
|
@@ -164,7 +175,12 @@ var builtinCommands = {
|
|
|
164
175
|
cd: import_cd2.cd,
|
|
165
176
|
tr: import_tr2.tr,
|
|
166
177
|
cut: import_cut2.cut,
|
|
167
|
-
od: import_od2.od
|
|
178
|
+
od: import_od2.od,
|
|
179
|
+
sh: import_sh2.sh,
|
|
180
|
+
eval: import_sh2.evalCmd,
|
|
181
|
+
source: import_sh2.source,
|
|
182
|
+
".": import_sh2.dot,
|
|
183
|
+
exit: import_exit2.exitCmd
|
|
168
184
|
};
|
|
169
185
|
|
|
170
|
-
//# debugId=
|
|
186
|
+
//# debugId=4755929D925B13DC64756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/commands/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { Command } from \"../types.cjs\";\n\nexport { echo } from \"./echo/echo.cjs\";\nexport { printf } from \"./printf/printf.cjs\";\nexport { cat } from \"./cat/cat.cjs\";\nexport { grep } from \"./grep/grep.cjs\";\nexport { wc } from \"./wc/wc.cjs\";\nexport { head } from \"./head/head.cjs\";\nexport { tail } from \"./tail/tail.cjs\";\nexport { sort } from \"./sort/sort.cjs\";\nexport { uniq } from \"./uniq/uniq.cjs\";\nexport { pwd } from \"./pwd/pwd.cjs\";\nexport { ls } from \"./ls/ls.cjs\";\nexport { mkdir } from \"./mkdir/mkdir.cjs\";\nexport { rm } from \"./rm/rm.cjs\";\nexport { test, bracket } from \"./test/test.cjs\";\nexport { trueCmd, falseCmd } from \"./true-false/true-false.cjs\";\nexport { touch } from \"./touch/touch.cjs\";\nexport { cp } from \"./cp/cp.cjs\";\nexport { mv } from \"./mv/mv.cjs\";\nexport { tee } from \"./tee/tee.cjs\";\nexport { tree } from \"./tree/tree.cjs\";\nexport { find } from \"./find/find.cjs\";\nexport { sed } from \"./sed/sed.cjs\";\nexport { awk } from \"./awk/awk.cjs\";\nexport { breakCmd, continueCmd } from \"./break-continue/break-continue.cjs\";\nexport { colon } from \"./colon/colon.cjs\";\nexport { cd } from \"./cd/cd.cjs\";\nexport { tr } from \"./tr/tr.cjs\";\nexport { cut } from \"./cut/cut.cjs\";\nexport { od } from \"./od/od.cjs\";\n\n// Re-export all commands as a bundle\nimport { echo } from \"./echo/echo.cjs\";\nimport { printf } from \"./printf/printf.cjs\";\nimport { cat } from \"./cat/cat.cjs\";\nimport { grep } from \"./grep/grep.cjs\";\nimport { wc } from \"./wc/wc.cjs\";\nimport { head } from \"./head/head.cjs\";\nimport { tail } from \"./tail/tail.cjs\";\nimport { sort } from \"./sort/sort.cjs\";\nimport { uniq } from \"./uniq/uniq.cjs\";\nimport { pwd } from \"./pwd/pwd.cjs\";\nimport { ls } from \"./ls/ls.cjs\";\nimport { mkdir } from \"./mkdir/mkdir.cjs\";\nimport { rm } from \"./rm/rm.cjs\";\nimport { test, bracket } from \"./test/test.cjs\";\nimport { trueCmd, falseCmd } from \"./true-false/true-false.cjs\";\nimport { touch } from \"./touch/touch.cjs\";\nimport { cp } from \"./cp/cp.cjs\";\nimport { mv } from \"./mv/mv.cjs\";\nimport { tee } from \"./tee/tee.cjs\";\nimport { tree } from \"./tree/tree.cjs\";\nimport { find } from \"./find/find.cjs\";\nimport { sed } from \"./sed/sed.cjs\";\nimport { awk } from \"./awk/awk.cjs\";\nimport { breakCmd, continueCmd } from \"./break-continue/break-continue.cjs\";\nimport { colon } from \"./colon/colon.cjs\";\nimport { cd } from \"./cd/cd.cjs\";\nimport { tr } from \"./tr/tr.cjs\";\nimport { cut } from \"./cut/cut.cjs\";\nimport { od } from \"./od/od.cjs\";\n\nexport const builtinCommands: Record<string, Command> = {\n echo,\n printf,\n cat,\n grep,\n wc,\n head,\n tail,\n sort,\n uniq,\n pwd,\n ls,\n mkdir,\n rm,\n test,\n \"[\": bracket,\n true: trueCmd,\n false: falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n break: breakCmd,\n continue: continueCmd,\n \":\": colon,\n cd,\n tr,\n cut,\n od,\n};\n"
|
|
5
|
+
"import type { Command } from \"../types.cjs\";\n\nexport { echo } from \"./echo/echo.cjs\";\nexport { printf } from \"./printf/printf.cjs\";\nexport { cat } from \"./cat/cat.cjs\";\nexport { grep } from \"./grep/grep.cjs\";\nexport { wc } from \"./wc/wc.cjs\";\nexport { head } from \"./head/head.cjs\";\nexport { tail } from \"./tail/tail.cjs\";\nexport { sort } from \"./sort/sort.cjs\";\nexport { uniq } from \"./uniq/uniq.cjs\";\nexport { pwd } from \"./pwd/pwd.cjs\";\nexport { ls } from \"./ls/ls.cjs\";\nexport { mkdir } from \"./mkdir/mkdir.cjs\";\nexport { rm } from \"./rm/rm.cjs\";\nexport { test, bracket } from \"./test/test.cjs\";\nexport { trueCmd, falseCmd } from \"./true-false/true-false.cjs\";\nexport { touch } from \"./touch/touch.cjs\";\nexport { cp } from \"./cp/cp.cjs\";\nexport { mv } from \"./mv/mv.cjs\";\nexport { tee } from \"./tee/tee.cjs\";\nexport { tree } from \"./tree/tree.cjs\";\nexport { find } from \"./find/find.cjs\";\nexport { sed } from \"./sed/sed.cjs\";\nexport { awk } from \"./awk/awk.cjs\";\nexport { breakCmd, continueCmd } from \"./break-continue/break-continue.cjs\";\nexport { colon } from \"./colon/colon.cjs\";\nexport { cd } from \"./cd/cd.cjs\";\nexport { tr } from \"./tr/tr.cjs\";\nexport { cut } from \"./cut/cut.cjs\";\nexport { od } from \"./od/od.cjs\";\nexport { sh, evalCmd as eval, evalCmd, source, dot } from \"./sh/sh.cjs\";\nexport { exitCmd as exit, exitCmd } from \"./exit/exit.cjs\";\n\n// Re-export all commands as a bundle\nimport { echo } from \"./echo/echo.cjs\";\nimport { printf } from \"./printf/printf.cjs\";\nimport { cat } from \"./cat/cat.cjs\";\nimport { grep } from \"./grep/grep.cjs\";\nimport { wc } from \"./wc/wc.cjs\";\nimport { head } from \"./head/head.cjs\";\nimport { tail } from \"./tail/tail.cjs\";\nimport { sort } from \"./sort/sort.cjs\";\nimport { uniq } from \"./uniq/uniq.cjs\";\nimport { pwd } from \"./pwd/pwd.cjs\";\nimport { ls } from \"./ls/ls.cjs\";\nimport { mkdir } from \"./mkdir/mkdir.cjs\";\nimport { rm } from \"./rm/rm.cjs\";\nimport { test, bracket } from \"./test/test.cjs\";\nimport { trueCmd, falseCmd } from \"./true-false/true-false.cjs\";\nimport { touch } from \"./touch/touch.cjs\";\nimport { cp } from \"./cp/cp.cjs\";\nimport { mv } from \"./mv/mv.cjs\";\nimport { tee } from \"./tee/tee.cjs\";\nimport { tree } from \"./tree/tree.cjs\";\nimport { find } from \"./find/find.cjs\";\nimport { sed } from \"./sed/sed.cjs\";\nimport { awk } from \"./awk/awk.cjs\";\nimport { breakCmd, continueCmd } from \"./break-continue/break-continue.cjs\";\nimport { colon } from \"./colon/colon.cjs\";\nimport { cd } from \"./cd/cd.cjs\";\nimport { tr } from \"./tr/tr.cjs\";\nimport { cut } from \"./cut/cut.cjs\";\nimport { od } from \"./od/od.cjs\";\nimport { sh, evalCmd, source, dot } from \"./sh/sh.cjs\";\nimport { exitCmd } from \"./exit/exit.cjs\";\n\nexport const builtinCommands: Record<string, Command> = {\n echo,\n printf,\n cat,\n grep,\n wc,\n head,\n tail,\n sort,\n uniq,\n pwd,\n ls,\n mkdir,\n rm,\n test,\n \"[\": bracket,\n true: trueCmd,\n false: falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n break: breakCmd,\n continue: continueCmd,\n \":\": colon,\n cd,\n tr,\n cut,\n od,\n sh,\n eval: evalCmd,\n source,\n \".\": dot,\n exit: exitCmd,\n};\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEqB,IAArB;AACuB,IAAvB;AACoB,IAApB;AACqB,IAArB;AACmB,IAAnB;AACqB,IAArB;AACqB,IAArB;AACqB,IAArB;AACqB,IAArB;AACoB,IAApB;AACmB,IAAnB;AACsB,IAAtB;AACmB,IAAnB;AAC8B,IAA9B;AACkC,IAAlC;AACsB,IAAtB;AACmB,IAAnB;AACmB,IAAnB;AACoB,IAApB;AACqB,IAArB;AACqB,IAArB;AACoB,IAApB;AACoB,IAApB;AACsC,IAAtC;AACsB,IAAtB;AACmB,IAAnB;AACmB,IAAnB;AACoB,IAApB;AACmB,IAAnB;AAC0D,IAA1D;AACyC,IAAzC;AAGqB,IAArB;AACuB,IAAvB;AACoB,IAApB;AACqB,IAArB;AACmB,IAAnB;AACqB,IAArB;AACqB,IAArB;AACqB,IAArB;AACqB,IAArB;AACoB,IAApB;AACmB,IAAnB;AACsB,IAAtB;AACmB,IAAnB;AAC8B,IAA9B;AACkC,IAAlC;AACsB,IAAtB;AACmB,IAAnB;AACmB,IAAnB;AACoB,IAApB;AACqB,IAArB;AACqB,IAArB;AACoB,IAApB;AACoB,IAApB;AACsC,IAAtC;AACsB,IAAtB;AACmB,IAAnB;AACmB,IAAnB;AACoB,IAApB;AACmB,IAAnB;AACyC,IAAzC;AACwB,IAAxB;AAEO,IAAM,kBAA2C;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,UAAU;AAAA,EACV,KAAK;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA,KAAK;AAAA,EACL,MAAM;AACR;",
|
|
8
|
+
"debugId": "4755929D925B13DC64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
8
|
+
var __toCommonJS = (from) => {
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
+
if (entry)
|
|
11
|
+
return entry;
|
|
12
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
__moduleCache.set(from, entry);
|
|
22
|
+
return entry;
|
|
23
|
+
};
|
|
24
|
+
var __moduleCache;
|
|
25
|
+
var __returnValue = (v) => v;
|
|
26
|
+
function __exportSetter(name, newValue) {
|
|
27
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
+
}
|
|
29
|
+
var __export = (target, all) => {
|
|
30
|
+
for (var name in all)
|
|
31
|
+
__defProp(target, name, {
|
|
32
|
+
get: all[name],
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
set: __exportSetter.bind(all, name)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/commands/sh/sh.ts
|
|
40
|
+
var exports_sh = {};
|
|
41
|
+
__export(exports_sh, {
|
|
42
|
+
source: () => source,
|
|
43
|
+
sh: () => sh,
|
|
44
|
+
evalCmd: () => evalCmd,
|
|
45
|
+
dot: () => dot
|
|
46
|
+
});
|
|
47
|
+
module.exports = __toCommonJS(exports_sh);
|
|
48
|
+
async function readShellFile(fs, cwd, pathName, stderr) {
|
|
49
|
+
const path = fs.resolve(cwd, pathName);
|
|
50
|
+
if (!await fs.exists(path)) {
|
|
51
|
+
await stderr.writeText(`sh: ${pathName}: No such file or directory
|
|
52
|
+
`);
|
|
53
|
+
return { ok: false, exitCode: 127 };
|
|
54
|
+
}
|
|
55
|
+
const stat = await fs.stat(path);
|
|
56
|
+
if (stat.isDirectory()) {
|
|
57
|
+
await stderr.writeText(`sh: ${pathName}: is a directory
|
|
58
|
+
`);
|
|
59
|
+
return { ok: false, exitCode: 126 };
|
|
60
|
+
}
|
|
61
|
+
if (!stat.isFile()) {
|
|
62
|
+
await stderr.writeText(`sh: ${pathName}: not a file
|
|
63
|
+
`);
|
|
64
|
+
return { ok: false, exitCode: 126 };
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
return { ok: true, source: await fs.readFile(path, "utf-8") };
|
|
68
|
+
} catch (err) {
|
|
69
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
70
|
+
await stderr.writeText(`sh: ${pathName}: ${message}
|
|
71
|
+
`);
|
|
72
|
+
return { ok: false, exitCode: 126 };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
var sh = async (ctx) => {
|
|
76
|
+
if (!ctx.shell) {
|
|
77
|
+
await ctx.stderr.writeText(`sh: shell evaluation not supported
|
|
78
|
+
`);
|
|
79
|
+
return 1;
|
|
80
|
+
}
|
|
81
|
+
if (ctx.args.length === 0) {
|
|
82
|
+
return ctx.shell.runShell(await ctx.stdin.text(), { argv0: "sh", args: [] });
|
|
83
|
+
}
|
|
84
|
+
const first = ctx.args[0];
|
|
85
|
+
if (first === "-c") {
|
|
86
|
+
const source = ctx.args[1];
|
|
87
|
+
if (source === undefined) {
|
|
88
|
+
await ctx.stderr.writeText(`sh: -c requires an argument
|
|
89
|
+
`);
|
|
90
|
+
return 2;
|
|
91
|
+
}
|
|
92
|
+
const argv0 = ctx.args[2] ?? "sh";
|
|
93
|
+
const args = ctx.args[2] === undefined ? [] : ctx.args.slice(3);
|
|
94
|
+
return ctx.shell.runShell(source, { argv0, args });
|
|
95
|
+
}
|
|
96
|
+
if (first.startsWith("-")) {
|
|
97
|
+
await ctx.stderr.writeText(`sh: unsupported option: ${first}
|
|
98
|
+
`);
|
|
99
|
+
return 2;
|
|
100
|
+
}
|
|
101
|
+
const loaded = await readShellFile(ctx.fs, ctx.cwd, first, ctx.stderr);
|
|
102
|
+
if (!loaded.ok) {
|
|
103
|
+
return loaded.exitCode;
|
|
104
|
+
}
|
|
105
|
+
return ctx.shell.runShell(loaded.source, { argv0: first, args: ctx.args.slice(1) });
|
|
106
|
+
};
|
|
107
|
+
var evalCmd = async (ctx) => {
|
|
108
|
+
if (!ctx.shell) {
|
|
109
|
+
await ctx.stderr.writeText(`eval: shell evaluation not supported
|
|
110
|
+
`);
|
|
111
|
+
return 1;
|
|
112
|
+
}
|
|
113
|
+
if (ctx.args.length === 0) {
|
|
114
|
+
return 0;
|
|
115
|
+
}
|
|
116
|
+
return ctx.shell.eval(ctx.args.join(" "));
|
|
117
|
+
};
|
|
118
|
+
var source = async (ctx) => {
|
|
119
|
+
if (!ctx.shell) {
|
|
120
|
+
await ctx.stderr.writeText(`source: shell evaluation not supported
|
|
121
|
+
`);
|
|
122
|
+
return 1;
|
|
123
|
+
}
|
|
124
|
+
const path = ctx.args[0];
|
|
125
|
+
if (path === undefined) {
|
|
126
|
+
await ctx.stderr.writeText(`source: filename argument required
|
|
127
|
+
`);
|
|
128
|
+
return 2;
|
|
129
|
+
}
|
|
130
|
+
return ctx.shell.source(path, ctx.args.slice(1));
|
|
131
|
+
};
|
|
132
|
+
var dot = source;
|
|
133
|
+
|
|
134
|
+
//# debugId=21C185C9E381C0F564756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/commands/sh/sh.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Command, Stderr, VirtualFS } from \"../../types.cjs\";\n\nasync function readShellFile(\n fs: VirtualFS,\n cwd: string,\n pathName: string,\n stderr: Stderr\n): Promise<{ ok: true; source: string } | { ok: false; exitCode: number }> {\n const path = fs.resolve(cwd, pathName);\n\n if (!(await fs.exists(path))) {\n await stderr.writeText(`sh: ${pathName}: No such file or directory\\n`);\n return { ok: false, exitCode: 127 };\n }\n\n const stat = await fs.stat(path);\n if (stat.isDirectory()) {\n await stderr.writeText(`sh: ${pathName}: is a directory\\n`);\n return { ok: false, exitCode: 126 };\n }\n if (!stat.isFile()) {\n await stderr.writeText(`sh: ${pathName}: not a file\\n`);\n return { ok: false, exitCode: 126 };\n }\n\n try {\n return { ok: true, source: await fs.readFile(path, \"utf-8\") };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await stderr.writeText(`sh: ${pathName}: ${message}\\n`);\n return { ok: false, exitCode: 126 };\n }\n}\n\nexport const sh: Command = async (ctx) => {\n if (!ctx.shell) {\n await ctx.stderr.writeText(\"sh: shell evaluation not supported\\n\");\n return 1;\n }\n\n if (ctx.args.length === 0) {\n return ctx.shell.runShell(await ctx.stdin.text(), { argv0: \"sh\", args: [] });\n }\n\n const first = ctx.args[0]!;\n if (first === \"-c\") {\n const source = ctx.args[1];\n if (source === undefined) {\n await ctx.stderr.writeText(\"sh: -c requires an argument\\n\");\n return 2;\n }\n\n const argv0 = ctx.args[2] ?? \"sh\";\n const args = ctx.args[2] === undefined ? [] : ctx.args.slice(3);\n return ctx.shell.runShell(source, { argv0, args });\n }\n\n if (first.startsWith(\"-\")) {\n await ctx.stderr.writeText(`sh: unsupported option: ${first}\\n`);\n return 2;\n }\n\n const loaded = await readShellFile(ctx.fs, ctx.cwd, first, ctx.stderr);\n if (!loaded.ok) {\n return loaded.exitCode;\n }\n\n return ctx.shell.runShell(loaded.source, { argv0: first, args: ctx.args.slice(1) });\n};\n\nexport const evalCmd: Command = async (ctx) => {\n if (!ctx.shell) {\n await ctx.stderr.writeText(\"eval: shell evaluation not supported\\n\");\n return 1;\n }\n if (ctx.args.length === 0) {\n return 0;\n }\n return ctx.shell.eval(ctx.args.join(\" \"));\n};\n\nexport const source: Command = async (ctx) => {\n if (!ctx.shell) {\n await ctx.stderr.writeText(\"source: shell evaluation not supported\\n\");\n return 1;\n }\n const path = ctx.args[0];\n if (path === undefined) {\n await ctx.stderr.writeText(\"source: filename argument required\\n\");\n return 2;\n }\n return ctx.shell.source(path, ctx.args.slice(1));\n};\n\nexport const dot = source;\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,eAAe,aAAa,CAC1B,IACA,KACA,UACA,QACyE;AAAA,EACzE,MAAM,OAAO,GAAG,QAAQ,KAAK,QAAQ;AAAA,EAErC,IAAI,CAAE,MAAM,GAAG,OAAO,IAAI,GAAI;AAAA,IAC5B,MAAM,OAAO,UAAU,OAAO;AAAA,CAAuC;AAAA,IACrE,OAAO,EAAE,IAAI,OAAO,UAAU,IAAI;AAAA,EACpC;AAAA,EAEA,MAAM,OAAO,MAAM,GAAG,KAAK,IAAI;AAAA,EAC/B,IAAI,KAAK,YAAY,GAAG;AAAA,IACtB,MAAM,OAAO,UAAU,OAAO;AAAA,CAA4B;AAAA,IAC1D,OAAO,EAAE,IAAI,OAAO,UAAU,IAAI;AAAA,EACpC;AAAA,EACA,IAAI,CAAC,KAAK,OAAO,GAAG;AAAA,IAClB,MAAM,OAAO,UAAU,OAAO;AAAA,CAAwB;AAAA,IACtD,OAAO,EAAE,IAAI,OAAO,UAAU,IAAI;AAAA,EACpC;AAAA,EAEA,IAAI;AAAA,IACF,OAAO,EAAE,IAAI,MAAM,QAAQ,MAAM,GAAG,SAAS,MAAM,OAAO,EAAE;AAAA,IAC5D,OAAO,KAAK;AAAA,IACZ,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IAC/D,MAAM,OAAO,UAAU,OAAO,aAAa;AAAA,CAAW;AAAA,IACtD,OAAO,EAAE,IAAI,OAAO,UAAU,IAAI;AAAA;AAAA;AAI/B,IAAM,KAAc,OAAO,QAAQ;AAAA,EACxC,IAAI,CAAC,IAAI,OAAO;AAAA,IACd,MAAM,IAAI,OAAO,UAAU;AAAA,CAAsC;AAAA,IACjE,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,IAAI,KAAK,WAAW,GAAG;AAAA,IACzB,OAAO,IAAI,MAAM,SAAS,MAAM,IAAI,MAAM,KAAK,GAAG,EAAE,OAAO,MAAM,MAAM,CAAC,EAAE,CAAC;AAAA,EAC7E;AAAA,EAEA,MAAM,QAAQ,IAAI,KAAK;AAAA,EACvB,IAAI,UAAU,MAAM;AAAA,IAClB,MAAM,SAAS,IAAI,KAAK;AAAA,IACxB,IAAI,WAAW,WAAW;AAAA,MACxB,MAAM,IAAI,OAAO,UAAU;AAAA,CAA+B;AAAA,MAC1D,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,QAAQ,IAAI,KAAK,MAAM;AAAA,IAC7B,MAAM,OAAO,IAAI,KAAK,OAAO,YAAY,CAAC,IAAI,IAAI,KAAK,MAAM,CAAC;AAAA,IAC9D,OAAO,IAAI,MAAM,SAAS,QAAQ,EAAE,OAAO,KAAK,CAAC;AAAA,EACnD;AAAA,EAEA,IAAI,MAAM,WAAW,GAAG,GAAG;AAAA,IACzB,MAAM,IAAI,OAAO,UAAU,2BAA2B;AAAA,CAAS;AAAA,IAC/D,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,MAAM,cAAc,IAAI,IAAI,IAAI,KAAK,OAAO,IAAI,MAAM;AAAA,EACrE,IAAI,CAAC,OAAO,IAAI;AAAA,IACd,OAAO,OAAO;AAAA,EAChB;AAAA,EAEA,OAAO,IAAI,MAAM,SAAS,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,IAAI,KAAK,MAAM,CAAC,EAAE,CAAC;AAAA;AAG7E,IAAM,UAAmB,OAAO,QAAQ;AAAA,EAC7C,IAAI,CAAC,IAAI,OAAO;AAAA,IACd,MAAM,IAAI,OAAO,UAAU;AAAA,CAAwC;AAAA,IACnE,OAAO;AAAA,EACT;AAAA,EACA,IAAI,IAAI,KAAK,WAAW,GAAG;AAAA,IACzB,OAAO;AAAA,EACT;AAAA,EACA,OAAO,IAAI,MAAM,KAAK,IAAI,KAAK,KAAK,GAAG,CAAC;AAAA;AAGnC,IAAM,SAAkB,OAAO,QAAQ;AAAA,EAC5C,IAAI,CAAC,IAAI,OAAO;AAAA,IACd,MAAM,IAAI,OAAO,UAAU;AAAA,CAA0C;AAAA,IACrE,OAAO;AAAA,EACT;AAAA,EACA,MAAM,OAAO,IAAI,KAAK;AAAA,EACtB,IAAI,SAAS,WAAW;AAAA,IACtB,MAAM,IAAI,OAAO,UAAU;AAAA,CAAsC;AAAA,IACjE,OAAO;AAAA,EACT;AAAA,EACA,OAAO,IAAI,MAAM,OAAO,MAAM,IAAI,KAAK,MAAM,CAAC,CAAC;AAAA;AAG1C,IAAM,MAAM;",
|
|
8
|
+
"debugId": "21C185C9E381C0F564756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/dist/cjs/src/index.cjs
CHANGED
|
@@ -62,12 +62,17 @@ __export(exports_src, {
|
|
|
62
62
|
createStdout: () => import_io2.createStdout,
|
|
63
63
|
createStdin: () => import_io.createStdin,
|
|
64
64
|
createStderr: () => import_io2.createStderr,
|
|
65
|
+
createShellSession: () => import_shell_session.createShellSession,
|
|
66
|
+
createShellInput: () => import_io2.createShellInput,
|
|
65
67
|
createShellDSL: () => import_shell_dsl.createShellDSL,
|
|
66
68
|
createPipe: () => import_io2.createPipe,
|
|
69
|
+
analyzeInput: () => import_input_analysis.analyzeInput,
|
|
67
70
|
WebFileSystem: () => import_fs2.WebFileSystem,
|
|
68
71
|
VersionControlSystem: () => import_vcs.VersionControlSystem,
|
|
69
72
|
StdinImpl: () => import_io.StdinImpl,
|
|
73
|
+
ShellSession: () => import_shell_session.ShellSession,
|
|
70
74
|
ShellPromise: () => import_shell_promise.ShellPromise,
|
|
75
|
+
ShellInputControllerImpl: () => import_io2.ShellInputControllerImpl,
|
|
71
76
|
ShellError: () => import_errors.ShellError,
|
|
72
77
|
ShellDSL: () => import_shell_dsl.ShellDSL,
|
|
73
78
|
ReadOnlyFileSystem: () => import_fs2.ReadOnlyFileSystem,
|
|
@@ -79,12 +84,14 @@ __export(exports_src, {
|
|
|
79
84
|
LexError: () => import_errors.LexError,
|
|
80
85
|
Interpreter: () => import_interpreter.Interpreter,
|
|
81
86
|
FileSystem: () => import_fs2.FileSystem,
|
|
87
|
+
ExitException: () => import_interpreter.ExitException,
|
|
82
88
|
ContinueException: () => import_interpreter.ContinueException,
|
|
83
89
|
BreakException: () => import_interpreter.BreakException
|
|
84
90
|
});
|
|
85
91
|
module.exports = __toCommonJS(exports_src);
|
|
86
92
|
var import_shell_dsl = require("./shell-dsl.cjs");
|
|
87
93
|
var import_shell_promise = require("./shell-promise.cjs");
|
|
94
|
+
var import_shell_session = require("./shell-session.cjs");
|
|
88
95
|
var import_types = require("./types.cjs");
|
|
89
96
|
var import_errors = require("./errors.cjs");
|
|
90
97
|
var import_lexer = require("./lexer/index.cjs");
|
|
@@ -95,7 +102,8 @@ var import_fs = require("./fs/index.cjs");
|
|
|
95
102
|
var import_fs2 = require("./fs/index.cjs");
|
|
96
103
|
var import_io = require("./io/index.cjs");
|
|
97
104
|
var import_io2 = require("./io/index.cjs");
|
|
105
|
+
var import_input_analysis = require("./input-analysis.cjs");
|
|
98
106
|
var import_utils = require("./utils/index.cjs");
|
|
99
107
|
var import_vcs = require("./vcs/index.cjs");
|
|
100
108
|
|
|
101
|
-
//# debugId=
|
|
109
|
+
//# debugId=CCA17BE2B94A373E64756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// Main class exports\nexport { ShellDSL, createShellDSL, type Program } from \"./shell-dsl.cjs\";\nexport { ShellPromise, type ShellPromiseOptions } from \"./shell-promise.cjs\";\n\n// Types\nexport type {\n VirtualFS,\n VirtualFSWritable,\n FileStat,\n Command,\n CommandContext,\n Stdin,\n Stdout,\n Stderr,\n OutputCollector,\n ExecResult,\n ShellConfig,\n RawValue,\n} from \"./types.cjs\";\nexport { isRawValue } from \"./types.cjs\";\n\n// Errors\nexport { ShellError, LexError, ParseError } from \"./errors.cjs\";\n\n// Lexer\nexport { Lexer, lex, tokenToString } from \"./lexer/index.cjs\";\nexport type { Token, RedirectMode } from \"./lexer/index.cjs\";\n\n// Parser\nexport { Parser, parse } from \"./parser/index.cjs\";\nexport type {\n ASTNode,\n Redirect,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n WordNode,\n WordPart,\n TextPart,\n VariablePart,\n SubstitutionPart,\n ArithmeticPart,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n} from \"./parser/index.cjs\";\nexport {\n isWordNode,\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isIfNode,\n isForNode,\n isWhileNode,\n isUntilNode,\n isCaseNode,\n} from \"./parser/index.cjs\";\n\n// Interpreter\nexport { Interpreter, type InterpreterOptions, BreakException, ContinueException } from \"./interpreter/index.cjs\";\n\n// Filesystem\nexport { createVirtualFS } from \"./fs/index.cjs\";\nexport {\n FileSystem,\n ReadOnlyFileSystem,\n WebFileSystem,\n createWebUnderlyingFS,\n type PathOps,\n type Permission,\n type PermissionRules,\n type UnderlyingFS,\n} from \"./fs/index.cjs\";\n\n// I/O\nexport { createStdin, StdinImpl } from \"./io/index.cjs\";\nexport {
|
|
5
|
+
"// Main class exports\nexport { ShellDSL, createShellDSL, type Program } from \"./shell-dsl.cjs\";\nexport { ShellPromise, type ShellPromiseOptions } from \"./shell-promise.cjs\";\nexport { ShellSession, createShellSession, type ShellSessionOptions } from \"./shell-session.cjs\";\n\n// Types\nexport type {\n VirtualFS,\n VirtualFSWritable,\n FileStat,\n Command,\n CommandContext,\n Stdin,\n Stdout,\n Stderr,\n OutputCollector,\n ExecResult,\n ShellConfig,\n ShellCommandApi,\n ShellCommandFallback,\n ExternalCommandContext,\n ShellRunOptions,\n TerminalInfo,\n ShellInputController,\n ShellInputSource,\n ShellExecutionOptions,\n ShellExecution,\n ShellOutputEvent,\n RawValue,\n} from \"./types.cjs\";\nexport { isRawValue } from \"./types.cjs\";\n\n// Errors\nexport { ShellError, LexError, ParseError } from \"./errors.cjs\";\n\n// Lexer\nexport { Lexer, lex, tokenToString } from \"./lexer/index.cjs\";\nexport type { Token, RedirectMode } from \"./lexer/index.cjs\";\n\n// Parser\nexport { Parser, parse } from \"./parser/index.cjs\";\nexport type {\n ASTNode,\n Redirect,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n WordNode,\n WordPart,\n TextPart,\n VariablePart,\n SubstitutionPart,\n ArithmeticPart,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n} from \"./parser/index.cjs\";\nexport {\n isWordNode,\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isIfNode,\n isForNode,\n isWhileNode,\n isUntilNode,\n isCaseNode,\n} from \"./parser/index.cjs\";\n\n// Interpreter\nexport { Interpreter, type InterpreterOptions, BreakException, ContinueException, ExitException } from \"./interpreter/index.cjs\";\n\n// Filesystem\nexport { createVirtualFS } from \"./fs/index.cjs\";\nexport {\n FileSystem,\n ReadOnlyFileSystem,\n WebFileSystem,\n createWebUnderlyingFS,\n type PathOps,\n type Permission,\n type PermissionRules,\n type UnderlyingFS,\n} from \"./fs/index.cjs\";\n\n// I/O\nexport { createStdin, StdinImpl } from \"./io/index.cjs\";\nexport {\n createStdout,\n createStderr,\n createPipe,\n createShellInput,\n OutputCollectorImpl,\n PipeBuffer,\n ShellInputControllerImpl,\n} from \"./io/index.cjs\";\n\n// Interactive input analysis\nexport { analyzeInput } from \"./input-analysis.cjs\";\nexport type { InputAnalysis, InputIncompleteReason } from \"./input-analysis.cjs\";\n\n// Utilities\nexport { escape, escapeForInterpolation, globVirtualFS } from \"./utils/index.cjs\";\nexport type { GlobVirtualFS, GlobOptions } from \"./utils/index.cjs\";\n\n// Version Control\nexport { VersionControlSystem } from \"./vcs/index.cjs\";\nexport type {\n VCSConfig,\n VCSAttributeRule,\n VCSResolvedAttributes,\n VCSDiffMode,\n VCSPatchSuppressionReason,\n Revision,\n DiffEntry,\n TreeManifest,\n TreeEntry,\n FileEntry,\n DirectoryEntry,\n VCSIndexEntry,\n VCSIndexFile,\n CommitOptions,\n CheckoutOptions,\n LogOptions,\n LogEntry,\n BranchInfo,\n} from \"./vcs/index.cjs\";\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACuD,IAAvD;AACuD,IAAvD;AAC2E,IAA3E;AA2B2B,IAA3B;AAGiD,IAAjD;AAG0C,IAA1C;AAI8B,IAA9B;AAkCO,IAZP;AAeuG,IAAvG;AAGgC,IAAhC;AAUO,IATP;AAYuC,IAAvC;AASO,IARP;AAW6B,IAA7B;AAI8D,IAA9D;AAIqC,IAArC;",
|
|
8
|
+
"debugId": "CCA17BE2B94A373E64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|