fix(tui): subclass Input to override _watch_value and eliminate layout=True per keystroke #11251

Merged
HAL9000 merged 6 commits from bugfix/m8-tui-input-live-refresh into master 2026-05-28 03:36:24 +00:00

6 Commits

Author SHA1 Message Date
HAL9000 153502feca fix(tui): suppress textual import errors for optional dependency in typecheck
CI / helm (pull_request) Successful in 31s
CI / lint (pull_request) Successful in 38s
CI / build (pull_request) Successful in 40s
CI / quality (pull_request) Successful in 49s
CI / push-validation (pull_request) Successful in 43s
CI / typecheck (pull_request) Successful in 1m15s
CI / security (pull_request) Successful in 1m16s
CI / integration_tests (pull_request) Successful in 3m56s
CI / unit_tests (pull_request) Successful in 6m3s
CI / docker (pull_request) Successful in 1m33s
CI / coverage (pull_request) Successful in 12m50s
CI / status-check (pull_request) Successful in 3s
Pyright evaluates `if _TEXTUAL_AVAILABLE:` blocks statically and raises
reportMissingImports for textual.geometry, textual.reactive, and
textual.widgets. Add `# type: ignore[import]` to the three conditional
imports so typecheck passes when textual is not installed in the
check environment.
2026-05-27 23:17:15 -04:00
drew 2537c5704f Revert "fix(typecheck): install tui optional dep in typecheck nox session"
This reverts commit fc66708231.
2026-05-27 23:17:15 -04:00
HAL9000 16baa60cb2 fix(typecheck): install tui optional dep in typecheck nox session
The typecheck session was installing only the base package (-e .)
without the tui optional dependency, so pyright could not resolve
the textual.geometry, textual.reactive, and textual.widgets imports
that prompt.py conditionally loads when _TEXTUAL_AVAILABLE is True.

Changing to -e .[tui] ensures textual is present in the typecheck
venv so pyright reports no reportMissingImports errors.
2026-05-27 23:17:15 -04:00
controller-ci-rerun 19c81ac388 chore: re-trigger CI [controller] 2026-05-27 23:17:15 -04:00
hamza.khyari 6bda792d2b fix(tui): subclass Input to override _watch_value and eliminate layout=True per keystroke
Input._watch_value sets self.virtual_size (Reactive layout=True) on every
keystroke, keeping Textual's WriterThread write queue permanently non-empty.
The queue never reaches qsize()==0 so flush() is never called and typed
characters are invisible until Enter drains the queue.

Two fixes applied:

1. _PromptTextInput subclasses textual.widgets.Input and overrides
   virtual_size with Reactive(layout=False). Setting virtual_size in
   _watch_value no longer triggers refresh(layout=True). Zero type:ignore
   suppressions — uses proper Textual reactive types.

2. CSS #prompt and #prompt > Input changed from height:auto to fixed
   heights (3 and 1). This prevents the auto_dimensions guard in
   _watch_value from adding a second refresh(layout=True) per keystroke.

3 BDD regression scenarios added covering: virtual_size layout=False,
_PromptInputBase usage in _TextualPromptInput, and fixed CSS height.

ISSUES CLOSED: #11249
2026-05-27 23:17:15 -04:00
hamza.khyari 412c338f4e fix(tui): subclass Input to override _watch_value and eliminate layout=True per keystroke
Input._watch_value sets self.virtual_size (Reactive layout=True) on every
keystroke, keeping Textual's WriterThread write queue permanently non-empty.
The queue never reaches qsize()==0 so flush() is never called and typed
characters are invisible until Enter drains the queue via conversation.update().

_PromptTextInput subclasses Input and overrides _watch_value to skip the
virtual_size update while preserving Changed event, _suggestion reset and
initial cursor positioning. The prompt is single-line and never scrolls
horizontally so omitting virtual_size is safe.

ISSUES CLOSED: #11249
2026-05-27 23:17:15 -04:00