@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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/repl.js +38 -34
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noobdemon/noob-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
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
- let pending = null;
25
- let lastPrompt = "";
26
- let awaitingInput = false;
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 (pending) {
30
- const res = pending;
31
- pending = null;
32
- res(null);
38
+ if (waiter) {
39
+ const w = waiter;
40
+ waiter = null;
41
+ w(null);
33
42
  }
34
43
  });
35
- const ask = (q) =>
36
- new Promise((res) => {
37
- if (closed) return res(null);
38
- lastPrompt = q;
39
- awaitingInput = true;
40
- pending = res;
41
- rl.question(q, (a) => {
42
- pending = null;
43
- awaitingInput = false;
44
- res(a);
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
- const msg = state.yolo ? c.err(" " + t.yoloOn) : c.ok(" " + t.yoloOff);
55
- if (awaitingInput) {
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
- if (awaitingInput) process.stdout.write(lastPrompt + (rl.line || ""));
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 (!closed) {
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("/")) {