@sagmans/dsh-tui 0.5.2 → 0.6.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 +32 -12
- package/lib/agent/host.d.ts +11 -0
- package/lib/agent/host.d.ts.map +1 -1
- package/lib/agent/host.js +16 -2
- package/lib/agent/host.js.map +1 -1
- package/lib/agent/undo.d.ts +52 -0
- package/lib/agent/undo.d.ts.map +1 -0
- package/lib/agent/undo.js +106 -0
- package/lib/agent/undo.js.map +1 -0
- package/lib/cards.d.ts +57 -2
- package/lib/cards.d.ts.map +1 -1
- package/lib/cards.js +38 -8
- package/lib/cards.js.map +1 -1
- package/lib/herdr/reporter.d.ts +9 -4
- package/lib/herdr/reporter.d.ts.map +1 -1
- package/lib/herdr/reporter.js +5 -9
- package/lib/herdr/reporter.js.map +1 -1
- package/lib/herdr/state.d.ts +35 -4
- package/lib/herdr/state.d.ts.map +1 -1
- package/lib/herdr/state.js +37 -4
- package/lib/herdr/state.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +349 -14
- package/lib/index.js.map +1 -1
- package/lib/input/actions.d.ts.map +1 -1
- package/lib/input/actions.js +4 -0
- package/lib/input/actions.js.map +1 -1
- package/lib/input/completion.d.ts +10 -0
- package/lib/input/completion.d.ts.map +1 -1
- package/lib/input/completion.js +15 -0
- package/lib/input/completion.js.map +1 -1
- package/lib/input/keymap.d.ts.map +1 -1
- package/lib/input/keymap.js +2 -0
- package/lib/input/keymap.js.map +1 -1
- package/lib/input/submission.d.ts +11 -1
- package/lib/input/submission.d.ts.map +1 -1
- package/lib/input/submission.js +10 -1
- package/lib/input/submission.js.map +1 -1
- package/lib/terminal/warning-screen.d.ts +8 -1
- package/lib/terminal/warning-screen.d.ts.map +1 -1
- package/lib/terminal/warning-screen.js +9 -0
- package/lib/terminal/warning-screen.js.map +1 -1
- package/lib/theme-schema.d.ts +6 -6
- package/lib/theme-settings.d.ts +8 -8
- package/lib/theme-tokens.d.ts +1 -1
- package/lib/theme-tokens.d.ts.map +1 -1
- package/lib/theme-tokens.js +27 -1
- package/lib/theme-tokens.js.map +1 -1
- package/lib/transcript.d.ts +50 -14
- package/lib/transcript.d.ts.map +1 -1
- package/lib/transcript.js +82 -47
- package/lib/transcript.js.map +1 -1
- package/lib/ui/copy.d.ts +17 -0
- package/lib/ui/copy.d.ts.map +1 -0
- package/lib/ui/copy.js +104 -0
- package/lib/ui/copy.js.map +1 -0
- package/lib/ui/dock.d.ts +21 -1
- package/lib/ui/dock.d.ts.map +1 -1
- package/lib/ui/dock.js +75 -16
- package/lib/ui/dock.js.map +1 -1
- package/lib/ui/frame.d.ts +31 -0
- package/lib/ui/frame.d.ts.map +1 -1
- package/lib/ui/frame.js +27 -4
- package/lib/ui/frame.js.map +1 -1
- package/lib/ui/view.d.ts +73 -2
- package/lib/ui/view.d.ts.map +1 -1
- package/lib/ui/view.js +180 -20
- package/lib/ui/view.js.map +1 -1
- package/package.json +1 -1
- package/themes/deepseek-blue.yaml +9 -0
- package/themes/violet-orbit.yaml +7 -0
package/lib/ui/dock.js
CHANGED
|
@@ -9,6 +9,17 @@ const PLAN_MODE_MARK = '⏸';
|
|
|
9
9
|
const TODOS_MARK = '☰';
|
|
10
10
|
const SUBAGENTS_MARK = '⚇';
|
|
11
11
|
const JOBS_MARK = '⛭';
|
|
12
|
+
/**
|
|
13
|
+
* The dashed rule that opens a section, and the two dashes that lead its name.
|
|
14
|
+
*
|
|
15
|
+
* Dashed, because a section is live state that changes under the reader's eye
|
|
16
|
+
* and a solid edge would claim the permanence of a border. The name rides the
|
|
17
|
+
* rule the heading used to spend a row on, so the edge costs neither a row nor
|
|
18
|
+
* a column of the rows a reader selects. Two dashes lead it: one would be read
|
|
19
|
+
* as part of the mark the name already carries.
|
|
20
|
+
*/
|
|
21
|
+
const SECTION_RULE_DASH = '┄';
|
|
22
|
+
const SECTION_RULE_LEAD = `${SECTION_RULE_DASH}${SECTION_RULE_DASH} `;
|
|
12
23
|
/** Whether a todo is still owed to the reader, narrowing it to the states the dock draws. */
|
|
13
24
|
const isOpenTodo = (todo) => todo.status !== 'completed';
|
|
14
25
|
/** The row marks, by the state the row reports. */
|
|
@@ -32,7 +43,9 @@ function orderTodos(todos) {
|
|
|
32
43
|
* The dock above the editor: what the agent is working on right now.
|
|
33
44
|
*
|
|
34
45
|
* It renders nothing when there is nothing to say, so a plain conversation
|
|
35
|
-
* keeps its rows for the conversation.
|
|
46
|
+
* keeps its rows for the conversation. Each list it draws opens on a rule that
|
|
47
|
+
* names it, in that section's own hue: the dock is several boards stacked, and
|
|
48
|
+
* which board a row belongs to has to be readable without reading the row.
|
|
36
49
|
*/
|
|
37
50
|
export class WorkDock {
|
|
38
51
|
state;
|
|
@@ -56,6 +69,43 @@ export class WorkDock {
|
|
|
56
69
|
invalidate() {
|
|
57
70
|
// The fold is the only state; nothing is cached.
|
|
58
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* The dashed rule that opens a section, with the section's name on it.
|
|
74
|
+
*
|
|
75
|
+
* A name with no room left for a dash after it is drawn as the heading it
|
|
76
|
+
* would otherwise have been: a rule earns its row by being the edge of a
|
|
77
|
+
* list, and an edge a reader cannot tell from a name is not one.
|
|
78
|
+
*/
|
|
79
|
+
sectionRule(width, section) {
|
|
80
|
+
const head = `${SECTION_RULE_LEAD}${section.heading} `;
|
|
81
|
+
if (visibleWidth(head) + 1 > width) {
|
|
82
|
+
return this.theme.style(section.headingToken, this.theme.cut(section.heading, width, '…'));
|
|
83
|
+
}
|
|
84
|
+
// Each run is painted on its own: a style wrapped around the finished row
|
|
85
|
+
// would end where the name's own style ended, taking the dashes after it
|
|
86
|
+
// with it, and the rule would lose the hue it is there to carry.
|
|
87
|
+
const lead = this.theme.style(section.borderToken, SECTION_RULE_LEAD);
|
|
88
|
+
const name = this.theme.style(section.headingToken, section.heading);
|
|
89
|
+
const tail = this.theme.style(section.borderToken, ` ${SECTION_RULE_DASH.repeat(width - visibleWidth(head))}`);
|
|
90
|
+
return `${lead}${name}${tail}`;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* One section as the dock draws it: the rule that names it, then its rows.
|
|
94
|
+
*
|
|
95
|
+
* The rows arrive already built and are pushed as they are, so a section costs
|
|
96
|
+
* the rows it always cost and no column of them. The name's element is what
|
|
97
|
+
* spends the row: a hidden rule leaves the heading it replaced, and a hidden
|
|
98
|
+
* name leaves the section exactly as it stood before the sections were edged —
|
|
99
|
+
* a rule with no name to carry would be an edge that says nothing.
|
|
100
|
+
*/
|
|
101
|
+
pushSection(lines, width, section, rows) {
|
|
102
|
+
if (this.theme.visible(section.headingToken)) {
|
|
103
|
+
lines.push(this.theme.visible(section.borderToken)
|
|
104
|
+
? this.sectionRule(width, section)
|
|
105
|
+
: this.theme.style(section.headingToken, this.theme.cut(section.heading, width, '…')));
|
|
106
|
+
}
|
|
107
|
+
lines.push(...rows);
|
|
108
|
+
}
|
|
59
109
|
pushTodos(lines, todos, width) {
|
|
60
110
|
// Settled items leave the dock: it reports what is still to do, and a row
|
|
61
111
|
// that stayed after its item finished would only grow the list as the turn
|
|
@@ -63,20 +113,23 @@ export class WorkDock {
|
|
|
63
113
|
const open = todos.filter(isOpenTodo);
|
|
64
114
|
if (open.length === 0)
|
|
65
115
|
return;
|
|
66
|
-
if (this.theme.visible('dock.todos.heading')) {
|
|
67
|
-
lines.push(this.theme.style('dock.todos.heading', this.theme.cut(`${TODOS_MARK} todos · ${open.length} left`, width, '…')));
|
|
68
|
-
}
|
|
69
116
|
const ordered = orderTodos(open);
|
|
117
|
+
const rows = [];
|
|
70
118
|
for (const todo of ordered.slice(0, DOCK_TODO_LIMIT)) {
|
|
71
119
|
const token = TODO_TOKENS[todo.status];
|
|
72
120
|
if (!this.theme.visible(token))
|
|
73
121
|
continue;
|
|
74
122
|
const lead = ` ${TODO_GLYPHS[todo.status]} `;
|
|
75
|
-
|
|
123
|
+
rows.push(this.theme.cut(this.theme.rich(`${lead}${todo.content}`, { token, column: visibleWidth(lead) }), width, '…'));
|
|
76
124
|
}
|
|
77
125
|
if (ordered.length > DOCK_TODO_LIMIT && this.theme.visible('dock.todos.overflow')) {
|
|
78
|
-
|
|
126
|
+
rows.push(this.theme.style('dock.todos.overflow', this.theme.cut(` … ${ordered.length - DOCK_TODO_LIMIT} more`, width, '…')));
|
|
79
127
|
}
|
|
128
|
+
this.pushSection(lines, width, {
|
|
129
|
+
heading: `${TODOS_MARK} todos · ${open.length} left`,
|
|
130
|
+
headingToken: 'dock.todos.heading',
|
|
131
|
+
borderToken: 'dock.todos.border',
|
|
132
|
+
}, rows);
|
|
80
133
|
}
|
|
81
134
|
pushSubagents(lines, runs, width) {
|
|
82
135
|
// A delegation that has reported back is no longer something to watch, for
|
|
@@ -84,19 +137,22 @@ export class WorkDock {
|
|
|
84
137
|
const running = runs.filter(run => run.status === 'running');
|
|
85
138
|
if (running.length === 0)
|
|
86
139
|
return;
|
|
87
|
-
if (this.theme.visible('dock.subagents.heading')) {
|
|
88
|
-
lines.push(this.theme.style('dock.subagents.heading', this.theme.cut(`${SUBAGENTS_MARK} subagents · ${running.length} running`, width, '…')));
|
|
89
|
-
}
|
|
90
140
|
const now = this.now();
|
|
141
|
+
const rows = [];
|
|
91
142
|
for (const run of running.slice(0, DOCK_SUBAGENT_LIMIT)) {
|
|
92
143
|
if (!this.theme.visible('dock.subagents.running'))
|
|
93
144
|
continue;
|
|
94
145
|
const lead = ` ${RUNNING_MARK} `;
|
|
95
|
-
|
|
146
|
+
rows.push(this.theme.cut(this.theme.rich(`${lead}${describeSubagent(run, now)}`, { token: 'dock.subagents.running', column: visibleWidth(lead) }), width, '…'));
|
|
96
147
|
}
|
|
97
148
|
if (running.length > DOCK_SUBAGENT_LIMIT && this.theme.visible('dock.subagents.overflow')) {
|
|
98
|
-
|
|
149
|
+
rows.push(this.theme.style('dock.subagents.overflow', this.theme.cut(` … ${running.length - DOCK_SUBAGENT_LIMIT} more`, width, '…')));
|
|
99
150
|
}
|
|
151
|
+
this.pushSection(lines, width, {
|
|
152
|
+
heading: `${SUBAGENTS_MARK} subagents · ${running.length} running`,
|
|
153
|
+
headingToken: 'dock.subagents.heading',
|
|
154
|
+
borderToken: 'dock.subagents.border',
|
|
155
|
+
}, rows);
|
|
100
156
|
}
|
|
101
157
|
pushJobs(lines, jobs, width) {
|
|
102
158
|
// Only work still holding resources earns a row: a settled job is a fact the
|
|
@@ -105,20 +161,23 @@ export class WorkDock {
|
|
|
105
161
|
const live = jobs.filter(job => isLive(job.status));
|
|
106
162
|
if (live.length === 0)
|
|
107
163
|
return;
|
|
108
|
-
if (this.theme.visible('dock.jobs.heading')) {
|
|
109
|
-
lines.push(this.theme.style('dock.jobs.heading', this.theme.cut(`${JOBS_MARK} jobs · ${live.length} running`, width, '…')));
|
|
110
|
-
}
|
|
111
164
|
const ordered = [...live].sort((left, right) => right.startedAt - left.startedAt);
|
|
112
165
|
const now = this.now();
|
|
166
|
+
const rows = [];
|
|
113
167
|
for (const job of ordered.slice(0, DOCK_JOB_LIMIT)) {
|
|
114
168
|
if (!this.theme.visible('dock.jobs.running'))
|
|
115
169
|
continue;
|
|
116
170
|
const lead = ` ${RUNNING_MARK} `;
|
|
117
|
-
|
|
171
|
+
rows.push(this.theme.cut(this.theme.rich(`${lead}${describeJob(job, now)}`, { token: 'dock.jobs.running', column: visibleWidth(lead) }), width, '…'));
|
|
118
172
|
}
|
|
119
173
|
if (ordered.length > DOCK_JOB_LIMIT && this.theme.visible('dock.jobs.overflow')) {
|
|
120
|
-
|
|
174
|
+
rows.push(this.theme.style('dock.jobs.overflow', this.theme.cut(` … ${ordered.length - DOCK_JOB_LIMIT} more`, width, '…')));
|
|
121
175
|
}
|
|
176
|
+
this.pushSection(lines, width, {
|
|
177
|
+
heading: `${JOBS_MARK} jobs · ${live.length} running`,
|
|
178
|
+
headingToken: 'dock.jobs.heading',
|
|
179
|
+
borderToken: 'dock.jobs.border',
|
|
180
|
+
}, rows);
|
|
122
181
|
}
|
|
123
182
|
render(width) {
|
|
124
183
|
if (width <= 0)
|
package/lib/ui/dock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dock.js","sourceRoot":"","sources":["../../src/ui/dock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAkB,MAAM,wBAAwB,CAAA;AACrE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,EAAmB,MAAM,YAAY,CAAA;AACjF,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAoB,MAAM,iBAAiB,CAAA;AAKzF,mEAAmE;AACnE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAA;AAEhC,uFAAuF;AACvF,MAAM,SAAS,GAAG,GAAG,CAAA;AACrB,MAAM,cAAc,GAAG,GAAG,CAAA;AAC1B,MAAM,UAAU,GAAG,GAAG,CAAA;AACtB,MAAM,cAAc,GAAG,GAAG,CAAA;AAC1B,MAAM,SAAS,GAAG,GAAG,CAAA;
|
|
1
|
+
{"version":3,"file":"dock.js","sourceRoot":"","sources":["../../src/ui/dock.ts"],"names":[],"mappings":"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"}
|
package/lib/ui/frame.d.ts
CHANGED
|
@@ -40,6 +40,30 @@ export interface FrameFaces {
|
|
|
40
40
|
/** Whether the frame may be drawn at all. */
|
|
41
41
|
readonly framed: boolean;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* One row a frame drew, as a copy of it comes back from the terminal.
|
|
45
|
+
*
|
|
46
|
+
* A copy is read off the screen, so it carries whatever the surface drew —
|
|
47
|
+
* including the frame — and something has to be able to tell the reader's text
|
|
48
|
+
* from the shape around it. This is that account of one row: the row exactly as
|
|
49
|
+
* it read, and the columns of frame standing at each end of its text.
|
|
50
|
+
*/
|
|
51
|
+
export interface FrameRow {
|
|
52
|
+
/** The row as a copy returns it: styling gone, trailing blanks gone. */
|
|
53
|
+
readonly drawn: string;
|
|
54
|
+
/** The frame's columns at each end of the row's own text; absent when the row is frame alone. */
|
|
55
|
+
readonly frame?: {
|
|
56
|
+
readonly lead: number;
|
|
57
|
+
readonly trail: number;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** One block of rows as it is drawn, and as a copy of it reads back. */
|
|
61
|
+
export interface FrameBlock {
|
|
62
|
+
/** The rows to draw, in the surface's own styling. */
|
|
63
|
+
readonly drawn: readonly string[];
|
|
64
|
+
/** The same rows as a copy of them reads back. */
|
|
65
|
+
readonly copy: readonly FrameRow[];
|
|
66
|
+
}
|
|
43
67
|
/** Whether a bar has the width, and the visible border, to close a frame. */
|
|
44
68
|
export declare function canFrame(width: number, borderVisible: boolean): boolean;
|
|
45
69
|
/**
|
|
@@ -51,7 +75,14 @@ export declare function canFrame(width: number, borderVisible: boolean): boolean
|
|
|
51
75
|
* just drew. A block with a limit is a preview, and the rows it drops are
|
|
52
76
|
* counted on the closing rule: a reader who cannot see the whole text still has
|
|
53
77
|
* to see that it continues.
|
|
78
|
+
*
|
|
79
|
+
* The copy of a block reads the same rows back as text: the frame's own rows
|
|
80
|
+
* carry no text at all, and a row the frame holds names the columns of it that
|
|
81
|
+
* are the frame's, so a copy taken off the screen can be read as the words alone
|
|
82
|
+
* rather than as the shape that held them.
|
|
54
83
|
*/
|
|
84
|
+
export declare function frameBlock(lines: readonly string[], width: number, faces: FrameFaces, limit?: number): FrameBlock;
|
|
85
|
+
/** The rows of a block to draw, without the account of them a copy needs. */
|
|
55
86
|
export declare function frameLines(lines: readonly string[], width: number, faces: FrameFaces, limit?: number): string[];
|
|
56
87
|
/**
|
|
57
88
|
* One block of plain text as a bar draws it.
|
package/lib/ui/frame.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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;AAG1B,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,CAQhE;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;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ;IACvB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,iGAAiG;IACjG,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CACnE;AAED,wEAAwE;AACxE,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAA;CACnC;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,GAAG,OAAO,CAEvE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,SAA2B,GAAG,UAAU,CAuBnI;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,SAA2B,GAAG,MAAM,EAAE,CAEjI;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,SAA2B,GAAG,MAAM,EAAE,CAIpH"}
|
package/lib/ui/frame.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';
|
|
1
|
+
import { stripTerminalSequences, truncateToWidth, visibleWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';
|
|
2
2
|
import { renderTerminalText } from "../terminal-text.js";
|
|
3
3
|
/**
|
|
4
4
|
* The frame every prompt is closed into.
|
|
@@ -13,6 +13,8 @@ export const FRAME_GLYPHS = { topLeft: '╭', topRight: '╮', bottomLeft: '╰'
|
|
|
13
13
|
export const FRAME_COLUMNS = 2;
|
|
14
14
|
/** One column of air inside the frame, so a full line never touches the border. */
|
|
15
15
|
export const PADDING_X = 1;
|
|
16
|
+
/** The frame's own column, the one `FRAME_GLYPHS.side` is drawn in. */
|
|
17
|
+
const SIDE_COLUMNS = 1;
|
|
16
18
|
/** A box needs both edges, both paddings, and one column left to type in. */
|
|
17
19
|
export const MIN_BOX_WIDTH = FRAME_COLUMNS + PADDING_X * 2 + 1;
|
|
18
20
|
/** The columns the text of a bar owns, given the width of everything inside its frame. */
|
|
@@ -68,19 +70,40 @@ export function canFrame(width, borderVisible) {
|
|
|
68
70
|
* just drew. A block with a limit is a preview, and the rows it drops are
|
|
69
71
|
* counted on the closing rule: a reader who cannot see the whole text still has
|
|
70
72
|
* to see that it continues.
|
|
73
|
+
*
|
|
74
|
+
* The copy of a block reads the same rows back as text: the frame's own rows
|
|
75
|
+
* carry no text at all, and a row the frame holds names the columns of it that
|
|
76
|
+
* are the frame's, so a copy taken off the screen can be read as the words alone
|
|
77
|
+
* rather than as the shape that held them.
|
|
71
78
|
*/
|
|
72
|
-
export function
|
|
79
|
+
export function frameBlock(lines, width, faces, limit = Number.POSITIVE_INFINITY) {
|
|
73
80
|
const inside = faces.framed ? width - FRAME_COLUMNS : width;
|
|
74
81
|
const body = lines.slice(0, Math.max(0, limit));
|
|
75
82
|
const rows = body.map(line => textRow(faces.text(line), inside));
|
|
83
|
+
// The row is kept as the frame laid it out rather than as a copy trims it: the
|
|
84
|
+
// trailing blanks a copy drops are columns the frame's own count is measured in.
|
|
85
|
+
const read = (row) => ({ drawn: stripTerminalSequences(row) });
|
|
86
|
+
// A hidden frame still pads its rows for the frame it would have drawn, and
|
|
87
|
+
// that padding is the frame's, so a copy of these rows drops it too.
|
|
76
88
|
if (!faces.framed)
|
|
77
|
-
return rows;
|
|
89
|
+
return { drawn: rows, copy: rows.map(row => ({ ...read(row), frame: { lead: PADDING_X, trail: PADDING_X } })) };
|
|
78
90
|
const side = faces.border(FRAME_GLYPHS.side);
|
|
79
|
-
|
|
91
|
+
const drawn = [
|
|
80
92
|
faces.border(`${FRAME_GLYPHS.topLeft}${frameRule(inside, 0)}${FRAME_GLYPHS.topRight}`),
|
|
81
93
|
...rows.map(row => `${side}${row}${side}`),
|
|
82
94
|
faces.border(`${FRAME_GLYPHS.bottomLeft}${frameRule(inside, lines.length - body.length)}${FRAME_GLYPHS.bottomRight}`),
|
|
83
95
|
];
|
|
96
|
+
// The side and the padding beside it are the frame's; the rest of the row is
|
|
97
|
+
// the text, which is the part a copy of this row is entitled to keep.
|
|
98
|
+
const held = { drawn: '', frame: { lead: SIDE_COLUMNS + PADDING_X, trail: PADDING_X + SIDE_COLUMNS } };
|
|
99
|
+
return {
|
|
100
|
+
drawn,
|
|
101
|
+
copy: [read(drawn[0]), ...drawn.slice(1, -1).map(row => ({ ...held, drawn: read(row).drawn })), read(drawn[drawn.length - 1])],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/** The rows of a block to draw, without the account of them a copy needs. */
|
|
105
|
+
export function frameLines(lines, width, faces, limit = Number.POSITIVE_INFINITY) {
|
|
106
|
+
return [...frameBlock(lines, width, faces, limit).drawn];
|
|
84
107
|
}
|
|
85
108
|
/**
|
|
86
109
|
* One block of plain text as a bar draws it.
|
package/lib/ui/frame.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../../src/ui/frame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../../src/ui/frame.ts"],"names":[],"mappings":"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"}
|
package/lib/ui/view.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type Component, type TuiMouseEvent, type TuiMouseEventResult } from '@earendil-works/pi-tui';
|
|
2
2
|
import { type Keymap } from '../input/actions.ts';
|
|
3
3
|
import { type GateCard } from '../gates.ts';
|
|
4
|
-
import type
|
|
4
|
+
import { type TranscriptEntry, type TranscriptModel } from '../transcript.ts';
|
|
5
5
|
import { type ToolDisplaySpec } from '../tool-display.ts';
|
|
6
6
|
import type { TuiTheme } from '../theme.ts';
|
|
7
|
+
import { type FrameRow } from './frame.ts';
|
|
7
8
|
import { type MarkdownRenderer } from './markdown.ts';
|
|
8
9
|
import type { PickerCard } from './picker.ts';
|
|
9
10
|
import { RowCache, type RowCacheStats } from './rows.ts';
|
|
@@ -73,6 +74,21 @@ export declare class TranscriptView implements Component {
|
|
|
73
74
|
private spans;
|
|
74
75
|
/** The same spans relative to their entry, so a cached entry still answers clicks. */
|
|
75
76
|
private readonly entrySpans;
|
|
77
|
+
/**
|
|
78
|
+
* The framed rows each entry drew last render, for reading a copy back out.
|
|
79
|
+
*
|
|
80
|
+
* Relative to the entry for the same reason the spans are: a cached entry draws
|
|
81
|
+
* no rows this frame and still has to answer for what it drew before.
|
|
82
|
+
*/
|
|
83
|
+
private readonly entryCopy;
|
|
84
|
+
/**
|
|
85
|
+
* The framed rows the in-flight entries drew this frame.
|
|
86
|
+
*
|
|
87
|
+
* They cannot be kept by entry the way the settled ones are: every frame builds
|
|
88
|
+
* a live entry as a fresh object, so a map keyed by it would never answer. A copy
|
|
89
|
+
* is read against the last frame, so it is the render that keeps them.
|
|
90
|
+
*/
|
|
91
|
+
private liveCopy;
|
|
76
92
|
constructor(model: TranscriptModel, theme: TuiTheme, markdown: MarkdownRenderer, options?: TranscriptViewOptions);
|
|
77
93
|
private get viewState();
|
|
78
94
|
/** The display the reader configured for a tool, or the shipped one. */
|
|
@@ -142,7 +158,9 @@ export declare class TranscriptView implements Component {
|
|
|
142
158
|
* bars rather than as one more stretch of rows; the face, the border's element,
|
|
143
159
|
* and whether the text is still arriving are the only differences. Markdown lays
|
|
144
160
|
* itself out to the frame's text width, so the frame may only place the rows:
|
|
145
|
-
* wrapping them again would break what it drew.
|
|
161
|
+
* wrapping them again would break what it drew. The rows are recorded as they
|
|
162
|
+
* are drawn, because a copy of this message will carry the frame with it and
|
|
163
|
+
* only the drawing knows which columns of a row are the frame's.
|
|
146
164
|
*/
|
|
147
165
|
private pushFramed;
|
|
148
166
|
/**
|
|
@@ -214,6 +232,50 @@ export declare class TranscriptView implements Component {
|
|
|
214
232
|
* argument that can be a whole command rather than a word.
|
|
215
233
|
*/
|
|
216
234
|
private renderHead;
|
|
235
|
+
/**
|
|
236
|
+
* The colour a call's name is drawn in, which is the whole of its state.
|
|
237
|
+
*
|
|
238
|
+
* The name is where a reader looking for a call looks first, so what that call
|
|
239
|
+
* is doing belongs in the name rather than in a glyph beside it: one name, in
|
|
240
|
+
* the colour of its state, and nothing a reader has to learn to read first.
|
|
241
|
+
*
|
|
242
|
+
* A state is only how a name is painted, though, so a reader who turns one of
|
|
243
|
+
* these colours off still gets the name: hiding a state token takes the colour
|
|
244
|
+
* away, not the word it was painted on.
|
|
245
|
+
*/
|
|
246
|
+
private titleToken;
|
|
247
|
+
/**
|
|
248
|
+
* The seconds a call has taken: counting while it is unanswered, and kept on
|
|
249
|
+
* the card of a program that dispatched calls.
|
|
250
|
+
*
|
|
251
|
+
* A plain tool's duration is not worth the width once its outcome is on the
|
|
252
|
+
* row, but a program is a thing that took time, and the reader who watched the
|
|
253
|
+
* timer count wants the total it ended on — quietly, since the work is over.
|
|
254
|
+
*/
|
|
255
|
+
private elapsedStat;
|
|
256
|
+
/**
|
|
257
|
+
* Whether this card drew calls a program dispatched.
|
|
258
|
+
*
|
|
259
|
+
* The child rows are the fold's own statement that the card is a program's, so
|
|
260
|
+
* the view never has to know the name of the tool that runs one.
|
|
261
|
+
*/
|
|
262
|
+
private dispatchedCalls;
|
|
263
|
+
/**
|
|
264
|
+
* The card as this frame reads it, with its elapsed time filled in.
|
|
265
|
+
*
|
|
266
|
+
* The entry itself is left alone: the rows are cached by entry identity, so
|
|
267
|
+
* rewriting one every second to carry a number that changes every second would
|
|
268
|
+
* discard the rows of a call that has been waiting all along.
|
|
269
|
+
*/
|
|
270
|
+
private cardOf;
|
|
271
|
+
/**
|
|
272
|
+
* Whether any part of one card is still in flight.
|
|
273
|
+
*
|
|
274
|
+
* Only a card with work outstanding has a clock attached to its cache, so the
|
|
275
|
+
* moment the last call settles the row stops being rebuilt: a program that
|
|
276
|
+
* came back must not keep spending the cache its result is now stored in.
|
|
277
|
+
*/
|
|
278
|
+
private isLive;
|
|
217
279
|
/** The separator a header uses between its label, its facts, and its outcome. */
|
|
218
280
|
private statSeparator;
|
|
219
281
|
/**
|
|
@@ -239,5 +301,14 @@ export declare class TranscriptView implements Component {
|
|
|
239
301
|
/** The mark and the space that introduce an element, empty when it has none. */
|
|
240
302
|
private elementLead;
|
|
241
303
|
render(width: number): string[];
|
|
304
|
+
/**
|
|
305
|
+
* The framed rows the last render drew, in the order the transcript reads.
|
|
306
|
+
*
|
|
307
|
+
* A copy of a selection is read off the screen, so it carries the frame the
|
|
308
|
+
* surface drew around a message — the sides, the padding beside them, and the
|
|
309
|
+
* rules above and below. This is the account that lets the surface take its own
|
|
310
|
+
* frame back out of a copy without ever touching a character the reader wrote.
|
|
311
|
+
*/
|
|
312
|
+
copyRows(): readonly FrameRow[];
|
|
242
313
|
}
|
|
243
314
|
//# sourceMappingURL=view.d.ts.map
|
package/lib/ui/view.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/ui/view.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,aAAa,EAClB,KAAK,mBAAmB,EAGzB,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EAA2B,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC1E,OAAO,EAAqB,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/ui/view.ts"],"names":[],"mappings":"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"}
|