@vincemakes/kiso-tui-cells 0.20.3 → 0.21.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/dist/approval-panel.d.ts +2 -2
- package/dist/approval-panel.js +3 -3
- package/dist/components.d.ts +12 -11
- package/dist/components.js +73 -54
- package/dist/render.d.ts +26 -1
- package/dist/render.js +18 -5
- package/dist/strings.js +6 -6
- package/dist/width.d.ts +1 -1
- package/dist/width.js +2 -2
- package/package.json +1 -1
package/dist/approval-panel.d.ts
CHANGED
|
@@ -266,7 +266,7 @@ export interface PanelView {
|
|
|
266
266
|
/** The fix hint per speaker (the v8 design §3.5 table). */
|
|
267
267
|
readonly hint?: string;
|
|
268
268
|
/** The options-phase status-left text — the CLI knows the context
|
|
269
|
-
* ("
|
|
269
|
+
* ("❯ run paused", the trust gate's line). */
|
|
270
270
|
readonly statusText: string;
|
|
271
271
|
/** The ALWAYS-verbose args — the full command/content/diff. */
|
|
272
272
|
readonly args: PanelArgs;
|
|
@@ -395,7 +395,7 @@ export declare function panelLeadPlain(view: PanelView, phase: PanelPhase, curso
|
|
|
395
395
|
export declare function panelLeadWidth(view: PanelView, phase: PanelPhase, cursor: number): number;
|
|
396
396
|
/** The status row's left text while the panel is up — the phase, not
|
|
397
397
|
* the CLI's painting status (the compositor derives it from the panel
|
|
398
|
-
* state; the "
|
|
398
|
+
* state; the "❯ run paused" etc. ride the options phase). */
|
|
399
399
|
export declare function panelStatus(view: PanelView, phase: PanelPhase, cursor: number): string;
|
|
400
400
|
/**
|
|
401
401
|
* The status row's right-aligned hint — the v4 frame's line, verbatim.
|
package/dist/approval-panel.js
CHANGED
|
@@ -432,8 +432,8 @@ export function panelLeadWidth(view, phase, cursor) {
|
|
|
432
432
|
}
|
|
433
433
|
/** The status row's left text while the panel is up — the phase, not
|
|
434
434
|
* the CLI's painting status (the compositor derives it from the panel
|
|
435
|
-
* state; the "
|
|
436
|
-
// R2 (design §4, the
|
|
435
|
+
* state; the "❯ run paused" etc. ride the options phase). */
|
|
436
|
+
// R2 (design §4, the ❯ ruling): a panel that is WAITING ON A HUMAN says
|
|
437
437
|
// so with the one mark that means it. `▸` is the checklist's "the
|
|
438
438
|
// current one" — a mark meaning two things is worse than two marks
|
|
439
439
|
// (law 4.2), and the thing this row has to convey is not "here" but
|
|
@@ -450,7 +450,7 @@ export function panelStatus(view, phase, cursor) {
|
|
|
450
450
|
// typing needs to know the model will read this and answer with a new
|
|
451
451
|
// call — which is what the v4 frame says, in those words.
|
|
452
452
|
if (phase === "amend")
|
|
453
|
-
return "
|
|
453
|
+
return "❯ your note goes to the model — it will propose a new call";
|
|
454
454
|
return view.statusText;
|
|
455
455
|
}
|
|
456
456
|
/**
|
package/dist/components.d.ts
CHANGED
|
@@ -151,7 +151,7 @@ export type BodyCell = {
|
|
|
151
151
|
* settled head row aggregates name + status + decidedBy in ONE
|
|
152
152
|
* row: a denied call's pinned row gains `· by <decidedBy>`; an
|
|
153
153
|
* extension-approved call's settled row gains `· approved by
|
|
154
|
-
* <decidedBy>` (the human approval needs no marker — the
|
|
154
|
+
* <decidedBy>` (the human approval needs no marker — the ❯ →
|
|
155
155
|
* spinner → ✓ sequence told the story). Null until a decision
|
|
156
156
|
* lands (the auto-allowed calls never have one). */
|
|
157
157
|
verdict: {
|
|
@@ -207,7 +207,7 @@ export type BodyCell = {
|
|
|
207
207
|
* live region); true once SETTLED — endTurn committed it as the
|
|
208
208
|
* turn's one recap block. */
|
|
209
209
|
done: boolean;
|
|
210
|
-
/** W20: the LIVE block's ctrl+
|
|
210
|
+
/** W20: the LIVE block's ctrl+o toggle (W15) — the capped form
|
|
211
211
|
* flips to the full list in place. The settled render ignores
|
|
212
212
|
* it (already full). */
|
|
213
213
|
expanded: boolean;
|
|
@@ -224,8 +224,9 @@ declare const TOOL_SUMMARY_MAX = 60;
|
|
|
224
224
|
* compositor stays a pure writer. */
|
|
225
225
|
export declare function cellComponent(cell: BodyCell): Component;
|
|
226
226
|
/** W22: the pending-queue chips — queued user lines pre-render above
|
|
227
|
-
* the input row as the SAME UserMessage chip (undimmed:
|
|
228
|
-
*
|
|
227
|
+
* the input row as the SAME UserMessage chip (undimmed: §2.1 forbids
|
|
228
|
+
* dim ON the wash, and on rung 4 reverse video would invert it into a
|
|
229
|
+
* dimmed block), the dim `□` gutter marking the queued
|
|
229
230
|
* state (the gutter rides EVERY row — the gutterFold precedent: the
|
|
230
231
|
* left edge alone distinguishes the states). Each chip folds at W−3
|
|
231
232
|
* (the gutter's 2 cells), so a long line hard-folds INSIDE the chip
|
|
@@ -245,7 +246,7 @@ export declare function expandSuffix(lines: number | null, room: number): string
|
|
|
245
246
|
/**
|
|
246
247
|
* TUI2-R2 ⑤ (D, candidate 1) — the FOCUS tint.
|
|
247
248
|
*
|
|
248
|
-
* The cell the next ctrl+
|
|
249
|
+
* The cell the next ctrl+o will act on brightens its own `ctrl+o` token
|
|
249
250
|
* to the code tint; the rest of the suffix — the separator, the count —
|
|
250
251
|
* stays dim, because what is being marked is the KEY's target, not the
|
|
251
252
|
* row. Zero new rows, zero new columns: the affordance the cell already
|
|
@@ -253,7 +254,7 @@ export declare function expandSuffix(lines: number | null, room: number): string
|
|
|
253
254
|
*
|
|
254
255
|
* Applied to a row rather than composed into it on purpose. The token is
|
|
255
256
|
* emitted from several places (the settled suffix, the renderer's own
|
|
256
|
-
* `└ +N … · ctrl+
|
|
257
|
+
* `└ +N … · ctrl+o` cut rows) and threading a flag through all of them
|
|
257
258
|
* would put the invariant "exactly one bright token" in as many hands as
|
|
258
259
|
* there are emitters. Here it has exactly one.
|
|
259
260
|
*
|
|
@@ -307,7 +308,7 @@ export declare function foldTerms(reads: number, edits: number, others: readonly
|
|
|
307
308
|
*
|
|
308
309
|
* thinking ✧ thinking 4s
|
|
309
310
|
* acting ✶ reading 6 files · running 4 shell commands
|
|
310
|
-
* settled ✦ thought 9s · read 6 files · ran 4 shell commands · ctrl+
|
|
311
|
+
* settled ✦ thought 9s · read 6 files · ran 4 shell commands · ctrl+o
|
|
311
312
|
*
|
|
312
313
|
* THE GIVE-WAY LADDER, in order, because at some width everything
|
|
313
314
|
* cannot fit:
|
|
@@ -384,7 +385,7 @@ export interface StretchTerms {
|
|
|
384
385
|
/**
|
|
385
386
|
* R4 (C1) — the fold NAMES ITS OWN TARGET.
|
|
386
387
|
*
|
|
387
|
-
* `ctrl+
|
|
388
|
+
* `ctrl+o` used to be printed identically on every fold on the screen,
|
|
388
389
|
* and the key walked a ring whose order nothing on screen expressed —
|
|
389
390
|
* so the owner's report was exact: "there is no way to know which
|
|
390
391
|
* stretch it opens". The tint that marks the next target can only be
|
|
@@ -508,7 +509,7 @@ export declare function formatDuration(totalSeconds: number): string;
|
|
|
508
509
|
* W21: the question param is gone — the old question slot retires; a
|
|
509
510
|
* pending approval's status IS the panel's (the compositor derives
|
|
510
511
|
* it from the bound panel state). */
|
|
511
|
-
/** R8b — THE IDLE HINT GIVES WAY IN ORDER, and `ctrl+
|
|
512
|
+
/** R8b — THE IDLE HINT GIVES WAY IN ORDER, and `ctrl+r` is on it.
|
|
512
513
|
*
|
|
513
514
|
* The transcript viewer shipped in 0.19.0 and was reachable only from
|
|
514
515
|
* the `?` sheet: not on the banner's key line, not here. A feature
|
|
@@ -519,9 +520,9 @@ export declare function formatDuration(totalSeconds: number): string;
|
|
|
519
520
|
* when it does not fit — a longer string would take `/ commands` down
|
|
520
521
|
* with it on a narrow terminal. So the forms are a ladder, and the
|
|
521
522
|
* order says which affordance is least replaceable: `/ commands`
|
|
522
|
-
* survives longest because it is the door to everything; `ctrl+
|
|
523
|
+
* survives longest because it is the door to everything; `ctrl+r`
|
|
523
524
|
* outranks `↑ history` because pressing up is how a person finds the
|
|
524
|
-
* history by accident, and nothing finds ctrl+
|
|
525
|
+
* history by accident, and nothing finds ctrl+r by accident. */
|
|
525
526
|
export declare function idleHint(room: number): string;
|
|
526
527
|
export declare function statusLine(status: string, tail: string, W: number, hint?: string): string;
|
|
527
528
|
/** The display-width prefix of a plain (SGR-free) text. W21: exported
|
package/dist/components.js
CHANGED
|
@@ -185,10 +185,20 @@ export function cellComponent(cell) {
|
|
|
185
185
|
*
|
|
186
186
|
* The padding is by cells (charWidth is the width authority), so a CJK
|
|
187
187
|
* row pads by width, never by chars, and the chip never overruns.
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
188
|
+
*
|
|
189
|
+
* R9 P1 — the surface is the WASH (§1.6, §7.9), closed with 49 rather
|
|
190
|
+
* than SGR 0 so the chip composes with a surrounding span. It drew with
|
|
191
|
+
* SGR 7 on every ground until now, which §7.9 never asked for: on a
|
|
192
|
+
* light terminal that is a full-width black band, on a dark one a white
|
|
193
|
+
* one, and every turn has exactly one. §11 settles which side was
|
|
194
|
+
* stale — the design said washed, the code predated DC-3's ground-
|
|
195
|
+
* resolved wash and was never moved onto it. The ladder makes the move
|
|
196
|
+
* safe: with no ground `wash` IS reverse video (§3 rung 4), so the
|
|
197
|
+
* unknown-ground chip is byte-identical to what shipped.
|
|
198
|
+
*
|
|
199
|
+
* NEVER dim inside it, on either surface: §2.1 on a resolved wash, and
|
|
200
|
+
* on rung 4 because reverse video inverts the CURRENT colours, so
|
|
201
|
+
* dimmed text inverts into a dimmed block with no contrast.
|
|
192
202
|
*/
|
|
193
203
|
/**
|
|
194
204
|
* REL-0152-D13 — how much of a turn the chip shows.
|
|
@@ -226,7 +236,13 @@ class UserMessage {
|
|
|
226
236
|
truncated = true;
|
|
227
237
|
break;
|
|
228
238
|
}
|
|
229
|
-
|
|
239
|
+
// R9 Q3: by WORD. The char fold was defended as lossless, and
|
|
240
|
+
// that argument does not survive CJK — a run with no spaces has
|
|
241
|
+
// nothing to lose — while every other prose surface in the
|
|
242
|
+
// product already folds by word (ErrorLine, VD-10). foldWords
|
|
243
|
+
// falls through to foldLine's hard break for a word wider than
|
|
244
|
+
// the row, so invariant ① still outranks the word.
|
|
245
|
+
for (const row of foldWords(escapeTerminal(para), chipW)) {
|
|
230
246
|
if (content.length >= USER_CHIP_ROWS) {
|
|
231
247
|
truncated = true;
|
|
232
248
|
break;
|
|
@@ -245,7 +261,7 @@ class UserMessage {
|
|
|
245
261
|
// row is two cells per character and pads by cells.
|
|
246
262
|
const inner = chipW;
|
|
247
263
|
for (const row of content) {
|
|
248
|
-
rows.push(`${p.
|
|
264
|
+
rows.push(`${p.wash} ${row}${" ".repeat(Math.max(0, inner - displayWidth(row)))} ${p.washEnd}`);
|
|
249
265
|
}
|
|
250
266
|
if (!truncated)
|
|
251
267
|
return rows;
|
|
@@ -262,8 +278,9 @@ class UserMessage {
|
|
|
262
278
|
}
|
|
263
279
|
}
|
|
264
280
|
/** W22: the pending-queue chips — queued user lines pre-render above
|
|
265
|
-
* the input row as the SAME UserMessage chip (undimmed:
|
|
266
|
-
*
|
|
281
|
+
* the input row as the SAME UserMessage chip (undimmed: §2.1 forbids
|
|
282
|
+
* dim ON the wash, and on rung 4 reverse video would invert it into a
|
|
283
|
+
* dimmed block), the dim `□` gutter marking the queued
|
|
267
284
|
* state (the gutter rides EVERY row — the gutterFold precedent: the
|
|
268
285
|
* left edge alone distinguishes the states). Each chip folds at W−3
|
|
269
286
|
* (the gutter's 2 cells), so a long line hard-folds INSIDE the chip
|
|
@@ -353,7 +370,7 @@ class ThinkingFold {
|
|
|
353
370
|
// opens with a numbered plan ("1. …\n2. …") produces exactly it.
|
|
354
371
|
// Invariant ①b now catches the class at the emit; this stops
|
|
355
372
|
// producing it. Whitespace collapses because the row is a
|
|
356
|
-
// SUMMARY — the full text is one ctrl+
|
|
373
|
+
// SUMMARY — the full text is one ctrl+o away, unchanged.
|
|
357
374
|
const trimmed = escapeTerminal(block.trim()).replace(/\s+/g, " ");
|
|
358
375
|
// R2 (owner, 2026-08-27) — three changes, each independent.
|
|
359
376
|
//
|
|
@@ -587,7 +604,7 @@ function toolTargetOf(c) {
|
|
|
587
604
|
* own render; the lines fold (the summary gives way first). W7 (the
|
|
588
605
|
* flow contract): the block's BODY (the rows below the header) is
|
|
589
606
|
* capped in SCREEN rows AFTER the fold, at the current width — the
|
|
590
|
-
* renderer-cut row (`└ +N … · ctrl+
|
|
607
|
+
* renderer-cut row (`└ +N … · ctrl+o`) sits INSIDE the cap (a
|
|
591
608
|
* truncated block is cap−1 output rows + the cut row); the TOOL-cut
|
|
592
609
|
* row (`└ capped by …` — the tool's OWN truncation note, W10) is a
|
|
593
610
|
* DIFFERENT fact, never counted in the output cap. W3: the verb is
|
|
@@ -626,7 +643,7 @@ class ToolExecution {
|
|
|
626
643
|
const head = ` explored ${p.bold}${counts}${p.reset}`; // R2: no tick
|
|
627
644
|
const tail = ` (${r.elapsed}s)`;
|
|
628
645
|
const room = W - visibleWidth(head) - tail.length;
|
|
629
|
-
const affordance = " · ctrl+
|
|
646
|
+
const affordance = " · ctrl+o lists them";
|
|
630
647
|
return [cutLine(`${head}${p.dim}${tail}${affordance.length <= room ? affordance : ""}${p.reset}`, W)];
|
|
631
648
|
}
|
|
632
649
|
if (c.rolled !== null) {
|
|
@@ -634,7 +651,7 @@ class ToolExecution {
|
|
|
634
651
|
// the work order's claimed shape, verbatim — the verbCol's
|
|
635
652
|
// 5-char pad reproduces the "read 5 files" double space, the
|
|
636
653
|
// children are the first 3 basename targets, the overflow row
|
|
637
|
-
// carries the ctrl+
|
|
654
|
+
// carries the ctrl+o affordance (its "└ … ctrl+o" joins the
|
|
638
655
|
// W15 expand history — the head's commit captures it).
|
|
639
656
|
const r = c.rolled;
|
|
640
657
|
const noun = ROLLUP_NOUN[c.name] ?? "calls";
|
|
@@ -643,7 +660,7 @@ class ToolExecution {
|
|
|
643
660
|
if (shown.length > 0)
|
|
644
661
|
out.push(` ${p.dim}${CUT_ROW}${escapeTerminal(shown.join(" · "))}${p.reset}`);
|
|
645
662
|
if (r.targets.length > 3)
|
|
646
|
-
out.push(` ${p.dim}${CUT_ROW}+${r.targets.length - 3} more — ctrl+
|
|
663
|
+
out.push(` ${p.dim}${CUT_ROW}+${r.targets.length - 3} more — ctrl+o expands${p.reset}`);
|
|
647
664
|
return out;
|
|
648
665
|
}
|
|
649
666
|
if (c.state === "done") {
|
|
@@ -674,7 +691,7 @@ class ToolExecution {
|
|
|
674
691
|
}
|
|
675
692
|
const elapsed = c.startedAt !== null && c.doneAt !== null ? ((c.doneAt - c.startedAt) / 1000).toFixed(1) : "?";
|
|
676
693
|
// TUI2-R1.5 ⑤ (VD-6): the line count is stated EXACTLY ONCE. Every
|
|
677
|
-
// read card carried it twice — `(2 lines, 0.0s) · 2 lines · ctrl+
|
|
694
|
+
// read card carried it twice — `(2 lines, 0.0s) · 2 lines · ctrl+o
|
|
678
695
|
// expands` — because the parens and the suffix were written by
|
|
679
696
|
// different rounds, each unaware the other was counting. The
|
|
680
697
|
// SUFFIX keeps it (it is the one that also names the key), so a
|
|
@@ -718,8 +735,8 @@ class ToolExecution {
|
|
|
718
735
|
return out;
|
|
719
736
|
}
|
|
720
737
|
if (c.state === "approval") {
|
|
721
|
-
// W2: the
|
|
722
|
-
const out = gutterCut(`${p.bold}
|
|
738
|
+
// W2: the ❯ is the GUTTER (the left edge), never the line's tail
|
|
739
|
+
const out = gutterCut(`${p.bold}❯${p.reset} `, `${verbCol} ${liveTarget(c)}`, W);
|
|
723
740
|
out.push(...toolBlockBody(c, W));
|
|
724
741
|
return out;
|
|
725
742
|
}
|
|
@@ -760,7 +777,7 @@ class ToolExecution {
|
|
|
760
777
|
* The affordance is a statement about hidden content: a cell whose body
|
|
761
778
|
* is already whole on screen must not advertise a key that would show it
|
|
762
779
|
* the same thing, and a cell that already carries its own renderer cut
|
|
763
|
-
* (`└ +N earlier rows · ctrl+
|
|
780
|
+
* (`└ +N earlier rows · ctrl+o`, `└ +N more · ctrl+o`) already teaches
|
|
764
781
|
* the key at the place the content stops. What is LEFT — and it is the
|
|
765
782
|
* common case — is every settled non-shell call, whose collapsed body is
|
|
766
783
|
* empty: the whole result sits behind the key with nothing on screen
|
|
@@ -799,12 +816,12 @@ function hiddenLines(c, W) {
|
|
|
799
816
|
* against the room the row actually has).
|
|
800
817
|
*/
|
|
801
818
|
/** TUI2-R1.5 ⑤ — the cells a settled head row reserves for its
|
|
802
|
-
* affordance: exactly the shortest tier, " · ctrl+
|
|
819
|
+
* affordance: exactly the shortest tier, " · ctrl+o". The suffix used
|
|
803
820
|
* to take whatever width happened to be left, so a long target spent it
|
|
804
821
|
* all and the card said nothing about the lines behind the key. Every
|
|
805
822
|
* row that fitted its head before still fits it; only a head that would
|
|
806
823
|
* have eaten the whole row gives up its last nine cells. */
|
|
807
|
-
const SUFFIX_MIN = " · ctrl+
|
|
824
|
+
const SUFFIX_MIN = " · ctrl+o".length;
|
|
808
825
|
/**
|
|
809
826
|
* TUI2-R1.5 pin 4 — the settled head row's text, with a PINNED cut
|
|
810
827
|
* order.
|
|
@@ -814,8 +831,8 @@ const SUFFIX_MIN = " · ctrl+r".length;
|
|
|
814
831
|
* came last, so the parens were what got cut. The walkthrough caught
|
|
815
832
|
* both consequences —
|
|
816
833
|
*
|
|
817
|
-
* ✓ shell printf '…' 1 2 … 12 (exit 0 · approv… · ctrl+
|
|
818
|
-
* ✓ shell for i in 1 2 3 … … · ctrl+
|
|
834
|
+
* ✓ shell printf '…' 1 2 … 12 (exit 0 · approv… · ctrl+o
|
|
835
|
+
* ✓ shell for i in 1 2 3 … … · ctrl+o
|
|
819
836
|
*
|
|
820
837
|
* — an UNCLOSED parenthesis, and a row that lost the exit code and the
|
|
821
838
|
* duration to a command string that had no claim on them. A cut that
|
|
@@ -880,7 +897,7 @@ export function expandSuffix(lines, room) {
|
|
|
880
897
|
if (lines === null)
|
|
881
898
|
return "";
|
|
882
899
|
const count = `${lines} line${lines === 1 ? "" : "s"}`;
|
|
883
|
-
for (const tier of [` · ${count} · ctrl+
|
|
900
|
+
for (const tier of [` · ${count} · ctrl+o expands`, ` · ${count} · ctrl+o`, " · ctrl+o"]) {
|
|
884
901
|
if (tier.length <= room)
|
|
885
902
|
return tier;
|
|
886
903
|
}
|
|
@@ -897,7 +914,7 @@ function appendSuffix(row, suffix) {
|
|
|
897
914
|
/**
|
|
898
915
|
* TUI2-R2 ⑤ (D, candidate 1) — the FOCUS tint.
|
|
899
916
|
*
|
|
900
|
-
* The cell the next ctrl+
|
|
917
|
+
* The cell the next ctrl+o will act on brightens its own `ctrl+o` token
|
|
901
918
|
* to the code tint; the rest of the suffix — the separator, the count —
|
|
902
919
|
* stays dim, because what is being marked is the KEY's target, not the
|
|
903
920
|
* row. Zero new rows, zero new columns: the affordance the cell already
|
|
@@ -905,7 +922,7 @@ function appendSuffix(row, suffix) {
|
|
|
905
922
|
*
|
|
906
923
|
* Applied to a row rather than composed into it on purpose. The token is
|
|
907
924
|
* emitted from several places (the settled suffix, the renderer's own
|
|
908
|
-
* `└ +N … · ctrl+
|
|
925
|
+
* `└ +N … · ctrl+o` cut rows) and threading a flag through all of them
|
|
909
926
|
* would put the invariant "exactly one bright token" in as many hands as
|
|
910
927
|
* there are emitters. Here it has exactly one.
|
|
911
928
|
*
|
|
@@ -913,7 +930,7 @@ function appendSuffix(row, suffix) {
|
|
|
913
930
|
*/
|
|
914
931
|
export function focusToken(row, W) {
|
|
915
932
|
const p = palette();
|
|
916
|
-
const at = row.lastIndexOf(
|
|
933
|
+
const at = row.lastIndexOf(EXPAND_KEY);
|
|
917
934
|
if (at !== -1) {
|
|
918
935
|
// the row already names the key — brighten the token in place, and
|
|
919
936
|
// leave every other span exactly as it was
|
|
@@ -927,10 +944,10 @@ export function focusToken(row, W) {
|
|
|
927
944
|
// attribute like bold is spent everywhere. It closes with washEnd
|
|
928
945
|
// rather than a reset, so the surrounding dim survives instead of
|
|
929
946
|
// having to be re-applied.
|
|
930
|
-
return `${row.slice(0, at)}${p.lift}${
|
|
947
|
+
return `${row.slice(0, at)}${p.lift}${EXPAND_KEY}${p.dim}${row.slice(at + EXPAND_KEY.length)}`;
|
|
931
948
|
}
|
|
932
949
|
// A LIVE row does not carry the affordance today, and the live cell is
|
|
933
|
-
// the one ctrl+
|
|
950
|
+
// the one ctrl+o takes FIRST (expandNext scans the live tail before
|
|
934
951
|
// the committed ring) — so the row the key is aimed at was the one row
|
|
935
952
|
// that never said the key existed. The affordance IS the marker here:
|
|
936
953
|
// it appears on the focused row and nowhere else, which is why no
|
|
@@ -939,13 +956,15 @@ export function focusToken(row, W) {
|
|
|
939
956
|
const room = W - visibleWidth(row);
|
|
940
957
|
if (room < SUFFIX_MIN)
|
|
941
958
|
return row; // never at the cost of invariant ①
|
|
942
|
-
return `${row}${p.dim} · ${p.lift}${
|
|
959
|
+
return `${row}${p.dim} · ${p.lift}${EXPAND_KEY}${p.reset}`;
|
|
943
960
|
}
|
|
944
|
-
|
|
961
|
+
/** DC-41 — the label in ONE place. The key has moved once now, and
|
|
962
|
+
* a constant named after its binding is a comment that lies. */
|
|
963
|
+
const EXPAND_KEY = "ctrl+o";
|
|
945
964
|
/** TUI2-R1 (A) — the expanded block's last row: the way back. The
|
|
946
965
|
* rollup's expanded list carries a second clause (its members' full
|
|
947
966
|
* outputs live in /last, which the group row cannot show). */
|
|
948
|
-
const COLLAPSE_ROW = "ctrl+
|
|
967
|
+
const COLLAPSE_ROW = "ctrl+o collapses";
|
|
949
968
|
/** W13 — the rollup opt-in table: which tools collapse, and the count
|
|
950
969
|
* NOUN (read_file calls → "5 files", list_dir → "5 dirs", search_text
|
|
951
970
|
* → "5 matches"). Only these tools opt in — a shell burst is never
|
|
@@ -1049,7 +1068,7 @@ function countTerm(n, singular, plural) {
|
|
|
1049
1068
|
* DECLARED SUPERSESSION (R3g, 2026-08-28) — A9 also ruled that "the
|
|
1050
1069
|
* metadata terms give way LAST". They do not any more: the KEY does.
|
|
1051
1070
|
* A9 was taken when this line carried no key, and at a width where the
|
|
1052
|
-
* chip, the full metadata and " · ctrl+
|
|
1071
|
+
* chip, the full metadata and " · ctrl+o" cannot coexist, a fold with
|
|
1053
1072
|
* no key is the turn's work behind a line with no way back to it. So
|
|
1054
1073
|
* the order is now words, then metadata, then — never — the key. The
|
|
1055
1074
|
* glyph is ✦ and the zero terms are dropped (R3b), so the example above
|
|
@@ -1153,7 +1172,7 @@ export function foldTerms(reads, edits, others) {
|
|
|
1153
1172
|
*
|
|
1154
1173
|
* thinking ✧ thinking 4s
|
|
1155
1174
|
* acting ✶ reading 6 files · running 4 shell commands
|
|
1156
|
-
* settled ✦ thought 9s · read 6 files · ran 4 shell commands · ctrl+
|
|
1175
|
+
* settled ✦ thought 9s · read 6 files · ran 4 shell commands · ctrl+o
|
|
1157
1176
|
*
|
|
1158
1177
|
* THE GIVE-WAY LADDER, in order, because at some width everything
|
|
1159
1178
|
* cannot fit:
|
|
@@ -1283,7 +1302,7 @@ function troubleClause(t) {
|
|
|
1283
1302
|
/**
|
|
1284
1303
|
* R4 (C1) — the fold NAMES ITS OWN TARGET.
|
|
1285
1304
|
*
|
|
1286
|
-
* `ctrl+
|
|
1305
|
+
* `ctrl+o` used to be printed identically on every fold on the screen,
|
|
1287
1306
|
* and the key walked a ring whose order nothing on screen expressed —
|
|
1288
1307
|
* so the owner's report was exact: "there is no way to know which
|
|
1289
1308
|
* stretch it opens". The tint that marks the next target can only be
|
|
@@ -1340,7 +1359,7 @@ export function stretchLine(t, W) {
|
|
|
1340
1359
|
const mark = t.mark ?? " ";
|
|
1341
1360
|
// R4a (owner ruling, 2026-08-30) — the fold row prints NO key.
|
|
1342
1361
|
//
|
|
1343
|
-
// R4 printed `· ctrl+
|
|
1362
|
+
// R4 printed `· ctrl+o 3` so the row could name its own target. The
|
|
1344
1363
|
// owner's objection is the right one: a number you cannot type is not
|
|
1345
1364
|
// a selector, it is decoration that costs a column — and the
|
|
1346
1365
|
// reference implementation, checked rather than assumed, prints
|
|
@@ -1349,7 +1368,7 @@ export function stretchLine(t, W) {
|
|
|
1349
1368
|
// scrolled away; the row itself stays clean.
|
|
1350
1369
|
//
|
|
1351
1370
|
// So the affordance is retired here and owed to that mode. Until it
|
|
1352
|
-
// exists, `ctrl+
|
|
1371
|
+
// exists, `ctrl+o` still opens the most recent fold — it is simply no
|
|
1353
1372
|
// longer advertised on a row that cannot say which one it means.
|
|
1354
1373
|
const key = "";
|
|
1355
1374
|
const lead = t.phase === "thinking" ? [`thinking ${t.thoughtSeconds}s`] : t.phase === "settled" && t.thoughtSeconds > 0 ? [`thought ${t.thoughtSeconds}s`] : [];
|
|
@@ -1441,7 +1460,7 @@ export function turnFold(t, W) {
|
|
|
1441
1460
|
out = out.replaceAll(long, short);
|
|
1442
1461
|
return out;
|
|
1443
1462
|
};
|
|
1444
|
-
const KEY = " · ctrl+
|
|
1463
|
+
const KEY = " · ctrl+o";
|
|
1445
1464
|
const keyW = KEY.length;
|
|
1446
1465
|
const key = `${p.dim}${KEY}${p.reset}`;
|
|
1447
1466
|
if (words === "") {
|
|
@@ -1585,11 +1604,11 @@ function toolBlockBody(c, W) {
|
|
|
1585
1604
|
? delegateSettled(c, W)
|
|
1586
1605
|
: // TUI2-R1.5 ④(c) (VD-5): a settled shell collapses like
|
|
1587
1606
|
// every other settled call. It used to keep its last
|
|
1588
|
-
// rows plus a "+N earlier rows · ctrl+
|
|
1607
|
+
// rows plus a "+N earlier rows · ctrl+o" cut FOREVER —
|
|
1589
1608
|
// six rows per call, so three shells owned a screen. The
|
|
1590
1609
|
// approved R1 prototype's state 2 is one line; the head
|
|
1591
1610
|
// row's own suffix already names the count and the key,
|
|
1592
|
-
// and ctrl+
|
|
1611
|
+
// and ctrl+o shows the whole block, not a five-row window
|
|
1593
1612
|
// of it.
|
|
1594
1613
|
[]
|
|
1595
1614
|
: c.state === "running"
|
|
@@ -1639,7 +1658,7 @@ function shellTail(text, W) {
|
|
|
1639
1658
|
if (rows.length <= CAP_SHELL_SETTLED)
|
|
1640
1659
|
return rows;
|
|
1641
1660
|
const kept = CAP_SHELL_SETTLED - 1;
|
|
1642
|
-
const cut = foldLine(`${p.dim}${NOTE_ROW}+${rows.length - kept} earlier rows · ctrl+
|
|
1661
|
+
const cut = foldLine(`${p.dim}${NOTE_ROW}+${rows.length - kept} earlier rows · ctrl+o${p.reset}`, W);
|
|
1643
1662
|
return [...rows.slice(rows.length - kept), ...cut];
|
|
1644
1663
|
}
|
|
1645
1664
|
/** The error text head: the FIRST rows, capped at 3 — the answer is at
|
|
@@ -1659,7 +1678,7 @@ function errorBody(c, W) {
|
|
|
1659
1678
|
const rows = blockRows(c.resultText.split("\n").slice(skipFirst).join("\n"), W);
|
|
1660
1679
|
if (rows.length <= CAP_ERROR)
|
|
1661
1680
|
return rows;
|
|
1662
|
-
const cut = foldLine(`${p.dim}${NOTE_ROW}+${rows.length - (CAP_ERROR - 1)} more · ctrl+
|
|
1681
|
+
const cut = foldLine(`${p.dim}${NOTE_ROW}+${rows.length - (CAP_ERROR - 1)} more · ctrl+o${p.reset}`, W);
|
|
1663
1682
|
return [...rows.slice(0, CAP_ERROR - 1), ...cut];
|
|
1664
1683
|
}
|
|
1665
1684
|
/** The running tool's FIXED-height window (W8): exactly 3 rows from
|
|
@@ -1686,7 +1705,7 @@ function liveWindow(text, W) {
|
|
|
1686
1705
|
rows.push(""); // R7a: blank, not a bar
|
|
1687
1706
|
return rows;
|
|
1688
1707
|
}
|
|
1689
|
-
const cut = foldLine(`${p.dim}${NOTE_ROW}+${rows.length - (CAP_LIVE_WINDOW - 1)} earlier rows · ctrl+
|
|
1708
|
+
const cut = foldLine(`${p.dim}${NOTE_ROW}+${rows.length - (CAP_LIVE_WINDOW - 1)} earlier rows · ctrl+o${p.reset}`, W);
|
|
1690
1709
|
return [...rows.slice(rows.length - (CAP_LIVE_WINDOW - 1)), ...cut];
|
|
1691
1710
|
}
|
|
1692
1711
|
/**
|
|
@@ -1891,7 +1910,7 @@ export function diffBody(diff, W, expanded = false) {
|
|
|
1891
1910
|
// W17: the └ cut is ONE row at every width — the count leads, the
|
|
1892
1911
|
// expand affordances are cuttable (the same one-line shape as W12's
|
|
1893
1912
|
// delegate row and W18's status row).
|
|
1894
|
-
const cut = (n) => oneLineRow(p, `+${n} rows · ctrl+
|
|
1913
|
+
const cut = (n) => oneLineRow(p, `+${n} rows · ctrl+o to expand · /last for the full diff`, W);
|
|
1895
1914
|
// W17: the floor — the head window shows the lines whose fold starts
|
|
1896
1915
|
// before `head` rows; the tail window the lines whose fold ENDS after
|
|
1897
1916
|
// `rows.length - tail` (starts[i+1] is line i's end). When the pair
|
|
@@ -2062,9 +2081,9 @@ export function formatDuration(totalSeconds) {
|
|
|
2062
2081
|
* the compositor-derived counts (the model tail rides AFTER — never
|
|
2063
2082
|
* model-controlled), the active item first with ▸ (the menu's "the
|
|
2064
2083
|
* current one"), pending next (≤2), the done items COLLAPSED behind the
|
|
2065
|
-
* W10 cut family `└ +N done · ctrl+
|
|
2066
|
-
* `└ +N more · ctrl+
|
|
2067
|
-
* width. ctrl+
|
|
2084
|
+
* W10 cut family `└ +N done · ctrl+o`, overflow pending behind
|
|
2085
|
+
* `└ +N more · ctrl+o` — every row cut at W so the cap holds at every
|
|
2086
|
+
* width. ctrl+o (W15) toggles the full list in place (expanded). SETTLED
|
|
2068
2087
|
* (done:true): the recap idiom `task done · N items · <duration>` + the
|
|
2069
2088
|
* FULL final item list in the checklist's existing shape (▖/□/▣ —
|
|
2070
2089
|
* indented two, the glyph leads, no │ gutter).
|
|
@@ -2087,7 +2106,7 @@ class Checklist {
|
|
|
2087
2106
|
: `task · ${plural(items.length, "item")} · ${active.length} active · ${doneCount} done`;
|
|
2088
2107
|
const header = `${p.bold}✦${p.reset} ${escapeTerminal(fixed + tail)}`;
|
|
2089
2108
|
// the FULL-list forms: SETTLED — the durable record (the fold is
|
|
2090
|
-
// fine — committed content wraps naturally) — and the LIVE ctrl+
|
|
2109
|
+
// fine — committed content wraps naturally) — and the LIVE ctrl+o
|
|
2091
2110
|
// toggle (the header CUTS — the block stays one window high; the
|
|
2092
2111
|
// expanded rows show the ▣ the collapse hid). The live flag picks
|
|
2093
2112
|
// the glyphs: the settled list keeps the durable ▖, the expanded
|
|
@@ -2105,7 +2124,7 @@ class Checklist {
|
|
|
2105
2124
|
// LIVE — the fixed window: the header + the item rows CUT at W
|
|
2106
2125
|
// (one screen row each — the block's height is its row count,
|
|
2107
2126
|
// CAP_TASK_LIVE, at every width). The cut is the momentary view;
|
|
2108
|
-
// the settle (and the ctrl+
|
|
2127
|
+
// the settle (and the ctrl+o toggle) show everything.
|
|
2109
2128
|
const itemRows = [];
|
|
2110
2129
|
if (active.length > 0)
|
|
2111
2130
|
itemRows.push(` ${p.bold}▸${p.reset} ${escapeTerminal(active[0].text)}`);
|
|
@@ -2113,9 +2132,9 @@ class Checklist {
|
|
|
2113
2132
|
itemRows.push(` □ ${escapeTerminal(item.text)}`);
|
|
2114
2133
|
const more = pending.length - 2;
|
|
2115
2134
|
if (more > 0)
|
|
2116
|
-
itemRows.push(` ${p.dim}└ +${more} more · ctrl+
|
|
2135
|
+
itemRows.push(` ${p.dim}└ +${more} more · ctrl+o${p.reset}`);
|
|
2117
2136
|
if (doneCount > 0)
|
|
2118
|
-
itemRows.push(` ${p.dim}└ +${doneCount} done · ctrl+
|
|
2137
|
+
itemRows.push(` ${p.dim}└ +${doneCount} done · ctrl+o${p.reset}`);
|
|
2119
2138
|
return [cutLine(header, W), ...itemRows.map((r) => cutLine(r, W))];
|
|
2120
2139
|
}
|
|
2121
2140
|
}
|
|
@@ -2128,7 +2147,7 @@ class Checklist {
|
|
|
2128
2147
|
* W21: the question param is gone — the old question slot retires; a
|
|
2129
2148
|
* pending approval's status IS the panel's (the compositor derives
|
|
2130
2149
|
* it from the bound panel state). */
|
|
2131
|
-
/** R8b — THE IDLE HINT GIVES WAY IN ORDER, and `ctrl+
|
|
2150
|
+
/** R8b — THE IDLE HINT GIVES WAY IN ORDER, and `ctrl+r` is on it.
|
|
2132
2151
|
*
|
|
2133
2152
|
* The transcript viewer shipped in 0.19.0 and was reachable only from
|
|
2134
2153
|
* the `?` sheet: not on the banner's key line, not here. A feature
|
|
@@ -2139,17 +2158,17 @@ class Checklist {
|
|
|
2139
2158
|
* when it does not fit — a longer string would take `/ commands` down
|
|
2140
2159
|
* with it on a narrow terminal. So the forms are a ladder, and the
|
|
2141
2160
|
* order says which affordance is least replaceable: `/ commands`
|
|
2142
|
-
* survives longest because it is the door to everything; `ctrl+
|
|
2161
|
+
* survives longest because it is the door to everything; `ctrl+r`
|
|
2143
2162
|
* outranks `↑ history` because pressing up is how a person finds the
|
|
2144
|
-
* history by accident, and nothing finds ctrl+
|
|
2163
|
+
* history by accident, and nothing finds ctrl+r by accident. */
|
|
2145
2164
|
export function idleHint(room) {
|
|
2146
2165
|
// The third rung is today's hint, kept so that NO width loses
|
|
2147
2166
|
// something that used to fit: without it, a room of 24-30 columns
|
|
2148
2167
|
// fell all the way to `/ commands` even though the old form fitted.
|
|
2149
2168
|
// So the ladder is not a strict ranking of the three affordances —
|
|
2150
|
-
// it is the widest honest form at each room, and ctrl+
|
|
2169
|
+
// it is the widest honest form at each room, and ctrl+r is on the
|
|
2151
2170
|
// first two rungs rather than on all of them.
|
|
2152
|
-
for (const form of [" / commands · ↑ history · ctrl+
|
|
2171
|
+
for (const form of [" / commands · ↑ history · ctrl+r transcript", " / commands · ctrl+r transcript", " / commands · ↑ history", " / commands"]) {
|
|
2153
2172
|
if (visibleWidth(form) <= room)
|
|
2154
2173
|
return form;
|
|
2155
2174
|
}
|
package/dist/render.d.ts
CHANGED
|
@@ -79,7 +79,7 @@ export interface Palette {
|
|
|
79
79
|
readonly washEnd: string;
|
|
80
80
|
/** R7a — THE FOCUS MARKER'S EMPHASIS, and it is not a background.
|
|
81
81
|
*
|
|
82
|
-
* DC-3 gave the `ctrl+
|
|
82
|
+
* DC-3 gave the `ctrl+o` token the wash, which is a BACKGROUND once
|
|
83
83
|
* a ground is resolved: `48;5;236` on dark reads as a black block
|
|
84
84
|
* behind the key, on a row that is otherwise plain text. The owner
|
|
85
85
|
* asked for it gone. The invariant DC-3 was serving — exactly one
|
|
@@ -94,6 +94,31 @@ export interface Palette {
|
|
|
94
94
|
* is the emphasis. It closes by re-opening the palette's own dim,
|
|
95
95
|
* like `washEnd`, so the surrounding span survives. */
|
|
96
96
|
readonly lift: string;
|
|
97
|
+
/** R9 P3 — THE ONE GREY ALLOWED ON THE WASH.
|
|
98
|
+
*
|
|
99
|
+
* §2.1 bars `dim` from the wash and the measurement is why: `#767676`
|
|
100
|
+
* on `#EEEEEE` is 3.91:1, under the 4.5:1 floor. A washed surface
|
|
101
|
+
* carrying metadata rows — a slab's `… N earlier lines`, its outcome
|
|
102
|
+
* line — still wants them quieter than the output they annotate, so
|
|
103
|
+
* the palette gains a grey chosen FOR the wash rather than against
|
|
104
|
+
* the ground:
|
|
105
|
+
*
|
|
106
|
+
* light 241 `#626262` 5.26:1 on the wash, 6.10:1 on the ground
|
|
107
|
+
* dark 247 `#9E9E9E` 4.93:1 on the wash, 6.22:1 on the ground
|
|
108
|
+
*
|
|
109
|
+
* §2.1 is untouched — `dim` still may not sit on the wash. This is a
|
|
110
|
+
* different token with a different job, the way `warn` was the mono
|
|
111
|
+
* ruling's own set gaining its missing member.
|
|
112
|
+
*
|
|
113
|
+
* With NO ground it is NOTHING: §3.1 forbids an absolute foreground
|
|
114
|
+
* in a palette that has not established a background, and rung 4's
|
|
115
|
+
* wash is reverse video, where any foreground grey inverts into a
|
|
116
|
+
* grey block. Body text on the surface is the correct degradation.
|
|
117
|
+
* It closes with 39 (the default foreground) rather than SGR 0, for
|
|
118
|
+
* the reason `washEnd` closes with 49: the wash underneath it must
|
|
119
|
+
* survive the close. */
|
|
120
|
+
readonly washDim: string;
|
|
121
|
+
readonly washDimEnd: string;
|
|
97
122
|
readonly reset: string;
|
|
98
123
|
}
|
|
99
124
|
/**
|
package/dist/render.js
CHANGED
|
@@ -28,7 +28,20 @@ const BASE = { bold: "\x1b[1m", dim: "\x1b[2m", red: "\x1b[31m", green: "\x1b[32
|
|
|
28
28
|
* 4's principle exactly: when the ground is unknown, use the thing that
|
|
29
29
|
* is correct on any ground rather than guessing one.
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
/** `washDimEnd` is DERIVED, never passed: a grey that cannot be closed
|
|
32
|
+
* without taking the wash with it is not a usable token, and deriving
|
|
33
|
+
* the close makes the pair impossible to mis-wire at a call site. */
|
|
34
|
+
const withWash = (wash, washEnd, red = BASE.red, dim = BASE.dim, washDim = "") => ({
|
|
35
|
+
...BASE,
|
|
36
|
+
red,
|
|
37
|
+
dim,
|
|
38
|
+
wash,
|
|
39
|
+
washEnd,
|
|
40
|
+
washDim,
|
|
41
|
+
washDimEnd: washDim === "" ? "" : "\x1b[39m",
|
|
42
|
+
code: wash,
|
|
43
|
+
lift: "\x1b[22m\x1b[39m\x1b[1m",
|
|
44
|
+
});
|
|
32
45
|
/**
|
|
33
46
|
* DC-3 — one table per ground.
|
|
34
47
|
*
|
|
@@ -50,13 +63,13 @@ const withWash = (wash, washEnd, red = BASE.red, dim = BASE.dim) => ({ ...BASE,
|
|
|
50
63
|
* attribute is exactly the "correct on any ground" degradation there.
|
|
51
64
|
*/
|
|
52
65
|
export const COLOR_NEUTRAL = withWash("\x1b[7m", "\x1b[27m");
|
|
53
|
-
export const COLOR_LIGHT = withWash("\x1b[48;5;255m", "\x1b[49m", "\x1b[38;5;124m", "\x1b[38;5;243m");
|
|
54
|
-
export const COLOR_DARK = withWash("\x1b[48;5;236m", "\x1b[49m", "\x1b[38;5;173m", "\x1b[38;5;246m");
|
|
66
|
+
export const COLOR_LIGHT = withWash("\x1b[48;5;255m", "\x1b[49m", "\x1b[38;5;124m", "\x1b[38;5;243m", "\x1b[38;5;241m");
|
|
67
|
+
export const COLOR_DARK = withWash("\x1b[48;5;236m", "\x1b[49m", "\x1b[38;5;173m", "\x1b[38;5;246m", "\x1b[38;5;247m");
|
|
55
68
|
/** The historical name — the palette for a colour TTY whose ground has
|
|
56
69
|
* not been established. Unchanged in every byte except `code`, which
|
|
57
70
|
* was the defect. */
|
|
58
71
|
export const COLOR_ON = COLOR_NEUTRAL;
|
|
59
|
-
export const COLOR_OFF = { bold: "", dim: "", red: "", green: "", warn: "", code: "", italic: "", italicEnd: "", underline: "", underlineEnd: "", rv: "", rvEnd: "", wash: "", washEnd: "", lift: "", reset: "" };
|
|
72
|
+
export const COLOR_OFF = { bold: "", dim: "", red: "", green: "", warn: "", code: "", italic: "", italicEnd: "", underline: "", underlineEnd: "", rv: "", rvEnd: "", wash: "", washEnd: "", washDim: "", washDimEnd: "", lift: "", reset: "" };
|
|
60
73
|
/** DC-3 — the resolved ground, set once at startup when the terminal
|
|
61
74
|
* answers (see `ground.ts`). It starts UNKNOWN and may stay that way
|
|
62
75
|
* forever; that is a supported state, not a failure. */
|
|
@@ -414,7 +427,7 @@ export function bannerLines(W, H, version, extensionsText, resume = [], now = Da
|
|
|
414
427
|
if (meta !== undefined && W >= 40) {
|
|
415
428
|
// R2/DC-2's device: the keys row is a list of independent clauses,
|
|
416
429
|
// so a narrow terminal drops whole clauses from the end rather than
|
|
417
|
-
// cutting one in half. `ctrl+
|
|
430
|
+
// cutting one in half. `ctrl+o ex (+8)` teaches nothing.
|
|
418
431
|
const clauses = BANNER_KEYS.split(" \u00b7 ");
|
|
419
432
|
let keys = clauses[0];
|
|
420
433
|
for (let n = clauses.length; n > 1; n -= 1) {
|
package/dist/strings.js
CHANGED
|
@@ -51,7 +51,7 @@ export function projectTrustView(root, files) {
|
|
|
51
51
|
name: "project trust",
|
|
52
52
|
title: root,
|
|
53
53
|
speaker: "kiso",
|
|
54
|
-
statusText: "
|
|
54
|
+
statusText: "❯ project trust",
|
|
55
55
|
args: { kind: "text", lines: projectTrustRows(files) },
|
|
56
56
|
ruleOverride: "trust this project's .kiso?",
|
|
57
57
|
fallbackQuestion: `trust this project's .kiso? (y/n) `,
|
|
@@ -109,7 +109,7 @@ export function uncertainView(name, executionId) {
|
|
|
109
109
|
name: "uncertain execution",
|
|
110
110
|
title: `${name} (${executionId})`,
|
|
111
111
|
speaker: "kiso",
|
|
112
|
-
statusText: "
|
|
112
|
+
statusText: "❯ uncertain execution",
|
|
113
113
|
args: { kind: "text", lines: [executionId] },
|
|
114
114
|
ruleOverride: "an interrupted execution may have applied — rerun it?",
|
|
115
115
|
simpleOptions: ["rerun it", "abandon it"],
|
|
@@ -136,7 +136,7 @@ export function unansweredAskView(executionId) {
|
|
|
136
136
|
name: "unanswered question",
|
|
137
137
|
title: `ask_user (${executionId})`,
|
|
138
138
|
speaker: "kiso",
|
|
139
|
-
statusText: "
|
|
139
|
+
statusText: "❯ unanswered question",
|
|
140
140
|
args: { kind: "text", lines: [executionId] },
|
|
141
141
|
ruleOverride: "an unanswered question was interrupted — ask it again?",
|
|
142
142
|
simpleOptions: ["ask it again", "drop it"],
|
|
@@ -188,12 +188,12 @@ export const KEY_BINDINGS = [
|
|
|
188
188
|
{ keys: "alt+⏎ / ctrl+⏎", what: "redirect" },
|
|
189
189
|
{ keys: "/", what: "commands" },
|
|
190
190
|
{ keys: "↑↓", what: "history / queue pop" },
|
|
191
|
-
{ keys: "ctrl+
|
|
191
|
+
{ keys: "ctrl+o", what: "expand cells" },
|
|
192
192
|
// R5 — the transcript viewer. It has to be HERE or it does not exist:
|
|
193
193
|
// R4a retired the printed key from the fold row on the ground that a
|
|
194
194
|
// row cannot say which fold a key opens, and the sheet is where the
|
|
195
195
|
// discoverability moved. A surface nobody can find is not a feature.
|
|
196
|
-
{ keys: "ctrl+
|
|
196
|
+
{ keys: "ctrl+r", what: "transcript" },
|
|
197
197
|
{ keys: "tab", what: "complete (menu / @)" },
|
|
198
198
|
{ keys: "?", what: "this sheet" },
|
|
199
199
|
{ keys: "ctrl+z / ctrl+y", what: "undo / redo" },
|
|
@@ -271,7 +271,7 @@ const SHEET_GRID = [
|
|
|
271
271
|
[0, 1, 2],
|
|
272
272
|
[3, 4, 5],
|
|
273
273
|
[6, 7],
|
|
274
|
-
// R5: ctrl+
|
|
274
|
+
// R5: ctrl+r joins at index 8, so the tail shifts by one. The grid is
|
|
275
275
|
// a SECOND table that must agree with KEY_BINDINGS and nothing makes
|
|
276
276
|
// it — adding a binding without touching this silently drops the LAST
|
|
277
277
|
// one off the sheet, which is exactly what happened on the first
|
package/dist/width.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* #16e: "charWidth is the width authority"). The table covers the East
|
|
4
4
|
* Asian Wide/Fullwidth ranges and Emoji_Presentation=Yes; everything
|
|
5
5
|
* else is one column, the box-drawing/brick glyphs █▀▄▞▸ and the text-
|
|
6
|
-
* presentation marks ✓ ✗ ⚠
|
|
6
|
+
* presentation marks ✓ ✗ ⚠ ❯ included.
|
|
7
7
|
*
|
|
8
8
|
* This is the compositor's FLOOR, not a cosmetic detail: a glyph scored
|
|
9
9
|
* one column that a terminal draws in two makes a line whose measured
|
package/dist/width.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* #16e: "charWidth is the width authority"). The table covers the East
|
|
4
4
|
* Asian Wide/Fullwidth ranges and Emoji_Presentation=Yes; everything
|
|
5
5
|
* else is one column, the box-drawing/brick glyphs █▀▄▞▸ and the text-
|
|
6
|
-
* presentation marks ✓ ✗ ⚠
|
|
6
|
+
* presentation marks ✓ ✗ ⚠ ❯ included.
|
|
7
7
|
*
|
|
8
8
|
* This is the compositor's FLOOR, not a cosmetic detail: a glyph scored
|
|
9
9
|
* one column that a terminal draws in two makes a line whose measured
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
/** TUI2-R2pre ① — the Emoji_Presentation=Yes code points inside
|
|
21
21
|
* U+2000..U+2BFF. The rest of that span is TEXT presentation and stays
|
|
22
|
-
* one column: ✓ ✗ ⚠
|
|
22
|
+
* one column: ✓ ✗ ⚠ ❯ ▞ ▸ and the box-drawing rails are all narrow, and
|
|
23
23
|
* widening any of them would move every card head on the screen. Listed
|
|
24
24
|
* as ranges because that is what the property is — the singles are
|
|
25
25
|
* singles in Unicode too. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-tui-cells",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "kiso tui-cells — the components cell renderer (components, diff, width, the render slice). Zero runtime dependencies: input is data, output is bytes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|