Skip to content

ctrl+space interpreted as ctrl+@ or \x00 in VSCode terminal (and many others) #5902

Open
@RedBeard0531

Description

@RedBeard0531

Have you checked closed issues? (https://github.com/Textualize/textual/issues?q=is%3Aissue+is%3Aclosed) yes

Have you checked against the most recent version of Textual? (https://pypi.org/search/?q=textual) yes

The ask / suggested fix

Interpret ctrl+@ as ctrl+space since that is what most terminals send when you hit ctrl+space.

The bug

Run textual keys in kitty and vscode terminal and press space and ctrl+space. In kitty you correctly get:

Key(key='space', character=' ', name='space', is_printable=True)                                                                                                                                                                                      
Key(key='ctrl+space', character=None, name='ctrl_space', is_printable=False) 

but VSCode shows

Image

(Screenshot since vscode doesn't support shift+highlight to bypass mouse interception)

I think ctrl+space is much more likely to be a useful mapping than ctrl+@, so it is probably best to just interpret the latter as the former. Interestingly if I hit ctrl+shift+2 (@ is shift+2 on my keyboard), vscode outputs the same line as ctrl+space, while kitty outputs nothing. Kitty defaults to mapping that to go to window 2, so it is intercepted before reaching textual (ctrl+shift is the default "kitty_mod" to send commands to kitty). If I remove that mapping it will send the following, so there is no way to generate ctrl+@ unless you have a dedicated @ key (or make a weird custom mapping...):

Key(key='ctrl+shift+2', character=None, name='ctrl_shift_2', is_printable=False)  

After typing most of this bug up, I also tried xterm, Apple's terminal.app, wezterm and ghostTTY (all on a mac but sshed into linux). ghostTTY behaved identically to kitty (although it sends ctrl+shift+2 by default since it is unmapped), but the rest send ctrl+@ like vscode. If I had to guess, kitty and ghost support the fancy kitty input protocol but the others don't.

Textual Diagnostics

Versions

Name Value
Textual 3.5.0
Rich 14.0.0

Python

Name Value
Version 3.13.5
Implementation CPython
Compiler GCC 6.3.0 20170516
Executable /home/mstearn/.local/share/uv/tools/textual-dev/bin/python

Operating System

Name Value
System Linux
Release 6.14.10
Version #1 SMP Sat Jun 7 02:45:18 UTC 2025

Terminal

Name Value
Terminal Application vscode (1.101.2)
TERM xterm-256color
COLORTERM truecolor
FORCE_COLOR Not set
NO_COLOR Not set

Rich Console options

Name Value
size width=214, height=31
legacy_windows False
min_width 1
max_width 214
is_terminal True
encoding utf-8
max_height 31
justify None
overflow None
no_wrap False
highlight None
markup None
height None

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions