Group snippets into sections in the ^B panel - #40
Merged
Merged
Conversation
Closes #38. A config long enough to be worth having is long enough to be hard to read. Twenty-seven snippets across four schemas were being told apart by their names alone — "Divider (rule)", "Plate - own page", "Part (division)" — which is the naming convention doing a grouping job badly, and it does not scale. A `<snippet>` may now sit inside a `<section name="...">`. The panel heads each group and indents what is under it; blocks stay in file order, because sections group rather than sort and ordering the file is how the panel is ordered. A heading is a label, not a choice. The selection steps over it in whichever direction it was travelling, so ^B-arrow-Enter still lands on something insertable, OK can never commit a row that inserts nothing, and typing a letter to jump works as before. Headings are drawn in vim's Title colour (orange — the one accent the tree does not already spend on a node kind), so a row at column 0 cannot be misread as an unindented snippet. Nothing changes for a config without sections: same rows, no indent, no headings. Getting a section wrong never costs the snippets inside it — an unnamed one leaves them ungrouped, a nested one folds them into its parent, both reported alongside the other skips. Three things found on the way, each fixed rather than worked around: * The panel has been under-sizing itself. It reserved 6 rows for chrome and spends 10, so a short config got a two-row list inside a twelve-row dialog. Long configs hid it — they clamp to the screen and scroll — and sections make short ones the case that matters, since every heading is another row to fit. §14b pins the number now. * Terminal.Gui 2.4.17's `ValueChanging` exposes a writable `NewValue` that reads exactly like a redirect hook and is ignored by ListView; its `Handled` cancels but only pins the selection where it is. Re-setting from `ValueChanged` behind a re-entrancy guard is what actually moves it. Verified through MoveDown, not assumed — the drill caught the first version sitting on the heading. * Type-ahead compares against the row as drawn, so the indent would have stopped every sectioned snippet answering to its own first letter. That jump is undocumented, which is why it was worth confirming it worked before breaking it; SnippetMatcher keeps it. A drill probe that throws now fails the run instead of wedging it: the exception used to escape the timeout callback, the Esc never fired, and the modal sat there until the harness deadline. Cost a mutation sweep to learn. §14b gains 22 checks. Ten mutations, each killing its own check and no others. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0146fhu1MJdAWimomPpjX6WY
| { | ||
| probed = true; | ||
| try { probe(); } | ||
| catch (Exception ex) { _lastDialogDiag += " PROBE THREW: " + ex.Message; } |
| { | ||
| probed = true; | ||
| try { probe(); } | ||
| catch (Exception ex) { _lastDialogDiag += " PROBE THREW: " + ex.Message; } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #38.
Why
Twenty-seven snippets across four schemas were being told apart by their names alone —
Divider (rule),Plate - own page,Part (division),Appendix (division)— which isthe naming convention doing a grouping job badly. The config already grouped them, in
banner comments (
BLOCKS.,ILLUSTRATIONS.,DIVISIONS.,BACK MATTER and FRAMING.)that the panel could not see.
What
A
<snippet>may now sit inside a<section name="…">:orders the panel.
direction it was travelling, so
^B-arrow-Enterstill lands on something insertableand OK can never commit a row that inserts nothing. One hook rather than arrow-key
bindings, so arrows, Home/End, PageUp/PageDown, the mouse and type-ahead are all covered
— and so the drill can exercise it, since injected keys reach app-scope bindings only.
Title→ orange, the one accent the tree does notalready spend on a node kind), so a row at column 0 cannot be misread as an unindented
snippet.
invisible to a config that has not asked for it, the way an absent config draws no group.
nested folds them into the parent, both reported alongside the other skips — the rule the
rest of the loader already follows.
Three things found on the way
The panel has been under-sizing itself. It reserved 6 rows for chrome and spends 10, so
a short config got a two-row list inside a twelve-row dialog. Long configs hid it — they
clamp to the screen and scroll — and sections make short ones the case that matters, since
every heading is another row to fit. The number is pinned in §14b now, so a framework change
to the chrome fails there rather than silently shrinking the list again.
ValueChanging.NewValueis a trap in Terminal.Gui 2.4.17. It is writable and readsexactly like a redirect hook; ListView ignores it. (
Handleddoes cancel, but that onlypins the selection where it is, so Down onto a heading would do nothing.) Re-setting from
ValueChangedbehind a re-entrancy guard is what actually moves it. The first version saton the heading and the drill caught it — verified through
MoveDown, not assumed.Type-ahead would have broken silently. Typing a letter jumps to the next entry starting
with it; the stock matcher compares against the row as drawn, so every sectioned snippet
would have stopped answering to its own first letter. That jump is documented nowhere,
which is exactly why it was worth confirming it worked before changing the rows —
measured first (typing
lreaches the off-screenLetter (division)), then preserved withSnippetMatcher.Verification
off the draw buffer, the panel height, and the matcher both as a function and as actually
attached to the live list.
after surviving a first pass.
to escape the timeout callback, the
Escnever fired, and the modal sat there until theharness deadline. Cost a mutation sweep to find. The probe also derives its row indices
from the rows rather than hard-coding them, so a build with the headings mutated away
goes red instead of indexing off the end.
Not in this change
Splitting
Blocksfurther — Text / Verse / Dividers — would help more than the foursections the banner comments already imply, but that is a judgement about the vocabulary
rather than about fux, so the conversion stays faithful to what the file already says.
🤖 Generated with Claude Code
https://claude.ai/code/session_0146fhu1MJdAWimomPpjX6WY