@vincemakes/kiso-tui 0.46.2 → 0.47.1
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/ask-panel.d.ts +10 -5
- package/dist/ask-panel.js +109 -54
- package/dist/at-picker.d.ts +38 -68
- package/dist/at-picker.js +50 -141
- package/dist/compositor.d.ts +79 -10
- package/dist/compositor.js +339 -57
- package/dist/context-ledger.d.ts +28 -0
- package/dist/context-ledger.js +62 -0
- package/dist/editor.d.ts +17 -0
- package/dist/editor.js +76 -15
- package/dist/index.d.ts +10 -10
- package/dist/index.js +10 -10
- package/dist/lines.d.ts +11 -0
- package/dist/lines.js +38 -0
- package/dist/notice-meta.d.ts +25 -0
- package/dist/notice-meta.js +85 -0
- package/dist/panel-input.d.ts +2 -2
- package/dist/panel-input.js +70 -60
- package/dist/pick-input.d.ts +23 -3
- package/dist/pick-input.js +9 -29
- package/dist/session-picker.d.ts +37 -22
- package/dist/session-picker.js +270 -57
- package/dist/status.d.ts +73 -69
- package/dist/status.js +177 -96
- package/package.json +2 -2
package/dist/at-picker.js
CHANGED
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
* on the machine's locale).
|
|
14
14
|
*/
|
|
15
15
|
import { escapeTerminal, palette } from "./lines.js";
|
|
16
|
-
import { selectionBar, visibleWidth, widthCut } from "./components.js";
|
|
16
|
+
import { atEmbed, bandKeyRow, bandVisible, bandWindow, goldHits, moreMark, selectionBar, visibleWidth, widthCut } from "./components.js";
|
|
17
|
+
// Graphite P3: the band helpers and the matcher moved to tui-cells, where
|
|
18
|
+
// the pick panels draw too; re-exported so every import site stays as it was
|
|
19
|
+
export { atEmbed, bandKeyRow, bandVisible, bandWindow, moreMark };
|
|
17
20
|
import { bandHeader } from "@vincemakes/kiso-tui-cells/strings";
|
|
18
21
|
/**
|
|
19
22
|
* KC3 §5 — the ONE cap. The file list is computed per open with no
|
|
@@ -39,53 +42,6 @@ export const AT_SKIP = new Set([".git", "node_modules", "dist", "build", "covera
|
|
|
39
42
|
/** KC3 §4 — the panel's visible height. A ceiling, not a promise: the
|
|
40
43
|
* compositor clamps further when the terminal is short. */
|
|
41
44
|
export const AT_VISIBLE = 5;
|
|
42
|
-
/**
|
|
43
|
-
* The subsequence embedding, TIGHTENED — the two-pass walk every good
|
|
44
|
-
* fuzzy finder uses, and the reason `@ra` emboldens the "ra" of
|
|
45
|
-
* "src/range.js" rather than the r of "src" and the a of "range".
|
|
46
|
-
*
|
|
47
|
-
* Pass 1 walks forward and stops at the EARLIEST index that completes
|
|
48
|
-
* the query — this both answers "does it match at all" and fixes the
|
|
49
|
-
* right-hand edge. Pass 2 walks backward from that edge, taking the
|
|
50
|
-
* LATEST position for each query character in turn, which slides every
|
|
51
|
-
* matched character as far right as it can go without crossing the
|
|
52
|
-
* next one. The result is the most clustered embedding that ends where
|
|
53
|
-
* the earliest match ends.
|
|
54
|
-
*
|
|
55
|
-
* Case-insensitive: both sides are lowercased by the caller once per
|
|
56
|
-
* query rather than once per character.
|
|
57
|
-
*
|
|
58
|
-
* Returns the ascending match indices, or null when the query is not a
|
|
59
|
-
* subsequence of the path at all.
|
|
60
|
-
*/
|
|
61
|
-
export function atEmbed(lowerPath, lowerQuery) {
|
|
62
|
-
if (lowerQuery === "")
|
|
63
|
-
return [];
|
|
64
|
-
// pass 1 — forward, to the earliest completing index
|
|
65
|
-
let qi = 0;
|
|
66
|
-
let end = -1;
|
|
67
|
-
for (let pi = 0; pi < lowerPath.length; pi += 1) {
|
|
68
|
-
if (lowerPath[pi] === lowerQuery[qi]) {
|
|
69
|
-
qi += 1;
|
|
70
|
-
if (qi === lowerQuery.length) {
|
|
71
|
-
end = pi;
|
|
72
|
-
break;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
if (end === -1)
|
|
77
|
-
return null; // not a subsequence — no embedding exists
|
|
78
|
-
// pass 2 — backward from that edge, sliding each character right
|
|
79
|
-
const hit = new Array(lowerQuery.length);
|
|
80
|
-
let pi = end;
|
|
81
|
-
for (let j = lowerQuery.length - 1; j >= 0; j -= 1) {
|
|
82
|
-
while (lowerPath[pi] !== lowerQuery[j])
|
|
83
|
-
pi -= 1;
|
|
84
|
-
hit[j] = pi;
|
|
85
|
-
pi -= 1;
|
|
86
|
-
}
|
|
87
|
-
return hit;
|
|
88
|
-
}
|
|
89
45
|
/** The longest run of CONSECUTIVE indices in an ascending list. An
|
|
90
46
|
* empty query has no run — every path ties on it, and the rank falls
|
|
91
47
|
* through to path length. */
|
|
@@ -140,117 +96,70 @@ export function atFilter(items, query) {
|
|
|
140
96
|
});
|
|
141
97
|
return { matches, capped };
|
|
142
98
|
}
|
|
143
|
-
/**
|
|
144
|
-
* KC3 §4 — the picker's WINDOW: which slice of the ranked list is on
|
|
145
|
-
* screen. The window TRAILS the selection exactly as the composer's
|
|
146
|
-
* own viewport trails the cursor (KC1 §5) — derived per read, never
|
|
147
|
-
* stored, so it can never disagree with the selection it is meant to
|
|
148
|
-
* follow.
|
|
149
|
-
*/
|
|
150
|
-
export function atWindow(total, selected, visible = AT_VISIBLE) {
|
|
151
|
-
const count = Math.min(total, visible);
|
|
152
|
-
const first = Math.max(0, Math.min(selected - count + 1, total - count));
|
|
153
|
-
return { first, count };
|
|
154
|
-
}
|
|
155
99
|
/** The path split into the two columns the panel draws: the file's own
|
|
156
100
|
* name, and the directory that qualifies it. A path with no slash is
|
|
157
101
|
* all name and no directory. */
|
|
102
|
+
/** The cells a file's NAME takes in its row — the measure the band's name
|
|
103
|
+
* column is laid over (escaped as the row draws it, so the column a
|
|
104
|
+
* wide or control-character name asks for is the one it gets). */
|
|
105
|
+
export function atNameWidth(path) {
|
|
106
|
+
return visibleWidth(splitPath(escapeTerminal(path)).name);
|
|
107
|
+
}
|
|
158
108
|
function splitPath(path) {
|
|
159
109
|
const cut = path.lastIndexOf("/");
|
|
160
110
|
return cut === -1 ? { dir: "", name: path } : { dir: path.slice(0, cut + 1), name: path.slice(cut + 1) };
|
|
161
111
|
}
|
|
162
112
|
/**
|
|
163
|
-
* KC3 §4 — ONE row of the panel
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* bold, and the DIRECTORY dim on the right, pushed to the far edge.
|
|
167
|
-
* The name is what the user is aiming at; the directory is what tells
|
|
168
|
-
* two same-named files apart, which is why it is present but quiet.
|
|
113
|
+
* KC3 §4, Graphite P2 (owner, 2026-10-03) — ONE row of the panel: the
|
|
114
|
+
* file's NAME, padded to the name column, then its FOLDER as a dim column,
|
|
115
|
+
* so the folders line up. The letters the query matched are gold in both.
|
|
169
116
|
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
117
|
+
* DECLARED REVERSAL of TUI2-R1.5 ⑧ (VD-9) in two parts: the folder no
|
|
118
|
+
* longer trails each name after an em dash — it is a column one gap after
|
|
119
|
+
* the longest name in the list (never the far edge, which was VD-9's
|
|
120
|
+
* complaint), so twenty rows read as a table; and a match inside the
|
|
121
|
+
* folder is drawn, gold, because the person typed it.
|
|
172
122
|
*
|
|
173
|
-
* The
|
|
174
|
-
*
|
|
175
|
-
* directory is simply not drawn bold — the directory column is
|
|
176
|
-
* uniformly dim by design (a bold fragment in a right-aligned dim
|
|
177
|
-
* column reads as damage, not as information).
|
|
178
|
-
*
|
|
179
|
-
* The row never exceeds W: the name cuts first (it is the flexible
|
|
180
|
-
* column), and the directory is dropped entirely before the name is
|
|
181
|
-
* cut to nothing.
|
|
123
|
+
* The name is the flexible column when the row is short: the folder gives
|
|
124
|
+
* way first, then the name is cut with an ellipsis.
|
|
182
125
|
*/
|
|
183
|
-
export function atRow(match, selected, W) {
|
|
126
|
+
export function atRow(match, selected, W, nameCol = 0, mark = null) {
|
|
184
127
|
const p = palette();
|
|
185
128
|
const { dir, name } = splitPath(escapeTerminal(match.path));
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const shownName = widthCut(name, nameRoom);
|
|
200
|
-
let painted = "";
|
|
201
|
-
for (let i = 0; i < shownName.length; i += 1) {
|
|
202
|
-
painted += marks.has(i) ? `${p.bold}${shownName[i]}${p.reset}` : shownName[i];
|
|
203
|
-
}
|
|
204
|
-
const text = `${painted}${suffix === "" ? "" : `${p.dim}${suffix}${p.reset}`}`;
|
|
205
|
-
const width = visibleWidth(shownName) + visibleWidth(suffix);
|
|
206
|
-
if (!selected)
|
|
207
|
-
return ` ${text}`;
|
|
208
|
-
// TUI2-R1.5 ⑧ (VD-9): the selection is a FULL-ROW bar — the W16 chip
|
|
209
|
-
// mechanism, which the user chip and the turn fold already use. A
|
|
210
|
-
// two-cell `→ ` marker on the inverse band is one character of
|
|
211
|
-
// highlight in an eighty-column row, and the walkthrough could barely
|
|
212
|
-
// find it. The bar spans the row's whole width so the selection is
|
|
213
|
-
// visible from anywhere on the line. Mono discipline: reverse video,
|
|
214
|
-
// no new colours.
|
|
215
|
-
//
|
|
216
|
-
// R2: the composition is selectionBar's — one copy, and with it the
|
|
217
|
-
// §2.1 rule that dim never sits on the wash (the directory column was
|
|
218
|
-
// rendering grey-on-grey inside the bar, i.e. the half of the row the
|
|
219
|
-
// selection was meant to help you read).
|
|
220
|
-
return selectionBar(`${painted}${suffix === "" ? "" : `${p.dim}${suffix}${p.reset}`}`, width, W);
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* KC3 §4 — the counter row: `(n/total)`, where n is the 1-based
|
|
224
|
-
* position of the SELECTION in the whole ranked list, not in the
|
|
225
|
-
* visible window. The user needs to know where they are in the list,
|
|
226
|
-
* which the five visible rows cannot tell them.
|
|
227
|
-
*
|
|
228
|
-
* When the source list was truncated the row SAYS SO. A file picker
|
|
229
|
-
* that quietly lists 2,000 of 40,000 files and shows a confident
|
|
230
|
-
* "(3/1998)" is lying by omission; this one admits the horizon.
|
|
231
|
-
*/
|
|
232
|
-
export function atCounterRow(selected, total, capped, W) {
|
|
233
|
-
const p = palette();
|
|
234
|
-
const text = capped ? ` (${selected + 1}/${total}) · first ${AT_CAP} files only` : ` (${selected + 1}/${total})`;
|
|
235
|
-
return `${p.dim}${widthCut(text, W)}${p.reset}`;
|
|
129
|
+
const nameHits = new Set(match.hit.filter((i) => i >= dir.length).map((i) => i - dir.length));
|
|
130
|
+
const dirHits = new Set(match.hit.filter((i) => i < dir.length));
|
|
131
|
+
const room = Math.max(1, W - 3); // the two-cell lead and one cell of margin
|
|
132
|
+
const col = Math.min(Math.max(nameCol, visibleWidth(name)), room);
|
|
133
|
+
const shownName = visibleWidth(name) <= col ? name : col <= 1 ? widthCut(name, col) : `${widthCut(name, col - 1)}…`;
|
|
134
|
+
const dirRoom = room - col - 2;
|
|
135
|
+
const shownDir = dir === "" || dirRoom < 4 ? "" : visibleWidth(dir) <= dirRoom ? dir : `${widthCut(dir, dirRoom - 1)}…`;
|
|
136
|
+
const pad = shownDir === "" ? "" : " ".repeat(col - visibleWidth(shownName) + 2);
|
|
137
|
+
const text = `${goldHits(shownName, nameHits, selected ? p.bold : "")}${pad}${shownDir === "" ? "" : goldHits(shownDir, dirHits, p.dim)}`;
|
|
138
|
+
const width = visibleWidth(shownName) + pad.length + visibleWidth(shownDir);
|
|
139
|
+
if (selected)
|
|
140
|
+
return selectionBar(` ${text}`, width + 1, W);
|
|
141
|
+
return mark === null ? ` ${text}` : `${p.dim}${mark}${p.reset} ${text}`;
|
|
236
142
|
}
|
|
237
143
|
/**
|
|
238
|
-
* KC3 §4 — the whole band:
|
|
144
|
+
* KC3 §4, Graphite P2 — the whole band: the named hairline with the count
|
|
145
|
+
* (`files · 8`, `2 of 8 match`, and `first 2000 only` when the walk was
|
|
146
|
+
* cut), the windowed rows with their more-marks, and the key row with the
|
|
239
147
|
* counter. Returned as plain strings for the menu-rows channel, which
|
|
240
|
-
* already accounts them in chromeRows — the picker needs no geometry
|
|
241
|
-
*
|
|
148
|
+
* already accounts them in chromeRows — the picker needs no geometry of
|
|
149
|
+
* its own, which is the entire reason it rides that channel.
|
|
242
150
|
*/
|
|
243
|
-
export function atPanelRows(state, W) {
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
const
|
|
151
|
+
export function atPanelRows(state, W, height = 24) {
|
|
152
|
+
const total = state.total ?? state.matches.length;
|
|
153
|
+
const query = state.query ?? "";
|
|
154
|
+
const facts = `${query === "" ? `${total}` : `${state.matches.length} of ${total} match`}${state.capped ? ` · first ${AT_CAP} only` : ""}`;
|
|
155
|
+
// TUI2-R1.5 ⑦(b) (VD-8): the band NAMES itself — with scrollback behind
|
|
156
|
+
// it, nothing else says where the surface begins
|
|
157
|
+
const rows = [bandHeader(`files · ${facts}`, W)];
|
|
158
|
+
const { first, count } = bandWindow(state.matches.length, state.selected, bandVisible(height));
|
|
159
|
+
const nameCol = state.nameCol ?? 0;
|
|
251
160
|
for (let i = first; i < first + count; i += 1)
|
|
252
|
-
rows.push(atRow(state.matches[i], i === state.selected, W));
|
|
253
|
-
rows.push(
|
|
161
|
+
rows.push(atRow(state.matches[i], i === state.selected, W, nameCol, moreMark(i, first, count, state.matches.length)));
|
|
162
|
+
rows.push(bandKeyRow(["↑↓ move", "tab inserts", "esc"], state.selected, state.matches.length, W));
|
|
254
163
|
return rows;
|
|
255
164
|
}
|
|
256
165
|
/**
|
package/dist/compositor.d.ts
CHANGED
|
@@ -55,11 +55,15 @@ export interface AtPanelState {
|
|
|
55
55
|
readonly selected: number;
|
|
56
56
|
readonly capped: boolean;
|
|
57
57
|
}
|
|
58
|
+
import { type NoticeMark, type RecallSection } from "./components.js";
|
|
58
59
|
import { type BannerMeta, type ResumeMeta } from "./lines.js";
|
|
60
|
+
import { type BarInput } from "./status.js";
|
|
59
61
|
/** The cursor marker — an APC private sequence the focus component
|
|
60
62
|
* embeds at the edit position; the compositor strips it and moves
|
|
61
63
|
* relatively (it never reaches the terminal). */
|
|
62
64
|
export declare const CURSOR_MARKER = "\u001B_[kiso-cur]\u001B\\";
|
|
65
|
+
/** R8 — the command band's window: five rows plus a counter, the same
|
|
66
|
+
* budget the composer's own ceiling can afford above it. */
|
|
63
67
|
/** KC1 §5 — the input row's bound state. The legacy pair stays
|
|
64
68
|
* REQUIRED and keeps its exact meaning (the cursor line's visible
|
|
65
69
|
* slice and its display column), so a one-row provider — the old
|
|
@@ -160,6 +164,38 @@ export declare class Body {
|
|
|
160
164
|
*/
|
|
161
165
|
fold(label: string, replay: () => void, summary?: string | null): void;
|
|
162
166
|
notice(text: string): void;
|
|
167
|
+
/** The tasks round (owner, 2026-10-06) — a notice whose terminal form
|
|
168
|
+
* is one meta row per thing it names (a task's end, a project's trust):
|
|
169
|
+
* each row a label (`TASK` once, `""` under it), the sentence cut to one
|
|
170
|
+
* row, its outcome word marked. A pipe keeps `text`, byte for byte. */
|
|
171
|
+
metaNotice(text: string, rows: readonly {
|
|
172
|
+
readonly label: string;
|
|
173
|
+
readonly sentence: string;
|
|
174
|
+
readonly mark?: NoticeMark;
|
|
175
|
+
}[]): void;
|
|
176
|
+
/** The last sweep (owner, 2026-10-06) — what `/think` or `/last` brings
|
|
177
|
+
* back: on the terminal ONE cell, a meta row (`label`, `sentence`) and
|
|
178
|
+
* the sections under it; a pipe keeps `text`, byte for byte. */
|
|
179
|
+
recall(text: string, label: string, sentence: string, sections: readonly RecallSection[]): void;
|
|
180
|
+
/** Graphite R3e (owner, 2026-09-29) — a mode switch: on the terminal
|
|
181
|
+
* `MODE` on a row of its own and `from → to` under it, the new tier
|
|
182
|
+
* bold (full access — the old bypass — in the failure colour, plan in
|
|
183
|
+
* blue) — no explanation:
|
|
184
|
+
* the picker that switched it says what each tier does. A pipe keeps
|
|
185
|
+
* the confirmation it always printed, byte for byte (`text`). */
|
|
186
|
+
modeNotice(text: string, from: string, to: string): void;
|
|
187
|
+
/** The main-sync round (owner, 2026-09-30) — the don't-ask switch, the
|
|
188
|
+
* MODE row's sibling: `DON'T ASK` gold (the person's choice) and
|
|
189
|
+
* `off → on` with the new state bold. It is a switch on top of the tier,
|
|
190
|
+
* not a tier, so it has a row of its own. A pipe keeps #203's words
|
|
191
|
+
* (`don't ask → on`), byte for byte. */
|
|
192
|
+
dontAskNotice(text: string, on: boolean): void;
|
|
193
|
+
/**
|
|
194
|
+
* Graphite §7.11 — the turn's SEAL. On the terminal a cell of its own,
|
|
195
|
+
* drawn at the current width (widest tier that fits); a pipe gets
|
|
196
|
+
* `pipe` — today's recap line — byte for byte.
|
|
197
|
+
*/
|
|
198
|
+
seal(tiers: readonly string[], pipe: string): void;
|
|
163
199
|
/** The startup banner (W1): a LIVE cell — the tier re-derives per
|
|
164
200
|
* frame (bannerLines with the CURRENT W and H), so a resize re-tiers
|
|
165
201
|
* the art instead of re-folding frozen rows (a window below 40 cols
|
|
@@ -169,6 +205,9 @@ export declare class Body {
|
|
|
169
205
|
* the pipe contract). */
|
|
170
206
|
banner(version: string, extensionsText: string, resume?: ResumeMeta[], meta?: BannerMeta | undefined): void;
|
|
171
207
|
raw(lines: string[], wrap?: "words"): void;
|
|
208
|
+
/** G3 (R2d) — the person's `!!cmd`: run, shown here, never sent. Off a
|
|
209
|
+
* dock the command and its output are written as they always were. */
|
|
210
|
+
bang(command: string, output: string, isError: boolean): void;
|
|
172
211
|
/** The last COMPLETE thinking block, for /think. */
|
|
173
212
|
lastThinking(): string | null;
|
|
174
213
|
/** The last completed tool call, for /last. */
|
|
@@ -266,10 +305,18 @@ export declare class Body {
|
|
|
266
305
|
* which time the first frame is already painted with the no-ground
|
|
267
306
|
* palette. Rather than delay the opening to wait for an answer that
|
|
268
307
|
* may never come, the frame is painted at once and repainted when the
|
|
269
|
-
* answer lands.
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
308
|
+
* answer lands.
|
|
309
|
+
*
|
|
310
|
+
* It is NOT a resize, and must not ride one: the settle returns early
|
|
311
|
+
* when the geometry did not change — which it never does here — so the
|
|
312
|
+
* old path cleared the held screen and painted nothing, leaving the
|
|
313
|
+
* no-ground palette up until the first keystroke. Nor is it a reprint:
|
|
314
|
+
* `3J` would erase the shell's scrollback at every launch, since the
|
|
315
|
+
* answer arrives at every launch. So: the committed cells' cached rows
|
|
316
|
+
* are dropped (their bytes carry the old palette; their geometry does
|
|
317
|
+
* not change, the palette sets no width), the held screen is voided,
|
|
318
|
+
* and one frame repaints what is on screen. Rows already in the
|
|
319
|
+
* terminal's scrollback keep the palette they were written in.
|
|
273
320
|
*/
|
|
274
321
|
onGroundChange(): void;
|
|
275
322
|
/**
|
|
@@ -325,6 +372,15 @@ export declare class Body {
|
|
|
325
372
|
* state — the compacting row passes "esc to cancel" (the affordance
|
|
326
373
|
* must survive repaints). */
|
|
327
374
|
setStatus(text: string, hint?: string | null): void;
|
|
375
|
+
/** Graphite §8.9 — hand the status bar its facts. */
|
|
376
|
+
setBar(bar: BarInput | null): void;
|
|
377
|
+
/** Graphite §8.7 — the live row (already composed for the width the
|
|
378
|
+
* caller measured; cut here if the terminal narrowed since), or null
|
|
379
|
+
* when nothing is live. */
|
|
380
|
+
setLive(row: string | null): void;
|
|
381
|
+
/** A confirmation that is true for a moment — `copied 212 chars` — on the
|
|
382
|
+
* live row, until the next keypress. It never displaces a live row. */
|
|
383
|
+
flash(text: string): void;
|
|
328
384
|
setTail(tail: string): void;
|
|
329
385
|
/** Bind the editor's panel state — the PanelSelect slot occupant
|
|
330
386
|
* (W21: the panel replaces the live region + the input lead while
|
|
@@ -335,10 +391,13 @@ export declare class Body {
|
|
|
335
391
|
/** Bind the editor's slash-command menu state — the MenuSelect slot
|
|
336
392
|
* occupant (the menu replaces the editor's view while open). */
|
|
337
393
|
/** TUI2-R1 (D): bind the editor's keys-sheet flag. */
|
|
338
|
-
bindSheet(state: () => boolean): void;
|
|
394
|
+
bindSheet(state: () => boolean | ((W: number) => string[])): void;
|
|
339
395
|
bindMenu(state: () => {
|
|
340
396
|
items: readonly MenuItem[];
|
|
341
397
|
selected: number;
|
|
398
|
+
total?: number;
|
|
399
|
+
query?: string;
|
|
400
|
+
nameCol?: number;
|
|
342
401
|
} | null): void;
|
|
343
402
|
/** KC3 §4: bind the editor's @ file picker. It shares the menu's
|
|
344
403
|
* band — see #menuRows for why that is a decision and not a
|
|
@@ -348,8 +407,9 @@ export declare class Body {
|
|
|
348
407
|
* occupant (see #menuRows for why they share one). */
|
|
349
408
|
bindPick(state: () => SessionPickState | null): void;
|
|
350
409
|
/** Bind the pending-turn queue — the CLI's live slots (chat.ts):
|
|
351
|
-
* the
|
|
352
|
-
* by their rows
|
|
410
|
+
* the queued rows render in the menu-rows family and the live caps
|
|
411
|
+
* shrink by their rows (Graphite §8.7). The status bar does not
|
|
412
|
+
* count them; without a bar the status row's hint still does. */
|
|
353
413
|
bindQueue(state: () => readonly string[]): void;
|
|
354
414
|
/** The input line's edit column — the old dock's API. v6: the CURSOR
|
|
355
415
|
* derives from the frame's marker; this is the same value computed
|
|
@@ -405,6 +465,12 @@ export declare class Dock {
|
|
|
405
465
|
size: number;
|
|
406
466
|
} | null;
|
|
407
467
|
setStatus(text: string, hint?: string | null): void;
|
|
468
|
+
/** Graphite §8.9 — the status bar's facts. */
|
|
469
|
+
setBar(bar: BarInput | null): void;
|
|
470
|
+
/** Graphite §8.7 — the live row, or null. */
|
|
471
|
+
setLive(row: string | null): void;
|
|
472
|
+
/** A short confirmation on the live row, gone at the next keypress. */
|
|
473
|
+
flash(text: string): void;
|
|
408
474
|
setTail(tail: string): void;
|
|
409
475
|
/** W21: bind the editor's panel state — the PanelSelect slot
|
|
410
476
|
* occupant (the panel replaces the live region + the input lead
|
|
@@ -412,7 +478,7 @@ export declare class Dock {
|
|
|
412
478
|
bindApproval(state: () => PanelState | null): void;
|
|
413
479
|
/** TUI2-R1 (D): bind the editor's keys-sheet flag — the slot read for
|
|
414
480
|
* the ? overlay (the menu/picker binding pattern). */
|
|
415
|
-
bindSheet(state: () => boolean): void;
|
|
481
|
+
bindSheet(state: () => boolean | ((W: number) => string[])): void;
|
|
416
482
|
/** R5 — the transcript viewer's three doors, forwarded to the live
|
|
417
483
|
* compositor. Unlike the other bindings there is no buffer: the
|
|
418
484
|
* viewer cannot be open before a compositor exists, so a call with
|
|
@@ -424,6 +490,9 @@ export declare class Dock {
|
|
|
424
490
|
bindMenu(state: () => {
|
|
425
491
|
items: readonly MenuItem[];
|
|
426
492
|
selected: number;
|
|
493
|
+
total?: number;
|
|
494
|
+
query?: string;
|
|
495
|
+
nameCol?: number;
|
|
427
496
|
} | null): void;
|
|
428
497
|
/** KC3 §4: bind the editor's @ picker — the SAME band as the slash
|
|
429
498
|
* menu (see Body#menuRows). Unbound, the picker cannot render, and
|
|
@@ -433,8 +502,8 @@ export declare class Dock {
|
|
|
433
502
|
* occupant. Unbound (every path but bare `kiso resume`), the picker
|
|
434
503
|
* cannot render and every frame is byte-identical to before. */
|
|
435
504
|
bindPick(state: () => SessionPickState | null): void;
|
|
436
|
-
/** W22: bind the pending-turn queue — the
|
|
437
|
-
*
|
|
505
|
+
/** W22: bind the pending-turn queue — the queued rows (the CLI
|
|
506
|
+
* binds it from chat(); the editor's pop keys ride
|
|
438
507
|
* the LineInput's own bindQueue). */
|
|
439
508
|
bindQueue(state: () => readonly string[]): void;
|
|
440
509
|
editCol(): number;
|