nexrall-code 0.5.173 → 0.5.174
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/index.js +237 -79
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -153361,7 +153361,17 @@ function renderInputSlices(line, cursorPos) {
|
|
|
153361
153361
|
}
|
|
153362
153362
|
|
|
153363
153363
|
// src/ui/vimMode.ts
|
|
153364
|
-
var initialVim = (mode = "insert") => ({
|
|
153364
|
+
var initialVim = (mode = "insert") => ({
|
|
153365
|
+
mode,
|
|
153366
|
+
count: "",
|
|
153367
|
+
op: "",
|
|
153368
|
+
reg: { text: "", linewise: false },
|
|
153369
|
+
undo: [],
|
|
153370
|
+
visual: null,
|
|
153371
|
+
anchor: 0,
|
|
153372
|
+
last: [],
|
|
153373
|
+
pend: []
|
|
153374
|
+
});
|
|
153365
153375
|
var MAX_UNDO = 100;
|
|
153366
153376
|
var isSpace2 = (c) => /\s/.test(c);
|
|
153367
153377
|
function nextWordStart(text, pos) {
|
|
@@ -153387,32 +153397,89 @@ function clampNormal(text, pos) {
|
|
|
153387
153397
|
return ls;
|
|
153388
153398
|
return p >= le ? prevGraphemeBoundary(text, le) : p;
|
|
153389
153399
|
}
|
|
153400
|
+
function visualRange(text, vim, cursor) {
|
|
153401
|
+
if (!vim.visual)
|
|
153402
|
+
return null;
|
|
153403
|
+
const a = clampNormal(text, vim.anchor), b = clampNormal(text, cursor);
|
|
153404
|
+
const lo = Math.min(a, b), hi = Math.max(a, b);
|
|
153405
|
+
if (vim.visual === "line") {
|
|
153406
|
+
const from = lineStart(text, lo);
|
|
153407
|
+
const le = lineEnd(text, hi);
|
|
153408
|
+
return { from, to: le < text.length ? le + 1 : le, linewise: true };
|
|
153409
|
+
}
|
|
153410
|
+
return { from: lo, to: nextGraphemeBoundary(text, hi) };
|
|
153411
|
+
}
|
|
153412
|
+
function tokenToKey(tok) {
|
|
153413
|
+
if (tok === "<Esc>")
|
|
153414
|
+
return { char: "", key: { escape: true } };
|
|
153415
|
+
if (tok === "<BS>")
|
|
153416
|
+
return { char: "", key: { backspace: true } };
|
|
153417
|
+
return { char: tok, key: {} };
|
|
153418
|
+
}
|
|
153419
|
+
function replayKeys(text, cursor, vim, keys, n) {
|
|
153420
|
+
let t2 = text, c = cursor, v = vim;
|
|
153421
|
+
for (let i2 = 0; i2 < n; i2++) {
|
|
153422
|
+
for (const tok of keys) {
|
|
153423
|
+
const { char, key } = tokenToKey(tok);
|
|
153424
|
+
const r2 = handleVimKey(t2, c, v, char, key);
|
|
153425
|
+
t2 = r2.text;
|
|
153426
|
+
c = r2.cursor;
|
|
153427
|
+
v = r2.vim;
|
|
153428
|
+
if (!r2.handled && v.mode === "insert") {
|
|
153429
|
+
if (key.backspace) {
|
|
153430
|
+
const p = prevGraphemeBoundary(t2, c);
|
|
153431
|
+
t2 = t2.slice(0, p) + t2.slice(c);
|
|
153432
|
+
c = p;
|
|
153433
|
+
} else if (char) {
|
|
153434
|
+
t2 = t2.slice(0, c) + char + t2.slice(c);
|
|
153435
|
+
c += char.length;
|
|
153436
|
+
}
|
|
153437
|
+
}
|
|
153438
|
+
}
|
|
153439
|
+
}
|
|
153440
|
+
return { text: t2, cursor: c, vim: v };
|
|
153441
|
+
}
|
|
153390
153442
|
function handleVimKey(text, cursor, vim, char, key) {
|
|
153391
153443
|
const pass = (v = vim) => ({ text, cursor, vim: v, handled: false });
|
|
153392
153444
|
const done = (t2, c, v) => ({ text: t2, cursor: c, vim: v, handled: true });
|
|
153445
|
+
const push2 = (v, tok) => ({ ...v, pend: [...v.pend, tok] });
|
|
153446
|
+
const commit = (v) => ({ ...v, last: v.pend, pend: [] });
|
|
153447
|
+
const noChange = (v) => ({ ...v, pend: [] });
|
|
153393
153448
|
if (vim.mode === "insert") {
|
|
153394
153449
|
if (key.escape) {
|
|
153395
153450
|
const c = cursor > 0 ? prevGraphemeBoundary(text, cursor) : 0;
|
|
153396
|
-
|
|
153451
|
+
const closed = {
|
|
153452
|
+
...vim,
|
|
153453
|
+
mode: "normal",
|
|
153454
|
+
count: "",
|
|
153455
|
+
op: "",
|
|
153456
|
+
last: vim.pend.length ? [...vim.pend, "<Esc>"] : vim.last,
|
|
153457
|
+
pend: []
|
|
153458
|
+
};
|
|
153459
|
+
return done(text, clampNormal(text, c), closed);
|
|
153397
153460
|
}
|
|
153398
|
-
return
|
|
153461
|
+
const typed = !key.ctrl && !key.meta && !key.return && !key.tab && !key.escape && !key.delete && (key.backspace || char.length > 0 && char.length <= 2);
|
|
153462
|
+
const v = typed ? push2(vim, key.backspace ? "<BS>" : char) : vim;
|
|
153463
|
+
return pass(v);
|
|
153399
153464
|
}
|
|
153400
153465
|
if (key.escape) {
|
|
153466
|
+
if (vim.visual)
|
|
153467
|
+
return done(text, clampNormal(text, cursor), { ...vim, visual: null, count: "", op: "", pend: [] });
|
|
153401
153468
|
if (!vim.count && !vim.op)
|
|
153402
153469
|
return pass();
|
|
153403
|
-
return done(text, clampNormal(text, cursor), { ...vim, count: "", op: "" });
|
|
153470
|
+
return done(text, clampNormal(text, cursor), { ...vim, count: "", op: "", pend: [] });
|
|
153404
153471
|
}
|
|
153405
153472
|
if (key.ctrl || key.meta)
|
|
153406
153473
|
return pass();
|
|
153407
153474
|
if (key.return || key.tab || key.upArrow || key.downArrow || key.leftArrow || key.rightArrow || key.delete)
|
|
153408
153475
|
return pass();
|
|
153409
153476
|
if (key.backspace)
|
|
153410
|
-
return done(text, clampNormal(text, prevGraphemeBoundary(text, cursor)), { ...vim, count: "", op: "" });
|
|
153477
|
+
return done(text, clampNormal(text, prevGraphemeBoundary(text, cursor)), noChange({ ...vim, count: "", op: "" }));
|
|
153411
153478
|
if (!char || char.length > 2)
|
|
153412
153479
|
return pass();
|
|
153413
153480
|
const pos = clampNormal(text, cursor);
|
|
153414
153481
|
if (/^[1-9]$/.test(char) || char === "0" && vim.count)
|
|
153415
|
-
return done(text, pos, { ...vim, count: vim.count + char });
|
|
153482
|
+
return done(text, pos, push2({ ...vim, count: vim.count + char }, char));
|
|
153416
153483
|
const n = vim.count ? Math.min(parseInt(vim.count, 10), 999) : 1;
|
|
153417
153484
|
const clear = { ...vim, count: "", op: "" };
|
|
153418
153485
|
const pushUndo = (v) => ({ ...v, undo: [...v.undo, { text, cursor: pos }].slice(-MAX_UNDO) });
|
|
@@ -153449,9 +153516,69 @@ function handleVimKey(text, cursor, vim, char, key) {
|
|
|
153449
153516
|
return null;
|
|
153450
153517
|
}
|
|
153451
153518
|
};
|
|
153519
|
+
const vertical = (dir) => {
|
|
153520
|
+
let p = pos;
|
|
153521
|
+
for (let i2 = 0; i2 < n && p !== null; i2++) {
|
|
153522
|
+
const nx = moveVertical({ text, cursor: p }, dir);
|
|
153523
|
+
if (nx === null) {
|
|
153524
|
+
if (i2 === 0)
|
|
153525
|
+
return null;
|
|
153526
|
+
break;
|
|
153527
|
+
}
|
|
153528
|
+
p = nx;
|
|
153529
|
+
}
|
|
153530
|
+
return p === null ? null : clampNormal(text, p);
|
|
153531
|
+
};
|
|
153532
|
+
const cut = (from, to, linewise) => {
|
|
153533
|
+
let nt = text.slice(0, from) + text.slice(to);
|
|
153534
|
+
let nc = from;
|
|
153535
|
+
if (linewise && nt.length && to >= text.length && from > 0) {
|
|
153536
|
+
nt = nt.slice(0, from - 1);
|
|
153537
|
+
nc = lineStart(nt, from - 1);
|
|
153538
|
+
}
|
|
153539
|
+
return { text: nt, cursor: clampNormal(nt, nc) };
|
|
153540
|
+
};
|
|
153541
|
+
if (vim.visual) {
|
|
153542
|
+
const mv = motion(char);
|
|
153543
|
+
if (mv !== null)
|
|
153544
|
+
return done(text, clampNormal(text, mv), noChange(clear));
|
|
153545
|
+
if (char === "j" || char === "k") {
|
|
153546
|
+
const p = vertical(char === "j" ? 1 : -1);
|
|
153547
|
+
if (p === null)
|
|
153548
|
+
return pass(noChange(clear));
|
|
153549
|
+
return done(text, p, noChange(clear));
|
|
153550
|
+
}
|
|
153551
|
+
if (char === "v" || char === "V") {
|
|
153552
|
+
const want = char === "v" ? "char" : "line";
|
|
153553
|
+
return done(text, pos, { ...clear, visual: vim.visual === want ? null : want, pend: [] });
|
|
153554
|
+
}
|
|
153555
|
+
const sel = visualRange(text, vim, pos);
|
|
153556
|
+
const removed = text.slice(sel.from, sel.to);
|
|
153557
|
+
const reg = { text: removed, linewise: !!sel.linewise };
|
|
153558
|
+
if (char === "y")
|
|
153559
|
+
return done(text, clampNormal(text, sel.from), noChange({ ...clear, visual: null, reg }));
|
|
153560
|
+
if (char === "d" || char === "x" || char === "c") {
|
|
153561
|
+
const base = pushUndo({ ...clear, visual: null, reg });
|
|
153562
|
+
const { text: nt, cursor: nc } = cut(sel.from, sel.to, !!sel.linewise);
|
|
153563
|
+
if (char === "c") {
|
|
153564
|
+
const keep = sel.linewise && removed.endsWith("\n") ? "\n" : "";
|
|
153565
|
+
const wt = text.slice(0, sel.from) + keep + text.slice(sel.to);
|
|
153566
|
+
return done(wt, sel.from, { ...base, mode: "insert" });
|
|
153567
|
+
}
|
|
153568
|
+
return done(nt, nc, noChange(base));
|
|
153569
|
+
}
|
|
153570
|
+
if ((char === "p" || char === "P") && vim.reg.text) {
|
|
153571
|
+
const base = pushUndo({ ...clear, visual: null });
|
|
153572
|
+
const body = vim.reg.linewise ? vim.reg.text.replace(/\n$/, "") : vim.reg.text;
|
|
153573
|
+
const nt = text.slice(0, sel.from) + body + text.slice(sel.to);
|
|
153574
|
+
return done(nt, clampNormal(nt, sel.from + Math.max(0, body.length - 1)), noChange(base));
|
|
153575
|
+
}
|
|
153576
|
+
return done(text, pos, noChange(clear));
|
|
153577
|
+
}
|
|
153452
153578
|
if (vim.op) {
|
|
153453
153579
|
const op = vim.op;
|
|
153454
153580
|
let r2 = null;
|
|
153581
|
+
let seq = "";
|
|
153455
153582
|
if (char === op) {
|
|
153456
153583
|
let end = pos;
|
|
153457
153584
|
for (let i2 = 0; i2 < n; i2++) {
|
|
@@ -153461,153 +153588,158 @@ function handleVimKey(text, cursor, vim, char, key) {
|
|
|
153461
153588
|
break;
|
|
153462
153589
|
}
|
|
153463
153590
|
r2 = { from: lineStart(text, pos), to: end, linewise: true };
|
|
153591
|
+
seq = char;
|
|
153464
153592
|
} else if (char === "w" && op === "c") {
|
|
153465
153593
|
const e2 = repeat((p) => wordLastChar(text, p));
|
|
153466
153594
|
r2 = { from: pos, to: nextGraphemeBoundary(text, e2) };
|
|
153595
|
+
seq = char;
|
|
153467
153596
|
} else {
|
|
153468
153597
|
const m3 = motion(char);
|
|
153469
153598
|
if (m3 !== null) {
|
|
153470
153599
|
const inclusive = char === "e";
|
|
153471
|
-
const
|
|
153472
|
-
r2 =
|
|
153600
|
+
const to = m3;
|
|
153601
|
+
r2 = to >= pos ? { from: pos, to: inclusive ? nextGraphemeBoundary(text, to) : to } : { from: to, to: pos };
|
|
153602
|
+
seq = char;
|
|
153473
153603
|
}
|
|
153474
153604
|
}
|
|
153605
|
+
const recorded = vim.count ? push2(push2(vim, vim.count), seq) : push2(vim, seq);
|
|
153475
153606
|
if (!r2)
|
|
153476
|
-
return done(text, pos, clear);
|
|
153477
|
-
|
|
153478
|
-
|
|
153479
|
-
|
|
153480
|
-
const
|
|
153481
|
-
const reg = { text: removed, linewise: !!r2.linewise };
|
|
153607
|
+
return done(text, pos, noChange(clear));
|
|
153608
|
+
if (r2.from === r2.to)
|
|
153609
|
+
return done(text, pos, noChange(clear));
|
|
153610
|
+
const removed2 = text.slice(r2.from, r2.to);
|
|
153611
|
+
const opend = { ...clear, visual: null, reg: { text: removed2, linewise: !!r2.linewise }, pend: recorded.pend };
|
|
153482
153612
|
if (op === "y")
|
|
153483
|
-
return done(text, from === pos ? pos : clampNormal(text, from),
|
|
153484
|
-
|
|
153485
|
-
|
|
153486
|
-
|
|
153487
|
-
|
|
153488
|
-
|
|
153489
|
-
}
|
|
153490
|
-
if (r2.linewise && op === "c") {
|
|
153491
|
-
const keep = removed.endsWith("\n") ? "\n" : "";
|
|
153492
|
-
nt = text.slice(0, from) + keep + text.slice(to);
|
|
153493
|
-
nc = from;
|
|
153613
|
+
return done(text, r2.from === pos ? pos : clampNormal(text, r2.from), noChange(opend));
|
|
153614
|
+
const { text: nt, cursor: nc } = cut(r2.from, r2.to, !!r2.linewise);
|
|
153615
|
+
if (op === "c") {
|
|
153616
|
+
const keep = r2.linewise && removed2.endsWith("\n") ? "\n" : "";
|
|
153617
|
+
const wt = text.slice(0, r2.from) + keep + text.slice(r2.to);
|
|
153618
|
+
return done(wt, r2.from, { ...pushUndo(opend), mode: "insert" });
|
|
153494
153619
|
}
|
|
153495
|
-
|
|
153496
|
-
if (op === "c")
|
|
153497
|
-
return done(nt, nc, { ...base, mode: "insert" });
|
|
153498
|
-
return done(nt, clampNormal(nt, nc), base);
|
|
153620
|
+
return done(nt, nc, noChange(commit(pushUndo(opend))));
|
|
153499
153621
|
}
|
|
153500
153622
|
const m2 = motion(char);
|
|
153501
153623
|
if (m2 !== null)
|
|
153502
|
-
return done(text, clampNormal(text, m2), clear);
|
|
153624
|
+
return done(text, clampNormal(text, m2), noChange(clear));
|
|
153503
153625
|
if (char === "j" || char === "k") {
|
|
153504
|
-
const
|
|
153505
|
-
|
|
153506
|
-
|
|
153507
|
-
|
|
153508
|
-
if (nx === null) {
|
|
153509
|
-
if (i2 === 0)
|
|
153510
|
-
return pass(clear);
|
|
153511
|
-
break;
|
|
153512
|
-
}
|
|
153513
|
-
p = nx;
|
|
153514
|
-
}
|
|
153515
|
-
return done(text, clampNormal(text, p ?? pos), clear);
|
|
153626
|
+
const p = vertical(char === "j" ? 1 : -1);
|
|
153627
|
+
if (p === null)
|
|
153628
|
+
return pass(noChange(clear));
|
|
153629
|
+
return done(text, p, noChange(clear));
|
|
153516
153630
|
}
|
|
153517
153631
|
switch (char) {
|
|
153518
153632
|
case "d":
|
|
153519
153633
|
case "c":
|
|
153520
153634
|
case "y":
|
|
153521
|
-
return done(text, pos, { ...vim, op: char, count: vim.count });
|
|
153635
|
+
return done(text, pos, push2({ ...vim, op: char, count: vim.count }, char));
|
|
153636
|
+
case ".": {
|
|
153637
|
+
if (!vim.last.length)
|
|
153638
|
+
return done(text, pos, noChange(clear));
|
|
153639
|
+
const rep = replayKeys(text, pos, { ...clear, last: vim.last, pend: [] }, vim.last, n);
|
|
153640
|
+
return done(rep.text, clampNormal(rep.text, rep.cursor), { ...rep.vim, last: vim.last, pend: [] });
|
|
153641
|
+
}
|
|
153642
|
+
case "v":
|
|
153643
|
+
case "V":
|
|
153644
|
+
return done(text, pos, noChange({ ...clear, visual: char === "v" ? "char" : "line", anchor: pos }));
|
|
153522
153645
|
case "i":
|
|
153523
|
-
return done(text, pos, { ...pushUndo(clear), mode: "insert" });
|
|
153646
|
+
return done(text, pos, push2({ ...pushUndo(clear), mode: "insert" }, char));
|
|
153524
153647
|
case "a":
|
|
153525
|
-
return done(text, text.length && lineEnd(text, pos) > pos ? nextGraphemeBoundary(text, pos) : pos, { ...pushUndo(clear), mode: "insert" });
|
|
153648
|
+
return done(text, text.length && lineEnd(text, pos) > pos ? nextGraphemeBoundary(text, pos) : pos, push2({ ...pushUndo(clear), mode: "insert" }, char));
|
|
153526
153649
|
case "I": {
|
|
153527
153650
|
let p = lineStart(text, pos);
|
|
153528
153651
|
const e2 = lineEnd(text, pos);
|
|
153529
153652
|
while (p < e2 && isSpace2(text[p]))
|
|
153530
153653
|
p++;
|
|
153531
|
-
return done(text, p, { ...pushUndo(clear), mode: "insert" });
|
|
153654
|
+
return done(text, p, push2({ ...pushUndo(clear), mode: "insert" }, char));
|
|
153532
153655
|
}
|
|
153533
153656
|
case "A":
|
|
153534
|
-
return done(text, lineEnd(text, pos), { ...pushUndo(clear), mode: "insert" });
|
|
153657
|
+
return done(text, lineEnd(text, pos), push2({ ...pushUndo(clear), mode: "insert" }, char));
|
|
153535
153658
|
case "o": {
|
|
153536
153659
|
const e2 = lineEnd(text, pos);
|
|
153537
|
-
return done(text.slice(0, e2) + "\n" + text.slice(e2), e2 + 1, { ...pushUndo(clear), mode: "insert" });
|
|
153660
|
+
return done(text.slice(0, e2) + "\n" + text.slice(e2), e2 + 1, push2({ ...pushUndo(clear), mode: "insert" }, char));
|
|
153538
153661
|
}
|
|
153539
153662
|
case "O": {
|
|
153540
153663
|
const s2 = lineStart(text, pos);
|
|
153541
|
-
return done(text.slice(0, s2) + "\n" + text.slice(s2), s2, { ...pushUndo(clear), mode: "insert" });
|
|
153664
|
+
return done(text.slice(0, s2) + "\n" + text.slice(s2), s2, push2({ ...pushUndo(clear), mode: "insert" }, char));
|
|
153542
153665
|
}
|
|
153543
153666
|
case "x": {
|
|
153544
153667
|
const e2 = lineEnd(text, pos);
|
|
153545
153668
|
if (pos >= e2)
|
|
153546
|
-
return done(text, pos, clear);
|
|
153669
|
+
return done(text, pos, noChange(clear));
|
|
153547
153670
|
let to = pos;
|
|
153548
153671
|
for (let i2 = 0; i2 < n && to < e2; i2++)
|
|
153549
153672
|
to = nextGraphemeBoundary(text, to);
|
|
153550
153673
|
const nt = text.slice(0, pos) + text.slice(to);
|
|
153551
|
-
return done(nt, clampNormal(nt, pos), { ...pushUndo(clear), reg: { text: text.slice(pos, to), linewise: false } });
|
|
153674
|
+
return done(nt, clampNormal(nt, pos), commit(push2({ ...pushUndo(clear), reg: { text: text.slice(pos, to), linewise: false } }, char)));
|
|
153552
153675
|
}
|
|
153553
153676
|
case "X": {
|
|
153554
153677
|
const s2 = lineStart(text, pos);
|
|
153555
153678
|
if (pos <= s2)
|
|
153556
|
-
return done(text, pos, clear);
|
|
153679
|
+
return done(text, pos, noChange(clear));
|
|
153557
153680
|
let from = pos;
|
|
153558
153681
|
for (let i2 = 0; i2 < n && from > s2; i2++)
|
|
153559
153682
|
from = prevGraphemeBoundary(text, from);
|
|
153560
153683
|
const nt = text.slice(0, from) + text.slice(pos);
|
|
153561
|
-
return done(nt, clampNormal(nt, from), { ...pushUndo(clear), reg: { text: text.slice(from, pos), linewise: false } });
|
|
153684
|
+
return done(nt, clampNormal(nt, from), commit(push2({ ...pushUndo(clear), reg: { text: text.slice(from, pos), linewise: false } }, char)));
|
|
153562
153685
|
}
|
|
153563
153686
|
case "D":
|
|
153564
153687
|
case "C": {
|
|
153565
153688
|
const e2 = lineEnd(text, pos);
|
|
153566
153689
|
const nt = text.slice(0, pos) + text.slice(e2);
|
|
153567
|
-
const v = { ...pushUndo(clear), reg: { text: text.slice(pos, e2), linewise: false } };
|
|
153568
|
-
return char === "C" ? done(nt, pos, { ...v, mode: "insert" }) : done(nt, clampNormal(nt, pos), v);
|
|
153690
|
+
const v = push2({ ...pushUndo(clear), reg: { text: text.slice(pos, e2), linewise: false } }, char);
|
|
153691
|
+
return char === "C" ? done(nt, pos, { ...v, mode: "insert" }) : done(nt, clampNormal(nt, pos), commit(v));
|
|
153569
153692
|
}
|
|
153570
153693
|
case "p":
|
|
153571
153694
|
case "P": {
|
|
153572
153695
|
if (!vim.reg.text)
|
|
153573
|
-
return done(text, pos, clear);
|
|
153574
|
-
const v = pushUndo(clear);
|
|
153696
|
+
return done(text, pos, noChange(clear));
|
|
153697
|
+
const v = push2(pushUndo(clear), char);
|
|
153575
153698
|
if (vim.reg.linewise) {
|
|
153576
153699
|
const body = vim.reg.text.replace(/\n$/, "");
|
|
153577
153700
|
if (char === "p") {
|
|
153578
153701
|
const e2 = lineEnd(text, pos);
|
|
153579
153702
|
const nt3 = text.slice(0, e2) + "\n" + body + text.slice(e2);
|
|
153580
|
-
return done(nt3, clampNormal(nt3, e2 + 1), v);
|
|
153703
|
+
return done(nt3, clampNormal(nt3, e2 + 1), commit(v));
|
|
153581
153704
|
}
|
|
153582
153705
|
const s2 = lineStart(text, pos);
|
|
153583
153706
|
const nt2 = text.slice(0, s2) + body + "\n" + text.slice(s2);
|
|
153584
|
-
return done(nt2, clampNormal(nt2, s2), v);
|
|
153707
|
+
return done(nt2, clampNormal(nt2, s2), commit(v));
|
|
153585
153708
|
}
|
|
153586
153709
|
const at = char === "p" && text.length && lineEnd(text, pos) > pos ? nextGraphemeBoundary(text, pos) : pos;
|
|
153587
153710
|
const nt = text.slice(0, at) + vim.reg.text + text.slice(at);
|
|
153588
|
-
return done(nt, clampNormal(nt, at + vim.reg.text.length - 1), v);
|
|
153711
|
+
return done(nt, clampNormal(nt, at + vim.reg.text.length - 1), commit(v));
|
|
153589
153712
|
}
|
|
153590
153713
|
case "u": {
|
|
153591
153714
|
const last = vim.undo[vim.undo.length - 1];
|
|
153592
153715
|
if (!last)
|
|
153593
|
-
return done(text, pos, clear);
|
|
153594
|
-
return done(last.text, clampNormal(last.text, last.cursor), { ...clear, undo: vim.undo.slice(0, -1) });
|
|
153716
|
+
return done(text, pos, noChange(clear));
|
|
153717
|
+
return done(last.text, clampNormal(last.text, last.cursor), noChange({ ...clear, undo: vim.undo.slice(0, -1) }));
|
|
153595
153718
|
}
|
|
153596
153719
|
default:
|
|
153597
|
-
return done(text, pos, clear);
|
|
153720
|
+
return done(text, pos, noChange(clear));
|
|
153598
153721
|
}
|
|
153599
153722
|
}
|
|
153723
|
+
var INSERT_ENTRY = /* @__PURE__ */ new Set(["i", "a", "I", "A", "o", "O", "C"]);
|
|
153600
153724
|
function handleVimChunk(text, cursor, vim, chunk, key) {
|
|
153601
153725
|
const chars = [...chunk];
|
|
153602
153726
|
const plain = !key.escape && !key.ctrl && !key.meta && !key.return && !key.tab && !key.backspace && !key.delete;
|
|
153603
|
-
if (vim.mode !== "normal" || !plain || chars.length < 2
|
|
153727
|
+
if (vim.mode !== "normal" || !plain || chars.length < 2)
|
|
153728
|
+
return handleVimKey(text, cursor, vim, chunk, key);
|
|
153729
|
+
const insertRun = INSERT_ENTRY.has(chars[0]) && chars.slice(1).every((c2) => c2 >= " " && c2 !== "\x7F");
|
|
153730
|
+
if (chars.length > 4 && !insertRun)
|
|
153604
153731
|
return handleVimKey(text, cursor, vim, chunk, key);
|
|
153605
153732
|
let t2 = text, c = cursor, v = vim;
|
|
153606
153733
|
for (const ch of chars) {
|
|
153607
|
-
const
|
|
153734
|
+
const esc = ch === "\x1B";
|
|
153735
|
+
const r2 = handleVimKey(t2, c, v, esc ? "" : ch, esc ? { escape: true } : {});
|
|
153608
153736
|
t2 = r2.text;
|
|
153609
153737
|
c = r2.cursor;
|
|
153610
153738
|
v = r2.vim;
|
|
153739
|
+
if (!r2.handled && v.mode === "insert" && !esc) {
|
|
153740
|
+
t2 = t2.slice(0, c) + ch + t2.slice(c);
|
|
153741
|
+
c += ch.length;
|
|
153742
|
+
}
|
|
153611
153743
|
}
|
|
153612
153744
|
return { text: t2, cursor: c, vim: v, handled: true };
|
|
153613
153745
|
}
|
|
@@ -157292,21 +157424,22 @@ function rowsOccupied(text, columns = process.stdout.columns || 80) {
|
|
|
157292
157424
|
function reserveBlockRows(previous, showing) {
|
|
157293
157425
|
return Math.max(0, previous, showing);
|
|
157294
157426
|
}
|
|
157295
|
-
|
|
157427
|
+
var LIVE_BLOCK_MAX_ROWS = 5;
|
|
157428
|
+
function fillerRowCount(rowsAlreadyPrinted, footerTextValue = "", columns = process.stdout.columns ?? 80, rows = process.stdout.rows, reservedRows = 0, headroom = 2) {
|
|
157296
157429
|
if (!rows)
|
|
157297
157430
|
return 0;
|
|
157298
157431
|
const chromeRows = bottomChromeRows({ footerText: footerTextValue, columns });
|
|
157299
|
-
const filler = rows - rowsAlreadyPrinted - chromeRows -
|
|
157432
|
+
const filler = rows - rowsAlreadyPrinted - reservedRows - chromeRows - headroom;
|
|
157300
157433
|
const MIN_WORTHWHILE_FILLER = 3;
|
|
157301
157434
|
return filler < MIN_WORTHWHILE_FILLER ? 0 : filler;
|
|
157302
157435
|
}
|
|
157303
|
-
function padToBottom(rowsAlreadyPrinted, footerText2 = "") {
|
|
157436
|
+
function padToBottom(rowsAlreadyPrinted, footerText2 = "", sink = (text) => console.log(text)) {
|
|
157304
157437
|
if (!process.stdout.isTTY)
|
|
157305
157438
|
return false;
|
|
157306
157439
|
const filler = fillerRowCount(rowsAlreadyPrinted, footerText2);
|
|
157307
157440
|
if (filler <= 0)
|
|
157308
157441
|
return false;
|
|
157309
|
-
|
|
157442
|
+
sink("\n".repeat(filler - 1));
|
|
157310
157443
|
return true;
|
|
157311
157444
|
}
|
|
157312
157445
|
var rowCounter = null;
|
|
@@ -168577,6 +168710,7 @@ var App2 = ({ onReady }) => {
|
|
|
168577
168710
|
const cursorRef = (0, import_react36.useRef)(0);
|
|
168578
168711
|
const vimRef = (0, import_react36.useRef)(initialVim("insert"));
|
|
168579
168712
|
const [vimMode, setVimMode] = (0, import_react36.useState)("insert");
|
|
168713
|
+
const [vimVisual, setVimVisual] = (0, import_react36.useState)(false);
|
|
168580
168714
|
const setCursorPos = (0, import_react36.useCallback)((next) => {
|
|
168581
168715
|
const value = typeof next === "function" ? next(cursorRef.current) : next;
|
|
168582
168716
|
cursorRef.current = value;
|
|
@@ -168693,7 +168827,9 @@ var App2 = ({ onReady }) => {
|
|
|
168693
168827
|
if (opts?.isBanner)
|
|
168694
168828
|
bannerChunkRef.current = bufferRef.current.length;
|
|
168695
168829
|
bufferRef.current.append(text);
|
|
168696
|
-
setItems((prev) =>
|
|
168830
|
+
setItems((prev) => {
|
|
168831
|
+
return [...prev, { id: idCounter++, content: text, isBanner: opts?.isBanner, isFiller: opts?.isFiller }];
|
|
168832
|
+
});
|
|
168697
168833
|
}, []);
|
|
168698
168834
|
const bannerRegeneratorRef = (0, import_react36.useRef)(null);
|
|
168699
168835
|
const setBannerRegenerator = (0, import_react36.useCallback)((fn) => {
|
|
@@ -168986,6 +169122,8 @@ var App2 = ({ onReady }) => {
|
|
|
168986
169122
|
if (r2.handled) {
|
|
168987
169123
|
if (r2.vim.mode !== vimRef.current.mode)
|
|
168988
169124
|
setVimMode(r2.vim.mode);
|
|
169125
|
+
if (!!r2.vim.visual !== !!vimRef.current.visual)
|
|
169126
|
+
setVimVisual(!!r2.vim.visual);
|
|
168989
169127
|
vimRef.current = r2.vim;
|
|
168990
169128
|
if (r2.text !== lineRef.current)
|
|
168991
169129
|
setLine(r2.text);
|
|
@@ -169389,20 +169527,32 @@ var App2 = ({ onReady }) => {
|
|
|
169389
169527
|
ctrlDArmedAtRef.current = null;
|
|
169390
169528
|
setHintText(null);
|
|
169391
169529
|
});
|
|
169392
|
-
const repadBottomChrome = (0, import_react36.useCallback)(() => {
|
|
169530
|
+
const repadBottomChrome = (0, import_react36.useCallback)((pendingRows = 0) => {
|
|
169393
169531
|
if (!process.stdout.isTTY)
|
|
169394
169532
|
return;
|
|
169395
169533
|
if (fullscreenRef.current)
|
|
169396
169534
|
return;
|
|
169397
|
-
liveReserveRef.current = 0;
|
|
169398
169535
|
searchReserveRef.current = 0;
|
|
169399
169536
|
setItems((prev) => {
|
|
169537
|
+
const columns = process.stdout.columns || 80;
|
|
169400
169538
|
const withoutOldFiller = prev.filter((it) => !it.isFiller);
|
|
169401
169539
|
const printedRows = withoutOldFiller.reduce(
|
|
169402
|
-
(sum, it) => sum + rowsOccupied(it.content,
|
|
169540
|
+
(sum, it) => sum + rowsOccupied(it.content, columns),
|
|
169403
169541
|
0
|
|
169404
169542
|
);
|
|
169405
|
-
const
|
|
169543
|
+
const liveRows = liveRef.current ? rowsOccupied(liveRef.current, columns) : 0;
|
|
169544
|
+
const footer2 = footerRef.current ? footerText(footerRef.current) : "";
|
|
169545
|
+
const slack = fillerRowCount(printedRows, footer2, columns, void 0, liveRows, 1);
|
|
169546
|
+
const seed = Math.min(LIVE_BLOCK_MAX_ROWS, slack);
|
|
169547
|
+
liveReserveRef.current = seed;
|
|
169548
|
+
const filler = fillerRowCount(
|
|
169549
|
+
printedRows,
|
|
169550
|
+
footer2,
|
|
169551
|
+
columns,
|
|
169552
|
+
void 0,
|
|
169553
|
+
Math.max(liveRows, seed) + Math.max(0, pendingRows),
|
|
169554
|
+
1
|
|
169555
|
+
);
|
|
169406
169556
|
if (filler <= 0)
|
|
169407
169557
|
return withoutOldFiller;
|
|
169408
169558
|
return [...withoutOldFiller, { id: idCounter++, content: fillerContent(filler), isFiller: true }];
|
|
@@ -169442,12 +169592,12 @@ var App2 = ({ onReady }) => {
|
|
|
169442
169592
|
repadBottomChrome();
|
|
169443
169593
|
setStaticKey((k) => k + 1);
|
|
169444
169594
|
}, [repadBottomChrome]);
|
|
169445
|
-
const collapseStartupPadding = (0, import_react36.useCallback)(async () => {
|
|
169595
|
+
const collapseStartupPadding = (0, import_react36.useCallback)(async (opts) => {
|
|
169446
169596
|
if (fullscreenRef.current)
|
|
169447
169597
|
return;
|
|
169448
169598
|
await inkInstance?.waitUntilRenderFlush();
|
|
169449
169599
|
process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
169450
|
-
repadBottomChrome();
|
|
169600
|
+
repadBottomChrome(opts?.pendingRows ?? 0);
|
|
169451
169601
|
setStaticKey((k) => k + 1);
|
|
169452
169602
|
}, [repadBottomChrome]);
|
|
169453
169603
|
const setFullscreen = (0, import_react36.useCallback)(async (on) => {
|
|
@@ -169545,6 +169695,7 @@ var App2 = ({ onReady }) => {
|
|
|
169545
169695
|
}, []);
|
|
169546
169696
|
const slices = renderInputSlices(line, cursorPos);
|
|
169547
169697
|
const shownPrompt = prompt2 ?? (isVimEnabled() && vimMode === "normal" ? paint.yellow("[N] ") : null);
|
|
169698
|
+
const vsel = isVimEnabled() && vimVisual ? visualRange(line, vimRef.current, cursorPos) : null;
|
|
169548
169699
|
const colorsOn = colorEnabled();
|
|
169549
169700
|
const inputRowRef = (0, import_react36.useRef)(null);
|
|
169550
169701
|
const inputMetrics = use_box_metrics_default(inputRowRef);
|
|
@@ -169646,7 +169797,7 @@ var App2 = ({ onReady }) => {
|
|
|
169646
169797
|
borderRight: false,
|
|
169647
169798
|
borderDimColor: colorsOn
|
|
169648
169799
|
}
|
|
169649
|
-
), /* @__PURE__ */ import_react36.default.createElement(Box_default, { ref: inputRowRef }, /* @__PURE__ */ import_react36.default.createElement(Text, { wrap: "hard" }, /* @__PURE__ */ import_react36.default.createElement(Text, null, promptFor(shownPrompt)), /* @__PURE__ */ import_react36.default.createElement(Text, null, slices.before), /* @__PURE__ */ import_react36.default.createElement(Text, { inverse: true }, slices.atCursor), /* @__PURE__ */ import_react36.default.createElement(Text, null, slices.after))), /* @__PURE__ */ import_react36.default.createElement(
|
|
169800
|
+
), /* @__PURE__ */ import_react36.default.createElement(Box_default, { ref: inputRowRef }, /* @__PURE__ */ import_react36.default.createElement(Text, { wrap: "hard" }, /* @__PURE__ */ import_react36.default.createElement(Text, null, promptFor(shownPrompt)), vsel ? /* @__PURE__ */ import_react36.default.createElement(import_react36.default.Fragment, null, /* @__PURE__ */ import_react36.default.createElement(Text, null, line.slice(0, vsel.from)), /* @__PURE__ */ import_react36.default.createElement(Text, { inverse: true }, line.slice(vsel.from, vsel.to)), /* @__PURE__ */ import_react36.default.createElement(Text, null, line.slice(vsel.to))) : /* @__PURE__ */ import_react36.default.createElement(import_react36.default.Fragment, null, /* @__PURE__ */ import_react36.default.createElement(Text, null, slices.before), /* @__PURE__ */ import_react36.default.createElement(Text, { inverse: true }, slices.atCursor), /* @__PURE__ */ import_react36.default.createElement(Text, null, slices.after)))), /* @__PURE__ */ import_react36.default.createElement(
|
|
169650
169801
|
Box_default,
|
|
169651
169802
|
{
|
|
169652
169803
|
borderStyle: "single",
|
|
@@ -173738,7 +173889,13 @@ ${text}` : "");
|
|
|
173738
173889
|
let startupPadded = false;
|
|
173739
173890
|
if (interactive) {
|
|
173740
173891
|
await flushInkFrame();
|
|
173741
|
-
startupPadded = padToBottom(stopRowCount(), footerText(currentFooter()))
|
|
173892
|
+
startupPadded = padToBottom(stopRowCount(), footerText(currentFooter()), (text) => {
|
|
173893
|
+
const inkHandle = getInkTerminal();
|
|
173894
|
+
if (inkHandle)
|
|
173895
|
+
inkHandle.print(text, { isFiller: true });
|
|
173896
|
+
else
|
|
173897
|
+
console.log(text);
|
|
173898
|
+
});
|
|
173742
173899
|
}
|
|
173743
173900
|
let agentRunning = false;
|
|
173744
173901
|
const abortSignal = { aborted: false };
|
|
@@ -174386,7 +174543,8 @@ ${text}` : "");
|
|
|
174386
174543
|
userInput = intent.text;
|
|
174387
174544
|
if (startupPadded) {
|
|
174388
174545
|
startupPadded = false;
|
|
174389
|
-
|
|
174546
|
+
const pendingRows = !userInput.startsWith("/") && parseBang(userInput) === null ? 1 : 0;
|
|
174547
|
+
await getInkTerminal().collapseStartupPadding({ pendingRows });
|
|
174390
174548
|
}
|
|
174391
174549
|
if (userInput.startsWith("/")) {
|
|
174392
174550
|
const parts = userInput.split(/\s+/);
|