shell-dsl 0.0.38 → 0.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -567,12 +567,13 @@ import { builtinCommands } from "shell-dsl/commands";
567
567
  Or import individually:
568
568
 
569
569
  ```ts
570
- import { echo, cat, grep, wc, cp, mv, touch, tee, tree, find, sed, awk, cut, od } from "shell-dsl/commands";
570
+ import { echo, printf, cat, grep, wc, cp, mv, touch, tee, tree, find, sed, awk, cut, od } from "shell-dsl/commands";
571
571
  ```
572
572
 
573
573
  | Command | Description |
574
574
  |---------|-------------|
575
575
  | `echo` | Print arguments to stdout |
576
+ | `printf` | Format output without an implicit trailing newline (`%s`, `%b`, numeric formats, escapes) |
576
577
  | `cat` | Concatenate files or stdin to stdout |
577
578
  | `grep` | Linux-compatible pattern search |
578
579
  | `wc` | Count lines, words, or characters (`-l`, `-w`, `-c`) |
@@ -69,6 +69,7 @@ __export(exports_shell_dsl, {
69
69
  sed: () => import_commands2.sed,
70
70
  rm: () => import_commands2.rm,
71
71
  pwd: () => import_commands2.pwd,
72
+ printf: () => import_commands2.printf,
72
73
  od: () => import_commands2.od,
73
74
  mv: () => import_commands2.mv,
74
75
  mkdir: () => import_commands2.mkdir,
@@ -91,4 +92,4 @@ __reExport(exports_shell_dsl, require("./src/index.cjs"), module.exports);
91
92
  var import_commands = require("./src/commands/index.cjs");
92
93
  var import_commands2 = require("./src/commands/index.cjs");
93
94
 
94
- //# debugId=D3C9D8D0D2FCEB0A64756E2164756E21
95
+ //# debugId=B2100C1B0A657D9464756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../index.ts"],
4
4
  "sourcesContent": [
5
- "// Re-export everything from src\nexport * from \"./src/index.cjs\";\n\n// Re-export built-in commands\nexport { builtinCommands } from \"./src/commands/index.cjs\";\nexport {\n echo,\n cat,\n grep,\n wc,\n head,\n tail,\n sort,\n uniq,\n pwd,\n ls,\n mkdir,\n rm,\n test,\n bracket,\n trueCmd,\n falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n breakCmd,\n continueCmd,\n od,\n} from \"./src/commands/index.cjs\";\n"
5
+ "// Re-export everything from src\nexport * from \"./src/index.cjs\";\n\n// Re-export built-in commands\nexport { builtinCommands } from \"./src/commands/index.cjs\";\nexport {\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 trueCmd,\n falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n breakCmd,\n continueCmd,\n od,\n} from \"./src/commands/index.cjs\";\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;AAGgC,IAAhC;AA6BO,IA5BP;",
8
- "debugId": "D3C9D8D0D2FCEB0A64756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;AAGgC,IAAhC;AA8BO,IA7BP;",
8
+ "debugId": "B2100C1B0A657D9464756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "shell-dsl",
3
- "version": "0.0.38",
3
+ "version": "0.0.39",
4
4
  "type": "commonjs"
5
5
  }
@@ -52,6 +52,7 @@ __export(exports_commands, {
52
52
  sed: () => import_sed.sed,
53
53
  rm: () => import_rm.rm,
54
54
  pwd: () => import_pwd.pwd,
55
+ printf: () => import_printf.printf,
55
56
  od: () => import_od.od,
56
57
  mv: () => import_mv.mv,
57
58
  mkdir: () => import_mkdir.mkdir,
@@ -74,6 +75,7 @@ __export(exports_commands, {
74
75
  });
75
76
  module.exports = __toCommonJS(exports_commands);
76
77
  var import_echo = require("./echo/echo.cjs");
78
+ var import_printf = require("./printf/printf.cjs");
77
79
  var import_cat = require("./cat/cat.cjs");
78
80
  var import_grep = require("./grep/grep.cjs");
79
81
  var import_wc = require("./wc/wc.cjs");
@@ -102,6 +104,7 @@ var import_tr = require("./tr/tr.cjs");
102
104
  var import_cut = require("./cut/cut.cjs");
103
105
  var import_od = require("./od/od.cjs");
104
106
  var import_echo2 = require("./echo/echo.cjs");
107
+ var import_printf2 = require("./printf/printf.cjs");
105
108
  var import_cat2 = require("./cat/cat.cjs");
106
109
  var import_grep2 = require("./grep/grep.cjs");
107
110
  var import_wc2 = require("./wc/wc.cjs");
@@ -131,6 +134,7 @@ var import_cut2 = require("./cut/cut.cjs");
131
134
  var import_od2 = require("./od/od.cjs");
132
135
  var builtinCommands = {
133
136
  echo: import_echo2.echo,
137
+ printf: import_printf2.printf,
134
138
  cat: import_cat2.cat,
135
139
  grep: import_grep2.grep,
136
140
  wc: import_wc2.wc,
@@ -163,4 +167,4 @@ var builtinCommands = {
163
167
  od: import_od2.od
164
168
  };
165
169
 
166
- //# debugId=3F2FAD85701006CD64756E2164756E21
170
+ //# debugId=2377F0DD6264750A64756E2164756E21
@@ -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 { 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 { 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 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\";\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"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEqB,IAArB;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;AAGqB,IAArB;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;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,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;AACF;",
8
- "debugId": "3F2FAD85701006CD64756E2164756E21",
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;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;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;AACF;",
8
+ "debugId": "2377F0DD6264750A64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -0,0 +1,416 @@
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/printf/printf.ts
40
+ var exports_printf = {};
41
+ __export(exports_printf, {
42
+ printf: () => printf
43
+ });
44
+ module.exports = __toCommonJS(exports_printf);
45
+ var INTEGER_SPECIFIERS = new Set(["d", "i", "u", "o", "x", "X"]);
46
+ var FLOAT_SPECIFIERS = new Set(["f", "F", "e", "E", "g", "G"]);
47
+ var STRING_SPECIFIERS = new Set(["s", "b", "c"]);
48
+ var LENGTH_MODIFIERS = new Set(["h", "l", "L", "j", "z", "t"]);
49
+ function isOctalDigit(char) {
50
+ return char !== undefined && char >= "0" && char <= "7";
51
+ }
52
+ function isDigit(char) {
53
+ return char !== undefined && char >= "0" && char <= "9";
54
+ }
55
+ function readEscape(input, index) {
56
+ if (index + 1 >= input.length) {
57
+ return { text: "\\", nextIndex: index + 1, stop: false };
58
+ }
59
+ const char = input[index + 1];
60
+ if (char === "c") {
61
+ return { text: "", nextIndex: index + 2, stop: true };
62
+ }
63
+ if (isOctalDigit(char)) {
64
+ let digits = "";
65
+ let nextIndex = index + 1;
66
+ if (input[nextIndex] === "0") {
67
+ nextIndex++;
68
+ }
69
+ while (digits.length < 3 && isOctalDigit(input[nextIndex])) {
70
+ digits += input[nextIndex];
71
+ nextIndex++;
72
+ }
73
+ const codePoint = digits === "" ? 0 : Number.parseInt(digits, 8);
74
+ return { text: String.fromCharCode(codePoint), nextIndex, stop: false };
75
+ }
76
+ if (char === "x") {
77
+ let digits = "";
78
+ let nextIndex = index + 2;
79
+ while (digits.length < 2 && nextIndex < input.length && /[0-9a-fA-F]/.test(input[nextIndex])) {
80
+ digits += input[nextIndex];
81
+ nextIndex++;
82
+ }
83
+ if (digits.length > 0) {
84
+ return { text: String.fromCharCode(Number.parseInt(digits, 16)), nextIndex, stop: false };
85
+ }
86
+ }
87
+ switch (char) {
88
+ case "a":
89
+ return { text: "\x07", nextIndex: index + 2, stop: false };
90
+ case "b":
91
+ return { text: "\b", nextIndex: index + 2, stop: false };
92
+ case "f":
93
+ return { text: "\f", nextIndex: index + 2, stop: false };
94
+ case "n":
95
+ return { text: `
96
+ `, nextIndex: index + 2, stop: false };
97
+ case "r":
98
+ return { text: "\r", nextIndex: index + 2, stop: false };
99
+ case "t":
100
+ return { text: "\t", nextIndex: index + 2, stop: false };
101
+ case "v":
102
+ return { text: "\v", nextIndex: index + 2, stop: false };
103
+ case "\\":
104
+ return { text: "\\", nextIndex: index + 2, stop: false };
105
+ default:
106
+ return { text: `\\${char}`, nextIndex: index + 2, stop: false };
107
+ }
108
+ }
109
+ function expandPrintfEscapes(input) {
110
+ let text = "";
111
+ for (let i = 0;i < input.length; ) {
112
+ if (input[i] !== "\\") {
113
+ text += input[i];
114
+ i++;
115
+ continue;
116
+ }
117
+ const escape = readEscape(input, i);
118
+ text += escape.text;
119
+ i = escape.nextIndex;
120
+ if (escape.stop) {
121
+ return { text, stop: true };
122
+ }
123
+ }
124
+ return { text, stop: false };
125
+ }
126
+ function readNumber(input, index) {
127
+ let digits = "";
128
+ let nextIndex = index;
129
+ while (isDigit(input[nextIndex])) {
130
+ digits += input[nextIndex];
131
+ nextIndex++;
132
+ }
133
+ return {
134
+ value: digits === "" ? undefined : Number.parseInt(digits, 10),
135
+ nextIndex
136
+ };
137
+ }
138
+ function parseConversion(format, index) {
139
+ let nextIndex = index + 1;
140
+ let flags = "";
141
+ while (true) {
142
+ const flag = format[nextIndex];
143
+ if (flag === undefined || !"-+ #0".includes(flag)) {
144
+ break;
145
+ }
146
+ flags += flag;
147
+ nextIndex++;
148
+ }
149
+ const widthResult = readNumber(format, nextIndex);
150
+ const width = widthResult.value;
151
+ nextIndex = widthResult.nextIndex;
152
+ let precision;
153
+ if (format[nextIndex] === ".") {
154
+ const precisionResult = readNumber(format, nextIndex + 1);
155
+ precision = precisionResult.value ?? 0;
156
+ nextIndex = precisionResult.nextIndex;
157
+ }
158
+ if (LENGTH_MODIFIERS.has(format[nextIndex] ?? "")) {
159
+ const modifier = format[nextIndex];
160
+ nextIndex++;
161
+ if (modifier === "h" && format[nextIndex] === "h" || modifier === "l" && format[nextIndex] === "l") {
162
+ nextIndex++;
163
+ }
164
+ }
165
+ const specifier = format[nextIndex];
166
+ if (specifier === undefined) {
167
+ return { nextIndex, error: "missing format character" };
168
+ }
169
+ if (!INTEGER_SPECIFIERS.has(specifier) && !FLOAT_SPECIFIERS.has(specifier) && !STRING_SPECIFIERS.has(specifier)) {
170
+ return { nextIndex: nextIndex + 1, error: `invalid format character '${specifier}'` };
171
+ }
172
+ return {
173
+ spec: { flags, width, precision, specifier },
174
+ nextIndex: nextIndex + 1
175
+ };
176
+ }
177
+ function pad(value, spec, numeric = false) {
178
+ const width = spec.width ?? 0;
179
+ if (value.length >= width) {
180
+ return value;
181
+ }
182
+ const leftAlign = spec.flags.includes("-");
183
+ const useZeroPad = numeric && spec.flags.includes("0") && !leftAlign && spec.precision === undefined;
184
+ const padChar = useZeroPad ? "0" : " ";
185
+ const padding = padChar.repeat(width - value.length);
186
+ if (leftAlign) {
187
+ return value + padding;
188
+ }
189
+ if (useZeroPad && (value.startsWith("-") || value.startsWith("+") || value.startsWith(" "))) {
190
+ return value[0] + padding + value.slice(1);
191
+ }
192
+ if (useZeroPad && (value.startsWith("0x") || value.startsWith("0X"))) {
193
+ return value.slice(0, 2) + padding + value.slice(2);
194
+ }
195
+ return padding + value;
196
+ }
197
+ function integerFromArg(arg) {
198
+ const trimmed = arg.trim();
199
+ if (/^[+-]?0[xX][0-9a-fA-F]+$/.test(trimmed)) {
200
+ const sign = trimmed.startsWith("-") ? -1 : 1;
201
+ return sign * Number.parseInt(trimmed.replace(/^[+-]?0[xX]/, ""), 16);
202
+ }
203
+ const parsed = Number.parseInt(trimmed, 10);
204
+ return Number.isNaN(parsed) ? 0 : parsed;
205
+ }
206
+ function floatFromArg(arg) {
207
+ const parsed = Number.parseFloat(arg.trim());
208
+ return Number.isNaN(parsed) ? 0 : parsed;
209
+ }
210
+ function formatInteger(arg, spec) {
211
+ const originalValue = Math.trunc(integerFromArg(arg));
212
+ const unsignedValue = originalValue < 0 ? originalValue >>> 0 : originalValue;
213
+ let value = spec.specifier === "u" || spec.specifier === "o" || spec.specifier === "x" || spec.specifier === "X" ? unsignedValue : originalValue;
214
+ let sign = "";
215
+ if ((spec.specifier === "d" || spec.specifier === "i") && value < 0) {
216
+ sign = "-";
217
+ value = Math.abs(value);
218
+ } else if ((spec.specifier === "d" || spec.specifier === "i") && spec.flags.includes("+")) {
219
+ sign = "+";
220
+ } else if ((spec.specifier === "d" || spec.specifier === "i") && spec.flags.includes(" ")) {
221
+ sign = " ";
222
+ }
223
+ let digits;
224
+ if (spec.specifier === "o") {
225
+ digits = value.toString(8);
226
+ } else if (spec.specifier === "x" || spec.specifier === "X") {
227
+ digits = value.toString(16);
228
+ if (spec.specifier === "X") {
229
+ digits = digits.toUpperCase();
230
+ }
231
+ } else {
232
+ digits = value.toString(10);
233
+ }
234
+ if (spec.precision !== undefined) {
235
+ if (spec.precision === 0 && value === 0) {
236
+ digits = "";
237
+ } else {
238
+ digits = digits.padStart(spec.precision, "0");
239
+ }
240
+ }
241
+ let prefix = "";
242
+ if (spec.flags.includes("#")) {
243
+ if (spec.specifier === "o" && !digits.startsWith("0")) {
244
+ prefix = "0";
245
+ } else if (spec.specifier === "x" && value !== 0) {
246
+ prefix = "0x";
247
+ } else if (spec.specifier === "X" && value !== 0) {
248
+ prefix = "0X";
249
+ }
250
+ }
251
+ return pad(sign + prefix + digits, spec, true);
252
+ }
253
+ function formatFloat(arg, spec) {
254
+ const value = floatFromArg(arg);
255
+ const precision = spec.precision ?? 6;
256
+ let formatted;
257
+ switch (spec.specifier) {
258
+ case "e":
259
+ case "E":
260
+ formatted = value.toExponential(precision);
261
+ break;
262
+ case "g":
263
+ case "G":
264
+ formatted = value.toPrecision(precision === 0 ? 1 : precision);
265
+ break;
266
+ default:
267
+ formatted = value.toFixed(precision);
268
+ break;
269
+ }
270
+ if (spec.specifier === "E" || spec.specifier === "G" || spec.specifier === "F") {
271
+ formatted = formatted.toUpperCase();
272
+ }
273
+ if (value >= 0 && spec.flags.includes("+")) {
274
+ formatted = `+${formatted}`;
275
+ } else if (value >= 0 && spec.flags.includes(" ")) {
276
+ formatted = ` ${formatted}`;
277
+ }
278
+ return pad(formatted, spec, true);
279
+ }
280
+ function formatString(value, spec) {
281
+ const truncated = spec.precision === undefined ? value : value.slice(0, spec.precision);
282
+ return pad(truncated, spec);
283
+ }
284
+ function renderConversion(spec, args, argIndex) {
285
+ const hasArg = argIndex < args.length;
286
+ const arg = hasArg ? args[argIndex] : "";
287
+ const nextArgIndex = hasArg ? argIndex + 1 : argIndex;
288
+ if (spec.specifier === "s") {
289
+ return {
290
+ output: formatString(arg, spec),
291
+ nextArgIndex,
292
+ consumedArg: hasArg,
293
+ stop: false
294
+ };
295
+ }
296
+ if (spec.specifier === "b") {
297
+ const expanded = expandPrintfEscapes(arg);
298
+ return {
299
+ output: formatString(expanded.text, spec),
300
+ nextArgIndex,
301
+ consumedArg: hasArg,
302
+ stop: expanded.stop
303
+ };
304
+ }
305
+ if (spec.specifier === "c") {
306
+ return {
307
+ output: formatString(arg.slice(0, 1), spec),
308
+ nextArgIndex,
309
+ consumedArg: hasArg,
310
+ stop: false
311
+ };
312
+ }
313
+ if (INTEGER_SPECIFIERS.has(spec.specifier)) {
314
+ return {
315
+ output: formatInteger(hasArg ? arg : "0", spec),
316
+ nextArgIndex,
317
+ consumedArg: hasArg,
318
+ stop: false
319
+ };
320
+ }
321
+ return {
322
+ output: formatFloat(hasArg ? arg : "0", spec),
323
+ nextArgIndex,
324
+ consumedArg: hasArg,
325
+ stop: false
326
+ };
327
+ }
328
+ function renderPass(format, args, startArgIndex) {
329
+ let output = "";
330
+ let argIndex = startArgIndex;
331
+ let consumedArgs = 0;
332
+ for (let i = 0;i < format.length; ) {
333
+ const char = format[i];
334
+ if (char === "\\") {
335
+ const escape = readEscape(format, i);
336
+ output += escape.text;
337
+ i = escape.nextIndex;
338
+ if (escape.stop) {
339
+ return { output, nextArgIndex: argIndex, consumedArgs, stop: true };
340
+ }
341
+ continue;
342
+ }
343
+ if (char !== "%") {
344
+ output += char;
345
+ i++;
346
+ continue;
347
+ }
348
+ if (format[i + 1] === "%") {
349
+ output += "%";
350
+ i += 2;
351
+ continue;
352
+ }
353
+ const parsed = parseConversion(format, i);
354
+ if (parsed.error || !parsed.spec) {
355
+ return {
356
+ output,
357
+ nextArgIndex: argIndex,
358
+ consumedArgs,
359
+ stop: false,
360
+ error: parsed.error ?? "invalid format"
361
+ };
362
+ }
363
+ const rendered = renderConversion(parsed.spec, args, argIndex);
364
+ output += rendered.output;
365
+ argIndex = rendered.nextArgIndex;
366
+ if (rendered.consumedArg) {
367
+ consumedArgs++;
368
+ }
369
+ i = parsed.nextIndex;
370
+ if (rendered.stop) {
371
+ return { output, nextArgIndex: argIndex, consumedArgs, stop: true };
372
+ }
373
+ }
374
+ return { output, nextArgIndex: argIndex, consumedArgs, stop: false };
375
+ }
376
+ function formatPrintf(format, args) {
377
+ let output = "";
378
+ let argIndex = 0;
379
+ let renderedAtLeastOnce = false;
380
+ while (!renderedAtLeastOnce || argIndex < args.length) {
381
+ const pass = renderPass(format, args, argIndex);
382
+ renderedAtLeastOnce = true;
383
+ output += pass.output;
384
+ argIndex = pass.nextArgIndex;
385
+ if (pass.error) {
386
+ return { output, error: pass.error };
387
+ }
388
+ if (pass.stop) {
389
+ return { output };
390
+ }
391
+ if (pass.consumedArgs === 0) {
392
+ break;
393
+ }
394
+ }
395
+ return { output };
396
+ }
397
+ var printf = async (ctx) => {
398
+ if (ctx.args.length === 0) {
399
+ await ctx.stderr.writeText(`printf: missing format operand
400
+ `);
401
+ return 1;
402
+ }
403
+ const [format, ...args] = ctx.args;
404
+ const result = formatPrintf(format, args);
405
+ if (result.output.length > 0) {
406
+ await ctx.stdout.writeText(result.output);
407
+ }
408
+ if (result.error) {
409
+ await ctx.stderr.writeText(`printf: ${result.error}
410
+ `);
411
+ return 1;
412
+ }
413
+ return 0;
414
+ };
415
+
416
+ //# debugId=E1A228909A799CE564756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/commands/printf/printf.ts"],
4
+ "sourcesContent": [
5
+ "import type { Command } from \"../../types.cjs\";\n\ninterface EscapeResult {\n text: string;\n nextIndex: number;\n stop: boolean;\n}\n\ninterface FormatResult {\n output: string;\n error?: string;\n}\n\ninterface ConversionSpec {\n flags: string;\n width?: number;\n precision?: number;\n specifier: string;\n}\n\ninterface RenderPassResult {\n output: string;\n nextArgIndex: number;\n consumedArgs: number;\n stop: boolean;\n error?: string;\n}\n\nconst INTEGER_SPECIFIERS = new Set([\"d\", \"i\", \"u\", \"o\", \"x\", \"X\"]);\nconst FLOAT_SPECIFIERS = new Set([\"f\", \"F\", \"e\", \"E\", \"g\", \"G\"]);\nconst STRING_SPECIFIERS = new Set([\"s\", \"b\", \"c\"]);\nconst LENGTH_MODIFIERS = new Set([\"h\", \"l\", \"L\", \"j\", \"z\", \"t\"]);\n\nfunction isOctalDigit(char: string | undefined): boolean {\n return char !== undefined && char >= \"0\" && char <= \"7\";\n}\n\nfunction isDigit(char: string | undefined): boolean {\n return char !== undefined && char >= \"0\" && char <= \"9\";\n}\n\nfunction readEscape(input: string, index: number): EscapeResult {\n if (index + 1 >= input.length) {\n return { text: \"\\\\\", nextIndex: index + 1, stop: false };\n }\n\n const char = input[index + 1]!;\n\n if (char === \"c\") {\n return { text: \"\", nextIndex: index + 2, stop: true };\n }\n\n if (isOctalDigit(char)) {\n let digits = \"\";\n let nextIndex = index + 1;\n\n if (input[nextIndex] === \"0\") {\n nextIndex++;\n }\n\n while (digits.length < 3 && isOctalDigit(input[nextIndex])) {\n digits += input[nextIndex]!;\n nextIndex++;\n }\n\n const codePoint = digits === \"\" ? 0 : Number.parseInt(digits, 8);\n return { text: String.fromCharCode(codePoint), nextIndex, stop: false };\n }\n\n if (char === \"x\") {\n let digits = \"\";\n let nextIndex = index + 2;\n\n while (digits.length < 2 && nextIndex < input.length && /[0-9a-fA-F]/.test(input[nextIndex]!)) {\n digits += input[nextIndex]!;\n nextIndex++;\n }\n\n if (digits.length > 0) {\n return { text: String.fromCharCode(Number.parseInt(digits, 16)), nextIndex, stop: false };\n }\n }\n\n switch (char) {\n case \"a\":\n return { text: \"\\x07\", nextIndex: index + 2, stop: false };\n case \"b\":\n return { text: \"\\b\", nextIndex: index + 2, stop: false };\n case \"f\":\n return { text: \"\\f\", nextIndex: index + 2, stop: false };\n case \"n\":\n return { text: \"\\n\", nextIndex: index + 2, stop: false };\n case \"r\":\n return { text: \"\\r\", nextIndex: index + 2, stop: false };\n case \"t\":\n return { text: \"\\t\", nextIndex: index + 2, stop: false };\n case \"v\":\n return { text: \"\\v\", nextIndex: index + 2, stop: false };\n case \"\\\\\":\n return { text: \"\\\\\", nextIndex: index + 2, stop: false };\n default:\n return { text: `\\\\${char}`, nextIndex: index + 2, stop: false };\n }\n}\n\nfunction expandPrintfEscapes(input: string): { text: string; stop: boolean } {\n let text = \"\";\n\n for (let i = 0; i < input.length;) {\n if (input[i] !== \"\\\\\") {\n text += input[i]!;\n i++;\n continue;\n }\n\n const escape = readEscape(input, i);\n text += escape.text;\n i = escape.nextIndex;\n\n if (escape.stop) {\n return { text, stop: true };\n }\n }\n\n return { text, stop: false };\n}\n\nfunction readNumber(input: string, index: number): { value?: number; nextIndex: number } {\n let digits = \"\";\n let nextIndex = index;\n\n while (isDigit(input[nextIndex])) {\n digits += input[nextIndex]!;\n nextIndex++;\n }\n\n return {\n value: digits === \"\" ? undefined : Number.parseInt(digits, 10),\n nextIndex,\n };\n}\n\nfunction parseConversion(format: string, index: number): { spec?: ConversionSpec; nextIndex: number; error?: string } {\n let nextIndex = index + 1;\n let flags = \"\";\n\n while (true) {\n const flag = format[nextIndex];\n if (flag === undefined || !\"-+ #0\".includes(flag)) {\n break;\n }\n flags += flag;\n nextIndex++;\n }\n\n const widthResult = readNumber(format, nextIndex);\n const width = widthResult.value;\n nextIndex = widthResult.nextIndex;\n\n let precision: number | undefined;\n if (format[nextIndex] === \".\") {\n const precisionResult = readNumber(format, nextIndex + 1);\n precision = precisionResult.value ?? 0;\n nextIndex = precisionResult.nextIndex;\n }\n\n if (LENGTH_MODIFIERS.has(format[nextIndex] ?? \"\")) {\n const modifier = format[nextIndex]!;\n nextIndex++;\n if ((modifier === \"h\" && format[nextIndex] === \"h\") || (modifier === \"l\" && format[nextIndex] === \"l\")) {\n nextIndex++;\n }\n }\n\n const specifier = format[nextIndex];\n if (specifier === undefined) {\n return { nextIndex, error: \"missing format character\" };\n }\n\n if (\n !INTEGER_SPECIFIERS.has(specifier) &&\n !FLOAT_SPECIFIERS.has(specifier) &&\n !STRING_SPECIFIERS.has(specifier)\n ) {\n return { nextIndex: nextIndex + 1, error: `invalid format character '${specifier}'` };\n }\n\n return {\n spec: { flags, width, precision, specifier },\n nextIndex: nextIndex + 1,\n };\n}\n\nfunction pad(value: string, spec: ConversionSpec, numeric = false): string {\n const width = spec.width ?? 0;\n if (value.length >= width) {\n return value;\n }\n\n const leftAlign = spec.flags.includes(\"-\");\n const useZeroPad = numeric && spec.flags.includes(\"0\") && !leftAlign && spec.precision === undefined;\n const padChar = useZeroPad ? \"0\" : \" \";\n const padding = padChar.repeat(width - value.length);\n\n if (leftAlign) {\n return value + padding;\n }\n\n if (useZeroPad && (value.startsWith(\"-\") || value.startsWith(\"+\") || value.startsWith(\" \"))) {\n return value[0]! + padding + value.slice(1);\n }\n\n if (useZeroPad && (value.startsWith(\"0x\") || value.startsWith(\"0X\"))) {\n return value.slice(0, 2) + padding + value.slice(2);\n }\n\n return padding + value;\n}\n\nfunction integerFromArg(arg: string): number {\n const trimmed = arg.trim();\n if (/^[+-]?0[xX][0-9a-fA-F]+$/.test(trimmed)) {\n const sign = trimmed.startsWith(\"-\") ? -1 : 1;\n return sign * Number.parseInt(trimmed.replace(/^[+-]?0[xX]/, \"\"), 16);\n }\n\n const parsed = Number.parseInt(trimmed, 10);\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\nfunction floatFromArg(arg: string): number {\n const parsed = Number.parseFloat(arg.trim());\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\nfunction formatInteger(arg: string, spec: ConversionSpec): string {\n const originalValue = Math.trunc(integerFromArg(arg));\n const unsignedValue = originalValue < 0 ? originalValue >>> 0 : originalValue;\n let value = spec.specifier === \"u\" || spec.specifier === \"o\" || spec.specifier === \"x\" || spec.specifier === \"X\"\n ? unsignedValue\n : originalValue;\n\n let sign = \"\";\n if ((spec.specifier === \"d\" || spec.specifier === \"i\") && value < 0) {\n sign = \"-\";\n value = Math.abs(value);\n } else if ((spec.specifier === \"d\" || spec.specifier === \"i\") && spec.flags.includes(\"+\")) {\n sign = \"+\";\n } else if ((spec.specifier === \"d\" || spec.specifier === \"i\") && spec.flags.includes(\" \")) {\n sign = \" \";\n }\n\n let digits: string;\n if (spec.specifier === \"o\") {\n digits = value.toString(8);\n } else if (spec.specifier === \"x\" || spec.specifier === \"X\") {\n digits = value.toString(16);\n if (spec.specifier === \"X\") {\n digits = digits.toUpperCase();\n }\n } else {\n digits = value.toString(10);\n }\n\n if (spec.precision !== undefined) {\n if (spec.precision === 0 && value === 0) {\n digits = \"\";\n } else {\n digits = digits.padStart(spec.precision, \"0\");\n }\n }\n\n let prefix = \"\";\n if (spec.flags.includes(\"#\")) {\n if (spec.specifier === \"o\" && !digits.startsWith(\"0\")) {\n prefix = \"0\";\n } else if (spec.specifier === \"x\" && value !== 0) {\n prefix = \"0x\";\n } else if (spec.specifier === \"X\" && value !== 0) {\n prefix = \"0X\";\n }\n }\n\n return pad(sign + prefix + digits, spec, true);\n}\n\nfunction formatFloat(arg: string, spec: ConversionSpec): string {\n const value = floatFromArg(arg);\n const precision = spec.precision ?? 6;\n let formatted: string;\n\n switch (spec.specifier) {\n case \"e\":\n case \"E\":\n formatted = value.toExponential(precision);\n break;\n case \"g\":\n case \"G\":\n formatted = value.toPrecision(precision === 0 ? 1 : precision);\n break;\n default:\n formatted = value.toFixed(precision);\n break;\n }\n\n if (spec.specifier === \"E\" || spec.specifier === \"G\" || spec.specifier === \"F\") {\n formatted = formatted.toUpperCase();\n }\n\n if (value >= 0 && spec.flags.includes(\"+\")) {\n formatted = `+${formatted}`;\n } else if (value >= 0 && spec.flags.includes(\" \")) {\n formatted = ` ${formatted}`;\n }\n\n return pad(formatted, spec, true);\n}\n\nfunction formatString(value: string, spec: ConversionSpec): string {\n const truncated = spec.precision === undefined ? value : value.slice(0, spec.precision);\n return pad(truncated, spec);\n}\n\nfunction renderConversion(\n spec: ConversionSpec,\n args: string[],\n argIndex: number\n): { output: string; nextArgIndex: number; consumedArg: boolean; stop: boolean } {\n const hasArg = argIndex < args.length;\n const arg = hasArg ? args[argIndex]! : \"\";\n const nextArgIndex = hasArg ? argIndex + 1 : argIndex;\n\n if (spec.specifier === \"s\") {\n return {\n output: formatString(arg, spec),\n nextArgIndex,\n consumedArg: hasArg,\n stop: false,\n };\n }\n\n if (spec.specifier === \"b\") {\n const expanded = expandPrintfEscapes(arg);\n return {\n output: formatString(expanded.text, spec),\n nextArgIndex,\n consumedArg: hasArg,\n stop: expanded.stop,\n };\n }\n\n if (spec.specifier === \"c\") {\n return {\n output: formatString(arg.slice(0, 1), spec),\n nextArgIndex,\n consumedArg: hasArg,\n stop: false,\n };\n }\n\n if (INTEGER_SPECIFIERS.has(spec.specifier)) {\n return {\n output: formatInteger(hasArg ? arg : \"0\", spec),\n nextArgIndex,\n consumedArg: hasArg,\n stop: false,\n };\n }\n\n return {\n output: formatFloat(hasArg ? arg : \"0\", spec),\n nextArgIndex,\n consumedArg: hasArg,\n stop: false,\n };\n}\n\nfunction renderPass(format: string, args: string[], startArgIndex: number): RenderPassResult {\n let output = \"\";\n let argIndex = startArgIndex;\n let consumedArgs = 0;\n\n for (let i = 0; i < format.length;) {\n const char = format[i]!;\n\n if (char === \"\\\\\") {\n const escape = readEscape(format, i);\n output += escape.text;\n i = escape.nextIndex;\n\n if (escape.stop) {\n return { output, nextArgIndex: argIndex, consumedArgs, stop: true };\n }\n continue;\n }\n\n if (char !== \"%\") {\n output += char;\n i++;\n continue;\n }\n\n if (format[i + 1] === \"%\") {\n output += \"%\";\n i += 2;\n continue;\n }\n\n const parsed = parseConversion(format, i);\n if (parsed.error || !parsed.spec) {\n return {\n output,\n nextArgIndex: argIndex,\n consumedArgs,\n stop: false,\n error: parsed.error ?? \"invalid format\",\n };\n }\n\n const rendered = renderConversion(parsed.spec, args, argIndex);\n output += rendered.output;\n argIndex = rendered.nextArgIndex;\n if (rendered.consumedArg) {\n consumedArgs++;\n }\n i = parsed.nextIndex;\n\n if (rendered.stop) {\n return { output, nextArgIndex: argIndex, consumedArgs, stop: true };\n }\n }\n\n return { output, nextArgIndex: argIndex, consumedArgs, stop: false };\n}\n\nfunction formatPrintf(format: string, args: string[]): FormatResult {\n let output = \"\";\n let argIndex = 0;\n let renderedAtLeastOnce = false;\n\n while (!renderedAtLeastOnce || argIndex < args.length) {\n const pass = renderPass(format, args, argIndex);\n renderedAtLeastOnce = true;\n output += pass.output;\n argIndex = pass.nextArgIndex;\n\n if (pass.error) {\n return { output, error: pass.error };\n }\n\n if (pass.stop) {\n return { output };\n }\n\n if (pass.consumedArgs === 0) {\n break;\n }\n }\n\n return { output };\n}\n\nexport const printf: Command = async (ctx) => {\n if (ctx.args.length === 0) {\n await ctx.stderr.writeText(\"printf: missing format operand\\n\");\n return 1;\n }\n\n const [format, ...args] = ctx.args;\n const result = formatPrintf(format!, args);\n\n if (result.output.length > 0) {\n await ctx.stdout.writeText(result.output);\n }\n\n if (result.error) {\n await ctx.stderr.writeText(`printf: ${result.error}\\n`);\n return 1;\n }\n\n return 0;\n};\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "E1A228909A799CE564756E2164756E21",
9
+ "names": []
10
+ }
@@ -3,6 +3,7 @@ export * from "./src/index.mjs";
3
3
  import { builtinCommands } from "./src/commands/index.mjs";
4
4
  import {
5
5
  echo,
6
+ printf,
6
7
  cat,
7
8
  grep,
8
9
  wc,
@@ -43,6 +44,7 @@ export {
43
44
  sed,
44
45
  rm,
45
46
  pwd,
47
+ printf,
46
48
  od,
47
49
  mv,
48
50
  mkdir,
@@ -61,4 +63,4 @@ export {
61
63
  awk
62
64
  };
63
65
 
64
- //# debugId=0230C6604254204664756E2164756E21
66
+ //# debugId=66DA617AC841474264756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../index.ts"],
4
4
  "sourcesContent": [
5
- "// Re-export everything from src\nexport * from \"./src/index.mjs\";\n\n// Re-export built-in commands\nexport { builtinCommands } from \"./src/commands/index.mjs\";\nexport {\n echo,\n cat,\n grep,\n wc,\n head,\n tail,\n sort,\n uniq,\n pwd,\n ls,\n mkdir,\n rm,\n test,\n bracket,\n trueCmd,\n falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n breakCmd,\n continueCmd,\n od,\n} from \"./src/commands/index.mjs\";\n"
5
+ "// Re-export everything from src\nexport * from \"./src/index.mjs\";\n\n// Re-export built-in commands\nexport { builtinCommands } from \"./src/commands/index.mjs\";\nexport {\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 trueCmd,\n falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n breakCmd,\n continueCmd,\n od,\n} from \"./src/commands/index.mjs\";\n"
6
6
  ],
7
- "mappings": ";AACA;AAGA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
8
- "debugId": "0230C6604254204664756E2164756E21",
7
+ "mappings": ";AACA;AAGA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
8
+ "debugId": "66DA617AC841474264756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "shell-dsl",
3
- "version": "0.0.38",
3
+ "version": "0.0.39",
4
4
  "type": "module"
5
5
  }
@@ -1,5 +1,6 @@
1
1
  // src/commands/index.ts
2
2
  import { echo } from "./echo/echo.mjs";
3
+ import { printf } from "./printf/printf.mjs";
3
4
  import { cat } from "./cat/cat.mjs";
4
5
  import { grep } from "./grep/grep.mjs";
5
6
  import { wc } from "./wc/wc.mjs";
@@ -28,6 +29,7 @@ import { tr } from "./tr/tr.mjs";
28
29
  import { cut } from "./cut/cut.mjs";
29
30
  import { od } from "./od/od.mjs";
30
31
  import { echo as echo2 } from "./echo/echo.mjs";
32
+ import { printf as printf2 } from "./printf/printf.mjs";
31
33
  import { cat as cat2 } from "./cat/cat.mjs";
32
34
  import { grep as grep2 } from "./grep/grep.mjs";
33
35
  import { wc as wc2 } from "./wc/wc.mjs";
@@ -57,6 +59,7 @@ import { cut as cut2 } from "./cut/cut.mjs";
57
59
  import { od as od2 } from "./od/od.mjs";
58
60
  var builtinCommands = {
59
61
  echo: echo2,
62
+ printf: printf2,
60
63
  cat: cat2,
61
64
  grep: grep2,
62
65
  wc: wc2,
@@ -102,6 +105,7 @@ export {
102
105
  sed,
103
106
  rm,
104
107
  pwd,
108
+ printf,
105
109
  od,
106
110
  mv,
107
111
  mkdir,
@@ -123,4 +127,4 @@ export {
123
127
  awk
124
128
  };
125
129
 
126
- //# debugId=B7E3709FE74A7FB764756E2164756E21
130
+ //# debugId=56B4F99C3CC35C8764756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/commands/index.ts"],
4
4
  "sourcesContent": [
5
- "import type { Command } from \"../types.mjs\";\n\nexport { echo } from \"./echo/echo.mjs\";\nexport { cat } from \"./cat/cat.mjs\";\nexport { grep } from \"./grep/grep.mjs\";\nexport { wc } from \"./wc/wc.mjs\";\nexport { head } from \"./head/head.mjs\";\nexport { tail } from \"./tail/tail.mjs\";\nexport { sort } from \"./sort/sort.mjs\";\nexport { uniq } from \"./uniq/uniq.mjs\";\nexport { pwd } from \"./pwd/pwd.mjs\";\nexport { ls } from \"./ls/ls.mjs\";\nexport { mkdir } from \"./mkdir/mkdir.mjs\";\nexport { rm } from \"./rm/rm.mjs\";\nexport { test, bracket } from \"./test/test.mjs\";\nexport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nexport { touch } from \"./touch/touch.mjs\";\nexport { cp } from \"./cp/cp.mjs\";\nexport { mv } from \"./mv/mv.mjs\";\nexport { tee } from \"./tee/tee.mjs\";\nexport { tree } from \"./tree/tree.mjs\";\nexport { find } from \"./find/find.mjs\";\nexport { sed } from \"./sed/sed.mjs\";\nexport { awk } from \"./awk/awk.mjs\";\nexport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nexport { colon } from \"./colon/colon.mjs\";\nexport { cd } from \"./cd/cd.mjs\";\nexport { tr } from \"./tr/tr.mjs\";\nexport { cut } from \"./cut/cut.mjs\";\nexport { od } from \"./od/od.mjs\";\n\n// Re-export all commands as a bundle\nimport { echo } from \"./echo/echo.mjs\";\nimport { cat } from \"./cat/cat.mjs\";\nimport { grep } from \"./grep/grep.mjs\";\nimport { wc } from \"./wc/wc.mjs\";\nimport { head } from \"./head/head.mjs\";\nimport { tail } from \"./tail/tail.mjs\";\nimport { sort } from \"./sort/sort.mjs\";\nimport { uniq } from \"./uniq/uniq.mjs\";\nimport { pwd } from \"./pwd/pwd.mjs\";\nimport { ls } from \"./ls/ls.mjs\";\nimport { mkdir } from \"./mkdir/mkdir.mjs\";\nimport { rm } from \"./rm/rm.mjs\";\nimport { test, bracket } from \"./test/test.mjs\";\nimport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nimport { touch } from \"./touch/touch.mjs\";\nimport { cp } from \"./cp/cp.mjs\";\nimport { mv } from \"./mv/mv.mjs\";\nimport { tee } from \"./tee/tee.mjs\";\nimport { tree } from \"./tree/tree.mjs\";\nimport { find } from \"./find/find.mjs\";\nimport { sed } from \"./sed/sed.mjs\";\nimport { awk } from \"./awk/awk.mjs\";\nimport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nimport { colon } from \"./colon/colon.mjs\";\nimport { cd } from \"./cd/cd.mjs\";\nimport { tr } from \"./tr/tr.mjs\";\nimport { cut } from \"./cut/cut.mjs\";\nimport { od } from \"./od/od.mjs\";\n\nexport const builtinCommands: Record<string, Command> = {\n echo,\n cat,\n grep,\n wc,\n head,\n tail,\n sort,\n uniq,\n pwd,\n ls,\n mkdir,\n rm,\n test,\n \"[\": bracket,\n true: trueCmd,\n false: falseCmd,\n touch,\n cp,\n mv,\n tee,\n tree,\n find,\n sed,\n awk,\n break: breakCmd,\n continue: continueCmd,\n \":\": colon,\n cd,\n tr,\n cut,\n od,\n};\n"
5
+ "import type { Command } from \"../types.mjs\";\n\nexport { echo } from \"./echo/echo.mjs\";\nexport { printf } from \"./printf/printf.mjs\";\nexport { cat } from \"./cat/cat.mjs\";\nexport { grep } from \"./grep/grep.mjs\";\nexport { wc } from \"./wc/wc.mjs\";\nexport { head } from \"./head/head.mjs\";\nexport { tail } from \"./tail/tail.mjs\";\nexport { sort } from \"./sort/sort.mjs\";\nexport { uniq } from \"./uniq/uniq.mjs\";\nexport { pwd } from \"./pwd/pwd.mjs\";\nexport { ls } from \"./ls/ls.mjs\";\nexport { mkdir } from \"./mkdir/mkdir.mjs\";\nexport { rm } from \"./rm/rm.mjs\";\nexport { test, bracket } from \"./test/test.mjs\";\nexport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nexport { touch } from \"./touch/touch.mjs\";\nexport { cp } from \"./cp/cp.mjs\";\nexport { mv } from \"./mv/mv.mjs\";\nexport { tee } from \"./tee/tee.mjs\";\nexport { tree } from \"./tree/tree.mjs\";\nexport { find } from \"./find/find.mjs\";\nexport { sed } from \"./sed/sed.mjs\";\nexport { awk } from \"./awk/awk.mjs\";\nexport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nexport { colon } from \"./colon/colon.mjs\";\nexport { cd } from \"./cd/cd.mjs\";\nexport { tr } from \"./tr/tr.mjs\";\nexport { cut } from \"./cut/cut.mjs\";\nexport { od } from \"./od/od.mjs\";\n\n// Re-export all commands as a bundle\nimport { echo } from \"./echo/echo.mjs\";\nimport { printf } from \"./printf/printf.mjs\";\nimport { cat } from \"./cat/cat.mjs\";\nimport { grep } from \"./grep/grep.mjs\";\nimport { wc } from \"./wc/wc.mjs\";\nimport { head } from \"./head/head.mjs\";\nimport { tail } from \"./tail/tail.mjs\";\nimport { sort } from \"./sort/sort.mjs\";\nimport { uniq } from \"./uniq/uniq.mjs\";\nimport { pwd } from \"./pwd/pwd.mjs\";\nimport { ls } from \"./ls/ls.mjs\";\nimport { mkdir } from \"./mkdir/mkdir.mjs\";\nimport { rm } from \"./rm/rm.mjs\";\nimport { test, bracket } from \"./test/test.mjs\";\nimport { trueCmd, falseCmd } from \"./true-false/true-false.mjs\";\nimport { touch } from \"./touch/touch.mjs\";\nimport { cp } from \"./cp/cp.mjs\";\nimport { mv } from \"./mv/mv.mjs\";\nimport { tee } from \"./tee/tee.mjs\";\nimport { tree } from \"./tree/tree.mjs\";\nimport { find } from \"./find/find.mjs\";\nimport { sed } from \"./sed/sed.mjs\";\nimport { awk } from \"./awk/awk.mjs\";\nimport { breakCmd, continueCmd } from \"./break-continue/break-continue.mjs\";\nimport { colon } from \"./colon/colon.mjs\";\nimport { cd } from \"./cd/cd.mjs\";\nimport { tr } from \"./tr/tr.mjs\";\nimport { cut } from \"./cut/cut.mjs\";\nimport { od } from \"./od/od.mjs\";\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"
6
6
  ],
7
- "mappings": ";AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA,iBAAS;AACT,gBAAS;AACT,iBAAS;AACT,eAAS;AACT,iBAAS;AACT,iBAAS;AACT,iBAAS;AACT,iBAAS;AACT,gBAAS;AACT,eAAS;AACT,kBAAS;AACT,eAAS;AACT,iBAAS,kBAAM;AACf,oBAAS,sBAAS;AAClB,kBAAS;AACT,eAAS;AACT,eAAS;AACT,gBAAS;AACT,iBAAS;AACT,iBAAS;AACT,gBAAS;AACT,gBAAS;AACT,qBAAS,0BAAU;AACnB,kBAAS;AACT,eAAS;AACT,eAAS;AACT,gBAAS;AACT,eAAS;AAEF,IAAM,kBAA2C;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,UAAU;AAAA,EACV,KAAK;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
8
- "debugId": "B7E3709FE74A7FB764756E2164756E21",
7
+ "mappings": ";AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA,iBAAS;AACT,mBAAS;AACT,gBAAS;AACT,iBAAS;AACT,eAAS;AACT,iBAAS;AACT,iBAAS;AACT,iBAAS;AACT,iBAAS;AACT,gBAAS;AACT,eAAS;AACT,kBAAS;AACT,eAAS;AACT,iBAAS,kBAAM;AACf,oBAAS,sBAAS;AAClB,kBAAS;AACT,eAAS;AACT,eAAS;AACT,gBAAS;AACT,iBAAS;AACT,iBAAS;AACT,gBAAS;AACT,gBAAS;AACT,qBAAS,0BAAU;AACnB,kBAAS;AACT,eAAS;AACT,eAAS;AACT,gBAAS;AACT,eAAS;AAEF,IAAM,kBAA2C;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;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;AACF;",
8
+ "debugId": "56B4F99C3CC35C8764756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -0,0 +1,376 @@
1
+ // src/commands/printf/printf.ts
2
+ var INTEGER_SPECIFIERS = new Set(["d", "i", "u", "o", "x", "X"]);
3
+ var FLOAT_SPECIFIERS = new Set(["f", "F", "e", "E", "g", "G"]);
4
+ var STRING_SPECIFIERS = new Set(["s", "b", "c"]);
5
+ var LENGTH_MODIFIERS = new Set(["h", "l", "L", "j", "z", "t"]);
6
+ function isOctalDigit(char) {
7
+ return char !== undefined && char >= "0" && char <= "7";
8
+ }
9
+ function isDigit(char) {
10
+ return char !== undefined && char >= "0" && char <= "9";
11
+ }
12
+ function readEscape(input, index) {
13
+ if (index + 1 >= input.length) {
14
+ return { text: "\\", nextIndex: index + 1, stop: false };
15
+ }
16
+ const char = input[index + 1];
17
+ if (char === "c") {
18
+ return { text: "", nextIndex: index + 2, stop: true };
19
+ }
20
+ if (isOctalDigit(char)) {
21
+ let digits = "";
22
+ let nextIndex = index + 1;
23
+ if (input[nextIndex] === "0") {
24
+ nextIndex++;
25
+ }
26
+ while (digits.length < 3 && isOctalDigit(input[nextIndex])) {
27
+ digits += input[nextIndex];
28
+ nextIndex++;
29
+ }
30
+ const codePoint = digits === "" ? 0 : Number.parseInt(digits, 8);
31
+ return { text: String.fromCharCode(codePoint), nextIndex, stop: false };
32
+ }
33
+ if (char === "x") {
34
+ let digits = "";
35
+ let nextIndex = index + 2;
36
+ while (digits.length < 2 && nextIndex < input.length && /[0-9a-fA-F]/.test(input[nextIndex])) {
37
+ digits += input[nextIndex];
38
+ nextIndex++;
39
+ }
40
+ if (digits.length > 0) {
41
+ return { text: String.fromCharCode(Number.parseInt(digits, 16)), nextIndex, stop: false };
42
+ }
43
+ }
44
+ switch (char) {
45
+ case "a":
46
+ return { text: "\x07", nextIndex: index + 2, stop: false };
47
+ case "b":
48
+ return { text: "\b", nextIndex: index + 2, stop: false };
49
+ case "f":
50
+ return { text: "\f", nextIndex: index + 2, stop: false };
51
+ case "n":
52
+ return { text: `
53
+ `, nextIndex: index + 2, stop: false };
54
+ case "r":
55
+ return { text: "\r", nextIndex: index + 2, stop: false };
56
+ case "t":
57
+ return { text: "\t", nextIndex: index + 2, stop: false };
58
+ case "v":
59
+ return { text: "\v", nextIndex: index + 2, stop: false };
60
+ case "\\":
61
+ return { text: "\\", nextIndex: index + 2, stop: false };
62
+ default:
63
+ return { text: `\\${char}`, nextIndex: index + 2, stop: false };
64
+ }
65
+ }
66
+ function expandPrintfEscapes(input) {
67
+ let text = "";
68
+ for (let i = 0;i < input.length; ) {
69
+ if (input[i] !== "\\") {
70
+ text += input[i];
71
+ i++;
72
+ continue;
73
+ }
74
+ const escape = readEscape(input, i);
75
+ text += escape.text;
76
+ i = escape.nextIndex;
77
+ if (escape.stop) {
78
+ return { text, stop: true };
79
+ }
80
+ }
81
+ return { text, stop: false };
82
+ }
83
+ function readNumber(input, index) {
84
+ let digits = "";
85
+ let nextIndex = index;
86
+ while (isDigit(input[nextIndex])) {
87
+ digits += input[nextIndex];
88
+ nextIndex++;
89
+ }
90
+ return {
91
+ value: digits === "" ? undefined : Number.parseInt(digits, 10),
92
+ nextIndex
93
+ };
94
+ }
95
+ function parseConversion(format, index) {
96
+ let nextIndex = index + 1;
97
+ let flags = "";
98
+ while (true) {
99
+ const flag = format[nextIndex];
100
+ if (flag === undefined || !"-+ #0".includes(flag)) {
101
+ break;
102
+ }
103
+ flags += flag;
104
+ nextIndex++;
105
+ }
106
+ const widthResult = readNumber(format, nextIndex);
107
+ const width = widthResult.value;
108
+ nextIndex = widthResult.nextIndex;
109
+ let precision;
110
+ if (format[nextIndex] === ".") {
111
+ const precisionResult = readNumber(format, nextIndex + 1);
112
+ precision = precisionResult.value ?? 0;
113
+ nextIndex = precisionResult.nextIndex;
114
+ }
115
+ if (LENGTH_MODIFIERS.has(format[nextIndex] ?? "")) {
116
+ const modifier = format[nextIndex];
117
+ nextIndex++;
118
+ if (modifier === "h" && format[nextIndex] === "h" || modifier === "l" && format[nextIndex] === "l") {
119
+ nextIndex++;
120
+ }
121
+ }
122
+ const specifier = format[nextIndex];
123
+ if (specifier === undefined) {
124
+ return { nextIndex, error: "missing format character" };
125
+ }
126
+ if (!INTEGER_SPECIFIERS.has(specifier) && !FLOAT_SPECIFIERS.has(specifier) && !STRING_SPECIFIERS.has(specifier)) {
127
+ return { nextIndex: nextIndex + 1, error: `invalid format character '${specifier}'` };
128
+ }
129
+ return {
130
+ spec: { flags, width, precision, specifier },
131
+ nextIndex: nextIndex + 1
132
+ };
133
+ }
134
+ function pad(value, spec, numeric = false) {
135
+ const width = spec.width ?? 0;
136
+ if (value.length >= width) {
137
+ return value;
138
+ }
139
+ const leftAlign = spec.flags.includes("-");
140
+ const useZeroPad = numeric && spec.flags.includes("0") && !leftAlign && spec.precision === undefined;
141
+ const padChar = useZeroPad ? "0" : " ";
142
+ const padding = padChar.repeat(width - value.length);
143
+ if (leftAlign) {
144
+ return value + padding;
145
+ }
146
+ if (useZeroPad && (value.startsWith("-") || value.startsWith("+") || value.startsWith(" "))) {
147
+ return value[0] + padding + value.slice(1);
148
+ }
149
+ if (useZeroPad && (value.startsWith("0x") || value.startsWith("0X"))) {
150
+ return value.slice(0, 2) + padding + value.slice(2);
151
+ }
152
+ return padding + value;
153
+ }
154
+ function integerFromArg(arg) {
155
+ const trimmed = arg.trim();
156
+ if (/^[+-]?0[xX][0-9a-fA-F]+$/.test(trimmed)) {
157
+ const sign = trimmed.startsWith("-") ? -1 : 1;
158
+ return sign * Number.parseInt(trimmed.replace(/^[+-]?0[xX]/, ""), 16);
159
+ }
160
+ const parsed = Number.parseInt(trimmed, 10);
161
+ return Number.isNaN(parsed) ? 0 : parsed;
162
+ }
163
+ function floatFromArg(arg) {
164
+ const parsed = Number.parseFloat(arg.trim());
165
+ return Number.isNaN(parsed) ? 0 : parsed;
166
+ }
167
+ function formatInteger(arg, spec) {
168
+ const originalValue = Math.trunc(integerFromArg(arg));
169
+ const unsignedValue = originalValue < 0 ? originalValue >>> 0 : originalValue;
170
+ let value = spec.specifier === "u" || spec.specifier === "o" || spec.specifier === "x" || spec.specifier === "X" ? unsignedValue : originalValue;
171
+ let sign = "";
172
+ if ((spec.specifier === "d" || spec.specifier === "i") && value < 0) {
173
+ sign = "-";
174
+ value = Math.abs(value);
175
+ } else if ((spec.specifier === "d" || spec.specifier === "i") && spec.flags.includes("+")) {
176
+ sign = "+";
177
+ } else if ((spec.specifier === "d" || spec.specifier === "i") && spec.flags.includes(" ")) {
178
+ sign = " ";
179
+ }
180
+ let digits;
181
+ if (spec.specifier === "o") {
182
+ digits = value.toString(8);
183
+ } else if (spec.specifier === "x" || spec.specifier === "X") {
184
+ digits = value.toString(16);
185
+ if (spec.specifier === "X") {
186
+ digits = digits.toUpperCase();
187
+ }
188
+ } else {
189
+ digits = value.toString(10);
190
+ }
191
+ if (spec.precision !== undefined) {
192
+ if (spec.precision === 0 && value === 0) {
193
+ digits = "";
194
+ } else {
195
+ digits = digits.padStart(spec.precision, "0");
196
+ }
197
+ }
198
+ let prefix = "";
199
+ if (spec.flags.includes("#")) {
200
+ if (spec.specifier === "o" && !digits.startsWith("0")) {
201
+ prefix = "0";
202
+ } else if (spec.specifier === "x" && value !== 0) {
203
+ prefix = "0x";
204
+ } else if (spec.specifier === "X" && value !== 0) {
205
+ prefix = "0X";
206
+ }
207
+ }
208
+ return pad(sign + prefix + digits, spec, true);
209
+ }
210
+ function formatFloat(arg, spec) {
211
+ const value = floatFromArg(arg);
212
+ const precision = spec.precision ?? 6;
213
+ let formatted;
214
+ switch (spec.specifier) {
215
+ case "e":
216
+ case "E":
217
+ formatted = value.toExponential(precision);
218
+ break;
219
+ case "g":
220
+ case "G":
221
+ formatted = value.toPrecision(precision === 0 ? 1 : precision);
222
+ break;
223
+ default:
224
+ formatted = value.toFixed(precision);
225
+ break;
226
+ }
227
+ if (spec.specifier === "E" || spec.specifier === "G" || spec.specifier === "F") {
228
+ formatted = formatted.toUpperCase();
229
+ }
230
+ if (value >= 0 && spec.flags.includes("+")) {
231
+ formatted = `+${formatted}`;
232
+ } else if (value >= 0 && spec.flags.includes(" ")) {
233
+ formatted = ` ${formatted}`;
234
+ }
235
+ return pad(formatted, spec, true);
236
+ }
237
+ function formatString(value, spec) {
238
+ const truncated = spec.precision === undefined ? value : value.slice(0, spec.precision);
239
+ return pad(truncated, spec);
240
+ }
241
+ function renderConversion(spec, args, argIndex) {
242
+ const hasArg = argIndex < args.length;
243
+ const arg = hasArg ? args[argIndex] : "";
244
+ const nextArgIndex = hasArg ? argIndex + 1 : argIndex;
245
+ if (spec.specifier === "s") {
246
+ return {
247
+ output: formatString(arg, spec),
248
+ nextArgIndex,
249
+ consumedArg: hasArg,
250
+ stop: false
251
+ };
252
+ }
253
+ if (spec.specifier === "b") {
254
+ const expanded = expandPrintfEscapes(arg);
255
+ return {
256
+ output: formatString(expanded.text, spec),
257
+ nextArgIndex,
258
+ consumedArg: hasArg,
259
+ stop: expanded.stop
260
+ };
261
+ }
262
+ if (spec.specifier === "c") {
263
+ return {
264
+ output: formatString(arg.slice(0, 1), spec),
265
+ nextArgIndex,
266
+ consumedArg: hasArg,
267
+ stop: false
268
+ };
269
+ }
270
+ if (INTEGER_SPECIFIERS.has(spec.specifier)) {
271
+ return {
272
+ output: formatInteger(hasArg ? arg : "0", spec),
273
+ nextArgIndex,
274
+ consumedArg: hasArg,
275
+ stop: false
276
+ };
277
+ }
278
+ return {
279
+ output: formatFloat(hasArg ? arg : "0", spec),
280
+ nextArgIndex,
281
+ consumedArg: hasArg,
282
+ stop: false
283
+ };
284
+ }
285
+ function renderPass(format, args, startArgIndex) {
286
+ let output = "";
287
+ let argIndex = startArgIndex;
288
+ let consumedArgs = 0;
289
+ for (let i = 0;i < format.length; ) {
290
+ const char = format[i];
291
+ if (char === "\\") {
292
+ const escape = readEscape(format, i);
293
+ output += escape.text;
294
+ i = escape.nextIndex;
295
+ if (escape.stop) {
296
+ return { output, nextArgIndex: argIndex, consumedArgs, stop: true };
297
+ }
298
+ continue;
299
+ }
300
+ if (char !== "%") {
301
+ output += char;
302
+ i++;
303
+ continue;
304
+ }
305
+ if (format[i + 1] === "%") {
306
+ output += "%";
307
+ i += 2;
308
+ continue;
309
+ }
310
+ const parsed = parseConversion(format, i);
311
+ if (parsed.error || !parsed.spec) {
312
+ return {
313
+ output,
314
+ nextArgIndex: argIndex,
315
+ consumedArgs,
316
+ stop: false,
317
+ error: parsed.error ?? "invalid format"
318
+ };
319
+ }
320
+ const rendered = renderConversion(parsed.spec, args, argIndex);
321
+ output += rendered.output;
322
+ argIndex = rendered.nextArgIndex;
323
+ if (rendered.consumedArg) {
324
+ consumedArgs++;
325
+ }
326
+ i = parsed.nextIndex;
327
+ if (rendered.stop) {
328
+ return { output, nextArgIndex: argIndex, consumedArgs, stop: true };
329
+ }
330
+ }
331
+ return { output, nextArgIndex: argIndex, consumedArgs, stop: false };
332
+ }
333
+ function formatPrintf(format, args) {
334
+ let output = "";
335
+ let argIndex = 0;
336
+ let renderedAtLeastOnce = false;
337
+ while (!renderedAtLeastOnce || argIndex < args.length) {
338
+ const pass = renderPass(format, args, argIndex);
339
+ renderedAtLeastOnce = true;
340
+ output += pass.output;
341
+ argIndex = pass.nextArgIndex;
342
+ if (pass.error) {
343
+ return { output, error: pass.error };
344
+ }
345
+ if (pass.stop) {
346
+ return { output };
347
+ }
348
+ if (pass.consumedArgs === 0) {
349
+ break;
350
+ }
351
+ }
352
+ return { output };
353
+ }
354
+ var printf = async (ctx) => {
355
+ if (ctx.args.length === 0) {
356
+ await ctx.stderr.writeText(`printf: missing format operand
357
+ `);
358
+ return 1;
359
+ }
360
+ const [format, ...args] = ctx.args;
361
+ const result = formatPrintf(format, args);
362
+ if (result.output.length > 0) {
363
+ await ctx.stdout.writeText(result.output);
364
+ }
365
+ if (result.error) {
366
+ await ctx.stderr.writeText(`printf: ${result.error}
367
+ `);
368
+ return 1;
369
+ }
370
+ return 0;
371
+ };
372
+ export {
373
+ printf
374
+ };
375
+
376
+ //# debugId=E3692C39E2D017E164756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/commands/printf/printf.ts"],
4
+ "sourcesContent": [
5
+ "import type { Command } from \"../../types.mjs\";\n\ninterface EscapeResult {\n text: string;\n nextIndex: number;\n stop: boolean;\n}\n\ninterface FormatResult {\n output: string;\n error?: string;\n}\n\ninterface ConversionSpec {\n flags: string;\n width?: number;\n precision?: number;\n specifier: string;\n}\n\ninterface RenderPassResult {\n output: string;\n nextArgIndex: number;\n consumedArgs: number;\n stop: boolean;\n error?: string;\n}\n\nconst INTEGER_SPECIFIERS = new Set([\"d\", \"i\", \"u\", \"o\", \"x\", \"X\"]);\nconst FLOAT_SPECIFIERS = new Set([\"f\", \"F\", \"e\", \"E\", \"g\", \"G\"]);\nconst STRING_SPECIFIERS = new Set([\"s\", \"b\", \"c\"]);\nconst LENGTH_MODIFIERS = new Set([\"h\", \"l\", \"L\", \"j\", \"z\", \"t\"]);\n\nfunction isOctalDigit(char: string | undefined): boolean {\n return char !== undefined && char >= \"0\" && char <= \"7\";\n}\n\nfunction isDigit(char: string | undefined): boolean {\n return char !== undefined && char >= \"0\" && char <= \"9\";\n}\n\nfunction readEscape(input: string, index: number): EscapeResult {\n if (index + 1 >= input.length) {\n return { text: \"\\\\\", nextIndex: index + 1, stop: false };\n }\n\n const char = input[index + 1]!;\n\n if (char === \"c\") {\n return { text: \"\", nextIndex: index + 2, stop: true };\n }\n\n if (isOctalDigit(char)) {\n let digits = \"\";\n let nextIndex = index + 1;\n\n if (input[nextIndex] === \"0\") {\n nextIndex++;\n }\n\n while (digits.length < 3 && isOctalDigit(input[nextIndex])) {\n digits += input[nextIndex]!;\n nextIndex++;\n }\n\n const codePoint = digits === \"\" ? 0 : Number.parseInt(digits, 8);\n return { text: String.fromCharCode(codePoint), nextIndex, stop: false };\n }\n\n if (char === \"x\") {\n let digits = \"\";\n let nextIndex = index + 2;\n\n while (digits.length < 2 && nextIndex < input.length && /[0-9a-fA-F]/.test(input[nextIndex]!)) {\n digits += input[nextIndex]!;\n nextIndex++;\n }\n\n if (digits.length > 0) {\n return { text: String.fromCharCode(Number.parseInt(digits, 16)), nextIndex, stop: false };\n }\n }\n\n switch (char) {\n case \"a\":\n return { text: \"\\x07\", nextIndex: index + 2, stop: false };\n case \"b\":\n return { text: \"\\b\", nextIndex: index + 2, stop: false };\n case \"f\":\n return { text: \"\\f\", nextIndex: index + 2, stop: false };\n case \"n\":\n return { text: \"\\n\", nextIndex: index + 2, stop: false };\n case \"r\":\n return { text: \"\\r\", nextIndex: index + 2, stop: false };\n case \"t\":\n return { text: \"\\t\", nextIndex: index + 2, stop: false };\n case \"v\":\n return { text: \"\\v\", nextIndex: index + 2, stop: false };\n case \"\\\\\":\n return { text: \"\\\\\", nextIndex: index + 2, stop: false };\n default:\n return { text: `\\\\${char}`, nextIndex: index + 2, stop: false };\n }\n}\n\nfunction expandPrintfEscapes(input: string): { text: string; stop: boolean } {\n let text = \"\";\n\n for (let i = 0; i < input.length;) {\n if (input[i] !== \"\\\\\") {\n text += input[i]!;\n i++;\n continue;\n }\n\n const escape = readEscape(input, i);\n text += escape.text;\n i = escape.nextIndex;\n\n if (escape.stop) {\n return { text, stop: true };\n }\n }\n\n return { text, stop: false };\n}\n\nfunction readNumber(input: string, index: number): { value?: number; nextIndex: number } {\n let digits = \"\";\n let nextIndex = index;\n\n while (isDigit(input[nextIndex])) {\n digits += input[nextIndex]!;\n nextIndex++;\n }\n\n return {\n value: digits === \"\" ? undefined : Number.parseInt(digits, 10),\n nextIndex,\n };\n}\n\nfunction parseConversion(format: string, index: number): { spec?: ConversionSpec; nextIndex: number; error?: string } {\n let nextIndex = index + 1;\n let flags = \"\";\n\n while (true) {\n const flag = format[nextIndex];\n if (flag === undefined || !\"-+ #0\".includes(flag)) {\n break;\n }\n flags += flag;\n nextIndex++;\n }\n\n const widthResult = readNumber(format, nextIndex);\n const width = widthResult.value;\n nextIndex = widthResult.nextIndex;\n\n let precision: number | undefined;\n if (format[nextIndex] === \".\") {\n const precisionResult = readNumber(format, nextIndex + 1);\n precision = precisionResult.value ?? 0;\n nextIndex = precisionResult.nextIndex;\n }\n\n if (LENGTH_MODIFIERS.has(format[nextIndex] ?? \"\")) {\n const modifier = format[nextIndex]!;\n nextIndex++;\n if ((modifier === \"h\" && format[nextIndex] === \"h\") || (modifier === \"l\" && format[nextIndex] === \"l\")) {\n nextIndex++;\n }\n }\n\n const specifier = format[nextIndex];\n if (specifier === undefined) {\n return { nextIndex, error: \"missing format character\" };\n }\n\n if (\n !INTEGER_SPECIFIERS.has(specifier) &&\n !FLOAT_SPECIFIERS.has(specifier) &&\n !STRING_SPECIFIERS.has(specifier)\n ) {\n return { nextIndex: nextIndex + 1, error: `invalid format character '${specifier}'` };\n }\n\n return {\n spec: { flags, width, precision, specifier },\n nextIndex: nextIndex + 1,\n };\n}\n\nfunction pad(value: string, spec: ConversionSpec, numeric = false): string {\n const width = spec.width ?? 0;\n if (value.length >= width) {\n return value;\n }\n\n const leftAlign = spec.flags.includes(\"-\");\n const useZeroPad = numeric && spec.flags.includes(\"0\") && !leftAlign && spec.precision === undefined;\n const padChar = useZeroPad ? \"0\" : \" \";\n const padding = padChar.repeat(width - value.length);\n\n if (leftAlign) {\n return value + padding;\n }\n\n if (useZeroPad && (value.startsWith(\"-\") || value.startsWith(\"+\") || value.startsWith(\" \"))) {\n return value[0]! + padding + value.slice(1);\n }\n\n if (useZeroPad && (value.startsWith(\"0x\") || value.startsWith(\"0X\"))) {\n return value.slice(0, 2) + padding + value.slice(2);\n }\n\n return padding + value;\n}\n\nfunction integerFromArg(arg: string): number {\n const trimmed = arg.trim();\n if (/^[+-]?0[xX][0-9a-fA-F]+$/.test(trimmed)) {\n const sign = trimmed.startsWith(\"-\") ? -1 : 1;\n return sign * Number.parseInt(trimmed.replace(/^[+-]?0[xX]/, \"\"), 16);\n }\n\n const parsed = Number.parseInt(trimmed, 10);\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\nfunction floatFromArg(arg: string): number {\n const parsed = Number.parseFloat(arg.trim());\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\nfunction formatInteger(arg: string, spec: ConversionSpec): string {\n const originalValue = Math.trunc(integerFromArg(arg));\n const unsignedValue = originalValue < 0 ? originalValue >>> 0 : originalValue;\n let value = spec.specifier === \"u\" || spec.specifier === \"o\" || spec.specifier === \"x\" || spec.specifier === \"X\"\n ? unsignedValue\n : originalValue;\n\n let sign = \"\";\n if ((spec.specifier === \"d\" || spec.specifier === \"i\") && value < 0) {\n sign = \"-\";\n value = Math.abs(value);\n } else if ((spec.specifier === \"d\" || spec.specifier === \"i\") && spec.flags.includes(\"+\")) {\n sign = \"+\";\n } else if ((spec.specifier === \"d\" || spec.specifier === \"i\") && spec.flags.includes(\" \")) {\n sign = \" \";\n }\n\n let digits: string;\n if (spec.specifier === \"o\") {\n digits = value.toString(8);\n } else if (spec.specifier === \"x\" || spec.specifier === \"X\") {\n digits = value.toString(16);\n if (spec.specifier === \"X\") {\n digits = digits.toUpperCase();\n }\n } else {\n digits = value.toString(10);\n }\n\n if (spec.precision !== undefined) {\n if (spec.precision === 0 && value === 0) {\n digits = \"\";\n } else {\n digits = digits.padStart(spec.precision, \"0\");\n }\n }\n\n let prefix = \"\";\n if (spec.flags.includes(\"#\")) {\n if (spec.specifier === \"o\" && !digits.startsWith(\"0\")) {\n prefix = \"0\";\n } else if (spec.specifier === \"x\" && value !== 0) {\n prefix = \"0x\";\n } else if (spec.specifier === \"X\" && value !== 0) {\n prefix = \"0X\";\n }\n }\n\n return pad(sign + prefix + digits, spec, true);\n}\n\nfunction formatFloat(arg: string, spec: ConversionSpec): string {\n const value = floatFromArg(arg);\n const precision = spec.precision ?? 6;\n let formatted: string;\n\n switch (spec.specifier) {\n case \"e\":\n case \"E\":\n formatted = value.toExponential(precision);\n break;\n case \"g\":\n case \"G\":\n formatted = value.toPrecision(precision === 0 ? 1 : precision);\n break;\n default:\n formatted = value.toFixed(precision);\n break;\n }\n\n if (spec.specifier === \"E\" || spec.specifier === \"G\" || spec.specifier === \"F\") {\n formatted = formatted.toUpperCase();\n }\n\n if (value >= 0 && spec.flags.includes(\"+\")) {\n formatted = `+${formatted}`;\n } else if (value >= 0 && spec.flags.includes(\" \")) {\n formatted = ` ${formatted}`;\n }\n\n return pad(formatted, spec, true);\n}\n\nfunction formatString(value: string, spec: ConversionSpec): string {\n const truncated = spec.precision === undefined ? value : value.slice(0, spec.precision);\n return pad(truncated, spec);\n}\n\nfunction renderConversion(\n spec: ConversionSpec,\n args: string[],\n argIndex: number\n): { output: string; nextArgIndex: number; consumedArg: boolean; stop: boolean } {\n const hasArg = argIndex < args.length;\n const arg = hasArg ? args[argIndex]! : \"\";\n const nextArgIndex = hasArg ? argIndex + 1 : argIndex;\n\n if (spec.specifier === \"s\") {\n return {\n output: formatString(arg, spec),\n nextArgIndex,\n consumedArg: hasArg,\n stop: false,\n };\n }\n\n if (spec.specifier === \"b\") {\n const expanded = expandPrintfEscapes(arg);\n return {\n output: formatString(expanded.text, spec),\n nextArgIndex,\n consumedArg: hasArg,\n stop: expanded.stop,\n };\n }\n\n if (spec.specifier === \"c\") {\n return {\n output: formatString(arg.slice(0, 1), spec),\n nextArgIndex,\n consumedArg: hasArg,\n stop: false,\n };\n }\n\n if (INTEGER_SPECIFIERS.has(spec.specifier)) {\n return {\n output: formatInteger(hasArg ? arg : \"0\", spec),\n nextArgIndex,\n consumedArg: hasArg,\n stop: false,\n };\n }\n\n return {\n output: formatFloat(hasArg ? arg : \"0\", spec),\n nextArgIndex,\n consumedArg: hasArg,\n stop: false,\n };\n}\n\nfunction renderPass(format: string, args: string[], startArgIndex: number): RenderPassResult {\n let output = \"\";\n let argIndex = startArgIndex;\n let consumedArgs = 0;\n\n for (let i = 0; i < format.length;) {\n const char = format[i]!;\n\n if (char === \"\\\\\") {\n const escape = readEscape(format, i);\n output += escape.text;\n i = escape.nextIndex;\n\n if (escape.stop) {\n return { output, nextArgIndex: argIndex, consumedArgs, stop: true };\n }\n continue;\n }\n\n if (char !== \"%\") {\n output += char;\n i++;\n continue;\n }\n\n if (format[i + 1] === \"%\") {\n output += \"%\";\n i += 2;\n continue;\n }\n\n const parsed = parseConversion(format, i);\n if (parsed.error || !parsed.spec) {\n return {\n output,\n nextArgIndex: argIndex,\n consumedArgs,\n stop: false,\n error: parsed.error ?? \"invalid format\",\n };\n }\n\n const rendered = renderConversion(parsed.spec, args, argIndex);\n output += rendered.output;\n argIndex = rendered.nextArgIndex;\n if (rendered.consumedArg) {\n consumedArgs++;\n }\n i = parsed.nextIndex;\n\n if (rendered.stop) {\n return { output, nextArgIndex: argIndex, consumedArgs, stop: true };\n }\n }\n\n return { output, nextArgIndex: argIndex, consumedArgs, stop: false };\n}\n\nfunction formatPrintf(format: string, args: string[]): FormatResult {\n let output = \"\";\n let argIndex = 0;\n let renderedAtLeastOnce = false;\n\n while (!renderedAtLeastOnce || argIndex < args.length) {\n const pass = renderPass(format, args, argIndex);\n renderedAtLeastOnce = true;\n output += pass.output;\n argIndex = pass.nextArgIndex;\n\n if (pass.error) {\n return { output, error: pass.error };\n }\n\n if (pass.stop) {\n return { output };\n }\n\n if (pass.consumedArgs === 0) {\n break;\n }\n }\n\n return { output };\n}\n\nexport const printf: Command = async (ctx) => {\n if (ctx.args.length === 0) {\n await ctx.stderr.writeText(\"printf: missing format operand\\n\");\n return 1;\n }\n\n const [format, ...args] = ctx.args;\n const result = formatPrintf(format!, args);\n\n if (result.output.length > 0) {\n await ctx.stdout.writeText(result.output);\n }\n\n if (result.error) {\n await ctx.stderr.writeText(`printf: ${result.error}\\n`);\n return 1;\n }\n\n return 0;\n};\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "E3692C39E2D017E164756E2164756E21",
9
+ "names": []
10
+ }
@@ -1,3 +1,3 @@
1
1
  export * from "./src/index.ts";
2
2
  export { builtinCommands } from "./src/commands/index.ts";
3
- export { echo, cat, grep, wc, head, tail, sort, uniq, pwd, ls, mkdir, rm, test, bracket, trueCmd, falseCmd, touch, cp, mv, tee, tree, find, sed, awk, breakCmd, continueCmd, od, } from "./src/commands/index.ts";
3
+ export { echo, printf, cat, grep, wc, head, tail, sort, uniq, pwd, ls, mkdir, rm, test, bracket, trueCmd, falseCmd, touch, cp, mv, tee, tree, find, sed, awk, breakCmd, continueCmd, od, } from "./src/commands/index.ts";
@@ -1,5 +1,6 @@
1
1
  import type { Command } from "../types.ts";
2
2
  export { echo } from "./echo/echo.ts";
3
+ export { printf } from "./printf/printf.ts";
3
4
  export { cat } from "./cat/cat.ts";
4
5
  export { grep } from "./grep/grep.ts";
5
6
  export { wc } from "./wc/wc.ts";
@@ -0,0 +1,2 @@
1
+ import type { Command } from "../../types.ts";
2
+ export declare const printf: Command;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shell-dsl",
3
- "version": "0.0.38",
3
+ "version": "0.0.39",
4
4
  "description": "A sandboxed shell-style DSL for running scriptable command pipelines in-process without host OS access",
5
5
  "author": "ricsam <oss@ricsam.dev>",
6
6
  "license": "MIT",