From a2f157233f274599739941e39673ca4d3b0291c3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 11 Apr 2022 10:23:33 +0800 Subject: [PATCH] fix(tui)!: remove `ESC NUL` forced escape (#17198) This make Nvim recognize `ESC NUL` as , as many terminal emulators (including libvterm) send as `ESC NUL`. There is already another unambiguous way to encode a `ESC` key supported by libtermkey: `ESC [ 2 7 u`, which is a `CSI u` sequence. If one still wants to use `ESC NUL` as `ESC`, they can just map to . --- src/nvim/tui/input.c | 17 ---------- test/functional/terminal/helpers.lua | 4 ++- test/functional/terminal/tui_spec.lua | 46 +++++++++++++++++++++++---- 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 24958ce041..17656c5ddc 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -439,22 +439,6 @@ static HandleState handle_bracketed_paste(TermInput *input) return kNotApplicable; } -// ESC NUL => -static bool handle_forced_escape(TermInput *input) -{ - if (rbuffer_size(input->read_stream.buffer) > 1 - && !rbuffer_cmp(input->read_stream.buffer, "\x1b\x00", 2)) { - // skip the ESC and NUL and push one to the input buffer - size_t rcnt; - termkey_push_bytes(input->tk, rbuffer_read_ptr(input->read_stream.buffer, - &rcnt), 1); - rbuffer_consumed(input->read_stream.buffer, 2); - tk_getkeys(input, true); - return true; - } - return false; -} - static void set_bg_deferred(void **argv) { char *bgvalue = argv[0]; @@ -583,7 +567,6 @@ static void handle_raw_buffer(TermInput *input, bool force) if (!force && (handle_focus_event(input) || (is_paste = handle_bracketed_paste(input)) != kNotApplicable - || handle_forced_escape(input) || (is_bc = handle_background_color(input)) != kNotApplicable)) { if (is_paste == kIncomplete || is_bc == kIncomplete) { // Wait for the next input, leaving it in the raw buffer due to an diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua index c5315d0185..51ecae663a 100644 --- a/test/functional/terminal/helpers.lua +++ b/test/functional/terminal/helpers.lua @@ -7,7 +7,9 @@ local nvim_dir = helpers.nvim_dir local feed_command, nvim = helpers.feed_command, helpers.nvim local function feed_data(data) - nvim('set_var', 'term_data', data) + -- A string containing NUL bytes is not converted to a Blob when + -- calling nvim_set_var() API, so convert it using Lua instead. + nvim('exec_lua', 'vim.g.term_data = ...', {data}) nvim('command', 'call jobsend(b:terminal_job_id, term_data)') end diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index c37cde06ab..8c6cba4def 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -214,7 +214,7 @@ describe('TUI', function() ]]) end) - it('interprets ESC+key as ALT chord', function() + it('interprets ESC+key as ALT chord in i_CTRL-V', function() -- Vim represents ALT/META by setting the "high bit" of the modified key: -- ALT+j inserts "ê". Nvim does not (#3982). feed_data('i\022\027j') @@ -229,6 +229,38 @@ describe('TUI', function() ]]) end) + it('interprets [27u as ', function() + feed_command('nnoremap ') + feed_command('nnoremap AESC') + feed_command('nnoremap ; Asemicolon') + feed_data('\027[27u;') + screen:expect([[ + ESCsemicolo{1:n} | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + | + {3:-- TERMINAL --} | + ]]) + -- ; should be recognized as when is mapped + feed_data('\027;') + screen:expect_unchanged() + end) + + it('interprets as #17198', function() + feed_data('i\022\027\000') + screen:expect([[ + {1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + {3:-- INSERT --} | + {3:-- TERMINAL --} | + ]]) + end) + it('accepts ASCII control sequences', function() feed_data('i') feed_data('\022\007') -- ctrl+g @@ -271,7 +303,7 @@ describe('TUI', function() {3:-- TERMINAL --} | ]]) feed_data('\027[201~') -- End paste. - feed_data('\027\000') -- ESC: go to Normal mode. + feed_data('\027[27u') -- ESC: go to Normal mode. wait_for_mode('n') screen:expect([[ "pasted from termina{1:l}" | @@ -453,7 +485,7 @@ describe('TUI', function() {3:-- TERMINAL --} | ]]} -- Dot-repeat/redo. - feed_data('\027\000') + feed_data('\027[27u') wait_for_mode('n') feed_data('.') screen:expect{grid=[[ @@ -499,7 +531,7 @@ describe('TUI', function() vim.paste = function(lines, phase) error("fake fail") end ]], {}) -- Prepare something for dot-repeat/redo. - feed_data('ifoo\n\027\000') + feed_data('ifoo\n\027[27u') wait_for_mode('n') screen:expect{grid=[[ foo | @@ -541,7 +573,7 @@ describe('TUI', function() {3:-- TERMINAL --} | ]]} -- Editor should still work after failed/drained paste. - feed_data('ityped input...\027\000') + feed_data('ityped input...\027[27u') screen:expect{grid=[[ foo | foo | @@ -575,7 +607,7 @@ describe('TUI', function() vim.paste = function(lines, phase) return false end ]], {}) feed_data('\027[200~line A\nline B\n\027[201~') - feed_data('ifoo\n\027\000') + feed_data('ifoo\n\027[27u') expect_child_buf_lines({'foo',''}) end) @@ -669,7 +701,7 @@ describe('TUI', function() {3:-- INSERT --} | {3:-- TERMINAL --} | ]]) - feed_data('\027\000') -- ESC: go to Normal mode. + feed_data('\027[27u') -- ESC: go to Normal mode. wait_for_mode('n') -- Dot-repeat/redo. feed_data('.')