nexrall-code 0.5.173 → 0.5.175
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 +249 -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,25 @@ 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
|
-
function
|
|
157427
|
+
function drainBlockRows(previous, printedRows) {
|
|
157428
|
+
return Math.max(0, previous - Math.max(0, printedRows));
|
|
157429
|
+
}
|
|
157430
|
+
var LIVE_BLOCK_MAX_ROWS = 5;
|
|
157431
|
+
function fillerRowCount(rowsAlreadyPrinted, footerTextValue = "", columns = process.stdout.columns ?? 80, rows = process.stdout.rows, reservedRows = 0, headroom = 2) {
|
|
157296
157432
|
if (!rows)
|
|
157297
157433
|
return 0;
|
|
157298
157434
|
const chromeRows = bottomChromeRows({ footerText: footerTextValue, columns });
|
|
157299
|
-
const filler = rows - rowsAlreadyPrinted - chromeRows -
|
|
157435
|
+
const filler = rows - rowsAlreadyPrinted - reservedRows - chromeRows - headroom;
|
|
157300
157436
|
const MIN_WORTHWHILE_FILLER = 3;
|
|
157301
157437
|
return filler < MIN_WORTHWHILE_FILLER ? 0 : filler;
|
|
157302
157438
|
}
|
|
157303
|
-
function padToBottom(rowsAlreadyPrinted, footerText2 = "") {
|
|
157439
|
+
function padToBottom(rowsAlreadyPrinted, footerText2 = "", sink = (text) => console.log(text)) {
|
|
157304
157440
|
if (!process.stdout.isTTY)
|
|
157305
157441
|
return false;
|
|
157306
157442
|
const filler = fillerRowCount(rowsAlreadyPrinted, footerText2);
|
|
157307
157443
|
if (filler <= 0)
|
|
157308
157444
|
return false;
|
|
157309
|
-
|
|
157445
|
+
sink("\n".repeat(filler - 1));
|
|
157310
157446
|
return true;
|
|
157311
157447
|
}
|
|
157312
157448
|
var rowCounter = null;
|
|
@@ -168577,6 +168713,7 @@ var App2 = ({ onReady }) => {
|
|
|
168577
168713
|
const cursorRef = (0, import_react36.useRef)(0);
|
|
168578
168714
|
const vimRef = (0, import_react36.useRef)(initialVim("insert"));
|
|
168579
168715
|
const [vimMode, setVimMode] = (0, import_react36.useState)("insert");
|
|
168716
|
+
const [vimVisual, setVimVisual] = (0, import_react36.useState)(false);
|
|
168580
168717
|
const setCursorPos = (0, import_react36.useCallback)((next) => {
|
|
168581
168718
|
const value = typeof next === "function" ? next(cursorRef.current) : next;
|
|
168582
168719
|
cursorRef.current = value;
|
|
@@ -168602,6 +168739,7 @@ var App2 = ({ onReady }) => {
|
|
|
168602
168739
|
const menuDismissedRef = (0, import_react36.useRef)(null);
|
|
168603
168740
|
const menuReserveRef = (0, import_react36.useRef)(0);
|
|
168604
168741
|
const liveReserveRef = (0, import_react36.useRef)(0);
|
|
168742
|
+
const pendingPrintRowsRef = (0, import_react36.useRef)(0);
|
|
168605
168743
|
const searchReserveRef = (0, import_react36.useRef)(0);
|
|
168606
168744
|
const [, bumpMenu] = (0, import_react36.useState)(0);
|
|
168607
168745
|
const [, setPaintTick] = (0, import_react36.useState)(0);
|
|
@@ -168693,7 +168831,16 @@ var App2 = ({ onReady }) => {
|
|
|
168693
168831
|
if (opts?.isBanner)
|
|
168694
168832
|
bannerChunkRef.current = bufferRef.current.length;
|
|
168695
168833
|
bufferRef.current.append(text);
|
|
168696
|
-
|
|
168834
|
+
if (!opts?.isBanner && !opts?.isFiller && !liveRef.current) {
|
|
168835
|
+
const rows = rowsOccupied(text, process.stdout.columns || 80);
|
|
168836
|
+
const pending = pendingPrintRowsRef.current;
|
|
168837
|
+
const paid = Math.min(pending, rows);
|
|
168838
|
+
pendingPrintRowsRef.current = pending - paid;
|
|
168839
|
+
liveReserveRef.current = drainBlockRows(liveReserveRef.current, rows - paid);
|
|
168840
|
+
}
|
|
168841
|
+
setItems((prev) => {
|
|
168842
|
+
return [...prev, { id: idCounter++, content: text, isBanner: opts?.isBanner, isFiller: opts?.isFiller }];
|
|
168843
|
+
});
|
|
168697
168844
|
}, []);
|
|
168698
168845
|
const bannerRegeneratorRef = (0, import_react36.useRef)(null);
|
|
168699
168846
|
const setBannerRegenerator = (0, import_react36.useCallback)((fn) => {
|
|
@@ -168986,6 +169133,8 @@ var App2 = ({ onReady }) => {
|
|
|
168986
169133
|
if (r2.handled) {
|
|
168987
169134
|
if (r2.vim.mode !== vimRef.current.mode)
|
|
168988
169135
|
setVimMode(r2.vim.mode);
|
|
169136
|
+
if (!!r2.vim.visual !== !!vimRef.current.visual)
|
|
169137
|
+
setVimVisual(!!r2.vim.visual);
|
|
168989
169138
|
vimRef.current = r2.vim;
|
|
168990
169139
|
if (r2.text !== lineRef.current)
|
|
168991
169140
|
setLine(r2.text);
|
|
@@ -169389,20 +169538,33 @@ var App2 = ({ onReady }) => {
|
|
|
169389
169538
|
ctrlDArmedAtRef.current = null;
|
|
169390
169539
|
setHintText(null);
|
|
169391
169540
|
});
|
|
169392
|
-
const repadBottomChrome = (0, import_react36.useCallback)(() => {
|
|
169541
|
+
const repadBottomChrome = (0, import_react36.useCallback)((pendingRows = 0) => {
|
|
169393
169542
|
if (!process.stdout.isTTY)
|
|
169394
169543
|
return;
|
|
169395
169544
|
if (fullscreenRef.current)
|
|
169396
169545
|
return;
|
|
169397
|
-
liveReserveRef.current = 0;
|
|
169398
169546
|
searchReserveRef.current = 0;
|
|
169547
|
+
pendingPrintRowsRef.current = Math.max(0, pendingRows);
|
|
169399
169548
|
setItems((prev) => {
|
|
169549
|
+
const columns = process.stdout.columns || 80;
|
|
169400
169550
|
const withoutOldFiller = prev.filter((it) => !it.isFiller);
|
|
169401
169551
|
const printedRows = withoutOldFiller.reduce(
|
|
169402
|
-
(sum, it) => sum + rowsOccupied(it.content,
|
|
169552
|
+
(sum, it) => sum + rowsOccupied(it.content, columns),
|
|
169403
169553
|
0
|
|
169404
169554
|
);
|
|
169405
|
-
const
|
|
169555
|
+
const liveRows = liveRef.current ? rowsOccupied(liveRef.current, columns) : 0;
|
|
169556
|
+
const footer2 = footerRef.current ? footerText(footerRef.current) : "";
|
|
169557
|
+
const slack = fillerRowCount(printedRows, footer2, columns, void 0, liveRows, 1);
|
|
169558
|
+
const seed = Math.min(LIVE_BLOCK_MAX_ROWS, slack);
|
|
169559
|
+
liveReserveRef.current = seed;
|
|
169560
|
+
const filler = fillerRowCount(
|
|
169561
|
+
printedRows,
|
|
169562
|
+
footer2,
|
|
169563
|
+
columns,
|
|
169564
|
+
void 0,
|
|
169565
|
+
Math.max(liveRows, seed) + Math.max(0, pendingRows),
|
|
169566
|
+
1
|
|
169567
|
+
);
|
|
169406
169568
|
if (filler <= 0)
|
|
169407
169569
|
return withoutOldFiller;
|
|
169408
169570
|
return [...withoutOldFiller, { id: idCounter++, content: fillerContent(filler), isFiller: true }];
|
|
@@ -169442,12 +169604,12 @@ var App2 = ({ onReady }) => {
|
|
|
169442
169604
|
repadBottomChrome();
|
|
169443
169605
|
setStaticKey((k) => k + 1);
|
|
169444
169606
|
}, [repadBottomChrome]);
|
|
169445
|
-
const collapseStartupPadding = (0, import_react36.useCallback)(async () => {
|
|
169607
|
+
const collapseStartupPadding = (0, import_react36.useCallback)(async (opts) => {
|
|
169446
169608
|
if (fullscreenRef.current)
|
|
169447
169609
|
return;
|
|
169448
169610
|
await inkInstance?.waitUntilRenderFlush();
|
|
169449
169611
|
process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
169450
|
-
repadBottomChrome();
|
|
169612
|
+
repadBottomChrome(opts?.pendingRows ?? 0);
|
|
169451
169613
|
setStaticKey((k) => k + 1);
|
|
169452
169614
|
}, [repadBottomChrome]);
|
|
169453
169615
|
const setFullscreen = (0, import_react36.useCallback)(async (on) => {
|
|
@@ -169545,6 +169707,7 @@ var App2 = ({ onReady }) => {
|
|
|
169545
169707
|
}, []);
|
|
169546
169708
|
const slices = renderInputSlices(line, cursorPos);
|
|
169547
169709
|
const shownPrompt = prompt2 ?? (isVimEnabled() && vimMode === "normal" ? paint.yellow("[N] ") : null);
|
|
169710
|
+
const vsel = isVimEnabled() && vimVisual ? visualRange(line, vimRef.current, cursorPos) : null;
|
|
169548
169711
|
const colorsOn = colorEnabled();
|
|
169549
169712
|
const inputRowRef = (0, import_react36.useRef)(null);
|
|
169550
169713
|
const inputMetrics = use_box_metrics_default(inputRowRef);
|
|
@@ -169646,7 +169809,7 @@ var App2 = ({ onReady }) => {
|
|
|
169646
169809
|
borderRight: false,
|
|
169647
169810
|
borderDimColor: colorsOn
|
|
169648
169811
|
}
|
|
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(
|
|
169812
|
+
), /* @__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
169813
|
Box_default,
|
|
169651
169814
|
{
|
|
169652
169815
|
borderStyle: "single",
|
|
@@ -173738,7 +173901,13 @@ ${text}` : "");
|
|
|
173738
173901
|
let startupPadded = false;
|
|
173739
173902
|
if (interactive) {
|
|
173740
173903
|
await flushInkFrame();
|
|
173741
|
-
startupPadded = padToBottom(stopRowCount(), footerText(currentFooter()))
|
|
173904
|
+
startupPadded = padToBottom(stopRowCount(), footerText(currentFooter()), (text) => {
|
|
173905
|
+
const inkHandle = getInkTerminal();
|
|
173906
|
+
if (inkHandle)
|
|
173907
|
+
inkHandle.print(text, { isFiller: true });
|
|
173908
|
+
else
|
|
173909
|
+
console.log(text);
|
|
173910
|
+
});
|
|
173742
173911
|
}
|
|
173743
173912
|
let agentRunning = false;
|
|
173744
173913
|
const abortSignal = { aborted: false };
|
|
@@ -174386,7 +174555,8 @@ ${text}` : "");
|
|
|
174386
174555
|
userInput = intent.text;
|
|
174387
174556
|
if (startupPadded) {
|
|
174388
174557
|
startupPadded = false;
|
|
174389
|
-
|
|
174558
|
+
const pendingRows = !userInput.startsWith("/") && parseBang(userInput) === null ? 1 : 0;
|
|
174559
|
+
await getInkTerminal().collapseStartupPadding({ pendingRows });
|
|
174390
174560
|
}
|
|
174391
174561
|
if (userInput.startsWith("/")) {
|
|
174392
174562
|
const parts = userInput.split(/\s+/);
|