buninu-linux 0.8.55 → 0.9.56

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.
Files changed (52) hide show
  1. package/NOTICE.md +46 -46
  2. package/README.md +7 -6
  3. package/initramfs/bin/tar +34 -46
  4. package/initramfs/buninu/apps/bunmsh/CHANGELOG.md +103 -0
  5. package/initramfs/buninu/apps/bunmsh/PORTING.md +133 -15
  6. package/initramfs/buninu/apps/bunmsh/help/awk.md +38 -0
  7. package/initramfs/buninu/apps/bunmsh/help/break.md +21 -0
  8. package/initramfs/buninu/apps/bunmsh/help/chmod.md +8 -2
  9. package/initramfs/buninu/apps/bunmsh/help/cmp.md +29 -0
  10. package/initramfs/buninu/apps/bunmsh/help/continue.md +22 -0
  11. package/initramfs/buninu/apps/bunmsh/help/cp.md +4 -0
  12. package/initramfs/buninu/apps/bunmsh/help/diff.md +30 -0
  13. package/initramfs/buninu/apps/bunmsh/help/egrep.md +26 -0
  14. package/initramfs/buninu/apps/bunmsh/help/export.md +2 -2
  15. package/initramfs/buninu/apps/bunmsh/help/expr.md +30 -0
  16. package/initramfs/buninu/apps/bunmsh/help/fgrep.md +25 -0
  17. package/initramfs/buninu/apps/bunmsh/help/grep.md +4 -0
  18. package/initramfs/buninu/apps/bunmsh/help/ls.md +4 -2
  19. package/initramfs/buninu/apps/bunmsh/help/mkdir.md +1 -1
  20. package/initramfs/buninu/apps/bunmsh/help/print.md +3 -0
  21. package/initramfs/buninu/apps/bunmsh/help/return.md +23 -0
  22. package/initramfs/buninu/apps/bunmsh/help/sed.md +8 -3
  23. package/initramfs/buninu/apps/bunmsh/help/set.md +12 -3
  24. package/initramfs/buninu/apps/bunmsh/help/tr.md +4 -0
  25. package/initramfs/buninu/apps/bunmsh/help/trap.md +22 -0
  26. package/initramfs/buninu/apps/bunmsh/help/uniq.md +27 -0
  27. package/initramfs/buninu/apps/bunmsh/package.json +1 -1
  28. package/initramfs/buninu/apps/bunmsh/src/awk.js +203 -0
  29. package/initramfs/buninu/apps/bunmsh/src/diff.js +222 -0
  30. package/initramfs/buninu/apps/bunmsh/src/fancy-ls.js +15 -4
  31. package/initramfs/buninu/apps/bunmsh/src/main.js +21 -5
  32. package/initramfs/buninu/apps/bunmsh/src/sed.js +159 -0
  33. package/initramfs/buninu/apps/bunmsh/src/shell.js +1283 -540
  34. package/initramfs/buninu/apps/bunmsh/test/awk-reference.test.js +35 -0
  35. package/initramfs/buninu/apps/bunmsh/test/awk.test.js +62 -0
  36. package/initramfs/buninu/apps/bunmsh/test/posix-bootstrap.test.js +595 -0
  37. package/initramfs/buninu/apps/bunmsh/test/utility-reference-cases.mjs +98 -0
  38. package/initramfs/buninu/apps/bunmsh/test/utility-reference.test.js +23 -0
  39. package/initramfs/buninu/apps/jsgotty/client-kitty.mjs +61 -0
  40. package/initramfs/buninu/apps/jsgotty/client.mjs +16 -0
  41. package/initramfs/buninu/apps/jsgotty/package-lock.json +2 -2
  42. package/initramfs/buninu/apps/jsgotty/package.json +1 -1
  43. package/initramfs/buninu/apps/jsgotty/tests/client-kitty.test.mjs +43 -0
  44. package/initramfs/etc/resolv.conf +2 -1
  45. package/initramfs/usr/share/doc/buninu-linux/tar.md +12 -1
  46. package/package.json +1 -1
  47. package/scripts/arch.js +5 -5
  48. package/scripts/arch.sh +5 -5
  49. package/scripts/fetch.js +2 -0
  50. package/scripts/npm-packages.md +4 -3
  51. package/test/fetch-npm.test.js +1 -1
  52. package/test/tar-strip.test.js +36 -0
@@ -0,0 +1,159 @@
1
+ // The fallback operates on pattern/hold spaces, with a program counter for
2
+ // branches. Parsing delimiters before command separators preserves s/;/x/.
3
+ export function compileSed(script, regexSource) {
4
+ let i = 0, lastPattern = null;
5
+ const commands = [], groups = [], labels = new Map();
6
+ const space = () => { while (/[ \t\r]/.test(script[i] ?? "") && i < script.length) i++; };
7
+ const field = delimiter => {
8
+ let value = "";
9
+ for (; i < script.length; i++) {
10
+ const ch = script[i];
11
+ if (ch === delimiter) { i++; return value; }
12
+ if (ch === "\\" && i + 1 < script.length) {
13
+ const next = script[++i];
14
+ value += next === delimiter && !'.*[]^$\\'.includes(next) ? next : `\\${next}`;
15
+ } else value += ch;
16
+ }
17
+ throw new Error("unterminated sed field");
18
+ };
19
+ const regex = pattern => {
20
+ if (pattern) lastPattern = pattern;
21
+ if (lastPattern === null) throw new Error("no previous regular expression");
22
+ return regexSource(lastPattern);
23
+ };
24
+ const address = () => {
25
+ if (script[i] === "$") { i++; return {last:true}; }
26
+ if (/\d/.test(script[i] ?? "")) { const match = /^\d+/.exec(script.slice(i))[0]; i += match.length; return {line:Number(match)}; }
27
+ if (script[i] === "/") { i++; return {regex:new RegExp(regex(field("/")))}; }
28
+ return null;
29
+ };
30
+ while (i < script.length) {
31
+ space();
32
+ if (";\n".includes(script[i])) { i++; continue; }
33
+ if (script[i] === "#") { while (i < script.length && script[i] !== "\n") i++; continue; }
34
+ if (i >= script.length) break;
35
+ const first = address(); space();
36
+ let second = null;
37
+ if (script[i] === ",") { i++; space(); second = address(); if (!second) throw new Error("missing range address"); }
38
+ space(); const invert = script[i] === "!"; if (invert) { i++; space(); }
39
+ const op = script[i++], command = {op, first, second, invert};
40
+ const index = commands.length;
41
+ if (op === "{") groups.push(index);
42
+ else if (op === "}") { const open = groups.pop(); if (open === undefined) throw new Error("unexpected }"); commands[open].end = index; }
43
+ else if (op === "s" || op === "y") {
44
+ const delimiter = script[i++];
45
+ const pattern = field(delimiter), replacement = field(delimiter);
46
+ if (op === "y") {
47
+ const unescape = s => s.replace(/\\n/g,"\n").replace(/\\(.)/g,"$1");
48
+ command.from = unescape(pattern); command.to = unescape(replacement);
49
+ if (command.from.length !== command.to.length) throw new Error("unequal y strings");
50
+ } else {
51
+ const flags = /^[gp0-9]*/.exec(script.slice(i))[0]; i += flags.length;
52
+ command.regex = new RegExp(regex(pattern), "g");
53
+ command.replacement = replacement;
54
+ command.global = flags.includes("g"); command.print = flags.includes("p");
55
+ command.occurrence = Number(/\d+/.exec(flags)?.[0] ?? 1);
56
+ }
57
+ } else if ([":","b","t","T"].includes(op)) {
58
+ space(); const start = i; while (i < script.length && !";\n}".includes(script[i])) i++;
59
+ command.label = script.slice(start,i).trim();
60
+ if (op === ":") labels.set(command.label,index);
61
+ } else if (op === "r") {
62
+ space(); const start=i; while (i<script.length && script[i]!=="\n") i++;
63
+ command.file=script.slice(start,i);
64
+ if (!command.file) throw new Error("r requires a filename");
65
+ } else if (["a","i","c"].includes(op)) {
66
+ space(); if (script[i] === "\\") { i++; if (script[i] === "\n") i++; }
67
+ let text = "";
68
+ while (i < script.length && script[i] !== "\n") {
69
+ if (script[i] === "\\" && script[i+1] === "\n") { text += "\n"; i+=2; }
70
+ else text += script[i++];
71
+ }
72
+ command.text = text;
73
+ } else if (!"pPdDqnhHgGxN=".includes(op ?? "")) throw new Error(`unsupported sed command: ${op}`);
74
+ commands.push(command);
75
+ }
76
+ if (groups.length) throw new Error("unclosed sed group");
77
+ for (const command of commands) if (["b","t","T"].includes(command.op)) {
78
+ command.target = command.label ? labels.get(command.label) : commands.length;
79
+ if (command.target === undefined) throw new Error(`undefined sed label: ${command.label}`);
80
+ }
81
+ return commands;
82
+ }
83
+
84
+ function replacementText(template, args) {
85
+ let output = "";
86
+ for (let i = 0; i < template.length; i++) {
87
+ if (template[i] === "&") output += args[0];
88
+ else if (template[i] === "\\" && i + 1 < template.length) {
89
+ const ch = template[++i];
90
+ output += /[1-9]/.test(ch) ? (args[Number(ch)] ?? "") : ch === "n" ? "\n" : ch;
91
+ } else output += template[i];
92
+ }
93
+ return output;
94
+ }
95
+
96
+ export function applySed(text, commands, quiet, readFile = () => "") {
97
+ if (!text) return "";
98
+ const trailing = text.endsWith("\n"), lines = text.split("\n");
99
+ if (trailing) lines.pop();
100
+ const active = new Set(), output = [];
101
+ let hold = "";
102
+ for (let index = 0; index < lines.length; index++) {
103
+ let pattern = lines[index], deleted = false, changed = false, quit = false;
104
+ const appended = [];
105
+ const emit = value => output.push(value + (index < lines.length-1 || trailing ? "\n" : ""));
106
+ const matches = a => a.last ? index === lines.length-1 : a.line !== undefined ? index+1 === a.line : a.regex.test(pattern);
107
+ for (let pc = 0; pc < commands.length; pc++) {
108
+ const c = commands[pc];
109
+ let selected = !c.first || matches(c.first);
110
+ if (c.second) {
111
+ const wasActive = active.has(pc);
112
+ selected ||= wasActive;
113
+ if (selected) {
114
+ active.add(pc);
115
+ if ((wasActive || !c.second.regex) && (c.second.line !== undefined ? index+1 >= c.second.line : matches(c.second))) active.delete(pc);
116
+ }
117
+ }
118
+ if (c.invert) selected = !selected;
119
+ if (!selected) { if (c.op === "{") pc = c.end; continue; }
120
+ if (c.op === "s") {
121
+ let count = 0, replaced = false;
122
+ pattern = pattern.replace(c.regex,(...args) => {
123
+ count++;
124
+ if (count !== c.occurrence && !(c.global && count >= c.occurrence)) return args[0];
125
+ replaced = true; return replacementText(c.replacement,args);
126
+ });
127
+ changed ||= replaced;
128
+ if (replaced && c.print) emit(pattern);
129
+ } else if (c.op === "y") pattern = [...pattern].map(ch => { const at=c.from.indexOf(ch); return at<0 ? ch : c.to[at]; }).join("");
130
+ else if (c.op === "p") emit(pattern);
131
+ else if (c.op === "P") emit(pattern.split("\n")[0]);
132
+ else if (c.op === "=") emit(String(index+1));
133
+ else if (c.op === "h") hold = pattern;
134
+ else if (c.op === "H") hold += "\n" + pattern;
135
+ else if (c.op === "g") pattern = hold;
136
+ else if (c.op === "G") pattern += "\n" + hold;
137
+ else if (c.op === "x") [pattern,hold] = [hold,pattern];
138
+ else if (c.op === "d") { deleted=true; break; }
139
+ else if (c.op === "D") { const nl=pattern.indexOf("\n"); if (nl<0) { deleted=true; break; } pattern=pattern.slice(nl+1); pc=-1; }
140
+ else if (c.op === "q") { quit=true; break; }
141
+ else if (c.op === "n" || c.op === "N") {
142
+ if (c.op === "n" && !quiet) emit(pattern);
143
+ if (index+1 >= lines.length) { deleted = c.op === "n"; quit=true; break; }
144
+ pattern = (c.op === "N" ? pattern + "\n" : "") + lines[++index]; changed=false;
145
+ } else if (["b","t","T"].includes(c.op)) {
146
+ const take = c.op === "b" || (c.op === "t" ? changed : !changed);
147
+ if (c.op !== "b") changed=false;
148
+ if (take) pc=c.target-1;
149
+ } else if (c.op === "r") appended.push(readFile(c.file));
150
+ else if (c.op === "a") appended.push(c.text+"\n");
151
+ else if (c.op === "i") output.push(c.text+"\n");
152
+ else if (c.op === "c") { if (!c.second || !active.has(pc)) output.push(c.text+"\n"); deleted=true; break; }
153
+ }
154
+ if (!quiet && !deleted) emit(pattern);
155
+ output.push(...appended);
156
+ if (quit) break;
157
+ }
158
+ return output.join("");
159
+ }