@noobdemon/noob-cli 1.0.1 → 1.0.2
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/package.json +1 -1
- package/src/repl.js +38 -34
package/package.json
CHANGED
package/src/repl.js
CHANGED
|
@@ -19,31 +19,43 @@ export async function startRepl(opts = {}) {
|
|
|
19
19
|
yolo: !!opts.yolo,
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
22
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, prompt: "" });
|
|
23
23
|
let closed = false;
|
|
24
|
-
|
|
25
|
-
let
|
|
26
|
-
|
|
24
|
+
const queue = []; // lines typed/piped, consumed in order
|
|
25
|
+
let waiter = null; // resolver awaiting the next line
|
|
26
|
+
|
|
27
|
+
rl.on("line", (line) => {
|
|
28
|
+
if (waiter) {
|
|
29
|
+
const w = waiter;
|
|
30
|
+
waiter = null;
|
|
31
|
+
w(line);
|
|
32
|
+
} else {
|
|
33
|
+
queue.push(line); // type-ahead / buffered input — never dropped
|
|
34
|
+
}
|
|
35
|
+
});
|
|
27
36
|
rl.on("close", () => {
|
|
28
37
|
closed = true;
|
|
29
|
-
if (
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
if (waiter) {
|
|
39
|
+
const w = waiter;
|
|
40
|
+
waiter = null;
|
|
41
|
+
w(null);
|
|
33
42
|
}
|
|
34
43
|
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
|
|
45
|
+
// Robust input: every line is captured by the 'line' event (nothing is lost
|
|
46
|
+
// while a turn is processing) and handed out one at a time. Works for an
|
|
47
|
+
// interactive TTY and for piped / non-TTY stdin (Git Bash, CI, etc.).
|
|
48
|
+
function nextLine() {
|
|
49
|
+
if (queue.length) return Promise.resolve(queue.shift());
|
|
50
|
+
if (closed) return Promise.resolve(null);
|
|
51
|
+
return new Promise((res) => (waiter = res));
|
|
52
|
+
}
|
|
53
|
+
function ask(promptStr) {
|
|
54
|
+
if (closed && !queue.length) return Promise.resolve(null);
|
|
55
|
+
rl.setPrompt(promptStr);
|
|
56
|
+
rl.prompt();
|
|
57
|
+
return nextLine();
|
|
58
|
+
}
|
|
47
59
|
|
|
48
60
|
// Shift+Tab — quick yolo toggle.
|
|
49
61
|
if (process.stdin.isTTY) {
|
|
@@ -51,16 +63,8 @@ export async function startRepl(opts = {}) {
|
|
|
51
63
|
process.stdin.on("keypress", (_str, key) => {
|
|
52
64
|
if (!key || key.name !== "tab" || !key.shift) return;
|
|
53
65
|
state.yolo = !state.yolo;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const buf = rl.line;
|
|
57
|
-
readline.cursorTo(process.stdout, 0);
|
|
58
|
-
readline.clearLine(process.stdout, 0);
|
|
59
|
-
console.log(msg);
|
|
60
|
-
process.stdout.write(lastPrompt + buf);
|
|
61
|
-
} else {
|
|
62
|
-
console.log("\n" + msg);
|
|
63
|
-
}
|
|
66
|
+
console.log(state.yolo ? c.err("\n " + t.yoloOn) : c.ok("\n " + t.yoloOff));
|
|
67
|
+
rl.prompt(true);
|
|
64
68
|
});
|
|
65
69
|
}
|
|
66
70
|
|
|
@@ -71,7 +75,7 @@ export async function startRepl(opts = {}) {
|
|
|
71
75
|
abort.abort();
|
|
72
76
|
abort = null;
|
|
73
77
|
console.log(c.err("\n ✗ " + t.interrupted));
|
|
74
|
-
return;
|
|
78
|
+
return; // the main loop will redraw the prompt
|
|
75
79
|
}
|
|
76
80
|
if (sigintArmed) {
|
|
77
81
|
console.log(c.dim("\n " + t.bye));
|
|
@@ -80,7 +84,7 @@ export async function startRepl(opts = {}) {
|
|
|
80
84
|
sigintArmed = true;
|
|
81
85
|
console.log(c.dim("\n " + t.pressAgainToExit));
|
|
82
86
|
setTimeout(() => (sigintArmed = false), 2000);
|
|
83
|
-
|
|
87
|
+
rl.prompt(true);
|
|
84
88
|
});
|
|
85
89
|
|
|
86
90
|
banner();
|
|
@@ -94,9 +98,9 @@ export async function startRepl(opts = {}) {
|
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
// Main loop — runs until /exit, double Ctrl+C, or EOF. Never exits after a task.
|
|
97
|
-
while (
|
|
101
|
+
while (true) {
|
|
98
102
|
const raw = await ask(c.user("\n" + t.promptYou) + c.dim("› "));
|
|
99
|
-
if (raw == null) break;
|
|
103
|
+
if (raw == null) break; // stdin fully closed and drained
|
|
100
104
|
const input = raw.trim();
|
|
101
105
|
if (!input) continue;
|
|
102
106
|
if (input.startsWith("/")) {
|