Skip to content

Answer numbered questions with the arrow keys - #97

Open
adamXbot wants to merge 2 commits into
mainfrom
ui/arrow-key-menus
Open

adamXbot wants to merge 2 commits into
mainfrom
ui/arrow-key-menus

Conversation

@adamXbot

@adamXbot adamXbot commented Nov 7, 2026 •

Copy link
Copy Markdown
Collaborator

What it does

Every numbered question fxcss asks now takes the arrow keys at a terminal, and still takes a typed answer exactly as before.

Key Single choice (build, theme, version, profile) Optional stylesheets
↑ ↓ move the › pointer (wraps) move down a column, then into the next
← → cross columns
a number moves the pointer as you type typed as before (1,3, 20 4, all), ticked as you type
Space ticks the sheet at the pointer (once you have typed, Space is part of the text, as in the plain prompt)
Home / End first / last first / last
Enter takes the pointer takes the ticks and anything typed
Esc, Ctrl+C stop stop
  • Look. The pointer sits in the margin and the row's name turns brand magenta. A ticked sheet's . becomes a green ✓, so the grid never shifts. The prompt names the keys (Which one? ↑↓ or 1-3 [2]) and its bracket shows what Enter will take.
  • Scrollback. Only the menu's own lines are redrawn; nothing takes over the screen. When you answer, the prompt line is rewritten as the typed answer would have left it (Which one? 1-3 [1] 3), and the chosen row keeps its › or ✓.
  • Fallbacks. The plain typed prompt is used for a pipe, CI, TERM=dumb, a terminal under 60 columns, a menu taller than the terminal, or FXCSS_PLAIN_PROMPTS=1. That last one is for screen readers that cope badly with lines redrawn in place. A retry of the stylesheet question (clashing sheets, or an unreadable token) is typed, because it asks you to retype the list.

Also in this PR

  • Ctrl+C or Esc at any point now ends with Stopped. and exit status 130 instead of a Python traceback. Clean-up still runs in each command's own finally blocks.
  • The stylesheet menu names --with after a choice (including a, b --with a,b skips this question), like the other four questions.
  • README: the profile and stylesheet examples were from before UI polish overhaul #96. They now show the current menus, followed by a paragraph on the keys and FXCSS_PLAIN_PROMPTS.

How it works

  • fxcss/prompt.py (new, standard library only):
    • arrows_ok() decides between the two modes.
    • decode() turns terminal key sequences into tokens, including modifier forms such as Ctrl+↑.
    • keypresses() reads keys: termios cbreak mode on macOS and Linux, restored however the menu ends; msvcrt on Windows, after switching the console to VT mode, and typed prompts if that fails.
    • Frame redraws the menu's lines in place.
    • pick_one and pick_many are the two pickers. pick_many returns its answer as the text the plain prompt would have read, so scan_selection and the existing clash and typo checks handle both modes.
  • _menu now takes a row renderer instead of pre-drawn lines. _menu_row gains pointer, and always keeps room for (Enter) so rows don't change length as the marker moves.
  • style.columns gains pointer and ticked; with neither set, its output is unchanged.

Test plan

  • python3 -m unittest discover -s tests: 716 tests, 1 skipped (Python 3.14). The new tests also pass on 3.9.
  • The whole suite run inside a pseudo-terminal (as a developer at a terminal would) passes, so no test can fall into the key reader and wait.
  • New tests/test_prompt.py:
    • key decoding;
    • the real reader against a pseudo-terminal, checking that the terminal settings are restored;
    • both pickers driven by scripted keys (moving, typing, wrapping, columns, ticks, Esc);
    • the grid layout not shifting;
    • every fallback;
    • main returning 130 on an interrupt.
  • Not tested on Windows. The msvcrt reader and VT switch are written but have not run on a real Windows console. Please try fxcss install there before release.
  • Try it in your own terminal: fxcss install <theme> with a theme that ships optional stylesheets.

🤖 Generated with Claude Code

At a terminal, every numbered question (Gecko build, theme in a
repository, version, profile) now also takes the arrow keys: ↑ and ↓
move a › pointer, a typed number moves it too, Enter takes it, Esc
stops. The optional-stylesheet menu adds Space to tick and ← → to cross
columns; typing 1,3 or all works as before and ticks as you type.

Only the menu's own lines are redrawn, and the scrollback ends as the
typed answer would. A pipe, CI, TERM=dumb, a terminal under 60 columns
or FXCSS_PLAIN_PROMPTS=1 keeps the plain typed prompt. Ctrl+C or Esc
now ends with "Stopped." and status 130 instead of a traceback. The
stylesheet menu names --with after a choice, like the others.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@adamXbot
adamXbot changed the base branch from polish/ui-terminal to main November 8, 2026 05:24
The interrupt test ran doctor's theme lookup first, which a checkout
holding a build/ copy (as after pip install .) finds ambiguous. The
Gecko build menu test expected a POSIX folder in the heading.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

1 participant