wormclaude 1.0.96 → 1.0.98
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/lineeditor.js +22 -13
- package/dist/theme.js +1 -1
- package/dist/tui.js +61 -12
- package/package.json +1 -1
package/dist/lineeditor.js
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import { Text, useInput } from 'ink';
|
|
3
3
|
// Tam imleç-kontrollü satır editörü (ink-text-input yerine).
|
|
4
|
-
//
|
|
4
|
+
// ÖNEMLİ: Ink'in useInput'u handler'ı bayat closure ile çağırabilir → value/cursor'u REF'ten okuruz
|
|
5
|
+
// (her render güncellenir) ki sağ-ok/yazma doğru konumu kullansın.
|
|
6
|
+
// Destekler: yazma (imleç konumuna), Backspace/Delete, ← →, Home/End (Ctrl+A/Ctrl+E).
|
|
5
7
|
// ↑↓/PageUp/PageDown/Esc/Tab'a DOKUNMAZ → menü/scroll/dialog handler'larına geçer.
|
|
6
8
|
export default function LineEditor({ value, onChange, onSubmit, placeholder, isActive = true, color }) {
|
|
7
9
|
const [cursor, setCursor] = useState(value.length);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
const valueRef = useRef(value);
|
|
11
|
+
const cursorRef = useRef(cursor);
|
|
12
|
+
valueRef.current = value; // her render'da güncel değer
|
|
13
|
+
cursorRef.current = cursor;
|
|
14
|
+
// value dışarıdan kısalırsa imleci sınırla (örn. submit'te temizlenince).
|
|
15
|
+
useEffect(() => { if (cursor > value.length)
|
|
16
|
+
setCursor(value.length); }, [value]); // eslint-disable-line
|
|
10
17
|
useInput((input, key) => {
|
|
18
|
+
const val = valueRef.current;
|
|
19
|
+
const cur = cursorRef.current;
|
|
11
20
|
if (key.leftArrow) {
|
|
12
|
-
setCursor(
|
|
21
|
+
setCursor(Math.max(0, cur - 1));
|
|
13
22
|
return;
|
|
14
23
|
}
|
|
15
24
|
if (key.rightArrow) {
|
|
16
|
-
setCursor(
|
|
25
|
+
setCursor(Math.min(val.length, cur + 1));
|
|
17
26
|
return;
|
|
18
27
|
}
|
|
19
28
|
if (key.return) {
|
|
20
|
-
onSubmit?.(
|
|
29
|
+
onSubmit?.(val);
|
|
21
30
|
return;
|
|
22
31
|
}
|
|
23
32
|
if (key.backspace || key.delete) {
|
|
24
|
-
if (
|
|
25
|
-
onChange(
|
|
26
|
-
setCursor(
|
|
33
|
+
if (cur > 0) {
|
|
34
|
+
onChange(val.slice(0, cur - 1) + val.slice(cur));
|
|
35
|
+
setCursor(cur - 1);
|
|
27
36
|
}
|
|
28
37
|
return;
|
|
29
38
|
}
|
|
@@ -32,15 +41,15 @@ export default function LineEditor({ value, onChange, onSubmit, placeholder, isA
|
|
|
32
41
|
return;
|
|
33
42
|
}
|
|
34
43
|
if (key.ctrl && input === 'e') {
|
|
35
|
-
setCursor(
|
|
44
|
+
setCursor(val.length);
|
|
36
45
|
return;
|
|
37
46
|
}
|
|
38
47
|
// Gezinme/özel tuşlar bize ait değil → metne yazma, başka handler'lara bırak.
|
|
39
48
|
if (key.ctrl || key.meta || key.tab || key.escape || key.upArrow || key.downArrow || key.pageUp || key.pageDown)
|
|
40
49
|
return;
|
|
41
50
|
if (input) {
|
|
42
|
-
onChange(
|
|
43
|
-
setCursor(
|
|
51
|
+
onChange(val.slice(0, cur) + input + val.slice(cur));
|
|
52
|
+
setCursor(cur + input.length);
|
|
44
53
|
}
|
|
45
54
|
}, { isActive });
|
|
46
55
|
// Placeholder (boş input)
|
package/dist/theme.js
CHANGED
package/dist/tui.js
CHANGED
|
@@ -64,7 +64,7 @@ export async function runTui() {
|
|
|
64
64
|
...(_memCtx ? [{ role: 'system', content: _memCtx }] : []),
|
|
65
65
|
];
|
|
66
66
|
const displayItems = [{ kind: 'banner' }];
|
|
67
|
-
let inputBuf = '', busy = false, streamChars = 0, spin = 0;
|
|
67
|
+
let inputBuf = '', inputCur = 0, busy = false, streamChars = 0, spin = 0;
|
|
68
68
|
// Canlı akış artık FOOTER'da DEĞİL — içerik akışına (mesajın altından aşağı) satır-satır basılır.
|
|
69
69
|
const SPIN = ['·', '✢', '✳', '✶', '✻', '✽', '✶', '✳', '✢'];
|
|
70
70
|
// Canlı bağlam ölçer: son isteğin prompt_tokens'ı = o anki kullanılan bağlam (footer'da gösterilir).
|
|
@@ -76,25 +76,36 @@ export async function runTui() {
|
|
|
76
76
|
const MAX_INPUT_LINES = 6;
|
|
77
77
|
const inputBoxLines = (W) => {
|
|
78
78
|
const inner = Math.max(4, W - 2); // "✶ " önek payı
|
|
79
|
+
const REV = '\x1b[7m', UNREV = '\x1b[27m'; // ters-video blok imleç
|
|
80
|
+
// Karakterleri hücreye çevir; imleçteki karakter ters-video (sondaysa boşluk bloğu).
|
|
81
|
+
const cells = [];
|
|
82
|
+
const chs = [...inputBuf];
|
|
83
|
+
for (let i = 0; i < chs.length; i++) {
|
|
84
|
+
cells.push({ s: i === inputCur ? REV + chs[i] + UNREV : chs[i], w: stringWidth(chs[i]) || 1 });
|
|
85
|
+
}
|
|
86
|
+
if (inputCur >= chs.length)
|
|
87
|
+
cells.push({ s: REV + ' ' + UNREV, w: 1 });
|
|
88
|
+
// Genişliğe göre sar.
|
|
79
89
|
const wrapped = [];
|
|
80
|
-
let cur = '';
|
|
81
|
-
for (const
|
|
82
|
-
if (
|
|
90
|
+
let cur = '', w = 0;
|
|
91
|
+
for (const c of cells) {
|
|
92
|
+
if (w + c.w > inner) {
|
|
83
93
|
wrapped.push(cur);
|
|
84
|
-
cur =
|
|
94
|
+
cur = '';
|
|
95
|
+
w = 0;
|
|
85
96
|
}
|
|
86
|
-
|
|
87
|
-
|
|
97
|
+
cur += c.s;
|
|
98
|
+
w += c.w;
|
|
88
99
|
}
|
|
89
100
|
wrapped.push(cur);
|
|
90
101
|
if (wrapped.length <= MAX_INPUT_LINES) {
|
|
91
|
-
return wrapped.map((ln, i) => (i === 0 ? paint('✶ ', theme.redBright, true) : ' ') + paint(ln, theme.white)
|
|
102
|
+
return wrapped.map((ln, i) => (i === 0 ? paint('✶ ', theme.redBright, true) : ' ') + paint(ln, theme.white));
|
|
92
103
|
}
|
|
93
104
|
// Çok uzun (büyük yapıştırma): son birkaç satır + üstte özet — footer'ı doldurmaz.
|
|
94
105
|
const extra = wrapped.length - (MAX_INPUT_LINES - 1);
|
|
95
106
|
const tail = wrapped.slice(-(MAX_INPUT_LINES - 1));
|
|
96
107
|
const head = paint('✶ ' + t('tui.pasteSummary', extra, inputBuf.length), theme.greyDim);
|
|
97
|
-
return [head, ...tail.map((ln
|
|
108
|
+
return [head, ...tail.map((ln) => ' ' + paint(ln, theme.white))];
|
|
98
109
|
};
|
|
99
110
|
// Footer yüksekliği DİNAMİK: izin=4; değilse (durum/menü) + çizgi + giriş-satırları + çizgi.
|
|
100
111
|
// SABİT rezerve footer alanı (scroll region bir kez ayarlanır → churn/duplicate yok). Footer bu
|
|
@@ -464,6 +475,7 @@ export async function runTui() {
|
|
|
464
475
|
if (key && key.ctrl && key.name === 'c') {
|
|
465
476
|
if (inputBuf) {
|
|
466
477
|
inputBuf = '';
|
|
478
|
+
inputCur = 0;
|
|
467
479
|
refresh();
|
|
468
480
|
return;
|
|
469
481
|
}
|
|
@@ -489,6 +501,7 @@ export async function runTui() {
|
|
|
489
501
|
if (inputHistory.length) {
|
|
490
502
|
histIdx = histIdx < 0 ? inputHistory.length - 1 : Math.max(0, histIdx - 1);
|
|
491
503
|
inputBuf = inputHistory[histIdx];
|
|
504
|
+
inputCur = inputBuf.length;
|
|
492
505
|
refresh();
|
|
493
506
|
}
|
|
494
507
|
return;
|
|
@@ -508,15 +521,38 @@ export async function runTui() {
|
|
|
508
521
|
}
|
|
509
522
|
else
|
|
510
523
|
inputBuf = inputHistory[histIdx];
|
|
524
|
+
inputCur = inputBuf.length;
|
|
511
525
|
refresh();
|
|
512
526
|
}
|
|
513
527
|
return;
|
|
514
528
|
}
|
|
529
|
+
// ← → imleç hareketi + Home/End (Ctrl+A/Ctrl+E)
|
|
530
|
+
if (key && key.name === 'left') {
|
|
531
|
+
inputCur = Math.max(0, inputCur - 1);
|
|
532
|
+
refresh();
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
if (key && key.name === 'right') {
|
|
536
|
+
inputCur = Math.min(inputBuf.length, inputCur + 1);
|
|
537
|
+
refresh();
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
if (key && (key.name === 'home' || (key.ctrl && key.name === 'a'))) {
|
|
541
|
+
inputCur = 0;
|
|
542
|
+
refresh();
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
if (key && (key.name === 'end' || (key.ctrl && key.name === 'e'))) {
|
|
546
|
+
inputCur = inputBuf.length;
|
|
547
|
+
refresh();
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
515
550
|
// Tab — seçili slash komutunu tamamla
|
|
516
551
|
if (key && key.name === 'tab') {
|
|
517
552
|
const m = cmdMatches();
|
|
518
553
|
if (m.length) {
|
|
519
554
|
inputBuf = m[Math.min(cmdSel, m.length - 1)].name + ' ';
|
|
555
|
+
inputCur = inputBuf.length;
|
|
520
556
|
cmdSel = 0;
|
|
521
557
|
refresh();
|
|
522
558
|
}
|
|
@@ -527,6 +563,7 @@ export async function runTui() {
|
|
|
527
563
|
return; // tur sürerken Enter beklemede; yazılan metin durur (type-ahead)
|
|
528
564
|
let v = inputBuf.trim();
|
|
529
565
|
inputBuf = '';
|
|
566
|
+
inputCur = 0;
|
|
530
567
|
histIdx = -1;
|
|
531
568
|
if (!v) {
|
|
532
569
|
refresh();
|
|
@@ -601,19 +638,31 @@ export async function runTui() {
|
|
|
601
638
|
return;
|
|
602
639
|
}
|
|
603
640
|
if (key && key.name === 'backspace') {
|
|
604
|
-
|
|
641
|
+
if (inputCur > 0) {
|
|
642
|
+
inputBuf = inputBuf.slice(0, inputCur - 1) + inputBuf.slice(inputCur);
|
|
643
|
+
inputCur--;
|
|
644
|
+
}
|
|
645
|
+
cmdSel = 0;
|
|
646
|
+
scheduleFooter();
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
if (key && key.name === 'delete') {
|
|
650
|
+
if (inputCur < inputBuf.length)
|
|
651
|
+
inputBuf = inputBuf.slice(0, inputCur) + inputBuf.slice(inputCur + 1);
|
|
605
652
|
cmdSel = 0;
|
|
606
653
|
scheduleFooter();
|
|
607
654
|
return;
|
|
608
655
|
}
|
|
609
656
|
if (key && key.name === 'escape') {
|
|
610
657
|
inputBuf = '';
|
|
658
|
+
inputCur = 0;
|
|
611
659
|
refresh();
|
|
612
660
|
return;
|
|
613
661
|
}
|
|
614
|
-
// sadece gerçek yazdırılabilir karakter (her zaman →
|
|
662
|
+
// sadece gerçek yazdırılabilir karakter — imleç KONUMUNA ekle (her zaman → type-ahead)
|
|
615
663
|
if (str && !key?.ctrl && !key?.meta && !str.startsWith('\x1b') && !/[\x00-\x1f]/.test(str)) {
|
|
616
|
-
inputBuf
|
|
664
|
+
inputBuf = inputBuf.slice(0, inputCur) + str + inputBuf.slice(inputCur);
|
|
665
|
+
inputCur += str.length;
|
|
617
666
|
cmdSel = 0;
|
|
618
667
|
scheduleFooter();
|
|
619
668
|
}
|