shell-dsl 0.0.7 → 0.0.9
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 +295 -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 +381 -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 +202 -7
- package/dist/cjs/src/lexer/lexer.cjs.map +3 -3
- package/dist/cjs/src/lexer/tokens.cjs +31 -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 +211 -7
- 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 +265 -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 +381 -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 +202 -7
- package/dist/mjs/src/lexer/lexer.mjs.map +3 -3
- package/dist/mjs/src/lexer/tokens.mjs +31 -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 +211 -7
- 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 +11 -2
- package/dist/types/src/lexer/tokens.d.ts +16 -0
- package/dist/types/src/parser/ast.d.ts +46 -1
- package/dist/types/src/parser/index.d.ts +2 -2
- package/dist/types/src/parser/parser.d.ts +14 -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
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// src/commands/touch/touch.ts
|
|
2
|
+
var touch = async (ctx) => {
|
|
3
|
+
let noCreate = false;
|
|
4
|
+
const files = [];
|
|
5
|
+
for (const arg of ctx.args) {
|
|
6
|
+
if (arg === "-c" || arg === "--no-create") {
|
|
7
|
+
noCreate = true;
|
|
8
|
+
} else if (!arg.startsWith("-")) {
|
|
9
|
+
files.push(arg);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
if (files.length === 0) {
|
|
13
|
+
await ctx.stderr.writeText(`touch: missing file operand
|
|
14
|
+
`);
|
|
15
|
+
return 1;
|
|
16
|
+
}
|
|
17
|
+
for (const file of files) {
|
|
18
|
+
const path = ctx.fs.resolve(ctx.cwd, file);
|
|
19
|
+
try {
|
|
20
|
+
const exists = await ctx.fs.exists(path);
|
|
21
|
+
if (exists) {
|
|
22
|
+
const content = await ctx.fs.readFile(path);
|
|
23
|
+
await ctx.fs.writeFile(path, content);
|
|
24
|
+
} else if (!noCreate) {
|
|
25
|
+
await ctx.fs.writeFile(path, "");
|
|
26
|
+
}
|
|
27
|
+
} catch (err) {
|
|
28
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
29
|
+
await ctx.stderr.writeText(`touch: cannot touch '${file}': ${message}
|
|
30
|
+
`);
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return 0;
|
|
35
|
+
};
|
|
36
|
+
export {
|
|
37
|
+
touch
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
//# debugId=022883A9907704D464756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/commands/touch/touch.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Command } from \"../../types.mjs\";\n\nexport const touch: Command = async (ctx) => {\n let noCreate = false;\n const files: string[] = [];\n\n for (const arg of ctx.args) {\n if (arg === \"-c\" || arg === \"--no-create\") {\n noCreate = true;\n } else if (!arg.startsWith(\"-\")) {\n files.push(arg);\n }\n }\n\n if (files.length === 0) {\n await ctx.stderr.writeText(\"touch: missing file operand\\n\");\n return 1;\n }\n\n for (const file of files) {\n const path = ctx.fs.resolve(ctx.cwd, file);\n try {\n const exists = await ctx.fs.exists(path);\n if (exists) {\n // Update mtime by reading and writing back\n const content = await ctx.fs.readFile(path);\n await ctx.fs.writeFile(path, content);\n } else if (!noCreate) {\n // Create empty file\n await ctx.fs.writeFile(path, \"\");\n }\n // If noCreate and doesn't exist, skip silently\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.stderr.writeText(`touch: cannot touch '${file}': ${message}\\n`);\n return 1;\n }\n }\n\n return 0;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAEO,IAAM,QAAiB,OAAO,QAAQ;AAAA,EAC3C,IAAI,WAAW;AAAA,EACf,MAAM,QAAkB,CAAC;AAAA,EAEzB,WAAW,OAAO,IAAI,MAAM;AAAA,IAC1B,IAAI,QAAQ,QAAQ,QAAQ,eAAe;AAAA,MACzC,WAAW;AAAA,IACb,EAAO,SAAI,CAAC,IAAI,WAAW,GAAG,GAAG;AAAA,MAC/B,MAAM,KAAK,GAAG;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,IAAI,MAAM,WAAW,GAAG;AAAA,IACtB,MAAM,IAAI,OAAO,UAAU;AAAA,CAA+B;AAAA,IAC1D,OAAO;AAAA,EACT;AAAA,EAEA,WAAW,QAAQ,OAAO;AAAA,IACxB,MAAM,OAAO,IAAI,GAAG,QAAQ,IAAI,KAAK,IAAI;AAAA,IACzC,IAAI;AAAA,MACF,MAAM,SAAS,MAAM,IAAI,GAAG,OAAO,IAAI;AAAA,MACvC,IAAI,QAAQ;AAAA,QAEV,MAAM,UAAU,MAAM,IAAI,GAAG,SAAS,IAAI;AAAA,QAC1C,MAAM,IAAI,GAAG,UAAU,MAAM,OAAO;AAAA,MACtC,EAAO,SAAI,CAAC,UAAU;AAAA,QAEpB,MAAM,IAAI,GAAG,UAAU,MAAM,EAAE;AAAA,MACjC;AAAA,MAEA,OAAO,KAAK;AAAA,MACZ,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MAC/D,MAAM,IAAI,OAAO,UAAU,wBAAwB,UAAU;AAAA,CAAW;AAAA,MACxE,OAAO;AAAA;AAAA,EAEX;AAAA,EAEA,OAAO;AAAA;",
|
|
8
|
+
"debugId": "022883A9907704D464756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// src/commands/tree/tree.ts
|
|
2
|
+
var tree = async (ctx) => {
|
|
3
|
+
let showAll = false;
|
|
4
|
+
let directoriesOnly = false;
|
|
5
|
+
let maxDepth = Infinity;
|
|
6
|
+
let targetPath = ".";
|
|
7
|
+
const args = [...ctx.args];
|
|
8
|
+
for (let i = 0;i < args.length; i++) {
|
|
9
|
+
const arg = args[i];
|
|
10
|
+
if (arg === "-a" || arg === "--all") {
|
|
11
|
+
showAll = true;
|
|
12
|
+
} else if (arg === "-d") {
|
|
13
|
+
directoriesOnly = true;
|
|
14
|
+
} else if (arg === "-L") {
|
|
15
|
+
const depthArg = args[++i];
|
|
16
|
+
if (depthArg === undefined || isNaN(parseInt(depthArg, 10))) {
|
|
17
|
+
await ctx.stderr.writeText(`tree: missing argument to -L
|
|
18
|
+
`);
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
maxDepth = parseInt(depthArg, 10);
|
|
22
|
+
if (maxDepth < 1) {
|
|
23
|
+
await ctx.stderr.writeText(`tree: Invalid level, must be greater than 0
|
|
24
|
+
`);
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
|
27
|
+
} else if (arg.startsWith("-L")) {
|
|
28
|
+
const depthStr = arg.slice(2);
|
|
29
|
+
const depth = parseInt(depthStr, 10);
|
|
30
|
+
if (isNaN(depth) || depth < 1) {
|
|
31
|
+
await ctx.stderr.writeText(`tree: Invalid level, must be greater than 0
|
|
32
|
+
`);
|
|
33
|
+
return 1;
|
|
34
|
+
}
|
|
35
|
+
maxDepth = depth;
|
|
36
|
+
} else if (arg.startsWith("-") && arg !== "-") {
|
|
37
|
+
for (const flag of arg.slice(1)) {
|
|
38
|
+
if (flag === "a")
|
|
39
|
+
showAll = true;
|
|
40
|
+
else if (flag === "d")
|
|
41
|
+
directoriesOnly = true;
|
|
42
|
+
else {
|
|
43
|
+
await ctx.stderr.writeText(`tree: Invalid argument -${flag}
|
|
44
|
+
`);
|
|
45
|
+
return 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
targetPath = arg;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const resolvedPath = ctx.fs.resolve(ctx.cwd, targetPath);
|
|
53
|
+
let stat;
|
|
54
|
+
try {
|
|
55
|
+
stat = await ctx.fs.stat(resolvedPath);
|
|
56
|
+
} catch {
|
|
57
|
+
await ctx.stderr.writeText(`tree: ${targetPath}: No such file or directory
|
|
58
|
+
`);
|
|
59
|
+
return 1;
|
|
60
|
+
}
|
|
61
|
+
if (stat.isFile()) {
|
|
62
|
+
await ctx.stdout.writeText(targetPath + `
|
|
63
|
+
|
|
64
|
+
0 directories, 1 file
|
|
65
|
+
`);
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
let dirCount = 0;
|
|
69
|
+
let fileCount = 0;
|
|
70
|
+
await ctx.stdout.writeText(targetPath + `
|
|
71
|
+
`);
|
|
72
|
+
async function printTree(path, prefix, depth) {
|
|
73
|
+
if (depth > maxDepth)
|
|
74
|
+
return;
|
|
75
|
+
let entries = await ctx.fs.readdir(path);
|
|
76
|
+
if (!showAll) {
|
|
77
|
+
entries = entries.filter((e) => !e.startsWith("."));
|
|
78
|
+
}
|
|
79
|
+
entries.sort();
|
|
80
|
+
const dirEntries = [];
|
|
81
|
+
const fileEntries = [];
|
|
82
|
+
for (const entry of entries) {
|
|
83
|
+
const entryPath = ctx.fs.resolve(path, entry);
|
|
84
|
+
try {
|
|
85
|
+
const entryStat = await ctx.fs.stat(entryPath);
|
|
86
|
+
if (entryStat.isDirectory()) {
|
|
87
|
+
dirEntries.push(entry);
|
|
88
|
+
} else {
|
|
89
|
+
fileEntries.push(entry);
|
|
90
|
+
}
|
|
91
|
+
} catch {}
|
|
92
|
+
}
|
|
93
|
+
const sortedEntries = directoriesOnly ? dirEntries : [...dirEntries, ...fileEntries];
|
|
94
|
+
for (let i = 0;i < sortedEntries.length; i++) {
|
|
95
|
+
const entry = sortedEntries[i];
|
|
96
|
+
const isLast = i === sortedEntries.length - 1;
|
|
97
|
+
const connector = isLast ? "└── " : "├── ";
|
|
98
|
+
const entryPath = ctx.fs.resolve(path, entry);
|
|
99
|
+
let isDir = false;
|
|
100
|
+
try {
|
|
101
|
+
const entryStat = await ctx.fs.stat(entryPath);
|
|
102
|
+
isDir = entryStat.isDirectory();
|
|
103
|
+
} catch {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
await ctx.stdout.writeText(prefix + connector + entry + `
|
|
107
|
+
`);
|
|
108
|
+
if (isDir) {
|
|
109
|
+
dirCount++;
|
|
110
|
+
if (depth < maxDepth) {
|
|
111
|
+
const newPrefix = prefix + (isLast ? " " : "│ ");
|
|
112
|
+
await printTree(entryPath, newPrefix, depth + 1);
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
fileCount++;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
await printTree(resolvedPath, "", 1);
|
|
120
|
+
const dirWord = dirCount === 1 ? "directory" : "directories";
|
|
121
|
+
const fileWord = fileCount === 1 ? "file" : "files";
|
|
122
|
+
await ctx.stdout.writeText(`
|
|
123
|
+
${dirCount} ${dirWord}, ${fileCount} ${fileWord}
|
|
124
|
+
`);
|
|
125
|
+
return 0;
|
|
126
|
+
};
|
|
127
|
+
export {
|
|
128
|
+
tree
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
//# debugId=226DC5A2B9E71D1764756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/commands/tree/tree.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Command } from \"../../types.mjs\";\n\nexport const tree: Command = async (ctx) => {\n let showAll = false;\n let directoriesOnly = false;\n let maxDepth = Infinity;\n let targetPath = \".\";\n\n // Parse arguments\n const args = [...ctx.args];\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === \"-a\" || arg === \"--all\") {\n showAll = true;\n } else if (arg === \"-d\") {\n directoriesOnly = true;\n } else if (arg === \"-L\") {\n const depthArg = args[++i];\n if (depthArg === undefined || isNaN(parseInt(depthArg, 10))) {\n await ctx.stderr.writeText(\"tree: missing argument to -L\\n\");\n return 1;\n }\n maxDepth = parseInt(depthArg, 10);\n if (maxDepth < 1) {\n await ctx.stderr.writeText(\"tree: Invalid level, must be greater than 0\\n\");\n return 1;\n }\n } else if (arg.startsWith(\"-L\")) {\n // Handle -L2 format (no space)\n const depthStr = arg.slice(2);\n const depth = parseInt(depthStr, 10);\n if (isNaN(depth) || depth < 1) {\n await ctx.stderr.writeText(\"tree: Invalid level, must be greater than 0\\n\");\n return 1;\n }\n maxDepth = depth;\n } else if (arg.startsWith(\"-\") && arg !== \"-\") {\n // Handle combined short flags\n for (const flag of arg.slice(1)) {\n if (flag === \"a\") showAll = true;\n else if (flag === \"d\") directoriesOnly = true;\n else {\n await ctx.stderr.writeText(`tree: Invalid argument -${flag}\\n`);\n return 1;\n }\n }\n } else {\n targetPath = arg;\n }\n }\n\n const resolvedPath = ctx.fs.resolve(ctx.cwd, targetPath);\n\n // Check if path exists\n let stat;\n try {\n stat = await ctx.fs.stat(resolvedPath);\n } catch {\n await ctx.stderr.writeText(`tree: ${targetPath}: No such file or directory\\n`);\n return 1;\n }\n\n // If it's a file, just print the filename\n if (stat.isFile()) {\n await ctx.stdout.writeText(targetPath + \"\\n\\n0 directories, 1 file\\n\");\n return 0;\n }\n\n let dirCount = 0;\n let fileCount = 0;\n\n // Print root\n await ctx.stdout.writeText(targetPath + \"\\n\");\n\n // Recursive function to build tree\n async function printTree(path: string, prefix: string, depth: number): Promise<void> {\n if (depth > maxDepth) return;\n\n let entries = await ctx.fs.readdir(path);\n\n // Filter hidden files unless -a\n if (!showAll) {\n entries = entries.filter((e) => !e.startsWith(\".\"));\n }\n\n // Sort entries\n entries.sort();\n\n // Separate dirs and files, dirs first\n const dirEntries: string[] = [];\n const fileEntries: string[] = [];\n\n for (const entry of entries) {\n const entryPath = ctx.fs.resolve(path, entry);\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n if (entryStat.isDirectory()) {\n dirEntries.push(entry);\n } else {\n fileEntries.push(entry);\n }\n } catch {\n // Skip entries we can't stat\n }\n }\n\n // Combine: directories first, then files (unless directoriesOnly)\n const sortedEntries = directoriesOnly\n ? dirEntries\n : [...dirEntries, ...fileEntries];\n\n for (let i = 0; i < sortedEntries.length; i++) {\n const entry = sortedEntries[i]!;\n const isLast = i === sortedEntries.length - 1;\n const connector = isLast ? \"└── \" : \"├── \";\n const entryPath = ctx.fs.resolve(path, entry);\n\n let isDir = false;\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n isDir = entryStat.isDirectory();\n } catch {\n continue;\n }\n\n await ctx.stdout.writeText(prefix + connector + entry + \"\\n\");\n\n if (isDir) {\n dirCount++;\n if (depth < maxDepth) {\n const newPrefix = prefix + (isLast ? \" \" : \"│ \");\n await printTree(entryPath, newPrefix, depth + 1);\n }\n } else {\n fileCount++;\n }\n }\n }\n\n await printTree(resolvedPath, \"\", 1);\n\n // Print summary\n const dirWord = dirCount === 1 ? \"directory\" : \"directories\";\n const fileWord = fileCount === 1 ? \"file\" : \"files\";\n await ctx.stdout.writeText(`\\n${dirCount} ${dirWord}, ${fileCount} ${fileWord}\\n`);\n\n return 0;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "226DC5A2B9E71D1764756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/commands/true-false/true-false.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Command } from \"../../types.mjs\";\n\nexport const trueCmd: Command = async () => {\n return 0;\n};\n\nexport const falseCmd: Command = async () => {\n return 1;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAEO,IAAM,UAAmB,YAAY;AAAA,EAC1C,OAAO;AAAA;AAGF,IAAM,WAAoB,YAAY;AAAA,EAC3C,OAAO;AAAA;",
|
|
8
|
+
"debugId": "7B305164589F4D3464756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// src/commands/uniq/uniq.ts
|
|
2
|
+
var uniq = async (ctx) => {
|
|
3
|
+
let countMode = false;
|
|
4
|
+
let duplicatesOnly = false;
|
|
5
|
+
let uniqueOnly = false;
|
|
6
|
+
const files = [];
|
|
7
|
+
for (const arg of ctx.args) {
|
|
8
|
+
if (arg === "-c") {
|
|
9
|
+
countMode = true;
|
|
10
|
+
} else if (arg === "-d") {
|
|
11
|
+
duplicatesOnly = true;
|
|
12
|
+
} else if (arg === "-u") {
|
|
13
|
+
uniqueOnly = true;
|
|
14
|
+
} else if (arg.startsWith("-")) {
|
|
15
|
+
for (const flag of arg.slice(1)) {
|
|
16
|
+
if (flag === "c")
|
|
17
|
+
countMode = true;
|
|
18
|
+
else if (flag === "d")
|
|
19
|
+
duplicatesOnly = true;
|
|
20
|
+
else if (flag === "u")
|
|
21
|
+
uniqueOnly = true;
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
files.push(arg);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
let lines = [];
|
|
28
|
+
if (files.length === 0) {
|
|
29
|
+
for await (const line of ctx.stdin.lines()) {
|
|
30
|
+
lines.push(line);
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
const file = files[0];
|
|
34
|
+
try {
|
|
35
|
+
const path = ctx.fs.resolve(ctx.cwd, file);
|
|
36
|
+
const content = (await ctx.fs.readFile(path)).toString();
|
|
37
|
+
lines = content.split(`
|
|
38
|
+
`);
|
|
39
|
+
if (lines[lines.length - 1] === "") {
|
|
40
|
+
lines.pop();
|
|
41
|
+
}
|
|
42
|
+
} catch (err) {
|
|
43
|
+
await ctx.stderr.writeText(`uniq: ${file}: No such file or directory
|
|
44
|
+
`);
|
|
45
|
+
return 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const results = [];
|
|
49
|
+
let currentLine = null;
|
|
50
|
+
let currentCount = 0;
|
|
51
|
+
for (const line of lines) {
|
|
52
|
+
if (line === currentLine) {
|
|
53
|
+
currentCount++;
|
|
54
|
+
} else {
|
|
55
|
+
if (currentLine !== null) {
|
|
56
|
+
results.push({ line: currentLine, count: currentCount });
|
|
57
|
+
}
|
|
58
|
+
currentLine = line;
|
|
59
|
+
currentCount = 1;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (currentLine !== null) {
|
|
63
|
+
results.push({ line: currentLine, count: currentCount });
|
|
64
|
+
}
|
|
65
|
+
for (const { line, count } of results) {
|
|
66
|
+
const isDuplicate = count > 1;
|
|
67
|
+
const isUnique = count === 1;
|
|
68
|
+
if (duplicatesOnly && !isDuplicate)
|
|
69
|
+
continue;
|
|
70
|
+
if (uniqueOnly && !isUnique)
|
|
71
|
+
continue;
|
|
72
|
+
if (countMode) {
|
|
73
|
+
await ctx.stdout.writeText(`${String(count).padStart(7)} ${line}
|
|
74
|
+
`);
|
|
75
|
+
} else {
|
|
76
|
+
await ctx.stdout.writeText(line + `
|
|
77
|
+
`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return 0;
|
|
81
|
+
};
|
|
82
|
+
export {
|
|
83
|
+
uniq
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
//# debugId=7EE1149CCDA4E33564756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/commands/uniq/uniq.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Command } from \"../../types.mjs\";\n\nexport const uniq: Command = async (ctx) => {\n let countMode = false;\n let duplicatesOnly = false;\n let uniqueOnly = false;\n const files: string[] = [];\n\n // Parse arguments\n for (const arg of ctx.args) {\n if (arg === \"-c\") {\n countMode = true;\n } else if (arg === \"-d\") {\n duplicatesOnly = true;\n } else if (arg === \"-u\") {\n uniqueOnly = true;\n } else if (arg.startsWith(\"-\")) {\n for (const flag of arg.slice(1)) {\n if (flag === \"c\") countMode = true;\n else if (flag === \"d\") duplicatesOnly = true;\n else if (flag === \"u\") uniqueOnly = true;\n }\n } else {\n files.push(arg);\n }\n }\n\n let lines: string[] = [];\n\n if (files.length === 0) {\n for await (const line of ctx.stdin.lines()) {\n lines.push(line);\n }\n } else {\n const file = files[0]!;\n try {\n const path = ctx.fs.resolve(ctx.cwd, file);\n const content = (await ctx.fs.readFile(path)).toString();\n lines = content.split(\"\\n\");\n if (lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n } catch (err) {\n await ctx.stderr.writeText(`uniq: ${file}: No such file or directory\\n`);\n return 1;\n }\n }\n\n // Process lines\n const results: Array<{ line: string; count: number }> = [];\n let currentLine: string | null = null;\n let currentCount = 0;\n\n for (const line of lines) {\n if (line === currentLine) {\n currentCount++;\n } else {\n if (currentLine !== null) {\n results.push({ line: currentLine, count: currentCount });\n }\n currentLine = line;\n currentCount = 1;\n }\n }\n if (currentLine !== null) {\n results.push({ line: currentLine, count: currentCount });\n }\n\n // Output\n for (const { line, count } of results) {\n const isDuplicate = count > 1;\n const isUnique = count === 1;\n\n if (duplicatesOnly && !isDuplicate) continue;\n if (uniqueOnly && !isUnique) continue;\n\n if (countMode) {\n await ctx.stdout.writeText(`${String(count).padStart(7)} ${line}\\n`);\n } else {\n await ctx.stdout.writeText(line + \"\\n\");\n }\n }\n\n return 0;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAEO,IAAM,OAAgB,OAAO,QAAQ;AAAA,EAC1C,IAAI,YAAY;AAAA,EAChB,IAAI,iBAAiB;AAAA,EACrB,IAAI,aAAa;AAAA,EACjB,MAAM,QAAkB,CAAC;AAAA,EAGzB,WAAW,OAAO,IAAI,MAAM;AAAA,IAC1B,IAAI,QAAQ,MAAM;AAAA,MAChB,YAAY;AAAA,IACd,EAAO,SAAI,QAAQ,MAAM;AAAA,MACvB,iBAAiB;AAAA,IACnB,EAAO,SAAI,QAAQ,MAAM;AAAA,MACvB,aAAa;AAAA,IACf,EAAO,SAAI,IAAI,WAAW,GAAG,GAAG;AAAA,MAC9B,WAAW,QAAQ,IAAI,MAAM,CAAC,GAAG;AAAA,QAC/B,IAAI,SAAS;AAAA,UAAK,YAAY;AAAA,QACzB,SAAI,SAAS;AAAA,UAAK,iBAAiB;AAAA,QACnC,SAAI,SAAS;AAAA,UAAK,aAAa;AAAA,MACtC;AAAA,IACF,EAAO;AAAA,MACL,MAAM,KAAK,GAAG;AAAA;AAAA,EAElB;AAAA,EAEA,IAAI,QAAkB,CAAC;AAAA,EAEvB,IAAI,MAAM,WAAW,GAAG;AAAA,IACtB,iBAAiB,QAAQ,IAAI,MAAM,MAAM,GAAG;AAAA,MAC1C,MAAM,KAAK,IAAI;AAAA,IACjB;AAAA,EACF,EAAO;AAAA,IACL,MAAM,OAAO,MAAM;AAAA,IACnB,IAAI;AAAA,MACF,MAAM,OAAO,IAAI,GAAG,QAAQ,IAAI,KAAK,IAAI;AAAA,MACzC,MAAM,WAAW,MAAM,IAAI,GAAG,SAAS,IAAI,GAAG,SAAS;AAAA,MACvD,QAAQ,QAAQ,MAAM;AAAA,CAAI;AAAA,MAC1B,IAAI,MAAM,MAAM,SAAS,OAAO,IAAI;AAAA,QAClC,MAAM,IAAI;AAAA,MACZ;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,MAAM,IAAI,OAAO,UAAU,SAAS;AAAA,CAAmC;AAAA,MACvE,OAAO;AAAA;AAAA;AAAA,EAKX,MAAM,UAAkD,CAAC;AAAA,EACzD,IAAI,cAA6B;AAAA,EACjC,IAAI,eAAe;AAAA,EAEnB,WAAW,QAAQ,OAAO;AAAA,IACxB,IAAI,SAAS,aAAa;AAAA,MACxB;AAAA,IACF,EAAO;AAAA,MACL,IAAI,gBAAgB,MAAM;AAAA,QACxB,QAAQ,KAAK,EAAE,MAAM,aAAa,OAAO,aAAa,CAAC;AAAA,MACzD;AAAA,MACA,cAAc;AAAA,MACd,eAAe;AAAA;AAAA,EAEnB;AAAA,EACA,IAAI,gBAAgB,MAAM;AAAA,IACxB,QAAQ,KAAK,EAAE,MAAM,aAAa,OAAO,aAAa,CAAC;AAAA,EACzD;AAAA,EAGA,aAAa,MAAM,WAAW,SAAS;AAAA,IACrC,MAAM,cAAc,QAAQ;AAAA,IAC5B,MAAM,WAAW,UAAU;AAAA,IAE3B,IAAI,kBAAkB,CAAC;AAAA,MAAa;AAAA,IACpC,IAAI,cAAc,CAAC;AAAA,MAAU;AAAA,IAE7B,IAAI,WAAW;AAAA,MACb,MAAM,IAAI,OAAO,UAAU,GAAG,OAAO,KAAK,EAAE,SAAS,CAAC,KAAK;AAAA,CAAQ;AAAA,IACrE,EAAO;AAAA,MACL,MAAM,IAAI,OAAO,UAAU,OAAO;AAAA,CAAI;AAAA;AAAA,EAE1C;AAAA,EAEA,OAAO;AAAA;",
|
|
8
|
+
"debugId": "7EE1149CCDA4E33564756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// src/commands/wc/wc.ts
|
|
2
|
+
var wc = async (ctx) => {
|
|
3
|
+
let showLines = false;
|
|
4
|
+
let showWords = false;
|
|
5
|
+
let showChars = false;
|
|
6
|
+
const files = [];
|
|
7
|
+
for (const arg of ctx.args) {
|
|
8
|
+
if (arg === "-l") {
|
|
9
|
+
showLines = true;
|
|
10
|
+
} else if (arg === "-w") {
|
|
11
|
+
showWords = true;
|
|
12
|
+
} else if (arg === "-c" || arg === "-m") {
|
|
13
|
+
showChars = true;
|
|
14
|
+
} else if (arg.startsWith("-")) {
|
|
15
|
+
for (const flag of arg.slice(1)) {
|
|
16
|
+
if (flag === "l")
|
|
17
|
+
showLines = true;
|
|
18
|
+
else if (flag === "w")
|
|
19
|
+
showWords = true;
|
|
20
|
+
else if (flag === "c" || flag === "m")
|
|
21
|
+
showChars = true;
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
files.push(arg);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!showLines && !showWords && !showChars) {
|
|
28
|
+
showLines = true;
|
|
29
|
+
showWords = true;
|
|
30
|
+
showChars = true;
|
|
31
|
+
}
|
|
32
|
+
const countContent = (content) => {
|
|
33
|
+
const lines = content.split(`
|
|
34
|
+
`).length - (content.endsWith(`
|
|
35
|
+
`) ? 1 : 0);
|
|
36
|
+
const words = content.split(/\s+/).filter((w) => w.length > 0).length;
|
|
37
|
+
const chars = content.length;
|
|
38
|
+
return { lines, words, chars };
|
|
39
|
+
};
|
|
40
|
+
const formatOutput = (counts, filename) => {
|
|
41
|
+
const parts = [];
|
|
42
|
+
if (showLines)
|
|
43
|
+
parts.push(String(counts.lines).padStart(8));
|
|
44
|
+
if (showWords)
|
|
45
|
+
parts.push(String(counts.words).padStart(8));
|
|
46
|
+
if (showChars)
|
|
47
|
+
parts.push(String(counts.chars).padStart(8));
|
|
48
|
+
if (filename)
|
|
49
|
+
parts.push(" " + filename);
|
|
50
|
+
return parts.join("") + `
|
|
51
|
+
`;
|
|
52
|
+
};
|
|
53
|
+
if (files.length === 0) {
|
|
54
|
+
const content = await ctx.stdin.text();
|
|
55
|
+
const counts = countContent(content);
|
|
56
|
+
await ctx.stdout.writeText(formatOutput(counts));
|
|
57
|
+
} else {
|
|
58
|
+
let totalLines = 0;
|
|
59
|
+
let totalWords = 0;
|
|
60
|
+
let totalChars = 0;
|
|
61
|
+
for (const file of files) {
|
|
62
|
+
try {
|
|
63
|
+
const path = ctx.fs.resolve(ctx.cwd, file);
|
|
64
|
+
const content = (await ctx.fs.readFile(path)).toString();
|
|
65
|
+
const counts = countContent(content);
|
|
66
|
+
totalLines += counts.lines;
|
|
67
|
+
totalWords += counts.words;
|
|
68
|
+
totalChars += counts.chars;
|
|
69
|
+
await ctx.stdout.writeText(formatOutput(counts, file));
|
|
70
|
+
} catch (err) {
|
|
71
|
+
await ctx.stderr.writeText(`wc: ${file}: No such file or directory
|
|
72
|
+
`);
|
|
73
|
+
return 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (files.length > 1) {
|
|
77
|
+
await ctx.stdout.writeText(formatOutput({ lines: totalLines, words: totalWords, chars: totalChars }, "total"));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return 0;
|
|
81
|
+
};
|
|
82
|
+
export {
|
|
83
|
+
wc
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
//# debugId=F4DC48F530142E6764756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/commands/wc/wc.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Command } from \"../../types.mjs\";\n\nexport const wc: Command = async (ctx) => {\n let showLines = false;\n let showWords = false;\n let showChars = false;\n const files: string[] = [];\n\n // Parse arguments\n for (const arg of ctx.args) {\n if (arg === \"-l\") {\n showLines = true;\n } else if (arg === \"-w\") {\n showWords = true;\n } else if (arg === \"-c\" || arg === \"-m\") {\n showChars = true;\n } else if (arg.startsWith(\"-\")) {\n // Handle combined flags\n for (const flag of arg.slice(1)) {\n if (flag === \"l\") showLines = true;\n else if (flag === \"w\") showWords = true;\n else if (flag === \"c\" || flag === \"m\") showChars = true;\n }\n } else {\n files.push(arg);\n }\n }\n\n // Default: show all\n if (!showLines && !showWords && !showChars) {\n showLines = true;\n showWords = true;\n showChars = true;\n }\n\n const countContent = (content: string) => {\n const lines = content.split(\"\\n\").length - (content.endsWith(\"\\n\") ? 1 : 0);\n const words = content.split(/\\s+/).filter((w) => w.length > 0).length;\n const chars = content.length;\n return { lines, words, chars };\n };\n\n const formatOutput = (counts: { lines: number; words: number; chars: number }, filename?: string) => {\n const parts: string[] = [];\n if (showLines) parts.push(String(counts.lines).padStart(8));\n if (showWords) parts.push(String(counts.words).padStart(8));\n if (showChars) parts.push(String(counts.chars).padStart(8));\n if (filename) parts.push(\" \" + filename);\n return parts.join(\"\") + \"\\n\";\n };\n\n if (files.length === 0) {\n // Read from stdin\n const content = await ctx.stdin.text();\n const counts = countContent(content);\n await ctx.stdout.writeText(formatOutput(counts));\n } else {\n let totalLines = 0;\n let totalWords = 0;\n let totalChars = 0;\n\n for (const file of files) {\n try {\n const path = ctx.fs.resolve(ctx.cwd, file);\n const content = (await ctx.fs.readFile(path)).toString();\n const counts = countContent(content);\n totalLines += counts.lines;\n totalWords += counts.words;\n totalChars += counts.chars;\n await ctx.stdout.writeText(formatOutput(counts, file));\n } catch (err) {\n await ctx.stderr.writeText(`wc: ${file}: No such file or directory\\n`);\n return 1;\n }\n }\n\n if (files.length > 1) {\n await ctx.stdout.writeText(\n formatOutput({ lines: totalLines, words: totalWords, chars: totalChars }, \"total\")\n );\n }\n }\n\n return 0;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "F4DC48F530142E6764756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/dist/mjs/src/index.mjs
CHANGED
|
@@ -15,9 +15,15 @@ import {
|
|
|
15
15
|
isVariableNode,
|
|
16
16
|
isSubstitutionNode,
|
|
17
17
|
isGlobNode,
|
|
18
|
-
isConcatNode
|
|
18
|
+
isConcatNode,
|
|
19
|
+
isIfNode,
|
|
20
|
+
isForNode,
|
|
21
|
+
isWhileNode,
|
|
22
|
+
isUntilNode,
|
|
23
|
+
isCaseNode,
|
|
24
|
+
isArithmeticNode
|
|
19
25
|
} from "./parser/index.mjs";
|
|
20
|
-
import { Interpreter } from "./interpreter/index.mjs";
|
|
26
|
+
import { Interpreter, BreakException, ContinueException } from "./interpreter/index.mjs";
|
|
21
27
|
import { createVirtualFS } from "./fs/index.mjs";
|
|
22
28
|
import {
|
|
23
29
|
FileSystem,
|
|
@@ -30,16 +36,22 @@ export {
|
|
|
30
36
|
tokenToString,
|
|
31
37
|
parse,
|
|
32
38
|
lex,
|
|
39
|
+
isWhileNode,
|
|
33
40
|
isVariableNode,
|
|
41
|
+
isUntilNode,
|
|
34
42
|
isSubstitutionNode,
|
|
35
43
|
isSequenceNode,
|
|
36
44
|
isRawValue,
|
|
37
45
|
isPipelineNode,
|
|
38
46
|
isOrNode,
|
|
39
47
|
isLiteralNode,
|
|
48
|
+
isIfNode,
|
|
40
49
|
isGlobNode,
|
|
50
|
+
isForNode,
|
|
41
51
|
isConcatNode,
|
|
42
52
|
isCommandNode,
|
|
53
|
+
isCaseNode,
|
|
54
|
+
isArithmeticNode,
|
|
43
55
|
isAndNode,
|
|
44
56
|
escapeForInterpolation,
|
|
45
57
|
escape,
|
|
@@ -61,7 +73,9 @@ export {
|
|
|
61
73
|
Lexer,
|
|
62
74
|
LexError,
|
|
63
75
|
Interpreter,
|
|
64
|
-
FileSystem
|
|
76
|
+
FileSystem,
|
|
77
|
+
ContinueException,
|
|
78
|
+
BreakException
|
|
65
79
|
};
|
|
66
80
|
|
|
67
|
-
//# debugId=
|
|
81
|
+
//# debugId=0CC96BD5A2BCA29264756E2164756E21
|
|
@@ -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.mjs\";\nexport { ShellPromise, type ShellPromiseOptions } from \"./shell-promise.mjs\";\n\n// Types\nexport type {\n VirtualFS,\n FileStat,\n Command,\n CommandContext,\n Stdin,\n Stdout,\n Stderr,\n OutputCollector,\n ExecResult,\n ShellConfig,\n RawValue,\n} from \"./types.mjs\";\nexport { isRawValue } from \"./types.mjs\";\n\n// Errors\nexport { ShellError, LexError, ParseError } from \"./errors.mjs\";\n\n// Lexer\nexport { Lexer, lex, tokenToString } from \"./lexer/index.mjs\";\nexport type { Token, RedirectMode } from \"./lexer/index.mjs\";\n\n// Parser\nexport { Parser, parse } from \"./parser/index.mjs\";\nexport type {\n ASTNode,\n Redirect,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n LiteralNode,\n VariableNode,\n SubstitutionNode,\n GlobNode,\n ConcatNode,\n} from \"./parser/index.mjs\";\nexport {\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isLiteralNode,\n isVariableNode,\n isSubstitutionNode,\n isGlobNode,\n isConcatNode,\n} from \"./parser/index.mjs\";\n\n// Interpreter\nexport { Interpreter, type InterpreterOptions } from \"./interpreter/index.mjs\";\n\n// Filesystem\nexport { createVirtualFS } from \"./fs/index.mjs\";\nexport {\n FileSystem,\n ReadOnlyFileSystem,\n type Permission,\n type PermissionRules,\n type UnderlyingFS,\n} from \"./fs/index.mjs\";\n\n// I/O\nexport { createStdin, StdinImpl } from \"./io/index.mjs\";\nexport { createStdout, createStderr, createPipe, OutputCollectorImpl, PipeBuffer } from \"./io/index.mjs\";\n\n// Utilities\nexport { escape, escapeForInterpolation } from \"./utils/index.mjs\";\n"
|
|
5
|
+
"// Main class exports\nexport { ShellDSL, createShellDSL, type Program } from \"./shell-dsl.mjs\";\nexport { ShellPromise, type ShellPromiseOptions } from \"./shell-promise.mjs\";\n\n// Types\nexport type {\n VirtualFS,\n FileStat,\n Command,\n CommandContext,\n Stdin,\n Stdout,\n Stderr,\n OutputCollector,\n ExecResult,\n ShellConfig,\n RawValue,\n} from \"./types.mjs\";\nexport { isRawValue } from \"./types.mjs\";\n\n// Errors\nexport { ShellError, LexError, ParseError } from \"./errors.mjs\";\n\n// Lexer\nexport { Lexer, lex, tokenToString } from \"./lexer/index.mjs\";\nexport type { Token, RedirectMode } from \"./lexer/index.mjs\";\n\n// Parser\nexport { Parser, parse } from \"./parser/index.mjs\";\nexport type {\n ASTNode,\n Redirect,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n LiteralNode,\n VariableNode,\n SubstitutionNode,\n GlobNode,\n ConcatNode,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n ArithmeticNode,\n} from \"./parser/index.mjs\";\nexport {\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isLiteralNode,\n isVariableNode,\n isSubstitutionNode,\n isGlobNode,\n isConcatNode,\n isIfNode,\n isForNode,\n isWhileNode,\n isUntilNode,\n isCaseNode,\n isArithmeticNode,\n} from \"./parser/index.mjs\";\n\n// Interpreter\nexport { Interpreter, type InterpreterOptions, BreakException, ContinueException } from \"./interpreter/index.mjs\";\n\n// Filesystem\nexport { createVirtualFS } from \"./fs/index.mjs\";\nexport {\n FileSystem,\n ReadOnlyFileSystem,\n type Permission,\n type PermissionRules,\n type UnderlyingFS,\n} from \"./fs/index.mjs\";\n\n// I/O\nexport { createStdin, StdinImpl } from \"./io/index.mjs\";\nexport { createStdout, createStderr, createPipe, OutputCollectorImpl, PipeBuffer } from \"./io/index.mjs\";\n\n// Utilities\nexport { escape, escapeForInterpolation } from \"./utils/index.mjs\";\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AACA;AACA;AAgBA;AAGA;AAGA;AAIA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AACA;AACA;AAgBA;AAGA;AAGA;AAIA;AAsBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBA;AAGA;AACA;AAAA;AAAA;AAAA;AASA;AACA;AAGA;",
|
|
8
|
+
"debugId": "0CC96BD5A2BCA29264756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// src/interpreter/index.ts
|
|
2
|
-
import { Interpreter } from "./interpreter.mjs";
|
|
2
|
+
import { Interpreter, BreakException, ContinueException } from "./interpreter.mjs";
|
|
3
3
|
import { createCommandContext } from "./context.mjs";
|
|
4
4
|
export {
|
|
5
5
|
createCommandContext,
|
|
6
|
-
Interpreter
|
|
6
|
+
Interpreter,
|
|
7
|
+
ContinueException,
|
|
8
|
+
BreakException
|
|
7
9
|
};
|
|
8
10
|
|
|
9
|
-
//# debugId=
|
|
11
|
+
//# debugId=71A1B05D75F46BFA64756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/interpreter/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"export { Interpreter, type InterpreterOptions } from \"./interpreter.mjs\";\nexport { createCommandContext, type ContextOptions } from \"./context.mjs\";\n"
|
|
5
|
+
"export { Interpreter, type InterpreterOptions, BreakException, ContinueException } from \"./interpreter.mjs\";\nexport { createCommandContext, type ContextOptions } from \"./context.mjs\";\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";AAAA;AACA;",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "71A1B05D75F46BFA64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|