@tritard/waterbrother 0.14.1 → 0.14.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/cli.js +62 -17
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -4704,29 +4704,74 @@ async function readInteractiveLine(options = {}) {
|
|
|
4704
4704
|
}
|
|
4705
4705
|
}
|
|
4706
4706
|
|
|
4707
|
+
// Track whether keypress handler processed the last data chunk
|
|
4708
|
+
let keypressHandled = false;
|
|
4709
|
+
const origOnKeypress = onKeypress;
|
|
4710
|
+
onKeypress = function (str, key) {
|
|
4711
|
+
keypressHandled = true;
|
|
4712
|
+
origOnKeypress(str, key);
|
|
4713
|
+
};
|
|
4714
|
+
|
|
4707
4715
|
function onData(chunk) {
|
|
4708
4716
|
if (settled) return;
|
|
4709
4717
|
const text = String(chunk || "");
|
|
4710
4718
|
if (!text) return;
|
|
4711
|
-
const normalized = normalizePastedChunk(text);
|
|
4712
|
-
const looksLikeBracketedPaste = text.includes("\x1b[200~") || text.includes("\x1b[201~");
|
|
4713
|
-
const looksLikePastedBlock =
|
|
4714
|
-
looksLikeBracketedPaste ||
|
|
4715
|
-
(normalized.length > 1 && normalized.includes("\n") && /[^\n]/.test(normalized));
|
|
4716
|
-
|
|
4717
|
-
if (!looksLikePastedBlock) {
|
|
4718
|
-
return;
|
|
4719
|
-
}
|
|
4720
4719
|
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4720
|
+
// Give keypress handler a chance to fire first (it's synchronous)
|
|
4721
|
+
keypressHandled = false;
|
|
4722
|
+
// readline.emitKeypressEvents will fire onKeypress synchronously before onData returns
|
|
4723
|
+
// on some platforms. Set a microtask to check if keypress handled it.
|
|
4724
|
+
Promise.resolve().then(() => {
|
|
4725
|
+
if (keypressHandled || settled) return;
|
|
4726
|
+
|
|
4727
|
+
// Keypress didn't fire — handle raw data as fallback
|
|
4728
|
+
const normalized = normalizePastedChunk(text);
|
|
4729
|
+
const looksLikeBracketedPaste = text.includes("\x1b[200~") || text.includes("\x1b[201~");
|
|
4730
|
+
const looksLikePastedBlock =
|
|
4731
|
+
looksLikeBracketedPaste ||
|
|
4732
|
+
(normalized.length > 1 && normalized.includes("\n") && /[^\n]/.test(normalized));
|
|
4733
|
+
|
|
4734
|
+
if (looksLikePastedBlock) {
|
|
4735
|
+
if (normalized) {
|
|
4736
|
+
buffer += normalized;
|
|
4737
|
+
selectedIndex = 0;
|
|
4738
|
+
render();
|
|
4739
|
+
}
|
|
4740
|
+
ignoredPastePrintable += [...normalized].filter((char) => char !== "\n").length;
|
|
4741
|
+
ignoredPasteEnters += (normalized.match(/\n/g) || []).length;
|
|
4742
|
+
pasteSuppressUntil = Date.now() + 300;
|
|
4743
|
+
return;
|
|
4744
|
+
}
|
|
4726
4745
|
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4746
|
+
// Single character fallback — keypress emitter failed to fire
|
|
4747
|
+
for (const ch of text) {
|
|
4748
|
+
if (ch === "\r" || ch === "\n") {
|
|
4749
|
+
handleSubmit();
|
|
4750
|
+
return;
|
|
4751
|
+
}
|
|
4752
|
+
if (ch === "\u0003") {
|
|
4753
|
+
if (settled) return;
|
|
4754
|
+
settled = true;
|
|
4755
|
+
cleanup();
|
|
4756
|
+
output.write("\n");
|
|
4757
|
+
reject(new Error("Interrupted"));
|
|
4758
|
+
return;
|
|
4759
|
+
}
|
|
4760
|
+
if (ch === "\u007f" || ch === "\b") {
|
|
4761
|
+
if (buffer.length > 0) {
|
|
4762
|
+
buffer = buffer.slice(0, -1);
|
|
4763
|
+
selectedIndex = 0;
|
|
4764
|
+
render();
|
|
4765
|
+
}
|
|
4766
|
+
continue;
|
|
4767
|
+
}
|
|
4768
|
+
if (ch.charCodeAt(0) < 32 || ch.charCodeAt(0) === 127) continue;
|
|
4769
|
+
if (ch.includes("\x1b")) continue;
|
|
4770
|
+
buffer += ch;
|
|
4771
|
+
selectedIndex = 0;
|
|
4772
|
+
render();
|
|
4773
|
+
}
|
|
4774
|
+
});
|
|
4730
4775
|
}
|
|
4731
4776
|
|
|
4732
4777
|
// Ensure stdin is in a clean state before attaching listeners.
|