Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 45 additions & 12 deletions authbridge/cmd/abctl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -755,24 +755,57 @@ abctl is for, and the other three are surfaces you visit and leave.

Layered on top of all of them:

- **Key help**: a modal overlay listing every keybinding, opened by `?`
from anywhere (picker included). The current pane's bindings come
first and are highlighted; the global keys and a one-line summary of
every other pane follow. While it's up it owns the keyboard — `?`,
`Esc`, or `q` closes it (`q` closes the overlay rather than quitting
abctl). This is the discoverable home for keys the single-line footer
has no room for, `P` among them. Two exceptions: while a pipeline edit
is in flight that overlay is already modal and owns `y`/`N`, and while
the filter input is focused `?` is a character you're typing (session
IDs and hosts can contain one). In both cases `?` is inert until the
keyboard is released.
- **Key help**: a modal overlay opened by `?` from anywhere (picker
included). It is a map of the panes as much as a key list, ordered by
what a lost reader asks first:

1. the current pane, highlighted — what it shows, then its own keys;
2. **GO TO ANOTHER PANE** — the keys that leave, each naming the pane
it opens and what is on it. Rendered per pane and only where the
key actually works: all four (`u`, `P`, `C`, `$`) from the session
views, `C` alone on Usage, and on the two pickers the heading kept

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion — the enumeration claims to be exhaustive and is missing half its cases.

This bullet says the section is "rendered per pane and only where the key actually works", then lists three cases: all four from the session views, C alone on Usage, and the two pickers. Because the sentence's whole point is that the set is pane-specific, a reader takes the list as complete — so the three unlisted panes read as having no jump keys at all.

I dumped jumpsFrom across every pane on this branch:

pane offers
NAMESPACES, PODS — (the pickers, as documented)
SESSIONS, EVENTS, EVENT DETAIL u P C $ (as documented)
PIPELINE C $
PLUGIN DETAIL C $
PLUGIN CATALOG $
USAGE C (as documented)

Six distinct cases, three documented. CodeRabbit flagged this independently and is right; its suggested wording covers it.

Worth noting where this lands, because it is the PR's own thesis: the old overlay advertised keys that did nothing on panes it never checked, and the fix was to derive availability per pane instead of writing prose beside a key (jumpsFrom, and "(not on usage)" giving way to spendDrawerHostPane). The README is now the one copy of that mapping still maintained by hand — the same shape of defect, one layer out. Nothing is broken for users: the overlay is correct and TestHelpBody_JumpSectionMatchesTheKeysThatActuallyWork holds it there. Only the prose can drift, and it has.

with a line saying they open once you're connected, rather than four
dead keys;
3. **THE DRILL PATH** — `namespaces → pods → sessions → events → event
detail` on one line, since that spine is also what `Esc` walks back.
If you're on one of its five panes it's in brackets; the four
key-opened panes are not steps on it, so they get a line naming that
and naming where `Esc` returns them;
4. **ANYWHERE** — `?`, `p`, `q`, the three keys with one meaning
everywhere — then **MOVING AROUND THIS HELP** (`↑↓`/`jk`, `b`/`f`,
`g`/`G`: these move the overlay on every pane, and a note names the
one pane where their closed-overlay meaning differs), then **INSIDE
THE SPEND DRAWER** (`a`/`w` are live only while it is open, so they
are not mixed in with the keys that always work — and the section is
omitted on the panes where `$` is refused);
5. **EVERY PANE** — the other eight in full, purpose and every
binding's description. Not compacted to bare keys: `USAGE m w b s
esc` said the pane has five keys and nothing about what any of them
do.

While it's up it owns the keyboard — `?`, `Esc`, or `q` closes it
(`q` closes the overlay rather than quitting abctl). This is the
discoverable home for keys the single-line footer has no room for,
`P` among them. Two exceptions: while a pipeline edit is in flight
that overlay is already modal and owns `y`/`N`, and while the filter
input is focused `?` is a character you're typing (session IDs and
hosts can contain one). In both cases `?` is inert until the keyboard
is released.

The body scrolls, so the full reference is reachable on a short
terminal: `↑↓`/`jk` by line, `b`/`f` or PgUp/PgDn by page, `u`/`d` by
half page, `g`/`G` to the ends. A `[↑↓] scroll <n>%` affordance
appears in the overlay's footer only when the content overflows; the
close hint stays pinned there at every scroll position. Resizing the
terminal re-ranges the body without losing your place.
terminal re-ranges AND re-wraps the body without losing your place —
prose wraps to the panel width rather than being clipped at the right
edge, so the descriptions and the scope note survive a narrow
terminal.

Spelling out all nine panes costs roughly four screens at 24 rows,
which `g`/`G` and the pinned close hint are what make affordable. The
overlay is the one surface with no width or height budget to defend,
so it is where completeness belongs.

## Keybindings

Expand Down
9 changes: 8 additions & 1 deletion authbridge/cmd/abctl/tui/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -821,8 +821,15 @@ func (m *model) backToPodsPane() {
// every resize while it's open, so the body re-wraps and the scroll range
// stays correct. resetScroll is true only on open — a resize should keep
// the reader where they were.
//
// THE BODY ACTUALLY RE-WRAPS NOW. This comment claimed it did while
// helpBodyLines took no width at all — it built one width-blind string and the
// viewport clipped whatever overran, so the overlay's longest line lost its
// second half on an 80-column terminal and said nothing about it. The wrap
// budget is the terminal minus the frame the panel draws around the viewport.
func (m *model) syncHelpViewport(resetScroll bool) {
body := helpBodyLines(m.pane)
frameW := styleBorder.GetHorizontalBorderSize() + helpPadX*2

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: styleBorder.GetHorizontalBorderSize() + helpPadX*2 is now computed here and again in helpViewportSize (help_overlay.go:706). The wrap budget and the viewport's width cap have to agree or the clipping this PR removes comes back — wrap wider than the cap and the viewport trims the overflow silently, which is the original defect.

A small helpFrameWidth() consumed by both would make it one derivation, in the same spirit as paneName and spendDrawerHostPane elsewhere in this change.

body := helpBodyLines(m.pane, m.width-frameW)
w, h := helpViewportSize(m.width, m.height, helpBodyWidth(body))
m.helpVp.Width = w
m.helpVp.Height = h
Expand Down
Loading
Loading