Problem
The TUI takes a quadraui::Key from the runner, converts it back into a crossterm event, then re-decodes it:
src/tui_main/shell_app.rs:3614 — synth_keyevent turns the quadraui::Key back into crossterm
src/tui_main/mod.rs:809-911 — translate_key (103 lines)
src/tui_main/mod.rs:789-808 — tui_key_to_engine_name
src/tui_main/mod.rs:753-788 — shift_map_us
src/tui_main/shell_app.rs:3171-3578 — ~200 lines of per-panel KeyCode tables inside handle_focus_owner_key
GTK decodes the same quadraui::Key to the same engine names in ~40 lines inline (src/app.rs:6807-6850) plus map_gtk_key_name (:617-639).
Both produce identical spellings — "Escape", "Return", "BackSpace", etc. The TUI's round-trip through crossterm is pure overhead, and it is the largest single block of TUI-only code that is not irreducible: ~300 lines.
Fix
One shared decoder in render.rs:
render::engine_key_from_ui(key, mods, keyboard_enhanced) -> (String, Option<char>, bool)
Delete synth_keyevent, translate_key, tui_key_to_engine_name and shift_map_us; have both backends call the shared function. The per-panel KeyCode tables in handle_focus_owner_key should then be expressible against engine key names rather than crossterm variants.
Watch keyboard_enhanced — the TUI sets it in setup and it changes how some chords arrive. It must be a parameter of the shared decoder, not a TUI-local branch.
Note for reference: <C-h>, <C-j> and <C-c> arrive as ctrl+h/ctrl+j/ctrl+c under crossterm; the Vim-conformance chain (#800-807) depends on those spellings. Do not change the engine-facing names.
Acceptance
- Black-box tests required, both backends. Key decoding is the highest-blast-radius surface in the editor.
- Cover: plain keys, shifted keys, ctrl chords, alt chords, function keys, Escape/Return/BackSpace/Tab, and per-panel focus routing.
- The Neovim-oracle harness (
tests/nvim_conformance.rs, 1,432 cases behind KNOWN_DEVIATIONS) is the regression net here — it must stay green, and no label may start passing or failing unexpectedly.
- State in the PR that the new tests fail against unfixed
develop.
Problem
The TUI takes a
quadraui::Keyfrom the runner, converts it back into a crossterm event, then re-decodes it:src/tui_main/shell_app.rs:3614—synth_keyeventturns thequadraui::Keyback into crosstermsrc/tui_main/mod.rs:809-911—translate_key(103 lines)src/tui_main/mod.rs:789-808—tui_key_to_engine_namesrc/tui_main/mod.rs:753-788—shift_map_ussrc/tui_main/shell_app.rs:3171-3578— ~200 lines of per-panelKeyCodetables insidehandle_focus_owner_keyGTK decodes the same
quadraui::Keyto the same engine names in ~40 lines inline (src/app.rs:6807-6850) plusmap_gtk_key_name(:617-639).Both produce identical spellings —
"Escape","Return","BackSpace", etc. The TUI's round-trip through crossterm is pure overhead, and it is the largest single block of TUI-only code that is not irreducible: ~300 lines.Fix
One shared decoder in
render.rs:Delete
synth_keyevent,translate_key,tui_key_to_engine_nameandshift_map_us; have both backends call the shared function. The per-panelKeyCodetables inhandle_focus_owner_keyshould then be expressible against engine key names rather than crossterm variants.Watch
keyboard_enhanced— the TUI sets it insetupand it changes how some chords arrive. It must be a parameter of the shared decoder, not a TUI-local branch.Note for reference:
<C-h>,<C-j>and<C-c>arrive asctrl+h/ctrl+j/ctrl+cunder crossterm; the Vim-conformance chain (#800-807) depends on those spellings. Do not change the engine-facing names.Acceptance
tests/nvim_conformance.rs, 1,432 cases behindKNOWN_DEVIATIONS) is the regression net here — it must stay green, and no label may start passing or failing unexpectedly.develop.