Skip to content

Explore output with the keyboard: Enter/Escape, siblings, Shift+arrows (#2382) - #2409

Merged
gunterkoenigsmann merged 2 commits into
mainfrom
claude/output-keyboard-explore
Sep 30, 2026
Merged

gunterkoenigsmann merged 2 commits into
mainfrom
claude/output-keyboard-explore

Conversation

@gunterkoenigsmann

Copy link
Copy Markdown
Member

Requested by Gunter · project thread

Steps two and three of #2382. Step one was #2383 and #2384.

Before: the keyboard could select a whole result of a cell's output, but nothing smaller. Enter on a selected result opened a new input cell holding its text.

After: with a part of an output selected, Enter goes into it and selects its first part: from a result to its expression, then from a fraction to its numerator, from a function to its name, from a matrix to its first entry, and so on. Escape goes back out one level at a time, and from a whole result back into the cell's input. Left and Right select the neighbouring part. In a matrix, all four arrow keys move from entry to entry and skip elided ones. Shift+Left and Shift+Right grow or shrink the selection over neighbouring parts. A matrix entry is selected as a one-entry block, so Shift+arrows grow it the same way they grow a block dragged with the mouse (#2370). Every move raises the same accessibility focus event step one does.

A few choices worth checking:

  • Enter on a part that has no parts (a lone x) keeps its old meaning: it opens a new cell holding the selection. So the old Enter still works on leaves, but not on whole results.
  • Up and Down below the result level keep doing what they did for a mouse-selected part: they leave the cell. Step one's tests pin that down, so I left it alone.
  • Left and Right on a whole result are unchanged, so they still step through an animation's frames.
  • Shift+Left/Right can't span numerator and denominator. Those are two separate cell lists, and a selection is a run within one list, so the key does nothing there.

How: a new OutputNavigation (in src/worksheet/) models the output as a tree built from the expression's structure (OnInner()), not from the draw list, so a line break doesn't change what a key does. Glyphs that a cell only draws while broken into lines (sqrt(, ,, ), /, ^, a limit's lim) are left out, and so are hidden and empty cells and elided matrix entries. An item that only wraps a single part, such as a matrix entry holding one fraction, is looked through, so that Enter always visibly changes the selection. It knows nothing about key events. Worksheet::NavigateOutput() maps the keys onto it. The node is found by searching the tree, so no state goes stale when the mouse changes the selection. The one exception is the Shift anchor, which is a CellPtr.

Tests: test_OutputKeyboardNavigation gains 5 scenarios, covering Enter/Escape round trips, glyph filtering, Enter on a leaf, Shift growing and shrinking from either end, and matrix entry movement, block growth and entering an entry. With the key handler disabled, 16 of the new assertions fail. All 58 unit tests pass locally with a unity build. I also checked it live in Xvfb on matrix([1,x/(y+1)],[3,sin(z)]) and a+b^2+sqrt(c): the entry and the numerator highlight, and so does a run grown with Shift. That live check is what found the numerator/denominator case, which now has its own test.

Docs: a new manual section, "Exploring output with the keyboard" (it covers step one too), and a NEWS entry.

🤖 Generated with Claude Code

https://claude.ai/code/session_014i39UdkdrHCP1EUWkG9snP


Generated by Claude Code

Steps two and three of #2382. With a part of an output selected:

- Enter goes into the selected expression: from a result to its
  expression, from a fraction to its numerator, from a matrix to its
  first entry. On a part with no parts it keeps its old meaning (a new
  input cell holding the selection).
- Escape goes back out, and from a whole result back into the input.
- Left/Right select the neighbouring part; in a matrix all four arrow
  keys move from entry to entry, skipping elided ones.
- Shift+Left/Right grow or shrink the selection over neighbouring parts
  of the same cell list; a matrix entry is selected as a one-entry block,
  so Shift+arrows grow it exactly like a dragged block (#2370).

The tree walked is the expression's structure (GetInnerCell()), not the
draw list, so line breaks don't change what a key does. It lives in the
new OutputNavigation, which knows nothing about key events and is
tested on parsed output. Glyphs a cell only draws while broken into
lines ("sqrt(", ",", ")") are not parts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014i39UdkdrHCP1EUWkG9snP
@gunterkoenigsmann gunterkoenigsmann self-assigned this Sep 30, 2026
The test is red on the Windows jobs on main: wxYield() dispatches no
socket events on MSW without an active event loop. Same change as #2410;
it no-ops once main carries it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014i39UdkdrHCP1EUWkG9snP
@gunterkoenigsmann
gunterkoenigsmann merged commit 358eea6 into main Sep 30, 2026
18 of 20 checks passed
@gunterkoenigsmann
gunterkoenigsmann deleted the claude/output-keyboard-explore branch September 30, 2026 06:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants