@oxecli/oxe 1.0.67 → 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 +52 -26
- 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
|
|
@@ -1136,14 +1137,19 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
1136
1137
|
// `\x1b[27;2;13~`), which Node's readline splits into several keypress
|
|
1137
1138
|
// events instead of one, so they must be reassembled here.
|
|
1138
1139
|
let modSeq = "";
|
|
1140
|
+
let modSeqTimeout = null;
|
|
1139
1141
|
readline.emitKeypressEvents(process.stdin);
|
|
1140
1142
|
if (process.stdin.isTTY) {
|
|
1141
1143
|
process.stdin.setRawMode(true);
|
|
1142
1144
|
process.stdout.write("\x1b[?2004h");
|
|
1143
|
-
// Enable
|
|
1144
|
-
//
|
|
1145
|
-
//
|
|
1146
|
-
|
|
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");
|
|
1147
1153
|
}
|
|
1148
1154
|
process.stdin.resume();
|
|
1149
1155
|
hideCursor();
|
|
@@ -1166,10 +1172,12 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
1166
1172
|
if (done)
|
|
1167
1173
|
return;
|
|
1168
1174
|
done = true;
|
|
1169
|
-
process.stdout.write("\x1b[?2004l
|
|
1175
|
+
process.stdout.write("\x1b[?2004l");
|
|
1170
1176
|
process.stdin.setRawMode(false);
|
|
1171
1177
|
if (pasteBurstTimer)
|
|
1172
1178
|
clearTimeout(pasteBurstTimer);
|
|
1179
|
+
if (modSeqTimeout)
|
|
1180
|
+
clearTimeout(modSeqTimeout);
|
|
1173
1181
|
clearBox();
|
|
1174
1182
|
process.stdin.removeListener("keypress", onKeypress);
|
|
1175
1183
|
process.stdin.pause();
|
|
@@ -1583,25 +1591,43 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
1583
1591
|
}
|
|
1584
1592
|
};
|
|
1585
1593
|
const onKeypress = (str, key) => {
|
|
1586
|
-
// Reassemble modifier-prefixed
|
|
1587
|
-
//
|
|
1588
|
-
//
|
|
1589
|
-
// sequence
|
|
1590
|
-
//
|
|
1591
|
-
//
|
|
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.
|
|
1592
1601
|
const seq = key?.sequence || str || "";
|
|
1593
|
-
if (
|
|
1594
|
-
modSeq
|
|
1595
|
-
if (
|
|
1596
|
-
|
|
1602
|
+
if (seq.startsWith("\x1b[") && /^\x1b\[[\d;]*$/.test(seq)) {
|
|
1603
|
+
modSeq = seq;
|
|
1604
|
+
if (modSeqTimeout)
|
|
1605
|
+
clearTimeout(modSeqTimeout);
|
|
1606
|
+
modSeqTimeout = setTimeout(() => {
|
|
1597
1607
|
modSeq = "";
|
|
1598
|
-
|
|
1599
|
-
}
|
|
1608
|
+
modSeqTimeout = null;
|
|
1609
|
+
}, 200);
|
|
1600
1610
|
return;
|
|
1601
1611
|
}
|
|
1602
|
-
if (
|
|
1603
|
-
|
|
1604
|
-
|
|
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;
|
|
1605
1631
|
}
|
|
1606
1632
|
if (consumeBracketedPaste(str, key))
|
|
1607
1633
|
return;
|