Skip to content

Bug: Ctrl+H is incorrectly intercepted as Backspace (0x08), breaking Neovim navigation #33

@Dailiduzhou

Description

@Dailiduzhou

Hi! Thanks for the great work on rmux. I've been testing it inside WSL via Windows Terminal and ran into an issue where Ctrl+H is completely swallowed and translated to <BS> (Backspace), which breaks standard terminal multiplexer workflows (like LazyVim's window navigation).

I did some digging into the codebase and found the root cause in the byte-parsing logic.

The Root Cause

In crates/rmux-server/src/key_table.rs, the control_byte_key function eagerly maps 0x08 to BSpace:

fn control_byte_key(byte: u8) -> Option<KeyCode> {
    match byte {
        // ...
        0x7f | 0x08 => key_string_lookup_string("BSpace"),  // <-- The culprit
        0x01..=0x1a => {
            let ch = char::from(b'a' + (byte - 1));
            key_string_lookup_string(&format!("C-{ch}"))
        }
        _ => None,
    }
}

The Fault Chain

While historically 0x08 is ^H (Backspace), modern terminal emulators (like Windows Terminal) generally distinguish the two by sending 0x7f (DEL) for Backspace and 0x08 for Ctrl+H.
Because rmux aliases 0x08 to BSpacebefore the 0x01..=0x1a range match, Ctrl+H never gets parsed as C-h.

[Windows Terminal: Presses Ctrl+H]
        │
        ▼ sends 0x08
[rmux: Parses byte]
        │
        ▼ hits `0x08 => BSpace` (Instead of falling through to C-h)
[rmux: Encodes to pane]
        │
        ▼ sends 0x7f (DEL)
[Neovim / Inner App]
        │
        ▼ Receives <BS>, making <C-h> mappings impossible to trigger

Note: If CSI u (Kitty keyboard protocol) is successfully negotiated by the inner app, this bypasses the legacy byte parsing. However, in standard legacy mode, Ctrl+H is strictly broken.

Suggested Solutions

This is a classic TTY parsing dilemma. Here are a few ways to approach it:

  1. Rely on Terminfo (kbs): Instead of hardcoding both 0x7f and 0x08 to BSpace, rmux could dynamically check the terminal's kbs (key_backspace) terminfo capability. If kbs=\177 (0x7f), then 0x08 should safely fall through to C-h.
  2. Prioritize 0x7f for Backspace: In modern environments, 0x7f is almost universally Backspace. Removing 0x08 from the BSpace match branch would instantly fix C-h for most users, though it might break Backspace on legacy terminals configured to send ^H for backspace.
  3. User Configuration: Expose a setting (similar to tmux behavior options) to let users explicitly dictate whether 0x08 means C-h or Backspace.
    I would love to hear how you'd prefer to handle this terminal quirk! I'd be happy to submit a PR once we decide on the best architectural approach.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions