@sagmans/dsh-tui 0.2.0 → 0.3.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.
- package/README.md +126 -21
- package/lib/agent/model.d.ts +26 -0
- package/lib/agent/model.d.ts.map +1 -1
- package/lib/agent/model.js +41 -0
- package/lib/agent/model.js.map +1 -1
- package/lib/agent/status.d.ts +10 -0
- package/lib/agent/status.d.ts.map +1 -1
- package/lib/agent/status.js +2 -0
- package/lib/agent/status.js.map +1 -1
- package/lib/cards.d.ts +1 -1
- package/lib/cards.d.ts.map +1 -1
- package/lib/cards.js +4 -3
- package/lib/cards.js.map +1 -1
- package/lib/gates.d.ts +145 -2
- package/lib/gates.d.ts.map +1 -1
- package/lib/gates.js +335 -40
- package/lib/gates.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +383 -102
- package/lib/index.js.map +1 -1
- package/lib/input/actions.d.ts +136 -0
- package/lib/input/actions.d.ts.map +1 -0
- package/lib/input/actions.js +740 -0
- package/lib/input/actions.js.map +1 -0
- package/lib/input/keymap-settings.d.ts +21 -0
- package/lib/input/keymap-settings.d.ts.map +1 -0
- package/lib/input/keymap-settings.js +28 -0
- package/lib/input/keymap-settings.js.map +1 -0
- package/lib/input/keymap.d.ts +91 -0
- package/lib/input/keymap.d.ts.map +1 -0
- package/lib/input/keymap.js +170 -0
- package/lib/input/keymap.js.map +1 -0
- package/lib/input/match.d.ts +10 -0
- package/lib/input/match.d.ts.map +1 -0
- package/lib/input/match.js +83 -0
- package/lib/input/match.js.map +1 -0
- package/lib/input/submission.d.ts +6 -1
- package/lib/input/submission.d.ts.map +1 -1
- package/lib/input/submission.js +6 -2
- package/lib/input/submission.js.map +1 -1
- package/lib/input.d.ts +17 -0
- package/lib/input.d.ts.map +1 -0
- package/lib/input.js +27 -0
- package/lib/input.js.map +1 -0
- package/lib/keys-command.d.ts +16 -0
- package/lib/keys-command.d.ts.map +1 -0
- package/lib/keys-command.js +60 -0
- package/lib/keys-command.js.map +1 -0
- package/lib/queue.d.ts +6 -0
- package/lib/queue.d.ts.map +1 -0
- package/lib/queue.js +68 -0
- package/lib/queue.js.map +1 -0
- package/lib/settings-notice.d.ts +19 -0
- package/lib/settings-notice.d.ts.map +1 -0
- package/lib/settings-notice.js +30 -0
- package/lib/settings-notice.js.map +1 -0
- package/lib/theme-settings.d.ts +43 -8
- package/lib/theme-settings.d.ts.map +1 -1
- package/lib/theme-settings.js +66 -3
- package/lib/theme-settings.js.map +1 -1
- package/lib/theme-tokens.d.ts +4 -4
- package/lib/theme-tokens.d.ts.map +1 -1
- package/lib/theme-tokens.js +31 -5
- package/lib/theme-tokens.js.map +1 -1
- package/lib/ui/editor.d.ts +18 -1
- package/lib/ui/editor.d.ts.map +1 -1
- package/lib/ui/editor.js +80 -19
- package/lib/ui/editor.js.map +1 -1
- package/lib/ui/frame.d.ts +54 -0
- package/lib/ui/frame.d.ts.map +1 -0
- package/lib/ui/frame.js +79 -0
- package/lib/ui/frame.js.map +1 -0
- package/lib/ui/gate-input.d.ts +20 -0
- package/lib/ui/gate-input.d.ts.map +1 -0
- package/lib/ui/gate-input.js +96 -0
- package/lib/ui/gate-input.js.map +1 -0
- package/lib/ui/markdown.d.ts +11 -2
- package/lib/ui/markdown.d.ts.map +1 -1
- package/lib/ui/markdown.js +25 -6
- package/lib/ui/markdown.js.map +1 -1
- package/lib/ui/mermaid.d.ts +44 -0
- package/lib/ui/mermaid.d.ts.map +1 -0
- package/lib/ui/mermaid.js +178 -0
- package/lib/ui/mermaid.js.map +1 -0
- package/lib/ui/picker.d.ts +30 -8
- package/lib/ui/picker.d.ts.map +1 -1
- package/lib/ui/picker.js +63 -23
- package/lib/ui/picker.js.map +1 -1
- package/lib/ui/prompt.d.ts +30 -0
- package/lib/ui/prompt.d.ts.map +1 -0
- package/lib/ui/prompt.js +45 -0
- package/lib/ui/prompt.js.map +1 -0
- package/lib/ui/queue.d.ts +24 -0
- package/lib/ui/queue.d.ts.map +1 -0
- package/lib/ui/queue.js +57 -0
- package/lib/ui/queue.js.map +1 -0
- package/lib/ui/status.d.ts +4 -0
- package/lib/ui/status.d.ts.map +1 -1
- package/lib/ui/status.js +8 -0
- package/lib/ui/status.js.map +1 -1
- package/lib/ui/view.d.ts +22 -2
- package/lib/ui/view.d.ts.map +1 -1
- package/lib/ui/view.js +84 -24
- package/lib/ui/view.js.map +1 -1
- package/lib/work.d.ts +48 -0
- package/lib/work.d.ts.map +1 -1
- package/lib/work.js +44 -0
- package/lib/work.js.map +1 -1
- package/package.json +3 -2
package/lib/theme-tokens.js
CHANGED
|
@@ -30,10 +30,10 @@ export const ARGUMENT_BLUE = '#8db3d9';
|
|
|
30
30
|
* The shade a submitted prompt takes.
|
|
31
31
|
*
|
|
32
32
|
* A reader's own turns and the assistant's reply both shipped on the default
|
|
33
|
-
* foreground, so telling the two apart meant reading them; a
|
|
34
|
-
*
|
|
33
|
+
* foreground, so telling the two apart meant reading them; a mint keeps them
|
|
34
|
+
* apart at a glance without the pink cast a rose gave every prompt.
|
|
35
35
|
*/
|
|
36
|
-
export const
|
|
36
|
+
export const USER_PROMPT_MINT = '#27F5C8';
|
|
37
37
|
/** Palette entries a token may name instead of a literal colour. */
|
|
38
38
|
export const PALETTE_NAMES = ['default', 'muted', 'accent', 'arg', 'warn', 'added', 'removed', 'user', 'assistant'];
|
|
39
39
|
/** A row class a tool card can carry, so styling follows what the row means. */
|
|
@@ -105,6 +105,14 @@ export const TUI_TOKENS = [
|
|
|
105
105
|
'markdown.italic',
|
|
106
106
|
'markdown.strikethrough',
|
|
107
107
|
'markdown.underline',
|
|
108
|
+
// A drawn mermaid diagram: the renderer reports what each run *is*, so every
|
|
109
|
+
// role a drawing can be made of is addressable on its own.
|
|
110
|
+
'markdown.diagram.border',
|
|
111
|
+
'markdown.diagram.text',
|
|
112
|
+
'markdown.diagram.edge',
|
|
113
|
+
'markdown.diagram.edgeLabel',
|
|
114
|
+
'markdown.diagram.title',
|
|
115
|
+
'markdown.diagram.warning',
|
|
108
116
|
// No markdown.tableHeader: pi-tui styles table headers through the bold hook
|
|
109
117
|
// it already owns, so a token here would be a setting with no call site.
|
|
110
118
|
// Picker
|
|
@@ -141,6 +149,8 @@ export const TUI_TOKENS = [
|
|
|
141
149
|
'dock.jobs.running',
|
|
142
150
|
'dock.jobs.overflow',
|
|
143
151
|
// Status bar
|
|
152
|
+
'status.prefix',
|
|
153
|
+
'status.back',
|
|
144
154
|
'status.activity.working',
|
|
145
155
|
'status.activity.ready',
|
|
146
156
|
'status.elapsed',
|
|
@@ -154,6 +164,8 @@ export const TUI_TOKENS = [
|
|
|
154
164
|
'status.separator',
|
|
155
165
|
// Editor
|
|
156
166
|
'editor.border',
|
|
167
|
+
'editor.queued',
|
|
168
|
+
'editor.queued.more',
|
|
157
169
|
'editor.selectList.selectedPrefix',
|
|
158
170
|
'editor.selectList.selectedText',
|
|
159
171
|
'editor.selectList.description',
|
|
@@ -188,7 +200,7 @@ export const DEFAULT_PALETTE = {
|
|
|
188
200
|
warn: '#d7af5f',
|
|
189
201
|
added: '#5faf5f',
|
|
190
202
|
removed: '#d75f5f',
|
|
191
|
-
user:
|
|
203
|
+
user: USER_PROMPT_MINT,
|
|
192
204
|
assistant: '#d0d0d0',
|
|
193
205
|
};
|
|
194
206
|
/**
|
|
@@ -209,7 +221,7 @@ const plain = {};
|
|
|
209
221
|
* A test asserts every token in {@link TUI_TOKENS} appears here.
|
|
210
222
|
*/
|
|
211
223
|
export const DEFAULT_TOKENS = {
|
|
212
|
-
'transcript.user': { fg: 'user'
|
|
224
|
+
'transcript.user': { fg: 'user' },
|
|
213
225
|
'transcript.notice': muted,
|
|
214
226
|
'transcript.marker': muted,
|
|
215
227
|
'transcript.reasoning.summary': muted,
|
|
@@ -261,6 +273,12 @@ export const DEFAULT_TOKENS = {
|
|
|
261
273
|
'markdown.italic': { italic: true },
|
|
262
274
|
'markdown.strikethrough': { strike: true },
|
|
263
275
|
'markdown.underline': { underline: true },
|
|
276
|
+
'markdown.diagram.border': muted,
|
|
277
|
+
'markdown.diagram.text': plain,
|
|
278
|
+
'markdown.diagram.edge': { fg: 'accent' },
|
|
279
|
+
'markdown.diagram.edgeLabel': muted,
|
|
280
|
+
'markdown.diagram.title': { fg: 'accent', bold: true },
|
|
281
|
+
'markdown.diagram.warning': { fg: 'warn' },
|
|
264
282
|
'picker.title': { bold: true },
|
|
265
283
|
'picker.glyph': { bold: true },
|
|
266
284
|
'picker.note': { bold: true },
|
|
@@ -291,6 +309,10 @@ export const DEFAULT_TOKENS = {
|
|
|
291
309
|
'dock.jobs.heading': { bold: true },
|
|
292
310
|
'dock.jobs.running': muted,
|
|
293
311
|
'dock.jobs.overflow': muted,
|
|
312
|
+
'status.prefix': { fg: 'accent' },
|
|
313
|
+
// The way back is a key the reader presses, so it carries the weight of an
|
|
314
|
+
// armed chord rather than toning down with the facts.
|
|
315
|
+
'status.back': { fg: 'accent' },
|
|
294
316
|
'status.activity.working': muted,
|
|
295
317
|
'status.activity.ready': muted,
|
|
296
318
|
'status.elapsed': muted,
|
|
@@ -303,6 +325,10 @@ export const DEFAULT_TOKENS = {
|
|
|
303
325
|
'status.cwd': muted,
|
|
304
326
|
'status.separator': muted,
|
|
305
327
|
'editor.border': muted,
|
|
328
|
+
// No colour: a faint is dropped the moment a colour is named, and faint is
|
|
329
|
+
// what makes queued text read as not-yet-sent rather than as being typed.
|
|
330
|
+
'editor.queued': { dim: true, italic: true },
|
|
331
|
+
'editor.queued.more': muted,
|
|
306
332
|
'editor.selectList.selectedPrefix': { fg: 'accent' },
|
|
307
333
|
'editor.selectList.selectedText': { bold: true },
|
|
308
334
|
'editor.selectList.description': muted,
|
package/lib/theme-tokens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-tokens.js","sourceRoot":"","sources":["../src/theme-tokens.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"theme-tokens.js","sourceRoot":"","sources":["../src/theme-tokens.ts"],"names":[],"mappings":"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"}
|
package/lib/ui/editor.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Editor, type EditorTheme, type TUI, type TuiMouseEvent, type TuiMouseEventResult } from '@earendil-works/pi-tui';
|
|
2
|
+
import { type Keymap } from '../input/actions.ts';
|
|
2
3
|
/**
|
|
3
4
|
* The input bar drawn as a box, with its completion menu above it.
|
|
4
5
|
*
|
|
@@ -8,17 +9,33 @@ import { Editor, type EditorTheme, type TUI, type TuiMouseEvent, type TuiMouseEv
|
|
|
8
9
|
* while writing: a list that grows upward never covers the line being typed.
|
|
9
10
|
*/
|
|
10
11
|
export declare class BoxedEditor extends Editor {
|
|
12
|
+
private readonly keymap;
|
|
11
13
|
/** Rows the menu took in the last render; a click there belongs to the list. */
|
|
12
14
|
private menuRows;
|
|
13
15
|
/** Rows between the rules in the last render; how the base editor counts its own. */
|
|
14
16
|
private textRows;
|
|
15
17
|
/** Whether the last render drew a frame, which is what a click is mapped through. */
|
|
16
18
|
private boxed;
|
|
17
|
-
constructor(tui: TUI, theme: EditorTheme);
|
|
19
|
+
constructor(tui: TUI, theme: EditorTheme, keymap?: () => Keymap);
|
|
20
|
+
/**
|
|
21
|
+
* Read the two presses the base class cannot place on its own.
|
|
22
|
+
*
|
|
23
|
+
* Enter breaks the line while the reader keeps that key for the line, so the
|
|
24
|
+
* press the base would submit with becomes a newline — except while it is
|
|
25
|
+
* picking a completion, the one press that chooses something instead of
|
|
26
|
+
* sending it, and except on a bar a question or a picker has borrowed, whose
|
|
27
|
+
* keys belong to whoever borrowed it.
|
|
28
|
+
*/
|
|
29
|
+
handleInput(data: string): void;
|
|
18
30
|
/** Tag the closing rule so {@link render} can find where the box ends. */
|
|
19
31
|
protected renderBottomBorder(width: number, hiddenLineCount: number): string;
|
|
20
32
|
/** A rule redrawn as a box edge, so the corners carry the border's own colour. */
|
|
21
33
|
private edge;
|
|
34
|
+
/**
|
|
35
|
+
* Rewrite one row of the text before it is framed, so a subclass can hide
|
|
36
|
+
* what it collects without hiding the box the reader types inside.
|
|
37
|
+
*/
|
|
38
|
+
protected decorateText(row: string): string;
|
|
22
39
|
render(width: number): string[];
|
|
23
40
|
/**
|
|
24
41
|
* Map a click back through the frame and the lifted menu.
|
package/lib/ui/editor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/ui/editor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/ui/editor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAIN,KAAK,WAAW,EAChB,KAAK,GAAG,EACR,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACzB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAA4B,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAuC3E;;;;;;;GAOG;AACH,qBAAa,WAAY,SAAQ,MAAM;IAQK,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPjE,gFAAgF;IAChF,OAAO,CAAC,QAAQ,CAAI;IACpB,qFAAqF;IACrF,OAAO,CAAC,QAAQ,CAAI;IACpB,qFAAqF;IACrF,OAAO,CAAC,KAAK,CAAQ;gBAET,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAmB,MAAM,GAAE,MAAM,MAAsB;IAI/F;;;;;;;;OAQG;IACM,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAiCxC,0EAA0E;cACvD,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM;IAIrF,kFAAkF;IAClF,OAAO,CAAC,IAAI;IAIZ;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIlC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IA2BxC;;;;;;;;OAQG;IACM,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,mBAAmB,GAAG,SAAS;CAQ5E"}
|
package/lib/ui/editor.js
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
import { Editor, stripTerminalSequences, } from '@earendil-works/pi-tui';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const BOTTOM_LEFT = '╰';
|
|
6
|
-
const BOTTOM_RIGHT = '╯';
|
|
7
|
-
const SIDE = '│';
|
|
8
|
-
/** The frame costs one column each side, so the text wraps that much narrower. */
|
|
9
|
-
const FRAME_COLUMNS = 2;
|
|
10
|
-
/** One column of air inside the frame, so a full line never touches the border. */
|
|
11
|
-
const PADDING_X = 1;
|
|
12
|
-
/** A box needs both edges, both paddings, and one column left to type in. */
|
|
13
|
-
const MIN_BOX_WIDTH = FRAME_COLUMNS + PADDING_X * 2 + 1;
|
|
1
|
+
import { Editor, isKittyProtocolActive, matchesKey, stripTerminalSequences, } from '@earendil-works/pi-tui';
|
|
2
|
+
import { ENTER_KEY, defaultKeymap } from "../input/actions.js";
|
|
3
|
+
import { promptKeys } from "../input/keymap.js";
|
|
4
|
+
import { FRAME_COLUMNS, FRAME_GLYPHS, MIN_BOX_WIDTH, PADDING_X } from "./frame.js";
|
|
14
5
|
/**
|
|
15
6
|
* Marks the rule that closes the input while one render is in flight.
|
|
16
7
|
*
|
|
@@ -22,6 +13,26 @@ const MIN_BOX_WIDTH = FRAME_COLUMNS + PADDING_X * 2 + 1;
|
|
|
22
13
|
* pass removes it.
|
|
23
14
|
*/
|
|
24
15
|
const CLOSING_TAG = '\u0000';
|
|
16
|
+
/**
|
|
17
|
+
* The line feed a plain Enter is handed to the base class as.
|
|
18
|
+
*
|
|
19
|
+
* The base owns what a newline does to paste markers, history, and undo, and it
|
|
20
|
+
* reads this byte as one in every terminal mode, including the modes where it
|
|
21
|
+
* no longer calls Enter itself a newline.
|
|
22
|
+
*/
|
|
23
|
+
const NEWLINE_BYTE = '\n';
|
|
24
|
+
/** The one sequence a terminal that reports no modifiers sends for alt+enter. */
|
|
25
|
+
const LEGACY_ALT_ENTER = '\u001b\r';
|
|
26
|
+
/**
|
|
27
|
+
* The chords as the keyboard protocol spells them.
|
|
28
|
+
*
|
|
29
|
+
* The base class reads a legacy alt+enter and a bare line feed as line breaks
|
|
30
|
+
* before it looks at any binding, so each press is handed over as the chord the
|
|
31
|
+
* map actually holds for it. The submit path then runs whole, with the same
|
|
32
|
+
* guards a real chord meets, instead of a second sender beside it.
|
|
33
|
+
*/
|
|
34
|
+
const KITTY_ALT_ENTER = '\u001b[13;3u';
|
|
35
|
+
const KITTY_CTRL_J = '\u001b[106;5u';
|
|
25
36
|
/**
|
|
26
37
|
* The input bar drawn as a box, with its completion menu above it.
|
|
27
38
|
*
|
|
@@ -31,14 +42,57 @@ const CLOSING_TAG = '\u0000';
|
|
|
31
42
|
* while writing: a list that grows upward never covers the line being typed.
|
|
32
43
|
*/
|
|
33
44
|
export class BoxedEditor extends Editor {
|
|
45
|
+
keymap;
|
|
34
46
|
/** Rows the menu took in the last render; a click there belongs to the list. */
|
|
35
47
|
menuRows = 0;
|
|
36
48
|
/** Rows between the rules in the last render; how the base editor counts its own. */
|
|
37
49
|
textRows = 0;
|
|
38
50
|
/** Whether the last render drew a frame, which is what a click is mapped through. */
|
|
39
51
|
boxed = false;
|
|
40
|
-
constructor(tui, theme) {
|
|
52
|
+
constructor(tui, theme, keymap = defaultKeymap) {
|
|
41
53
|
super(tui, theme, { paddingX: PADDING_X });
|
|
54
|
+
this.keymap = keymap;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Read the two presses the base class cannot place on its own.
|
|
58
|
+
*
|
|
59
|
+
* Enter breaks the line while the reader keeps that key for the line, so the
|
|
60
|
+
* press the base would submit with becomes a newline — except while it is
|
|
61
|
+
* picking a completion, the one press that chooses something instead of
|
|
62
|
+
* sending it, and except on a bar a question or a picker has borrowed, whose
|
|
63
|
+
* keys belong to whoever borrowed it.
|
|
64
|
+
*/
|
|
65
|
+
handleInput(data) {
|
|
66
|
+
if (this.disableSubmit) {
|
|
67
|
+
super.handleInput(data);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const keys = promptKeys(this.keymap());
|
|
71
|
+
// A bare line feed is a line break in the base class whatever the map says,
|
|
72
|
+
// so a reader who moved the line break off ctrl+j and sends with it would
|
|
73
|
+
// keep getting lines. It is read before the Return guard because a terminal
|
|
74
|
+
// without the protocol reports that byte as Return as well — and only
|
|
75
|
+
// without it, because a terminal that speaks the protocol sends the chord
|
|
76
|
+
// itself and reports a line feed for a key the reader meant as a line.
|
|
77
|
+
if (data === NEWLINE_BYTE && !isKittyProtocolActive() && keys.submit.includes('ctrl+j')) {
|
|
78
|
+
super.handleInput(KITTY_CTRL_J);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (keys.enterBreaksLine && matchesKey(data, ENTER_KEY) && !this.isShowingAutocomplete()) {
|
|
82
|
+
super.handleInput(NEWLINE_BYTE);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// Only while the terminal cannot tell alt+enter apart from a mapping, and
|
|
86
|
+
// only for the reader who bound that key: with the protocol active the same
|
|
87
|
+
// sequence is the reader's shift+enter, and a bar that answered it as a send
|
|
88
|
+
// because some other chord contains the same bytes would be submitting a key
|
|
89
|
+
// the reader never bound. A reader who keeps the sequence for a line is
|
|
90
|
+
// answered by the library's own rule.
|
|
91
|
+
if (data === LEGACY_ALT_ENTER && !isKittyProtocolActive() && keys.submit.includes('alt+enter')) {
|
|
92
|
+
super.handleInput(KITTY_ALT_ENTER);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
super.handleInput(data);
|
|
42
96
|
}
|
|
43
97
|
/** Tag the closing rule so {@link render} can find where the box ends. */
|
|
44
98
|
renderBottomBorder(width, hiddenLineCount) {
|
|
@@ -48,14 +102,21 @@ export class BoxedEditor extends Editor {
|
|
|
48
102
|
edge(open, close, row) {
|
|
49
103
|
return this.borderColor(`${open}${stripTerminalSequences(row)}${close}`);
|
|
50
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Rewrite one row of the text before it is framed, so a subclass can hide
|
|
107
|
+
* what it collects without hiding the box the reader types inside.
|
|
108
|
+
*/
|
|
109
|
+
decorateText(row) {
|
|
110
|
+
return row;
|
|
111
|
+
}
|
|
51
112
|
render(width) {
|
|
52
|
-
const side = this.borderColor(
|
|
113
|
+
const side = this.borderColor(FRAME_GLYPHS.side);
|
|
53
114
|
// A frame narrower than its own furniture would eat the text it exists to
|
|
54
115
|
// hold, and a hidden border token asks for no frame at all: both cases keep
|
|
55
116
|
// the plain rules rather than reserve columns for what nobody can see.
|
|
56
117
|
if (width < MIN_BOX_WIDTH || side === '') {
|
|
57
118
|
this.boxed = false;
|
|
58
|
-
return super.render(width);
|
|
119
|
+
return super.render(width).map(row => this.decorateText(row));
|
|
59
120
|
}
|
|
60
121
|
const rows = super.render(width - FRAME_COLUMNS);
|
|
61
122
|
const closing = rows.findIndex(row => row.includes(CLOSING_TAG));
|
|
@@ -70,10 +131,10 @@ export class BoxedEditor extends Editor {
|
|
|
70
131
|
this.boxed = true;
|
|
71
132
|
// The menu keeps the page's own width; only its rows moved above the box.
|
|
72
133
|
const lines = menu.map(row => row + ' '.repeat(FRAME_COLUMNS));
|
|
73
|
-
lines.push(this.edge(
|
|
134
|
+
lines.push(this.edge(FRAME_GLYPHS.topLeft, FRAME_GLYPHS.topRight, rows[0] ?? ''));
|
|
74
135
|
for (const row of text)
|
|
75
|
-
lines.push(`${side}${row}${side}`);
|
|
76
|
-
lines.push(this.edge(
|
|
136
|
+
lines.push(`${side}${this.decorateText(row)}${side}`);
|
|
137
|
+
lines.push(this.edge(FRAME_GLYPHS.bottomLeft, FRAME_GLYPHS.bottomRight, rows[closing].replace(CLOSING_TAG, '')));
|
|
77
138
|
return lines;
|
|
78
139
|
}
|
|
79
140
|
/**
|
package/lib/ui/editor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/ui/editor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,sBAAsB,GAKvB,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/ui/editor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The frame every prompt is closed into.
|
|
3
|
+
*
|
|
4
|
+
* The editor, the prompts queued above it, and the prompts already submitted
|
|
5
|
+
* draw the same glyphs at the same width, so one prompt reads as the same object
|
|
6
|
+
* through its whole life; keeping the shape here is what stops the three from
|
|
7
|
+
* drifting.
|
|
8
|
+
*/
|
|
9
|
+
export declare const FRAME_GLYPHS: {
|
|
10
|
+
readonly topLeft: "╭";
|
|
11
|
+
readonly topRight: "╮";
|
|
12
|
+
readonly bottomLeft: "╰";
|
|
13
|
+
readonly bottomRight: "╯";
|
|
14
|
+
readonly side: "│";
|
|
15
|
+
};
|
|
16
|
+
/** The frame costs one column each side, so the text wraps that much narrower. */
|
|
17
|
+
export declare const FRAME_COLUMNS = 2;
|
|
18
|
+
/** One column of air inside the frame, so a full line never touches the border. */
|
|
19
|
+
export declare const PADDING_X = 1;
|
|
20
|
+
/** A box needs both edges, both paddings, and one column left to type in. */
|
|
21
|
+
export declare const MIN_BOX_WIDTH: number;
|
|
22
|
+
/** The columns the text of a bar owns, given the width of everything inside its frame. */
|
|
23
|
+
export declare function textWidth(innerWidth: number): number;
|
|
24
|
+
/** One text row of a bar: the air, the text, and the rest of the inside width. */
|
|
25
|
+
export declare function textRow(text: string, innerWidth: number): string;
|
|
26
|
+
/**
|
|
27
|
+
* The rule that closes a bar, naming what the bar could not fit.
|
|
28
|
+
*
|
|
29
|
+
* A hidden count is a fact about the text, not extra text, so it rides the rule
|
|
30
|
+
* the way the editor's own scroll indicator does: the same label in the same
|
|
31
|
+
* place, at the same width, so both bars report a fold identically.
|
|
32
|
+
*/
|
|
33
|
+
export declare function frameRule(innerWidth: number, hiddenRows: number): string;
|
|
34
|
+
/** How one block of text paints itself inside the bar that carries it. */
|
|
35
|
+
export interface FrameFaces {
|
|
36
|
+
/** Paints one row of the block's own text. */
|
|
37
|
+
readonly text: (line: string) => string;
|
|
38
|
+
/** Paints the frame's rules and its two sides. */
|
|
39
|
+
readonly border: (rule: string) => string;
|
|
40
|
+
/** Whether the frame may be drawn at all. */
|
|
41
|
+
readonly framed: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Whether a bar has the width, and the visible border, to close a frame. */
|
|
44
|
+
export declare function canFrame(width: number, borderVisible: boolean): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* One block of text as a bar draws it: wrapped to the frame's own width, and
|
|
47
|
+
* closed into it when the frame can be drawn.
|
|
48
|
+
*
|
|
49
|
+
* A block with a limit is a preview, and the rows it drops are counted on the
|
|
50
|
+
* closing rule: a reader who cannot see the whole text still has to see that it
|
|
51
|
+
* continues. A block without a limit is the prompt itself, which is never cut.
|
|
52
|
+
*/
|
|
53
|
+
export declare function frameText(text: string, width: number, faces: FrameFaces, limit?: number): string[];
|
|
54
|
+
//# sourceMappingURL=frame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../src/ui/frame.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY;;;;;;CAAyF,CAAA;AAElH,kFAAkF;AAClF,eAAO,MAAM,aAAa,IAAI,CAAA;AAC9B,mFAAmF;AACnF,eAAO,MAAM,SAAS,IAAI,CAAA;AAC1B,6EAA6E;AAC7E,eAAO,MAAM,aAAa,QAAoC,CAAA;AAE9D,0FAA0F;AAC1F,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,kFAAkF;AAClF,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAgBxE;AAED,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IACzB,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACvC,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACzC,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACzB;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,GAAG,OAAO,CAEvE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,SAA2B,GAAG,MAAM,EAAE,CAYpH"}
|
package/lib/ui/frame.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { visibleWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';
|
|
2
|
+
import { displayText } from "../text.js";
|
|
3
|
+
/**
|
|
4
|
+
* The frame every prompt is closed into.
|
|
5
|
+
*
|
|
6
|
+
* The editor, the prompts queued above it, and the prompts already submitted
|
|
7
|
+
* draw the same glyphs at the same width, so one prompt reads as the same object
|
|
8
|
+
* through its whole life; keeping the shape here is what stops the three from
|
|
9
|
+
* drifting.
|
|
10
|
+
*/
|
|
11
|
+
export const FRAME_GLYPHS = { topLeft: '╭', topRight: '╮', bottomLeft: '╰', bottomRight: '╯', side: '│' };
|
|
12
|
+
/** The frame costs one column each side, so the text wraps that much narrower. */
|
|
13
|
+
export const FRAME_COLUMNS = 2;
|
|
14
|
+
/** One column of air inside the frame, so a full line never touches the border. */
|
|
15
|
+
export const PADDING_X = 1;
|
|
16
|
+
/** A box needs both edges, both paddings, and one column left to type in. */
|
|
17
|
+
export const MIN_BOX_WIDTH = FRAME_COLUMNS + PADDING_X * 2 + 1;
|
|
18
|
+
/** The columns the text of a bar owns, given the width of everything inside its frame. */
|
|
19
|
+
export function textWidth(innerWidth) {
|
|
20
|
+
return Math.max(1, innerWidth - PADDING_X * 2);
|
|
21
|
+
}
|
|
22
|
+
/** One text row of a bar: the air, the text, and the rest of the inside width. */
|
|
23
|
+
export function textRow(text, innerWidth) {
|
|
24
|
+
const room = Math.max(0, textWidth(innerWidth) - visibleWidth(text));
|
|
25
|
+
return `${' '.repeat(PADDING_X)}${text}${' '.repeat(room)}${' '.repeat(PADDING_X)}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The rule that closes a bar, naming what the bar could not fit.
|
|
29
|
+
*
|
|
30
|
+
* A hidden count is a fact about the text, not extra text, so it rides the rule
|
|
31
|
+
* the way the editor's own scroll indicator does: the same label in the same
|
|
32
|
+
* place, at the same width, so both bars report a fold identically.
|
|
33
|
+
*/
|
|
34
|
+
export function frameRule(innerWidth, hiddenRows) {
|
|
35
|
+
const width = Math.max(0, innerWidth);
|
|
36
|
+
if (hiddenRows <= 0)
|
|
37
|
+
return '─'.repeat(width);
|
|
38
|
+
const label = ` ↓ ${hiddenRows} more `;
|
|
39
|
+
const labelWidth = visibleWidth(label);
|
|
40
|
+
if (labelWidth + 2 <= width) {
|
|
41
|
+
const left = Math.floor((width - labelWidth) / 2);
|
|
42
|
+
return `${'─'.repeat(left)}${label}${'─'.repeat(width - left - labelWidth)}`;
|
|
43
|
+
}
|
|
44
|
+
// Too narrow for a centred label: name it as far as it fits instead of
|
|
45
|
+
// dropping the fact. Both the label and the fallback are ASCII, so slicing by
|
|
46
|
+
// character is slicing by column here.
|
|
47
|
+
const indicator = `─── ↓ ${hiddenRows} more `;
|
|
48
|
+
if (visibleWidth(indicator) <= width)
|
|
49
|
+
return indicator + '─'.repeat(width - visibleWidth(indicator));
|
|
50
|
+
const ellipsis = '...'.slice(0, width);
|
|
51
|
+
return indicator.slice(0, Math.max(0, width - ellipsis.length)) + ellipsis;
|
|
52
|
+
}
|
|
53
|
+
/** Whether a bar has the width, and the visible border, to close a frame. */
|
|
54
|
+
export function canFrame(width, borderVisible) {
|
|
55
|
+
return borderVisible && width >= MIN_BOX_WIDTH;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* One block of text as a bar draws it: wrapped to the frame's own width, and
|
|
59
|
+
* closed into it when the frame can be drawn.
|
|
60
|
+
*
|
|
61
|
+
* A block with a limit is a preview, and the rows it drops are counted on the
|
|
62
|
+
* closing rule: a reader who cannot see the whole text still has to see that it
|
|
63
|
+
* continues. A block without a limit is the prompt itself, which is never cut.
|
|
64
|
+
*/
|
|
65
|
+
export function frameText(text, width, faces, limit = Number.POSITIVE_INFINITY) {
|
|
66
|
+
const inside = faces.framed ? width - FRAME_COLUMNS : width;
|
|
67
|
+
const wrapped = wrapTextWithAnsi(displayText(text), textWidth(inside));
|
|
68
|
+
const body = wrapped.slice(0, Math.max(0, limit));
|
|
69
|
+
const rows = body.map(line => textRow(faces.text(line), inside));
|
|
70
|
+
if (!faces.framed)
|
|
71
|
+
return rows;
|
|
72
|
+
const side = faces.border(FRAME_GLYPHS.side);
|
|
73
|
+
return [
|
|
74
|
+
faces.border(`${FRAME_GLYPHS.topLeft}${frameRule(inside, 0)}${FRAME_GLYPHS.topRight}`),
|
|
75
|
+
...rows.map(row => `${side}${row}${side}`),
|
|
76
|
+
faces.border(`${FRAME_GLYPHS.bottomLeft}${frameRule(inside, wrapped.length - body.length)}${FRAME_GLYPHS.bottomRight}`),
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../../src/ui/frame.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BoxedEditor } from './editor.ts';
|
|
2
|
+
/** How a question's answer is shown while it is written. */
|
|
3
|
+
export type GateInputMode = 'answer' | 'secret';
|
|
4
|
+
/**
|
|
5
|
+
* The input bar a gate collects an answer with.
|
|
6
|
+
*
|
|
7
|
+
* It is the prompt bar's own component, so an answer is written with the
|
|
8
|
+
* movement, deletion, undo, and paste that bar already has. Its mode decides
|
|
9
|
+
* only how the answer is shown: a question that declares a credential is
|
|
10
|
+
* answered in the same bar with the middle of the value hidden, never in a
|
|
11
|
+
* second widget that would have to grow its own editing.
|
|
12
|
+
*/
|
|
13
|
+
export declare class GateInputBar extends BoxedEditor {
|
|
14
|
+
private mode;
|
|
15
|
+
/** Switch what the bar shows without changing a character of what it holds. */
|
|
16
|
+
setMode(mode: GateInputMode): void;
|
|
17
|
+
/** Hide a credential's middle while its owner still recognizes both ends. */
|
|
18
|
+
protected decorateText(row: string): string;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=gate-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-input.d.ts","sourceRoot":"","sources":["../../src/ui/gate-input.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC,4DAA4D;AAC5D,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,CAAA;AA2E/C;;;;;;;;GAQG;AACH,qBAAa,YAAa,SAAQ,WAAW;IAC3C,OAAO,CAAC,IAAI,CAA0B;IAEtC,+EAA+E;IAC/E,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAMlC,6EAA6E;cAC1D,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;CAGrD"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { visibleWidth } from '@earendil-works/pi-tui';
|
|
2
|
+
import { BoxedEditor } from "./editor.js";
|
|
3
|
+
/** One character of the mask, repeated to the width of what it hides. */
|
|
4
|
+
const MASKED = '*';
|
|
5
|
+
/** How much of a credential stays readable at each end, so its owner can recognize it. */
|
|
6
|
+
const MASK_HEAD = 4;
|
|
7
|
+
const MASK_TAIL = 4;
|
|
8
|
+
/**
|
|
9
|
+
* A terminal sequence, so masking can tell a row's styling from its text: the
|
|
10
|
+
* cursor is drawn as an escape around a character, and hiding the character
|
|
11
|
+
* must not hide the mark that says where the cursor is.
|
|
12
|
+
*
|
|
13
|
+
* The string forms carry payloads a terminal reads rather than shows, and a
|
|
14
|
+
* cursor marker is one of them: masking a marker's own text would replace the
|
|
15
|
+
* position the terminal was told to place the cursor at with asterisks.
|
|
16
|
+
*/
|
|
17
|
+
const SEQUENCE = /\u001b(?:\[[0-9;?]*[ -/]*[@-~]|[\][P_^X][^\u0007\u001b]*(?:\u0007|\u001b\\)|[@-Z\\-_])/gu;
|
|
18
|
+
const GRAPHEMES = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
|
|
19
|
+
/**
|
|
20
|
+
* One visible grapheme, and where it sits among the row's visible characters.
|
|
21
|
+
*
|
|
22
|
+
* Whitespace is not among them: the editor lays the answer out with spaces that
|
|
23
|
+
* belong to its own drawing, and hiding them would move the text under the
|
|
24
|
+
* cursor rather than hide it.
|
|
25
|
+
*/
|
|
26
|
+
function visibleAt(text) {
|
|
27
|
+
const found = [];
|
|
28
|
+
let position = 0;
|
|
29
|
+
for (const { segment } of GRAPHEMES.segment(text)) {
|
|
30
|
+
if (segment.trim() === '') {
|
|
31
|
+
found.push({ segment, position: -1 });
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
found.push({ segment, position });
|
|
35
|
+
position += 1;
|
|
36
|
+
}
|
|
37
|
+
return found;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Hide the middle of a credential and keep its ends readable.
|
|
41
|
+
*
|
|
42
|
+
* The reader is checking which key they pasted, and a row of asterisks answers
|
|
43
|
+
* nothing; a bystander is not meant to read it either, so only the first and
|
|
44
|
+
* last few characters survive. Rows are masked one at a time because that is
|
|
45
|
+
* how the editor hands them over, and a credential is written on one line.
|
|
46
|
+
*/
|
|
47
|
+
function maskCredentialRow(row) {
|
|
48
|
+
const segments = [];
|
|
49
|
+
let last = 0;
|
|
50
|
+
for (const match of row.matchAll(SEQUENCE)) {
|
|
51
|
+
segments.push({ escape: false, text: row.slice(last, match.index) });
|
|
52
|
+
segments.push({ escape: true, text: match[0] });
|
|
53
|
+
last = match.index + match[0].length;
|
|
54
|
+
}
|
|
55
|
+
segments.push({ escape: false, text: row.slice(last) });
|
|
56
|
+
const visible = segments.filter(segment => !segment.escape).flatMap(segment => visibleAt(segment.text));
|
|
57
|
+
const total = visible.reduce((count, entry) => count + (entry.position >= 0 ? 1 : 0), 0);
|
|
58
|
+
if (total <= MASK_HEAD + MASK_TAIL)
|
|
59
|
+
return row;
|
|
60
|
+
let seen = 0;
|
|
61
|
+
return segments.map((segment) => {
|
|
62
|
+
if (segment.escape)
|
|
63
|
+
return segment.text;
|
|
64
|
+
return visibleAt(segment.text).map((entry) => {
|
|
65
|
+
if (entry.position < 0)
|
|
66
|
+
return entry.segment;
|
|
67
|
+
const readable = seen < MASK_HEAD || seen >= total - MASK_TAIL;
|
|
68
|
+
seen += 1;
|
|
69
|
+
return readable ? entry.segment : MASKED.repeat(Math.max(1, visibleWidth(entry.segment)));
|
|
70
|
+
}).join('');
|
|
71
|
+
}).join('');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The input bar a gate collects an answer with.
|
|
75
|
+
*
|
|
76
|
+
* It is the prompt bar's own component, so an answer is written with the
|
|
77
|
+
* movement, deletion, undo, and paste that bar already has. Its mode decides
|
|
78
|
+
* only how the answer is shown: a question that declares a credential is
|
|
79
|
+
* answered in the same bar with the middle of the value hidden, never in a
|
|
80
|
+
* second widget that would have to grow its own editing.
|
|
81
|
+
*/
|
|
82
|
+
export class GateInputBar extends BoxedEditor {
|
|
83
|
+
mode = 'answer';
|
|
84
|
+
/** Switch what the bar shows without changing a character of what it holds. */
|
|
85
|
+
setMode(mode) {
|
|
86
|
+
if (this.mode === mode)
|
|
87
|
+
return;
|
|
88
|
+
this.mode = mode;
|
|
89
|
+
this.invalidate();
|
|
90
|
+
}
|
|
91
|
+
/** Hide a credential's middle while its owner still recognizes both ends. */
|
|
92
|
+
decorateText(row) {
|
|
93
|
+
return this.mode === 'secret' ? maskCredentialRow(row) : row;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=gate-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-input.js","sourceRoot":"","sources":["../../src/ui/gate-input.ts"],"names":[],"mappings":"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"}
|