@oxecli/oxe 1.0.68 → 1.0.69
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/dist/ui.js +44 -30
- package/package.json +1 -1
package/dist/ui.js
CHANGED
|
@@ -9,7 +9,7 @@ export function enableRawStdin() {
|
|
|
9
9
|
readline.emitKeypressEvents(process.stdin);
|
|
10
10
|
if (process.stdin.isTTY) {
|
|
11
11
|
process.stdin.setRawMode(true);
|
|
12
|
-
process.stdout.write("\x1b[
|
|
12
|
+
process.stdout.write("\x1b[>1u");
|
|
13
13
|
}
|
|
14
14
|
process.stdin.resume();
|
|
15
15
|
hideCursor();
|
|
@@ -927,7 +927,7 @@ export function renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor
|
|
|
927
927
|
* application (SS3): ESC O M
|
|
928
928
|
* win32-input-mode: ESC [ G ; R ; C ; VK ; MOD u
|
|
929
929
|
* (VK = 13 for Enter, MOD = raw bitmask where
|
|
930
|
-
*
|
|
930
|
+
* bit2 = Shift)
|
|
931
931
|
*/
|
|
932
932
|
function parseEnterSequence(seq) {
|
|
933
933
|
if (!seq)
|
|
@@ -939,7 +939,7 @@ function parseEnterSequence(seq) {
|
|
|
939
939
|
if (vk !== 13)
|
|
940
940
|
return null;
|
|
941
941
|
const mod = parseInt(m[5], 10);
|
|
942
|
-
return mod &
|
|
942
|
+
return mod & 4 ? "newline" : "submit";
|
|
943
943
|
}
|
|
944
944
|
// modifyOtherKeys / kitty: ESC [ 27 ; M ; 13 ~ (or _)
|
|
945
945
|
m = seq.match(/^\x1b\[27;(\d+);13[~_]$/);
|
|
@@ -1045,9 +1045,10 @@ function decodeWin32Key(seq) {
|
|
|
1045
1045
|
return null;
|
|
1046
1046
|
const vk = parseInt(m[4], 10);
|
|
1047
1047
|
const mod = parseInt(m[5], 10);
|
|
1048
|
-
|
|
1049
|
-
const
|
|
1050
|
-
const
|
|
1048
|
+
// win32-input-mode MOD bitmask: bit2 = Shift, bit1 = Ctrl, bit0 = Alt
|
|
1049
|
+
const shift = (mod & 4) === 4;
|
|
1050
|
+
const ctrl = (mod & 2) === 2;
|
|
1051
|
+
const alt = (mod & 1) === 1;
|
|
1051
1052
|
const cmd = (c) => ({ type: "cmd", cmd: c });
|
|
1052
1053
|
const text = (t) => ({ type: "text", text: t });
|
|
1053
1054
|
// Control combos
|
|
@@ -1141,10 +1142,14 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
1141
1142
|
if (process.stdin.isTTY) {
|
|
1142
1143
|
process.stdin.setRawMode(true);
|
|
1143
1144
|
process.stdout.write("\x1b[?2004h");
|
|
1144
|
-
// Enable
|
|
1145
|
-
//
|
|
1146
|
-
//
|
|
1147
|
-
|
|
1145
|
+
// Enable CSI-u disambiguation so Shift+Enter arrives as a distinct code
|
|
1146
|
+
// (`\x1b[13;2u`) instead of a plain Enter. Plain keys still arrive as
|
|
1147
|
+
// single keypress events. Deliberately NOT enabling win32-input-mode
|
|
1148
|
+
// (`\x1b[?9001h`): it rewrites EVERY keystroke into a long CSI sequence
|
|
1149
|
+
// that readline splits across many events, and an interrupted split
|
|
1150
|
+
// leaves modSeq stuck so the next keystroke is silently dropped —
|
|
1151
|
+
// that regression made typing in the prompt impossible.
|
|
1152
|
+
process.stdout.write("\x1b[>1u");
|
|
1148
1153
|
}
|
|
1149
1154
|
process.stdin.resume();
|
|
1150
1155
|
hideCursor();
|
|
@@ -1167,7 +1172,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
1167
1172
|
if (done)
|
|
1168
1173
|
return;
|
|
1169
1174
|
done = true;
|
|
1170
|
-
process.stdout.write("\x1b[?2004l
|
|
1175
|
+
process.stdout.write("\x1b[?2004l");
|
|
1171
1176
|
process.stdin.setRawMode(false);
|
|
1172
1177
|
if (pasteBurstTimer)
|
|
1173
1178
|
clearTimeout(pasteBurstTimer);
|
|
@@ -1586,26 +1591,15 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
1586
1591
|
}
|
|
1587
1592
|
};
|
|
1588
1593
|
const onKeypress = (str, key) => {
|
|
1589
|
-
// Reassemble modifier-prefixed
|
|
1590
|
-
//
|
|
1591
|
-
//
|
|
1592
|
-
// sequence
|
|
1593
|
-
//
|
|
1594
|
-
//
|
|
1594
|
+
// Reassemble modifier-prefixed CSI sequences that Node's readline may
|
|
1595
|
+
// split across keypress events (e.g. `\x1b[13;2u` arriving as `\x1b[13;2`
|
|
1596
|
+
// + "u"). Only start/continue accumulation on bytes that can belong to a
|
|
1597
|
+
// CSI sequence: digits / `;` while incomplete, or a terminator byte
|
|
1598
|
+
// [A-Z~_u] that completes it. Any other keystroke (a typed letter, for
|
|
1599
|
+
// instance) ABANDONS the partial instead of being swallowed, so a stuck
|
|
1600
|
+
// partial can never eat input.
|
|
1595
1601
|
const seq = key?.sequence || str || "";
|
|
1596
|
-
if (
|
|
1597
|
-
modSeq += str || seq || "";
|
|
1598
|
-
if (/^\x1b\[[\d;]*[a-zA-Z~_u]$/.test(modSeq)) {
|
|
1599
|
-
const full = modSeq;
|
|
1600
|
-
modSeq = "";
|
|
1601
|
-
if (modSeqTimeout)
|
|
1602
|
-
clearTimeout(modSeqTimeout);
|
|
1603
|
-
modSeqTimeout = null;
|
|
1604
|
-
handleRawSequence(full);
|
|
1605
|
-
}
|
|
1606
|
-
return;
|
|
1607
|
-
}
|
|
1608
|
-
if (/^\x1b\[[\d;]*$/.test(seq)) {
|
|
1602
|
+
if (seq.startsWith("\x1b[") && /^\x1b\[[\d;]*$/.test(seq)) {
|
|
1609
1603
|
modSeq = seq;
|
|
1610
1604
|
if (modSeqTimeout)
|
|
1611
1605
|
clearTimeout(modSeqTimeout);
|
|
@@ -1615,6 +1609,26 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
1615
1609
|
}, 200);
|
|
1616
1610
|
return;
|
|
1617
1611
|
}
|
|
1612
|
+
if (modSeq) {
|
|
1613
|
+
const s = str ?? seq ?? "";
|
|
1614
|
+
const completes = /^\x1b\[[\d;]*[A-Z~_u]$/.test(modSeq + s);
|
|
1615
|
+
if (/^[0-9;]$/.test(s) || completes) {
|
|
1616
|
+
modSeq += s;
|
|
1617
|
+
if (completes) {
|
|
1618
|
+
const full = modSeq;
|
|
1619
|
+
modSeq = "";
|
|
1620
|
+
if (modSeqTimeout)
|
|
1621
|
+
clearTimeout(modSeqTimeout);
|
|
1622
|
+
modSeqTimeout = null;
|
|
1623
|
+
handleRawSequence(full);
|
|
1624
|
+
}
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
modSeq = "";
|
|
1628
|
+
if (modSeqTimeout)
|
|
1629
|
+
clearTimeout(modSeqTimeout);
|
|
1630
|
+
modSeqTimeout = null;
|
|
1631
|
+
}
|
|
1618
1632
|
if (consumeBracketedPaste(str, key))
|
|
1619
1633
|
return;
|
|
1620
1634
|
if (pasteBurst && str && str.length === 1 && !key?.ctrl && !key?.meta) {
|