@oxecli/oxe 1.0.63 → 1.0.65
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 +56 -8
- 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[>1u");
|
|
12
|
+
process.stdout.write("\x1b[<u\x1b[>1u");
|
|
13
13
|
}
|
|
14
14
|
process.stdin.resume();
|
|
15
15
|
hideCursor();
|
|
@@ -902,10 +902,37 @@ export function renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor
|
|
|
902
902
|
const totalRows = body.length + 2;
|
|
903
903
|
return { frame, cursorRow, cursorCol, totalRows };
|
|
904
904
|
}
|
|
905
|
+
/**
|
|
906
|
+
* Generic CSI Shift+Enter detection. The modifier encoding used by CSI-u,
|
|
907
|
+
* legacy and kitty/modifyOtherKeys is a bitmask + 1, where Shift is bit0
|
|
908
|
+
* (so modifier 2 = shift, 4 = shift+alt, 6 = shift+ctrl, ...). Enter has
|
|
909
|
+
* key code 13. Handles:
|
|
910
|
+
* CSI-u / legacy: ESC [ 13 ; M u and ESC [ 13 ; M ~
|
|
911
|
+
* modifyOtherKeys: ESC [ 27 ; M ; 13 ~
|
|
912
|
+
* application: ESC O M
|
|
913
|
+
*/
|
|
914
|
+
function csiShiftEnter(seq) {
|
|
915
|
+
if (seq === "\x1bOM")
|
|
916
|
+
return true;
|
|
917
|
+
// modifyOtherKeys: ESC [ 27 ; M ; 13 ~
|
|
918
|
+
const mod = seq.match(/^\x1b\[27;(\d+);13[~_]$/);
|
|
919
|
+
if (mod) {
|
|
920
|
+
const m = parseInt(mod[1], 10);
|
|
921
|
+
return Number.isInteger(m) && ((m - 1) & 1) === 1;
|
|
922
|
+
}
|
|
923
|
+
// CSI-u / legacy: ESC [ 13 ; M u (or ~ or _)
|
|
924
|
+
const csi = seq.match(/^\x1b\[13;(\d+)[~u_]$/);
|
|
925
|
+
if (csi) {
|
|
926
|
+
const m = parseInt(csi[1], 10);
|
|
927
|
+
return Number.isInteger(m) && ((m - 1) & 1) === 1;
|
|
928
|
+
}
|
|
929
|
+
return false;
|
|
930
|
+
}
|
|
905
931
|
export function isShiftEnterKey(str, key) {
|
|
906
932
|
if (!key)
|
|
907
933
|
return false;
|
|
908
934
|
const seq = key.sequence || str || "";
|
|
935
|
+
// Shift modifier reported by readline on a return/enter/linefeed key.
|
|
909
936
|
if (key.shift &&
|
|
910
937
|
(key.name === "return" ||
|
|
911
938
|
key.name === "enter" ||
|
|
@@ -914,13 +941,8 @@ export function isShiftEnterKey(str, key) {
|
|
|
914
941
|
seq === "\n")) {
|
|
915
942
|
return true;
|
|
916
943
|
}
|
|
917
|
-
if (seq
|
|
918
|
-
seq === "\x1b[13;2~" ||
|
|
919
|
-
seq === "\x1b[13;2_" ||
|
|
920
|
-
seq === "\x1b[27;2;13~" ||
|
|
921
|
-
seq === "\x1bOM") {
|
|
944
|
+
if (csiShiftEnter(seq))
|
|
922
945
|
return true;
|
|
923
|
-
}
|
|
924
946
|
return false;
|
|
925
947
|
}
|
|
926
948
|
export const isNewlineKey = isShiftEnterKey;
|
|
@@ -965,11 +987,18 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
965
987
|
let bracketedPasteBuffer = "";
|
|
966
988
|
let pasteBurst = false;
|
|
967
989
|
let pasteBurstTimer = null;
|
|
990
|
+
// Accumulator for modifier-prefixed CSI sequences (e.g. Shift+Enter sent as
|
|
991
|
+
// `\x1b[27;2;13~`), which Node's readline splits into several keypress
|
|
992
|
+
// events instead of one, so they must be reassembled here.
|
|
993
|
+
let modSeq = "";
|
|
968
994
|
readline.emitKeypressEvents(process.stdin);
|
|
969
995
|
if (process.stdin.isTTY) {
|
|
970
996
|
process.stdin.setRawMode(true);
|
|
971
997
|
process.stdout.write("\x1b[?2004h");
|
|
972
|
-
|
|
998
|
+
// Enable CSI-u "disambiguate" so the terminal reports Shift+Enter as a
|
|
999
|
+
// distinct code (`ESC [ 13 ; 2 u`) instead of collapsing it into a plain
|
|
1000
|
+
// Enter. Pop any prior mode, then push flags=1 (disambiguate).
|
|
1001
|
+
process.stdout.write("\x1b[<u\x1b[>1u");
|
|
973
1002
|
}
|
|
974
1003
|
process.stdin.resume();
|
|
975
1004
|
hideCursor();
|
|
@@ -1313,6 +1342,25 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
1313
1342
|
}, 500);
|
|
1314
1343
|
};
|
|
1315
1344
|
const onKeypress = (str, key) => {
|
|
1345
|
+
// Reassemble a modifier-prefixed CSI sequence that readline splits up,
|
|
1346
|
+
// e.g. Shift+Enter arriving as `\x1b[27;2;` + "1" + "3" + "~".
|
|
1347
|
+
if (key?.sequence === "\x1b[27;" || key?.sequence === "\x1b[27;2;") {
|
|
1348
|
+
modSeq = key.sequence;
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
if (modSeq) {
|
|
1352
|
+
modSeq += str || key?.sequence || "";
|
|
1353
|
+
if (/[~u_]/.test(modSeq.slice(-1)) || modSeq.endsWith("~")) {
|
|
1354
|
+
const full = modSeq;
|
|
1355
|
+
modSeq = "";
|
|
1356
|
+
// e.g. `\x1b[27;2;13~` = Shift+Enter.
|
|
1357
|
+
if (csiShiftEnter(full)) {
|
|
1358
|
+
insert("\n");
|
|
1359
|
+
repaint();
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1316
1364
|
if (consumeBracketedPaste(str, key))
|
|
1317
1365
|
return;
|
|
1318
1366
|
if (pasteBurst && str && str.length === 1 && !key?.ctrl && !key?.meta) {
|