buninu 0.4.5 → 0.4.7
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/CHANGELOG.md +71 -1
- package/README.md +545 -223
- package/apps/jsgotty/static/js/kitty.js +66 -13
- package/apps/jsgotty/viu.mjs +29 -0
- package/apps/musl-la/NOTICE +21 -0
- package/bin/init.js +130 -28
- package/bin/multicall.sh +7 -5
- package/package.json +24 -1
- package/apps/musl-la/LICENSES/Apache-2.0_LLVM_Exceptions_license.txt +0 -311
- package/apps/musl-la/LICENSES/Apache-2.0_license.txt +0 -177
- package/apps/musl-la/LICENSES/BSD-3-Clause_license.txt +0 -43
- package/apps/musl-la/LICENSES/LGPL-3.0.txt +0 -165
- package/apps/musl-la/LICENSES/MIT.txt +0 -21
- package/apps/musl-la/LICENSES/curl_license.txt +0 -22
- package/apps/musl-la/LICENSES/zlib_license.txt +0 -22
|
@@ -20,9 +20,32 @@
|
|
|
20
20
|
touchScroll: null,
|
|
21
21
|
contextMenu: null,
|
|
22
22
|
imageContextBound: false,
|
|
23
|
-
socket: null
|
|
23
|
+
socket: null,
|
|
24
|
+
// False until the client has sent its first resize. Until then cols/rows
|
|
25
|
+
// above are placeholders, not the PTY's real geometry.
|
|
26
|
+
sizeFromClient: false
|
|
24
27
|
};
|
|
25
28
|
|
|
29
|
+
// The PTY size only reaches us through the resize messages the client
|
|
30
|
+
// sends. A placement that arrives before the first of those would be laid
|
|
31
|
+
// out against 80x24 instead of the terminal the user is looking at, so
|
|
32
|
+
// borrow xterm's own geometry until the real size shows up.
|
|
33
|
+
function syncViewerSize() {
|
|
34
|
+
if (state.sizeFromClient) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const xterm = terminal && terminal.__gottyXterm;
|
|
38
|
+
if (!xterm) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (Number.isFinite(xterm.cols) && xterm.cols > 0) {
|
|
42
|
+
state.cols = xterm.cols;
|
|
43
|
+
}
|
|
44
|
+
if (Number.isFinite(xterm.rows) && xterm.rows > 0) {
|
|
45
|
+
state.rows = xterm.rows;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
26
49
|
function browserTerminalState() {
|
|
27
50
|
const xterm = terminal && terminal.__gottyXterm;
|
|
28
51
|
const active = xterm && xterm.buffer && xterm.buffer.active;
|
|
@@ -152,6 +175,7 @@
|
|
|
152
175
|
}
|
|
153
176
|
|
|
154
177
|
function createPlacementMarker(cursor) {
|
|
178
|
+
syncViewerSize();
|
|
155
179
|
const xterm = terminal && terminal.__gottyXterm;
|
|
156
180
|
if (!xterm || typeof xterm.registerMarker !== "function") {
|
|
157
181
|
return null;
|
|
@@ -372,6 +396,7 @@
|
|
|
372
396
|
return;
|
|
373
397
|
}
|
|
374
398
|
const { control, cursor, intrinsicWidth, intrinsicHeight, sourceRect } = node.__kittyPlacement;
|
|
399
|
+
syncViewerSize();
|
|
375
400
|
const metrics = cellMetrics();
|
|
376
401
|
const anchor = anchorOffset();
|
|
377
402
|
const controlCols = Math.max(0, Number.parseInt(control.c || "0", 10) || 0);
|
|
@@ -825,6 +850,17 @@
|
|
|
825
850
|
const generation = (node.__kittyGeneration || 0) + 1;
|
|
826
851
|
node.__kittyGeneration = generation;
|
|
827
852
|
|
|
853
|
+
// Bind before the decode, not after it. The server sends the placement
|
|
854
|
+
// ahead of the synthetic newlines that scroll room for the image, so the
|
|
855
|
+
// scroll this layout depends on can land while we are still decoding.
|
|
856
|
+
// Binding afterwards left the very first image of a session with no
|
|
857
|
+
// listener to correct it, which is why it could come out blank while
|
|
858
|
+
// every later image in the same session was fine.
|
|
859
|
+
bindViewportScroll();
|
|
860
|
+
bindTerminalRender();
|
|
861
|
+
bindTouchScrolling();
|
|
862
|
+
bindImageContextMenu();
|
|
863
|
+
|
|
828
864
|
const asset = await resolveImageAsset(message.image, control);
|
|
829
865
|
if (!asset || node.__kittyGeneration !== generation) {
|
|
830
866
|
return;
|
|
@@ -839,11 +875,14 @@
|
|
|
839
875
|
intrinsicHeight: asset.height,
|
|
840
876
|
sourceRect: asset.sourceRect,
|
|
841
877
|
};
|
|
842
|
-
node.__kittyImageElement
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
878
|
+
const imageElement = node.__kittyImageElement;
|
|
879
|
+
imageElement.onload = () => {
|
|
880
|
+
imageElement.onload = null;
|
|
881
|
+
if (node.__kittyGeneration === generation) {
|
|
882
|
+
layoutNode(node);
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
imageElement.src = objectUrl;
|
|
847
886
|
layoutNode(node);
|
|
848
887
|
}
|
|
849
888
|
|
|
@@ -995,7 +1034,14 @@
|
|
|
995
1034
|
return nativeRemoveEventListener.call(this, type, listener, options);
|
|
996
1035
|
};
|
|
997
1036
|
|
|
998
|
-
|
|
1037
|
+
// Walk the prototype chain to find the native onmessage descriptor.
|
|
1038
|
+
// Safari/WebKit defines it on a parent prototype (e.g. EventTarget),
|
|
1039
|
+
// not directly on WebSocket.prototype, so a single-level lookup fails.
|
|
1040
|
+
let descriptor = null;
|
|
1041
|
+
for (let proto = WebSocket.prototype; proto; proto = Object.getPrototypeOf(proto)) {
|
|
1042
|
+
descriptor = Object.getOwnPropertyDescriptor(proto, "onmessage");
|
|
1043
|
+
if (descriptor) break;
|
|
1044
|
+
}
|
|
999
1045
|
Object.defineProperty(WebSocket.prototype, "onmessage", {
|
|
1000
1046
|
configurable: true,
|
|
1001
1047
|
enumerable: descriptor ? descriptor.enumerable : true,
|
|
@@ -1004,14 +1050,13 @@
|
|
|
1004
1050
|
},
|
|
1005
1051
|
set(handler) {
|
|
1006
1052
|
this.__kittyOnMessage = handler;
|
|
1007
|
-
if (!descriptor || !descriptor.set) {
|
|
1008
|
-
return;
|
|
1009
|
-
}
|
|
1010
1053
|
if (typeof handler !== "function") {
|
|
1011
|
-
descriptor.set
|
|
1054
|
+
if (descriptor && descriptor.set) {
|
|
1055
|
+
descriptor.set.call(this, handler);
|
|
1056
|
+
}
|
|
1012
1057
|
return;
|
|
1013
1058
|
}
|
|
1014
|
-
|
|
1059
|
+
const wrapped = function (event) {
|
|
1015
1060
|
state.socket = this;
|
|
1016
1061
|
inspectTerminalOutput(event.data);
|
|
1017
1062
|
if (typeof event.data === "string" && event.data[0] === MSG_KITTY) {
|
|
@@ -1020,7 +1065,13 @@
|
|
|
1020
1065
|
}
|
|
1021
1066
|
}
|
|
1022
1067
|
return handler.call(this, event);
|
|
1023
|
-
}
|
|
1068
|
+
};
|
|
1069
|
+
if (descriptor && descriptor.set) {
|
|
1070
|
+
descriptor.set.call(this, wrapped);
|
|
1071
|
+
} else {
|
|
1072
|
+
// Fallback: use addEventListener when no native setter is available.
|
|
1073
|
+
this.addEventListener("message", wrapped);
|
|
1074
|
+
}
|
|
1024
1075
|
}
|
|
1025
1076
|
});
|
|
1026
1077
|
|
|
@@ -1034,9 +1085,11 @@
|
|
|
1034
1085
|
const resize = JSON.parse(data.slice(1));
|
|
1035
1086
|
if (resize.columns) {
|
|
1036
1087
|
state.cols = resize.columns;
|
|
1088
|
+
state.sizeFromClient = true;
|
|
1037
1089
|
}
|
|
1038
1090
|
if (resize.rows) {
|
|
1039
1091
|
state.rows = resize.rows;
|
|
1092
|
+
state.sizeFromClient = true;
|
|
1040
1093
|
}
|
|
1041
1094
|
} catch (error) {
|
|
1042
1095
|
// ignore
|
package/apps/jsgotty/viu.mjs
CHANGED
|
@@ -27,6 +27,34 @@ function usage(exitCode = 0) {
|
|
|
27
27
|
process.exitCode = exitCode;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
// A browser terminal only reports its size to the PTY once the page has laid
|
|
31
|
+
// out, so a window that was just opened, restored, resized or rotated answers
|
|
32
|
+
// with a couple of columns for a few hundred milliseconds. An image sized
|
|
33
|
+
// against that is emitted as a one-cell speck — indistinguishable from the
|
|
34
|
+
// command having printed nothing — while the next run in the same session,
|
|
35
|
+
// by which time the real size has arrived, comes out correct. Give the size a
|
|
36
|
+
// short chance to settle when what we read back is too small to be a terminal
|
|
37
|
+
// anyone could be looking at.
|
|
38
|
+
const MIN_SANE_COLS = 20;
|
|
39
|
+
const MIN_SANE_ROWS = 5;
|
|
40
|
+
const SIZE_SETTLE_TIMEOUT_MS = 400;
|
|
41
|
+
const SIZE_POLL_INTERVAL_MS = 25;
|
|
42
|
+
|
|
43
|
+
function terminalSizeLooksUnset() {
|
|
44
|
+
return (process.stdout.columns || 0) < MIN_SANE_COLS
|
|
45
|
+
|| (process.stdout.rows || 0) < MIN_SANE_ROWS;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function waitForStableTerminalSize() {
|
|
49
|
+
if (!process.stdout.isTTY) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const deadline = Date.now() + SIZE_SETTLE_TIMEOUT_MS;
|
|
53
|
+
while (terminalSizeLooksUnset() && Date.now() < deadline) {
|
|
54
|
+
await new Promise((resolve) => setTimeout(resolve, SIZE_POLL_INTERVAL_MS));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
30
58
|
function fitImageCells(width, height) {
|
|
31
59
|
const terminalCols = Math.max(1, process.stdout.columns || 80);
|
|
32
60
|
const maxCols = Math.max(1, terminalCols - 1);
|
|
@@ -384,6 +412,7 @@ async function main() {
|
|
|
384
412
|
const fullPath = path.resolve(inputPath);
|
|
385
413
|
const buffer = fs.readFileSync(fullPath);
|
|
386
414
|
const image = sniffImage(buffer, fullPath, { compat });
|
|
415
|
+
await waitForStableTerminalSize();
|
|
387
416
|
writeKittyImage(buffer, image.mime, image.width, image.height, compat);
|
|
388
417
|
}
|
|
389
418
|
|
package/apps/musl-la/NOTICE
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
This product includes third-party components:
|
|
2
2
|
|
|
3
|
+
- ld-musl-aarch64.so.1
|
|
4
|
+
License: MIT
|
|
5
|
+
See: ./LICENSE_musl.txt
|
|
6
|
+
|
|
7
|
+
The musl dynamic loader, version 1.2.5, as packaged by Alpine Linux
|
|
8
|
+
(package musl, version 1.2.5-r10, aarch64).
|
|
9
|
+
|
|
10
|
+
Upstream musl source:
|
|
11
|
+
https://musl.libc.org/releases/musl-1.2.5.tar.gz
|
|
12
|
+
|
|
13
|
+
Alpine's CDN serves only the current pkgrel of each branch, and 1.2.5-r10
|
|
14
|
+
has since been superseded, so it is no longer downloadable there. An
|
|
15
|
+
archived copy of that exact build ships in the Alpine aarch64 rootfs
|
|
16
|
+
published by Termux proot-distro, which reports Alpine 3.22.2 and
|
|
17
|
+
musl 1.2.5-r10 in its apk database:
|
|
18
|
+
https://github.com/termux/proot-distro/releases/download/v4.30.1/alpine-aarch64-pd-v4.30.1.tar.xz
|
|
19
|
+
|
|
20
|
+
SHA-256 (verified byte-for-byte identical to lib/ld-musl-aarch64.so.1 in
|
|
21
|
+
that rootfs):
|
|
22
|
+
ld-musl-aarch64.so.1: da9c2d18642cf67ade0947b88b6859385c085fdbc6a022f5a8b518d7677e55df
|
|
23
|
+
|
|
3
24
|
- libgcc_s.so.1 / libstdc++.so.6
|
|
4
25
|
License: GPL-3.0 + GCC Runtime Library Exception
|
|
5
26
|
See: ./LICENSES/GPL-3.0.txt and ./LICENSES/gcc_runtime_exception.txt
|
package/bin/init.js
CHANGED
|
@@ -23,26 +23,73 @@ Usage:
|
|
|
23
23
|
${pkg.name} [init options] [jsgotty options]
|
|
24
24
|
|
|
25
25
|
Init options:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
--
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
--
|
|
45
|
-
|
|
26
|
+
--local
|
|
27
|
+
Start Buninu in this terminal
|
|
28
|
+
instead of a Remote Shell
|
|
29
|
+
reached from a browser
|
|
30
|
+
(via jsgotty, the default)
|
|
31
|
+
|
|
32
|
+
-h, --help
|
|
33
|
+
Show this help and exit
|
|
34
|
+
-V, --version
|
|
35
|
+
Show version & runtime info, then exit
|
|
36
|
+
|
|
37
|
+
--readme
|
|
38
|
+
Render README.md in the terminal and exit
|
|
39
|
+
--changelog
|
|
40
|
+
Render CHANGELOG.md in the terminal and exit
|
|
41
|
+
|
|
42
|
+
--readme-tui
|
|
43
|
+
Open README.md as a Terminal UI
|
|
44
|
+
--readme-wui
|
|
45
|
+
Serve README.md as a Web UI
|
|
46
|
+
|
|
47
|
+
--export [output.tgz]
|
|
48
|
+
Export this Buninu installation
|
|
49
|
+
(default: ./buninu.tgz)
|
|
50
|
+
|
|
51
|
+
--export-config [output.json]
|
|
52
|
+
Export Buninu's package.json
|
|
53
|
+
(default: ./buninu.json)
|
|
54
|
+
|
|
55
|
+
Install options:
|
|
56
|
+
-i, --install [dir]
|
|
57
|
+
Install this package into <dir>/${pkg.name}
|
|
58
|
+
(default: .)
|
|
59
|
+
|
|
60
|
+
-si, --strip-install [dir]
|
|
61
|
+
Install into <dir> directly
|
|
62
|
+
Without a top-level directory of its own
|
|
63
|
+
|
|
64
|
+
(--install --help for full options)
|
|
65
|
+
|
|
66
|
+
Remote Shell options:
|
|
67
|
+
--shell <path|name>
|
|
68
|
+
Override buninu.shell for this run
|
|
69
|
+
--command <command>
|
|
70
|
+
Override buninu.command for this run
|
|
71
|
+
|
|
72
|
+
Direct app launch
|
|
73
|
+
(must be the first argument)
|
|
74
|
+
(skips the shell/command startup flow entirely):
|
|
75
|
+
|
|
76
|
+
--jsgotty [args...]
|
|
77
|
+
Spawn jsgotty directly,
|
|
78
|
+
forwarding remaining arguments,
|
|
79
|
+
and exit with its exit code
|
|
80
|
+
(--jsgotty --help = jsgotty options)
|
|
81
|
+
|
|
82
|
+
--jsmdcui [args...]
|
|
83
|
+
Spawn jsmdcui directly,
|
|
84
|
+
same forwarding behavior
|
|
85
|
+
|
|
86
|
+
--bunmsh [args...]
|
|
87
|
+
Spawn bunmsh directly,
|
|
88
|
+
same forwarding behavior
|
|
89
|
+
|
|
90
|
+
--musl-la [args...]
|
|
91
|
+
Spawn musl-la directly,
|
|
92
|
+
same forwarding behavior
|
|
46
93
|
|
|
47
94
|
Package configuration:
|
|
48
95
|
package.json contains a buninu section for default and platform settings.
|
|
@@ -93,6 +140,16 @@ async function handleInformationArguments(arguments_) {
|
|
|
93
140
|
return true;
|
|
94
141
|
}
|
|
95
142
|
|
|
143
|
+
const markdownUi = arguments_.includes("--readme-tui")
|
|
144
|
+
? "--tui"
|
|
145
|
+
: arguments_.includes("--readme-wui")
|
|
146
|
+
? "--wui"
|
|
147
|
+
: null;
|
|
148
|
+
if (markdownUi) {
|
|
149
|
+
await openReadmeMarkdownUi(markdownUi);
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
|
|
96
153
|
if (arguments_.includes("--changelog")) {
|
|
97
154
|
const changelogPath = resolve(REPO_ROOT, "CHANGELOG.md");
|
|
98
155
|
if (!await pathExists(changelogPath)) fail(`CHANGELOG not found: ${changelogPath}`);
|
|
@@ -105,6 +162,47 @@ async function handleInformationArguments(arguments_) {
|
|
|
105
162
|
return false;
|
|
106
163
|
}
|
|
107
164
|
|
|
165
|
+
// jsmdcui writes five generated companion files beside the Markdown it opens
|
|
166
|
+
// (`*.md.front.js`, `*.md.back.js`, `*.md.html`, `*.md-rpc.js`,
|
|
167
|
+
// `*.md-server.js`), and needs that directory to be writable. Run it on a copy
|
|
168
|
+
// under TMPDIR rather than on README.md in place: an installation is the
|
|
169
|
+
// user's to keep, `--export` would carry the generated files to another
|
|
170
|
+
// machine, an update never deletes them again, and under `npx` the package
|
|
171
|
+
// directory is a cache that should not be written to at all. Nothing is lost
|
|
172
|
+
// by the move -- the README's only image is a remote URL, and what makes it
|
|
173
|
+
// navigable is same-document `#heading-id` links, which resolve wherever the
|
|
174
|
+
// file sits.
|
|
175
|
+
async function openReadmeMarkdownUi(mode) {
|
|
176
|
+
const readmePath = resolve(REPO_ROOT, "README.md");
|
|
177
|
+
if (!await pathExists(readmePath)) fail(`README not found: ${readmePath}`);
|
|
178
|
+
|
|
179
|
+
const entry = resolve(rootDir, "apps", "jsmdcui", "src", "index.js");
|
|
180
|
+
if (!await pathExists(entry)) fail(`jsmdcui not found: ${entry}`);
|
|
181
|
+
|
|
182
|
+
const environment = await detectEnvironment();
|
|
183
|
+
const workDir = resolve(resolveTmpDir(environment), "buninu-readme");
|
|
184
|
+
// Start from a clean directory so a stale generated file from an older
|
|
185
|
+
// README can never be served in place of a freshly generated one.
|
|
186
|
+
rmSync(workDir, { recursive: true, force: true });
|
|
187
|
+
mkdirSync(workDir, { recursive: true });
|
|
188
|
+
|
|
189
|
+
const target = resolve(workDir, "README.md");
|
|
190
|
+
await Bun.write(target, Bun.file(readmePath));
|
|
191
|
+
|
|
192
|
+
// jsmdcui's entry point is a bundled CLI with no exports: it reads
|
|
193
|
+
// process.argv at the top level and runs. Set the argv it expects and import
|
|
194
|
+
// it, so this stays one process instead of spawning a second Bun.
|
|
195
|
+
process.argv = [process.argv[0], entry, mode, target];
|
|
196
|
+
await import(entry);
|
|
197
|
+
|
|
198
|
+
// jsmdcui owns the process from here on: it holds the terminal UI, or the
|
|
199
|
+
// Web UI server, open. Never resolve -- returning would hand control back to
|
|
200
|
+
// the caller, whose process.exit(0) would cut the UI off before it draws.
|
|
201
|
+
// This keeps no handle of its own, so once jsmdcui's are gone the process
|
|
202
|
+
// still ends on its own.
|
|
203
|
+
await new Promise(() => {});
|
|
204
|
+
}
|
|
205
|
+
|
|
108
206
|
function readExportArgument(arguments_) {
|
|
109
207
|
for (let index = 0; index < arguments_.length; index += 1) {
|
|
110
208
|
const argument = arguments_[index];
|
|
@@ -418,16 +516,19 @@ function configuredXdgDataHome() {
|
|
|
418
516
|
return isAbsolute(configured) ? configured : resolve(rootDir, configured);
|
|
419
517
|
}
|
|
420
518
|
|
|
421
|
-
|
|
422
|
-
const
|
|
423
|
-
|
|
424
|
-
const tmpDir = process.env.TMPDIR || (
|
|
519
|
+
function resolveTmpDir(environment) {
|
|
520
|
+
const androidCacheDir = resolve(dirname(rootDir), "cache");
|
|
521
|
+
return process.env.TMPDIR || (
|
|
425
522
|
environment.name === "android"
|
|
426
523
|
? existsSync(androidCacheDir)
|
|
427
524
|
? androidCacheDir
|
|
428
525
|
: resolve(rootDir, "tmp")
|
|
429
526
|
: systemTmpDir()
|
|
430
527
|
);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
async function createChildEnvironment(environment) {
|
|
531
|
+
const tmpDir = resolveTmpDir(environment);
|
|
431
532
|
const homeDir = process.env.HOME || homedir() || rootDir;
|
|
432
533
|
const envFile = await pathExists(resolve(rootDir, ".bashrc"))
|
|
433
534
|
? resolve(rootDir, ".bashrc")
|
|
@@ -474,6 +575,7 @@ async function createChildEnvironment(environment) {
|
|
|
474
575
|
const directAppTargets = {
|
|
475
576
|
"--jsgotty": "jsgotty",
|
|
476
577
|
"--jsmdcui": "jsmdcui",
|
|
578
|
+
"--bunmsh": "bunmsh",
|
|
477
579
|
"--musl-la": "musl-la",
|
|
478
580
|
};
|
|
479
581
|
|
|
@@ -557,10 +659,10 @@ function shellCommandArguments(shell, command, exitAfterCmd) {
|
|
|
557
659
|
}
|
|
558
660
|
|
|
559
661
|
const wrapped =
|
|
560
|
-
`buninu_command=$1; shift; ( eval "$buninu_command" );
|
|
561
|
-
`if [ "$
|
|
562
|
-
`echo "buninu: startup command failed with exit $
|
|
563
|
-
(exitAfterCmd ? `fi; exit "$
|
|
662
|
+
`buninu_command=$1; shift; ( eval "$buninu_command" ); _buninu_status=$?; ` +
|
|
663
|
+
`if [ "$_buninu_status" -ne 0 ]; then ` +
|
|
664
|
+
`echo "buninu: startup command failed with exit $_buninu_status" >&2; ` +
|
|
665
|
+
(exitAfterCmd ? `fi; exit "$_buninu_status"` : `fi; exec "$0"`);
|
|
564
666
|
// Pass both the shell and startup command as argv instead of interpolating
|
|
565
667
|
// them into the wrapper. This keeps the wrapper single-line and avoids LF
|
|
566
668
|
// (Ctrl+J) characters in its process-list representation.
|
package/bin/multicall.sh
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
caller=$(echo "$args" | head -n 1)
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
if [ -f /proc/$$/cmdline ] ; then
|
|
4
|
+
args=$(tr '\0' '\n' < /proc/$$/cmdline)
|
|
5
|
+
caller=$(echo "$args" | head -n 1)
|
|
6
|
+
callerb=$(basename "$caller")
|
|
7
|
+
else
|
|
8
|
+
callerb=$(basename "$0")
|
|
9
|
+
fi
|
|
8
10
|
|
|
9
11
|
if [ "$callerb" = sh ] ; then
|
|
10
12
|
callerb=$(basename "$0")
|
package/package.json
CHANGED
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "buninu",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"description": "Buninu is a portable, self-bootstrapping Unix-like userspace built on Bun that runs across operating systems",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./bin/init.js",
|
|
7
7
|
"license": "MIT",
|
|
8
|
+
"author": "Dr. John (醫者小智)",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/jjtseng93/buninu.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/jjtseng93/buninu#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/jjtseng93/buninu/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"bun",
|
|
19
|
+
"terminal",
|
|
20
|
+
"web-terminal",
|
|
21
|
+
"browser-terminal",
|
|
22
|
+
"shell",
|
|
23
|
+
"userspace",
|
|
24
|
+
"portable",
|
|
25
|
+
"cross-platform",
|
|
26
|
+
"android",
|
|
27
|
+
"termux",
|
|
28
|
+
"pty",
|
|
29
|
+
"self-bootstrapping"
|
|
30
|
+
],
|
|
8
31
|
"bin": {
|
|
9
32
|
"buninu": "bin/init.js"
|
|
10
33
|
},
|