oharness 0.1.0

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.
Files changed (76) hide show
  1. package/dist/bin/sync.d.ts +3 -0
  2. package/dist/bin/sync.js +4 -0
  3. package/dist/bin/sync.js.map +1 -0
  4. package/dist/bin/web.d.ts +10 -0
  5. package/dist/bin/web.js +11 -0
  6. package/dist/bin/web.js.map +1 -0
  7. package/dist/headless/main.d.ts +2 -0
  8. package/dist/headless/main.js +133 -0
  9. package/dist/headless/main.js.map +1 -0
  10. package/dist/index.d.ts +8 -0
  11. package/dist/index.js +9 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/providers.d.ts +2 -0
  14. package/dist/providers.js +3 -0
  15. package/dist/providers.js.map +1 -0
  16. package/dist/tools.d.ts +2 -0
  17. package/dist/tools.js +3 -0
  18. package/dist/tools.js.map +1 -0
  19. package/dist/ui/artifact.d.ts +32 -0
  20. package/dist/ui/artifact.js +49 -0
  21. package/dist/ui/artifact.js.map +1 -0
  22. package/dist/ui/auth.d.ts +14 -0
  23. package/dist/ui/auth.js +177 -0
  24. package/dist/ui/auth.js.map +1 -0
  25. package/dist/ui/colors.d.ts +21 -0
  26. package/dist/ui/colors.js +28 -0
  27. package/dist/ui/colors.js.map +1 -0
  28. package/dist/ui/ink/app.d.ts +13 -0
  29. package/dist/ui/ink/app.js +418 -0
  30. package/dist/ui/ink/app.js.map +1 -0
  31. package/dist/ui/ink/logo.d.ts +6 -0
  32. package/dist/ui/ink/logo.js +20 -0
  33. package/dist/ui/ink/logo.js.map +1 -0
  34. package/dist/ui/ink/main.d.ts +2 -0
  35. package/dist/ui/ink/main.js +55 -0
  36. package/dist/ui/ink/main.js.map +1 -0
  37. package/dist/ui/ink/screen.d.ts +15 -0
  38. package/dist/ui/ink/screen.js +76 -0
  39. package/dist/ui/ink/screen.js.map +1 -0
  40. package/dist/ui/ink/select.d.ts +24 -0
  41. package/dist/ui/ink/select.js +74 -0
  42. package/dist/ui/ink/select.js.map +1 -0
  43. package/dist/ui/main.d.ts +2 -0
  44. package/dist/ui/main.js +1062 -0
  45. package/dist/ui/main.js.map +1 -0
  46. package/dist/ui/render.d.ts +15 -0
  47. package/dist/ui/render.js +130 -0
  48. package/dist/ui/render.js.map +1 -0
  49. package/dist/ui/select.d.ts +26 -0
  50. package/dist/ui/select.js +107 -0
  51. package/dist/ui/select.js.map +1 -0
  52. package/dist/ui/tui/app.d.ts +96 -0
  53. package/dist/ui/tui/app.js +476 -0
  54. package/dist/ui/tui/app.js.map +1 -0
  55. package/dist/ui/tui/editor.d.ts +40 -0
  56. package/dist/ui/tui/editor.js +124 -0
  57. package/dist/ui/tui/editor.js.map +1 -0
  58. package/dist/ui/tui/keys.d.ts +25 -0
  59. package/dist/ui/tui/keys.js +133 -0
  60. package/dist/ui/tui/keys.js.map +1 -0
  61. package/dist/ui/tui/layout.d.ts +63 -0
  62. package/dist/ui/tui/layout.js +202 -0
  63. package/dist/ui/tui/layout.js.map +1 -0
  64. package/dist/ui/tui/logo.d.ts +18 -0
  65. package/dist/ui/tui/logo.js +33 -0
  66. package/dist/ui/tui/logo.js.map +1 -0
  67. package/dist/ui/tui/screen.d.ts +48 -0
  68. package/dist/ui/tui/screen.js +150 -0
  69. package/dist/ui/tui/screen.js.map +1 -0
  70. package/dist/ui/tui/width.d.ts +30 -0
  71. package/dist/ui/tui/width.js +197 -0
  72. package/dist/ui/tui/width.js.map +1 -0
  73. package/dist/ui/wordmark.d.ts +30 -0
  74. package/dist/ui/wordmark.js +63 -0
  75. package/dist/ui/wordmark.js.map +1 -0
  76. package/package.json +49 -0
@@ -0,0 +1,476 @@
1
+ import { MODE_DESCRIPTIONS, MODE_LABELS, PERMISSION_MODES, } from "@oharness/engine/agent/permissions.ts";
2
+ import { errorMessage } from "@oharness/engine/core/errors.ts";
3
+ import { previewJson } from "@oharness/engine/util/json.ts";
4
+ import { artifactNote, artifactSummary } from "../artifact.js";
5
+ import { Editor } from "./editor.js";
6
+ import { parseKeys } from "./keys.js";
7
+ import { composeFrame } from "./layout.js";
8
+ import { openScreen } from "./screen.js";
9
+ /**
10
+ * The full-screen frontend: state, key handling, and the redraw loop.
11
+ *
12
+ * Redrawing is coalesced rather than immediate. A streaming reply delivers
13
+ * text several times per line, and painting a frame per token spends more time
14
+ * writing escape codes than the model spends generating — so state changes set
15
+ * a dirty flag and one frame is drawn per animation slot.
16
+ */
17
+ const FRAME_MS = 33; // ~30fps: fast enough to feel live, cheap enough to ignore
18
+ const ESCAPE = "\u001b";
19
+ /** How long a lone Escape waits for a continuation before counting as itself. */
20
+ const ESCAPE_MS = 40;
21
+ export class Tui {
22
+ harness;
23
+ session;
24
+ agent;
25
+ screen;
26
+ editor = new Editor();
27
+ blocks = [];
28
+ onCommand;
29
+ buffered = "";
30
+ scroll = 0;
31
+ dirty = false;
32
+ tick = 0;
33
+ busy = false;
34
+ pending;
35
+ abort;
36
+ /** The in-flight turn, so shutdown can wait for it to finish writing. */
37
+ turn;
38
+ exiting = false;
39
+ timer;
40
+ resolveExit;
41
+ escapeTimer;
42
+ constructor(opts) {
43
+ this.harness = opts.harness;
44
+ this.session = opts.session;
45
+ this.agent = opts.agent;
46
+ this.onCommand = opts.onCommand;
47
+ this.screen = openScreen(opts.streams, { beforeExit: () => this.shutdown() });
48
+ // The mark first, then the banner: the session details mean more once you
49
+ // know which program printed them.
50
+ this.blocks.push({ kind: "logo", text: "" });
51
+ for (const line of opts.banner ?? [])
52
+ this.blocks.push({ kind: "notice", text: line, center: true });
53
+ this.screen.onKey((data) => this.onData(data));
54
+ this.screen.onResize(() => this.markDirty());
55
+ }
56
+ /** Feed raw bytes as if typed. Used by tests; the screen calls this too. */
57
+ feed(data) {
58
+ this.onData(data);
59
+ }
60
+ /** Draw immediately rather than waiting for the next frame slot. */
61
+ flush() {
62
+ this.draw();
63
+ }
64
+ /** Print a line into the transcript area. */
65
+ write(text, kind = "notice") {
66
+ this.blocks.push({ kind, text });
67
+ this.markDirty();
68
+ }
69
+ /**
70
+ * Show an engine diagnostic in the transcript.
71
+ *
72
+ * These arrive on their own schedule — a sync retry, an MCP server going
73
+ * away — so they are dimmed: they belong to the program rather than to the
74
+ * conversation, and at full weight a background retry loop would read as
75
+ * the reply.
76
+ */
77
+ log(line) {
78
+ this.blocks.push({ kind: "log", text: line });
79
+ this.markDirty();
80
+ }
81
+ /** Replace the running session, as /clear and /fork do. */
82
+ adopt(session, agent) {
83
+ this.session = session;
84
+ this.agent = agent;
85
+ this.markDirty();
86
+ }
87
+ async run() {
88
+ this.timer = setInterval(() => {
89
+ if (this.busy) {
90
+ this.tick++;
91
+ this.dirty = true;
92
+ }
93
+ if (this.dirty)
94
+ this.draw();
95
+ }, FRAME_MS);
96
+ // Unref so a forgotten timer cannot hold the process open after exit.
97
+ this.timer.unref?.();
98
+ this.markDirty();
99
+ await new Promise((resolve) => {
100
+ this.resolveExit = resolve;
101
+ });
102
+ clearInterval(this.timer);
103
+ this.screen.close();
104
+ }
105
+ /**
106
+ * Ask the user to choose, as an overlay.
107
+ *
108
+ * Returns the chosen index, or undefined if they cancelled — callers must
109
+ * treat cancellation as a refusal, never as the highlighted option.
110
+ */
111
+ choose(overlay, initial = 0) {
112
+ return new Promise((resolve) => {
113
+ this.pending = {
114
+ overlay: { ...overlay, selected: initial },
115
+ resolve,
116
+ };
117
+ this.markDirty();
118
+ });
119
+ }
120
+ permissionPrompt = async (request) => {
121
+ const detail = [previewJson(request.input, 200)];
122
+ if (request.reason)
123
+ detail.unshift(request.reason);
124
+ const answers = [
125
+ { allow: true },
126
+ { allow: true, remember: "session" },
127
+ { allow: true, remember: "project" },
128
+ { allow: false },
129
+ ];
130
+ const picked = await this.choose({
131
+ title: `? ${request.title}`,
132
+ detail,
133
+ choices: [
134
+ { label: "Yes", hint: "just this once" },
135
+ { label: "Yes, and don't ask again this session" },
136
+ { label: "Yes, and remember for this project" },
137
+ { label: "No", hint: "tell the model what to do instead" },
138
+ ],
139
+ });
140
+ return picked === undefined ? { allow: false } : answers[picked];
141
+ };
142
+ async pickMode() {
143
+ const current = this.session.permissions.getMode();
144
+ const picked = await this.choose({
145
+ title: "Mode",
146
+ choices: PERMISSION_MODES.map((mode) => ({
147
+ label: MODE_LABELS[mode],
148
+ hint: MODE_DESCRIPTIONS[mode],
149
+ current: mode === current,
150
+ })),
151
+ }, Math.max(0, PERMISSION_MODES.indexOf(current)));
152
+ if (picked === undefined)
153
+ return;
154
+ const mode = PERMISSION_MODES[picked];
155
+ this.session.permissions.setMode(mode);
156
+ this.write(`mode → ${MODE_LABELS[mode]}`);
157
+ }
158
+ /** Run a prompt that did not come from the keyboard, e.g. an argv prompt. */
159
+ async submitExternal(prompt) {
160
+ this.blocks.push({ kind: "user", text: prompt });
161
+ await this.runTurn(prompt);
162
+ }
163
+ exit() {
164
+ if (this.exiting)
165
+ return;
166
+ this.exiting = true;
167
+ this.abort?.abort();
168
+ this.resolveExit?.();
169
+ }
170
+ // --- input ---------------------------------------------------------------
171
+ onData(data) {
172
+ if (this.escapeTimer) {
173
+ clearTimeout(this.escapeTimer);
174
+ this.escapeTimer = undefined;
175
+ }
176
+ // Keep any partial escape sequence: a chunk boundary in the middle of one
177
+ // would otherwise look like a bare Escape and cancel an open dialog.
178
+ const { keys, rest } = parseKeys(this.buffered + data);
179
+ this.buffered = rest;
180
+ for (const key of keys)
181
+ this.onKey(key);
182
+ // A held-back lone Escape is genuinely ambiguous — it is either the Escape
183
+ // key or the start of a sequence still in flight. Waiting briefly resolves
184
+ // it: real sequences arrive in the same read or the very next one, so if
185
+ // nothing follows, the user pressed Escape.
186
+ if (this.buffered === ESCAPE) {
187
+ this.escapeTimer = setTimeout(() => {
188
+ this.buffered = "";
189
+ this.escapeTimer = undefined;
190
+ this.onKey({ name: "escape" });
191
+ }, ESCAPE_MS);
192
+ this.escapeTimer.unref?.();
193
+ }
194
+ }
195
+ onKey(key) {
196
+ if (this.pending)
197
+ return this.overlayKey(key);
198
+ if (key.ctrl && key.name === "c") {
199
+ // First Ctrl-C interrupts the turn; a second one with nothing running
200
+ // quits, which is what a user expects from a shell.
201
+ if (this.busy) {
202
+ this.abort?.abort();
203
+ this.write("(interrupted)");
204
+ }
205
+ else
206
+ this.exit();
207
+ return;
208
+ }
209
+ if (key.ctrl && key.name === "d" && this.editor.text === "")
210
+ return this.exit();
211
+ switch (key.name) {
212
+ case "enter":
213
+ if (key.alt || key.shift) {
214
+ this.editor.insert("\n");
215
+ break;
216
+ }
217
+ void this.submit();
218
+ break;
219
+ case "paste":
220
+ this.editor.insert(key.text ?? "");
221
+ break;
222
+ case "text":
223
+ if (key.alt)
224
+ break; // an unhandled Alt-chord, not text to insert
225
+ this.editor.insert(key.text ?? "");
226
+ break;
227
+ case "backspace":
228
+ this.editor.backspace();
229
+ break;
230
+ case "delete":
231
+ this.editor.deleteForward();
232
+ break;
233
+ case "left":
234
+ key.ctrl || key.alt ? this.editor.wordLeft() : this.editor.left();
235
+ break;
236
+ case "right":
237
+ key.ctrl || key.alt ? this.editor.wordRight() : this.editor.right();
238
+ break;
239
+ case "up":
240
+ this.editor.previous();
241
+ break;
242
+ case "down":
243
+ this.editor.next();
244
+ break;
245
+ case "home":
246
+ this.editor.home();
247
+ break;
248
+ case "end":
249
+ this.editor.end();
250
+ break;
251
+ case "pageup":
252
+ this.scroll += Math.max(1, this.screen.rows - 6);
253
+ break;
254
+ case "pagedown":
255
+ this.scroll = Math.max(0, this.scroll - Math.max(1, this.screen.rows - 6));
256
+ break;
257
+ case "w":
258
+ if (key.ctrl)
259
+ this.editor.deleteWordBefore();
260
+ break;
261
+ case "u":
262
+ if (key.ctrl)
263
+ this.editor.deleteToStart();
264
+ break;
265
+ case "k":
266
+ if (key.ctrl)
267
+ this.editor.deleteToEnd();
268
+ break;
269
+ case "a":
270
+ if (key.ctrl)
271
+ this.editor.home();
272
+ break;
273
+ case "e":
274
+ if (key.ctrl)
275
+ this.editor.end();
276
+ break;
277
+ case "l":
278
+ if (key.ctrl)
279
+ this.blocks.length = 0;
280
+ break;
281
+ }
282
+ this.markDirty();
283
+ }
284
+ overlayKey(key) {
285
+ const pending = this.pending;
286
+ const total = pending.overlay.choices.length;
287
+ const finish = (index) => {
288
+ this.pending = undefined;
289
+ pending.resolve(index);
290
+ this.markDirty();
291
+ };
292
+ if (key.name === "escape" || (key.ctrl && key.name === "c"))
293
+ return finish(undefined);
294
+ if (key.name === "enter")
295
+ return finish(pending.overlay.selected);
296
+ if (key.name === "up")
297
+ pending.overlay.selected = (pending.overlay.selected - 1 + total) % total;
298
+ else if (key.name === "down")
299
+ pending.overlay.selected = (pending.overlay.selected + 1) % total;
300
+ else if (key.name === "text") {
301
+ const digit = Number.parseInt(key.text ?? "", 10);
302
+ if (Number.isInteger(digit) && digit >= 1 && digit <= total)
303
+ return finish(digit - 1);
304
+ }
305
+ this.markDirty();
306
+ }
307
+ async submit() {
308
+ const line = this.editor.text.trim();
309
+ if (line === "" || this.busy)
310
+ return;
311
+ this.editor.remember(line);
312
+ this.editor.clear();
313
+ this.scroll = 0;
314
+ if (line.startsWith("/")) {
315
+ this.blocks.push({ kind: "user", text: line });
316
+ const outcome = await this.onCommand(line, this);
317
+ if (outcome === "exit")
318
+ return this.exit();
319
+ if (outcome)
320
+ this.adopt(outcome.session, outcome.agent);
321
+ this.markDirty();
322
+ return;
323
+ }
324
+ this.blocks.push({ kind: "user", text: line });
325
+ await this.runTurn(line);
326
+ }
327
+ /**
328
+ * Stop an in-flight turn and wait for it to finish writing.
329
+ *
330
+ * The agent persists a turn's tool results only once the whole batch is
331
+ * done, so exiting the instant a signal arrives strands the assistant
332
+ * message with unanswered tool calls. Aborting instead lets the loop take
333
+ * its normal interrupted path, which records results for the calls that did
334
+ * finish.
335
+ */
336
+ async shutdown() {
337
+ this.abort?.abort();
338
+ // `runTurn` handles its own errors; the catch is only here so a rejection
339
+ // can never turn shutdown into an unhandled rejection.
340
+ await this.turn?.catch(() => { });
341
+ }
342
+ async runTurn(prompt) {
343
+ const turn = this.executeTurn(prompt);
344
+ this.turn = turn;
345
+ try {
346
+ await turn;
347
+ }
348
+ finally {
349
+ if (this.turn === turn)
350
+ this.turn = undefined;
351
+ }
352
+ }
353
+ async executeTurn(prompt) {
354
+ this.busy = true;
355
+ this.abort = new AbortController();
356
+ this.markDirty();
357
+ // One block per contiguous run of text, so streaming appends to the same
358
+ // paragraph instead of pushing a new one per delta.
359
+ let streaming;
360
+ const tools = new Map();
361
+ /** Artifact id → its row, so a revision updates in place. */
362
+ const artifacts = new Map();
363
+ try {
364
+ for await (const event of this.agent.run(prompt, { signal: this.abort.signal })) {
365
+ switch (event.type) {
366
+ case "text_delta":
367
+ if (!streaming) {
368
+ streaming = { kind: "assistant", text: "" };
369
+ this.blocks.push(streaming);
370
+ }
371
+ streaming.text += event.text;
372
+ break;
373
+ case "assistant_message":
374
+ streaming = undefined;
375
+ break;
376
+ case "tool_start": {
377
+ const block = { kind: "tool", text: event.title, done: false };
378
+ tools.set(event.toolCallId, block);
379
+ this.blocks.push(block);
380
+ streaming = undefined;
381
+ break;
382
+ }
383
+ case "tool_end": {
384
+ const block = tools.get(event.toolCallId);
385
+ if (block) {
386
+ block.done = true;
387
+ block.detail = `${event.durationMs}ms${event.result.isError ? " · failed" : ""}`;
388
+ }
389
+ break;
390
+ }
391
+ case "artifact": {
392
+ // Revisions replace the row rather than stacking: a model iterating
393
+ // on one page would otherwise push the conversation off the screen
394
+ // with eight near-identical lines.
395
+ const existing = artifacts.get(event.artifact.id);
396
+ const text = artifactSummary(event.artifact);
397
+ const note = artifactNote(event.artifact);
398
+ if (existing) {
399
+ existing.text = text;
400
+ if (note === undefined)
401
+ delete existing.note;
402
+ else
403
+ existing.note = note;
404
+ }
405
+ else {
406
+ const block = { kind: "artifact", text, ...(note ? { note } : {}) };
407
+ artifacts.set(event.artifact.id, block);
408
+ this.blocks.push(block);
409
+ }
410
+ streaming = undefined;
411
+ break;
412
+ }
413
+ case "permission_result":
414
+ if (!event.allowed) {
415
+ this.blocks.push({ kind: "error", text: event.reason ?? "denied" });
416
+ }
417
+ else if (event.remembered) {
418
+ this.blocks.push({ kind: "notice", text: `remembered: ${event.remembered}` });
419
+ }
420
+ break;
421
+ case "compacted":
422
+ this.blocks.push({
423
+ kind: "notice",
424
+ text: `compacted ${event.droppedMessages} messages (${event.tokensBefore} → ${event.tokensAfter} tokens)`,
425
+ });
426
+ break;
427
+ case "model_changed":
428
+ this.blocks.push({ kind: "notice", text: `${event.from} → ${event.to}` });
429
+ break;
430
+ case "notice":
431
+ this.blocks.push({ kind: "notice", text: event.message });
432
+ break;
433
+ case "error":
434
+ this.blocks.push({ kind: "error", text: event.error });
435
+ break;
436
+ }
437
+ this.markDirty();
438
+ }
439
+ }
440
+ catch (err) {
441
+ this.blocks.push({ kind: "error", text: errorMessage(err) });
442
+ }
443
+ finally {
444
+ this.busy = false;
445
+ this.abort = undefined;
446
+ this.markDirty();
447
+ }
448
+ }
449
+ // --- drawing -------------------------------------------------------------
450
+ markDirty() {
451
+ this.dirty = true;
452
+ }
453
+ draw() {
454
+ this.dirty = false;
455
+ const { rows, columns } = this.screen;
456
+ const contextLimit = this.session.model.contextWindow;
457
+ const used = this.session.usage.inputTokens + this.session.usage.outputTokens;
458
+ const frame = composeFrame({
459
+ blocks: this.blocks,
460
+ input: this.editor.text,
461
+ cursorColumns: this.editor.cursorColumns,
462
+ scroll: this.scroll,
463
+ ...(this.pending ? { overlay: this.pending.overlay } : {}),
464
+ status: {
465
+ model: this.session.model.id,
466
+ mode: MODE_LABELS[this.session.permissions.getMode()],
467
+ ...(contextLimit ? { contextUsed: Math.min(1, used / contextLimit) } : {}),
468
+ costUsd: this.session.costUsd,
469
+ busy: this.busy,
470
+ tick: this.tick,
471
+ },
472
+ }, rows, columns);
473
+ this.screen.render(frame.lines, frame.cursor);
474
+ }
475
+ }
476
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/ui/tui/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The text being typed, and where the caret sits in it.
3
+ *
4
+ * Positions are indices into an array of code points, never into the string.
5
+ * A JavaScript string index lands halfway through an astral character and one
6
+ * character before the end of a surrogate pair, so cursor arithmetic on raw
7
+ * `string.length` corrupts emoji and rare CJK the moment either is typed.
8
+ */
9
+ export declare class Editor {
10
+ private chars;
11
+ private caret;
12
+ private history;
13
+ private historyIndex;
14
+ /** What was being typed before walking into history, so Down can restore it. */
15
+ private draft;
16
+ get text(): string;
17
+ get cursor(): number;
18
+ /** Columns from the start of the text to the caret, for cursor placement. */
19
+ get cursorColumns(): number;
20
+ set(text: string): void;
21
+ clear(): void;
22
+ insert(text: string): void;
23
+ backspace(): void;
24
+ deleteForward(): void;
25
+ /** Delete the word before the caret, as Ctrl-W does in a shell. */
26
+ deleteWordBefore(): void;
27
+ deleteToStart(): void;
28
+ deleteToEnd(): void;
29
+ left(): void;
30
+ right(): void;
31
+ wordLeft(): void;
32
+ wordRight(): void;
33
+ home(): void;
34
+ end(): void;
35
+ /** Remember a submitted line. Consecutive duplicates are not stored twice. */
36
+ remember(text: string): void;
37
+ previous(): void;
38
+ next(): void;
39
+ private wordStart;
40
+ }
@@ -0,0 +1,124 @@
1
+ import { visibleWidth } from "./width.js";
2
+ /**
3
+ * The text being typed, and where the caret sits in it.
4
+ *
5
+ * Positions are indices into an array of code points, never into the string.
6
+ * A JavaScript string index lands halfway through an astral character and one
7
+ * character before the end of a surrogate pair, so cursor arithmetic on raw
8
+ * `string.length` corrupts emoji and rare CJK the moment either is typed.
9
+ */
10
+ export class Editor {
11
+ chars = [];
12
+ caret = 0;
13
+ history = [];
14
+ historyIndex = 0;
15
+ /** What was being typed before walking into history, so Down can restore it. */
16
+ draft = "";
17
+ get text() {
18
+ return this.chars.join("");
19
+ }
20
+ get cursor() {
21
+ return this.caret;
22
+ }
23
+ /** Columns from the start of the text to the caret, for cursor placement. */
24
+ get cursorColumns() {
25
+ return visibleWidth(this.chars.slice(0, this.caret).join(""));
26
+ }
27
+ set(text) {
28
+ this.chars = [...text];
29
+ this.caret = this.chars.length;
30
+ }
31
+ clear() {
32
+ this.chars = [];
33
+ this.caret = 0;
34
+ this.historyIndex = this.history.length;
35
+ }
36
+ insert(text) {
37
+ const incoming = [...text];
38
+ this.chars.splice(this.caret, 0, ...incoming);
39
+ this.caret += incoming.length;
40
+ }
41
+ backspace() {
42
+ if (this.caret === 0)
43
+ return;
44
+ this.chars.splice(this.caret - 1, 1);
45
+ this.caret--;
46
+ }
47
+ deleteForward() {
48
+ if (this.caret >= this.chars.length)
49
+ return;
50
+ this.chars.splice(this.caret, 1);
51
+ }
52
+ /** Delete the word before the caret, as Ctrl-W does in a shell. */
53
+ deleteWordBefore() {
54
+ const target = this.wordStart();
55
+ this.chars.splice(target, this.caret - target);
56
+ this.caret = target;
57
+ }
58
+ deleteToStart() {
59
+ this.chars.splice(0, this.caret);
60
+ this.caret = 0;
61
+ }
62
+ deleteToEnd() {
63
+ this.chars.splice(this.caret);
64
+ }
65
+ left() {
66
+ if (this.caret > 0)
67
+ this.caret--;
68
+ }
69
+ right() {
70
+ if (this.caret < this.chars.length)
71
+ this.caret++;
72
+ }
73
+ wordLeft() {
74
+ this.caret = this.wordStart();
75
+ }
76
+ wordRight() {
77
+ let i = this.caret;
78
+ while (i < this.chars.length && isSpace(this.chars[i]))
79
+ i++;
80
+ while (i < this.chars.length && !isSpace(this.chars[i]))
81
+ i++;
82
+ this.caret = i;
83
+ }
84
+ home() {
85
+ this.caret = 0;
86
+ }
87
+ end() {
88
+ this.caret = this.chars.length;
89
+ }
90
+ /** Remember a submitted line. Consecutive duplicates are not stored twice. */
91
+ remember(text) {
92
+ if (text && this.history.at(-1) !== text)
93
+ this.history.push(text);
94
+ this.historyIndex = this.history.length;
95
+ this.draft = "";
96
+ }
97
+ previous() {
98
+ if (!this.history.length || this.historyIndex === 0)
99
+ return;
100
+ // Stepping into history must not lose a half-typed line.
101
+ if (this.historyIndex === this.history.length)
102
+ this.draft = this.text;
103
+ this.historyIndex--;
104
+ this.set(this.history[this.historyIndex]);
105
+ }
106
+ next() {
107
+ if (this.historyIndex >= this.history.length)
108
+ return;
109
+ this.historyIndex++;
110
+ this.set(this.historyIndex === this.history.length ? this.draft : this.history[this.historyIndex]);
111
+ }
112
+ wordStart() {
113
+ let i = this.caret;
114
+ while (i > 0 && isSpace(this.chars[i - 1]))
115
+ i--;
116
+ while (i > 0 && !isSpace(this.chars[i - 1]))
117
+ i--;
118
+ return i;
119
+ }
120
+ }
121
+ function isSpace(char) {
122
+ return /\s/.test(char);
123
+ }
124
+ //# sourceMappingURL=editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../../src/ui/tui/editor.ts"],"names":[],"mappings":"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"}