Skip to content

Commit 4576439

Browse files
committed
docs(nook): mark completion type-to-filter shipped, correct the visual-loop note
The 'Depth passes' candidate still listed type-to-filter as open and repeated 'wants a visual loop, not a blind hour' — both stale since it landed in a128fa0. Move it to an Unreleased ledger entry, retarget the next completion slice to matched-character highlighting (which genuinely wants a visual loop, for the lipgloss nested-background-bleed reason now documented), and add a harness note recording that host-view slices are verifiable headless via newModel + Update + View.
1 parent a128fa0 commit 4576439

1 file changed

Lines changed: 43 additions & 6 deletions

File tree

docs/nook/roadmap.md

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,19 @@ Grouped by arc. One line per capability; the tag is where it landed.
7272
switcher, settings overlay, LSP-ordered completions) and the
7373
`multi-select` component completing the form-input family.
7474

75+
### Unreleased (on main, not yet tagged)
76+
77+
- Completion type-to-filter (`a128fa0`): typing an identifier rune while
78+
the completion popup is open now narrows the visible list live against
79+
the trailing word prefix (case-insensitive subsequence, so "wg" keeps
80+
"WaitGroup") instead of dismissing the popup. Backspace widens back
81+
without a fresh server round-trip; deleting the whole prefix or typing a
82+
non-identifier rune dismisses and falls through to the buffer. This is
83+
the Zed/VSCode contract. `complete.Popup` retains the full sorted server
84+
set (`all`) so `Narrow` can widen without re-querying; the host arms a
85+
`completeNarrowPending` flag on the keystroke, lets the rune reach the
86+
buffer, then recomputes `WordPrefix` from the live line and narrows.
87+
7588
## Standing constraints (do not regress)
7689

7790
These are operator-stated DNA. They override convenience.
@@ -91,6 +104,23 @@ These are operator-stated DNA. They override convenience.
91104
components in v0.48.0 had to backfill entries into the release commit
92105
because they didn't; toggle did it right.
93106

107+
## Harness note: host-view slices are testable headless
108+
109+
A recurring miscall in this file was tagging keystroke-routing plus
110+
live-render work as "wants a visual loop, not a blind hour." The
111+
completion type-to-filter slice disproved the blanket version of that:
112+
the host model is fully drivable in a unit test. `newModel(dir)` (or
113+
`fixtureRepo(t)` + `newModel(root)`), set `width`/`height`, `m.resize()`,
114+
`openBufferForTest(t, m, "a.go")`, then feed `m.Update(tea.KeyMsg{...})`
115+
and assert on `m.View()` — the full rendered frame — or on sub-pane
116+
state. The narrow tests check exactly this: type 'i', assert the popup
117+
survives and the frame drops the filtered-out item. So a live-render
118+
change is a blind hour only when the thing being rendered is invisible to
119+
`stripANSI` assertions — the matched-highlight ANSI-bleed case above, or
120+
anything whose correctness is a color/background composition. Structural
121+
render changes (which rows appear, what text they carry) are verifiable
122+
headless; reach for the harness before deferring to a visual loop.
123+
94124
## Release ritual (reusable)
95125

96126
1. Release commit updating `CHANGELOG.md` (move `[Unreleased]` into the
@@ -132,12 +162,19 @@ shipped, so the remaining surface is narrower than it once was.
132162
- **Settings/themes surface** — config inheritance and theme hot-reload
133163
ship; a discoverable settings UI on top does not yet.
134164
- **Depth passes on shipped panes** — diagnostics presentation and
135-
multibuffer ergonomics are each self-contained slices. Completion has a
136-
concrete gap: the popup sorts by LSP SortText but has no type-to-filter
137-
— typing any rune while it is open dismisses it (main.go, the "any
138-
other key" branch) rather than narrowing the list live the way Zed and
139-
VSCode do. Closing that is a host keystroke-routing plus live-render
140-
change, so it wants a visual loop, not a blind hour.
165+
multibuffer ergonomics are each self-contained slices. Completion's
166+
type-to-filter gap is now closed (see Unreleased above). The next
167+
completion slice is **matched-character highlighting**: bold or accent
168+
the runes in each label that the current prefix matched, the way Zed
169+
underlines the fuzzy hits. That one genuinely wants a visual loop, and
170+
for a specific reason — the row already renders through a lipgloss style
171+
that sets a `Background` (`rowStyle` uses `Surface`, `selStyle` uses
172+
`Primary`). Embedding a per-rune inner style inside that line emits an
173+
ANSI reset mid-line that clears the outer background for the rest of the
174+
row, a bleed a `stripANSI`-based headless test cannot see. The correct
175+
build composes the highlight into the same style pass (or pre-segments
176+
the row so no inner reset lands before the background is re-applied) and
177+
eyeballs the rendered frame. Do not ship it blind.
141178

142179
Pick the smallest finishable slice that advances parity; one capability,
143180
its tests, its CHANGELOG line, one commit.

0 commit comments

Comments
 (0)