commit 4b5364b4231815ca1ba750068a68816e539d318f
parent 1fb0126a086de32daf800b773337bc8fc7996221
Author: zeertzjq <zeertzjq@outlook.com>
Date: Fri, 2 May 2025 17:40:24 +0800
fix(tui): forward C0 control codes literally (#33759)
This fixes the problem that sending a raw C0 control code to trigger a
mapping for it does not work in Terminal mode.
Note: this isn't done for 00 or 7F, as that'll be backward-incompatible.
Diffstat:
4 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
@@ -145,8 +145,8 @@ void tinput_init(TermInput *input, Loop *loop)
term = ""; // termkey_new_abstract assumes non-null (#2745)
}
- input->tk = termkey_new_abstract(term,
- TERMKEY_FLAG_UTF8 | TERMKEY_FLAG_NOSTART);
+ input->tk = termkey_new_abstract(term, (TERMKEY_FLAG_UTF8 | TERMKEY_FLAG_NOSTART
+ | TERMKEY_FLAG_KEEPC0));
termkey_set_buffer_size(input->tk, INPUT_BUFFER_SIZE);
termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, input);
termkey_start(input->tk);
diff --git a/src/nvim/tui/termkey/termkey.c b/src/nvim/tui/termkey/termkey.c
@@ -719,7 +719,7 @@ static void emit_codepoint(TermKey *tk, int codepoint, TermKeyKey *key)
key->type = TERMKEY_TYPE_KEYSYM;
key->code.sym = TERMKEY_SYM_SPACE;
key->modifiers = TERMKEY_KEYMOD_CTRL;
- } else if (codepoint < 0x20) {
+ } else if (codepoint < 0x20 && !(tk->flags & TERMKEY_FLAG_KEEPC0)) {
// C0 range
key->code.codepoint = 0;
key->modifiers = 0;
@@ -750,7 +750,7 @@ static void emit_codepoint(TermKey *tk, int codepoint, TermKeyKey *key)
key->type = TERMKEY_TYPE_KEYSYM;
key->code.sym = TERMKEY_SYM_DEL;
key->modifiers = 0;
- } else if (codepoint >= 0x20 && codepoint < 0x80) {
+ } else if (codepoint > 0 && codepoint < 0x80) {
// ASCII lowbyte range
key->type = TERMKEY_TYPE_UNICODE;
key->code.codepoint = codepoint;
diff --git a/src/nvim/tui/termkey/termkey_defs.h b/src/nvim/tui/termkey/termkey_defs.h
@@ -151,6 +151,7 @@ enum {
TERMKEY_FLAG_CTRLC = 1 << 6, // Allow Ctrl-C to be read as normal, disabling SIGINT
TERMKEY_FLAG_EINTR = 1 << 7, // Return ERROR on signal (EINTR) rather than retry
TERMKEY_FLAG_NOSTART = 1 << 8, // Do not call termkey_start() in constructor
+ TERMKEY_FLAG_KEEPC0 = 1 << 9, // Keep raw C0 control codes
};
enum {
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
@@ -486,6 +486,38 @@ describe('TUI', function()
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
+ child_session:request('nvim_set_keymap', 'i', '\031', '!!!', {})
+ feed_data('\031')
+ screen:expect([[
+ {6:^G^V^M}!!!^ |
+ {4:~ }|*3
+ {5:[No Name] [+] }|
+ {3:-- INSERT --} |
+ {3:-- TERMINAL --} |
+ ]])
+ child_session:request('nvim_buf_delete', 0, { force = true })
+ child_session:request('nvim_set_option_value', 'laststatus', 0, {})
+ child_session:request(
+ 'nvim_call_function',
+ 'jobstart',
+ { { testprg('shell-test'), 'INTERACT' }, { term = true } }
+ )
+ screen:expect([[
+ interact $ ^ |
+ |*4
+ {3:-- TERMINAL --} |*2
+ ]])
+ -- mappings for C0 control codes should work in Terminal mode #33750
+ child_session:request('nvim_set_keymap', 't', '\031', '<Cmd>new<CR>', {})
+ feed_data('\031')
+ screen:expect([[
+ ^ |
+ {4:~ }|
+ {5:[No Name] }|
+ interact $ |
+ |*2
+ {3:-- TERMINAL --} |
+ ]])
end)
local function test_mouse_wheel(esc)
@@ -1198,7 +1230,6 @@ describe('TUI', function()
pending('tty-test complains about not owning the terminal -- actions/runner#241')
end
screen:set_default_attr_ids({
- [1] = { reverse = true }, -- focused cursor
[3] = { bold = true },
[19] = { bold = true, background = 121, foreground = 0 }, -- StatusLineTerm
})