[ Deep dives ]
Troubleshooting
App::run() fails immediately with NotATty
Section titled “App::run() fails immediately with NotATty”- Cause:
App::run()checksm_term.is_tty(), which requires bothisatty(STDIN_FILENO) != 0andisatty(STDOUT_FILENO) != 0(src/terminal.cpp:221, 427). Running the binary with redirected input/output (./app > out.logor inside a non-interactive test runner) returnsTerminalError::NotATty(system_errno = ENOTTY). - Fix: Run interactive binaries directly in a terminal emulator, or use
app.draw_frame(false)andapp.dispatch_event(...)for automated headless tests.
Terminal left in raw mode or mouse tracking after SIGKILL (kill -9)
Section titled “Terminal left in raw mode or mouse tracking after SIGKILL (kill -9)”- Cause:
Terminalinstalls signal handlers forSIGTERM,SIGINT,SIGQUIT,SIGHUP,SIGSEGV,SIGABRT,SIGBUS,SIGFPE,SIGILL,std::terminate, andstd::atexitthat callrestore_minimal()(src/terminal.cpp:27-38, 140-183). However, the kernel does not allow any process to catchSIGKILL(kill -9) orSIGSTOP. - Fix: Run the exact escape sequence from
restore_minimal()(src/terminal.cpp:29-33) and resettermios:
printf "[?1006l[?1003l[?1002l[?1000l[<u[?2004l[?25h[?1049l"stty saneColors are missing or quantized to 16 or 256 colors
Section titled “Colors are missing or quantized to 16 or 256 colors”- Cause:
detect_system_color_mode()(src/color.cpp:226-273) evaluates environment variables in this exact order:- If
NO_COLORis set and non-empty (no_color[0] != '�'), returnsColorMode::NoColor. - If
TERMequals"dumb", returnsColorMode::NoColor. - If
COLORTERMequals"truecolor"or"24bit", returnsColorMode::TrueColor. - If
TERMis set:- If
TERMends with"-direct"or contains"truecolor", returnsColorMode::TrueColor. - If
TERMcontains"256color"or"256", returnsColorMode::Ansi256. - Otherwise, returns
ColorMode::Ansi16.
- If
- If
TERMis unset, defaults toColorMode::TrueColor.
- If
- Fix: Export
COLORTERM=truecolorin your shell ortmuxenvironment, unsetNO_COLOR, or override the mode in code viaTerminal::color_mode(ColorMode::TrueColor).
Modified keys like Ctrl+Enter or Shift+Enter behave like plain Enter
Section titled “Modified keys like Ctrl+Enter or Shift+Enter behave like plain Enter”- Cause: Legacy VT100/xterm terminals send
(0x0D) for bothEnterandCtrl+Enter/Shift+Enter.Terminal::enter_raw_mode()sends[>1uto enable Kitty keyboard protocol flag 1 (DISAMBIGUATE_ESCAPE_CODES) (src/terminal.cpp:347-355), which causes supporting terminals to emit[13;5u(Ctrl+Enter) and[13;2u(Shift+Enter) (src/event.cpp:269-280). Terminals that do not implement the Kitty keyboard protocol ignore[>1uand continue sending. - Fix: Provide fallback key bindings (such as
Alt+Enter, which sendsand is decoded asKeyEvent{Key::Enter, false, false, true, false}atsrc/event.cpp:506, orCtrl+S) for terminals without Kitty keyboard protocol support.
Global hotkeys stop working when TextInput, TextArea, List, or Tabs is focused
Section titled “Global hotkeys stop working when TextInput, TextArea, List, or Tabs is focused”- Cause: When
app.use_focus(fm)is active,App::dispatch_eventcallsfm.handle_key(*key)beforem_key_handler(*key)(src/app.cpp:166-180).TextInputStateandTextAreaStateconsume all unmodified printable characters (!key.ctrl && !key.alt && key.is_char()).ListStateconsumes'j','k','g','G',Up,Down,Home, andEnd.TabsStateconsumes'h','l','1'..'9',Left,Right,Home, andEnd.
- Fix: Use
Key::Escape,ctrlcombinations (key.ctrl && key.ch == 'Q'), or register a pre-hook viafm.interceptor(...)(src/focus.cpp:540-543).