Skip to content

Commit 5bd990f

Browse files
author
gluck
committed
plans: status bar, round 5 -- every drawer has a row, help is one Esc away in the box, the ticker retires the alert
1 parent a15dcc4 commit 5bd990f

1 file changed

Lines changed: 44 additions & 20 deletions

File tree

‎plans/status-bar-and-modes.md‎

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -89,23 +89,40 @@ One table keyed by drawer id gives the glyph and the name.
8989
| search | `⌕` | search | — |
9090
| help | `?` | help | — |
9191
| status | `!` | status | — |
92+
| message | — | — | — |
93+
| output | — | — | `♭` |
94+
| live (hosted verb) | — | *(the verb's own)* | `♭` |
9295
| *(reserved)* | | input | |
9396

97+
**Every drawer needs a row, including the ones with nothing to show.** If
98+
`drawerID` is the source of `keys()`, then message, command output and a hosted
99+
live view are identities too — they just contribute **no token** to the bar
100+
(glyph `—` means the left group starts at the state) and take `modePanel`.
101+
Completion candidates are not a drawer: they are rows inside the command box,
102+
which is why they do not appear here.
103+
94104
**`⌕` (U+2315), not `🔍`.** The bar is width-sensitive and every other glyph
95105
here is single-width; the emoji magnifier is double-width and font-dependent,
96106
which would make the left group's width a property of the reader's terminal.
97107

98-
**Help is a mode, not a panel.** It sits at the same level as queue, command and
99-
notifications: its own row, its own glyph, and `?` SWITCHES TO IT from every
100-
mode except command, where `?` is text. That settles the "help always works"
101-
question — no `:help`, no Esc-then-`?`, just the key, everywhere it is not
102-
literal.
108+
**Help is a first-class drawer identity**, at the same level as queue, command
109+
and notifications: its own row, its own glyph, and `?` SWITCHES TO IT from every
110+
mode except command, where `?` is text. Its keyboard behaviour is still
111+
`modePanel` — being first-class is about identity, not about inventing a
112+
keyMode nothing needs.
113+
114+
**Two consequences, stated because they are real costs.**
115+
116+
`?` is text in the SEARCH box too, and this rule takes it: searching for a
117+
literal `?` has no route here. The alternative — exempting search as well —
118+
leaves help unreachable from the box where a reader is most likely to be lost,
119+
so the key wins and the literal loses.
103120

104-
**One consequence, stated because it is a real cost:** `?` is text in the SEARCH
105-
box too, and this rule takes it. Searching for a literal `?` then needs a route
106-
this plan does not give it. The alternative — exempting search as well as
107-
command — leaves help unreachable from the box where a reader is most likely to
108-
be lost, so the key wins and the literal loses.
121+
**In the command box, help is one `Esc` away**, and that is the answer to "help
122+
should always work" there. It is an exception with a route, not a hole: `?` must
123+
stay literal where a command is being typed (`:send -- what?`), and every other
124+
mode reaches help with one key. The hint row says so, which is why that row is
125+
not gated on verbose.
109126

110127
## 3. `turnState`: symbol, name, colour
111128

@@ -157,13 +174,20 @@ wire. Claiming "all warnings and errors" without a transport would be a lie.
157174
Nothing about it is tied to the drawer being read. A bar item that waits to be
158175
dismissed is a bar item that is still there tomorrow.
159176

160-
**This is the one piece with a liveness requirement.** Everything else in the
161-
pager repaints because something arrived — a key, a frame, a resize. An alert
162-
that expires on a clock has to repaint when *nothing happened*, so `statusView`
163-
gains an expiry and the render loop gains one scheduled wake at it. That is
164-
cheap (one timer, armed only while an alert is live, cancelled when it is
165-
displaced) but it must be deliberate: a TTL with no wake is an alert that
166-
disappears the next time you press a key, which reads as randomness.
177+
**This is the one piece with a liveness requirement**, and the mechanism is
178+
already in the building. Everything else in the pager repaints because something
179+
arrived — a key, a frame, a resize — so an alert that expires on a clock would
180+
otherwise vanish on the next keypress, which reads as randomness rather than as
181+
a timeout.
182+
183+
**Use the 11 Hz ticker, not a new timer.** `mustPromptFigaro` and `tailFigaro`
184+
already keep it alive and call `lt.tick()` under the render mutex even when
185+
nothing is animating; having `tick()` retire an expired alert gives expiry
186+
within ~90 ms with no second scheduler and no teardown path to get wrong.
187+
188+
**And keep the clock out of `render`.** Expiry is evaluated where the tick is,
189+
not inside `statusView.render(w)` — otherwise the pure renderer this section
190+
promised becomes a function of the wall clock and its goldens become flaky.
167191

168192
**Next steps, named:** a notify transport so daemon and agent records arrive
169193
(the aria socket already carries frames; this is one more method); level
@@ -212,9 +236,9 @@ Each step ships alone; none changes what the pager can do.
212236
example shows a bare rule and `✓ · 123abc · test`; one sketch line says the
213237
rule right-justifies the id. The examples win. Say the word and it flips
214238
back.
215-
2. **`𝄞` is both the notifications glyph and its selection cue.** The spec asks
216-
for a treble clef in both places and nothing says they must differ; an
217-
aesthetic objection is not an ambiguity.
239+
2. **`𝄞` is the notifications glyph; `♩` is its selection cue.** One symbol
240+
cannot do both jobs on one screen, and Gluck settled it on 2026-08-28.
241+
Selection glyphs are per-drawer: queue keeps `♭`.
218242
3. **`cost` and the clock leave the bar** (§1), to the `!` panel.
219243

220244
4. **Search is `⌕` and help is a mode** (§2). The doubled `∴` in the sketch was

0 commit comments

Comments
 (0)