From c03d38c51dbe416410c79b9981e0b3d529f025f9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 23 Jul 2023 08:23:07 +0800 Subject: [PATCH 1/4] test: check real cursor position in Terminal mode --- test/functional/terminal/cursor_spec.lua | 66 +++++++++++++----------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua index 98ac03211a..47bc02373c 100644 --- a/test/functional/terminal/cursor_spec.lua +++ b/test/functional/terminal/cursor_spec.lua @@ -187,13 +187,16 @@ describe('buffer cursor position is correct in terminal without number column', ..[[", "-u", "NONE", "-i", "NONE", "-E", "--cmd", "let @r = ']]..str..[['", ]] -- and don't always work ..[["--cmd", "cnoremap ", "--cmd", "cnoremap "]]..']', 70) + -- Also check for real cursor position, as it is used for stuff like input methods + screen._handle_busy_start = function() end + screen._handle_busy_stop = function() end screen:expect([[ | | | | Entering Ex mode. Type "visual" to go to Normal mode. | - :{1: } | + :{1:^ } | {3:-- TERMINAL --} | ]]) end @@ -213,7 +216,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :aaaaaaaa{1: } | + :aaaaaaaa{1:^ } | {3:-- TERMINAL --} | ]]) eq({6, 9}, eval('nvim_win_get_cursor(0)')) @@ -238,7 +241,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :aaaaaa{1:a}a | + :aaaaaa{1:^a}a | {3:-- TERMINAL --} | ]]) eq({6, 7}, eval('nvim_win_get_cursor(0)')) @@ -263,7 +266,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :a{1:a}aaaaaa | + :a{1:^a}aaaaaa | {3:-- TERMINAL --} | ]]) eq({6, 2}, eval('nvim_win_get_cursor(0)')) @@ -294,7 +297,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :µµµµµµµµ{1: } | + :µµµµµµµµ{1:^ } | {3:-- TERMINAL --} | ]]) eq({6, 17}, eval('nvim_win_get_cursor(0)')) @@ -319,7 +322,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :µµµµµµ{1:µ}µ | + :µµµµµµ{1:^µ}µ | {3:-- TERMINAL --} | ]]) eq({6, 13}, eval('nvim_win_get_cursor(0)')) @@ -344,7 +347,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :µ{1:µ}µµµµµµ | + :µ{1:^µ}µµµµµµ | {3:-- TERMINAL --} | ]]) eq({6, 3}, eval('nvim_win_get_cursor(0)')) @@ -377,7 +380,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{1: } | + :µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{1:^ } | {3:-- TERMINAL --} | ]]) eq({6, 33}, eval('nvim_win_get_cursor(0)')) @@ -402,7 +405,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :µ̳µ̳µ̳µ̳µ̳µ̳{1:µ̳}µ̳ | + :µ̳µ̳µ̳µ̳µ̳µ̳{1:^µ̳}µ̳ | {3:-- TERMINAL --} | ]]) eq({6, 25}, eval('nvim_win_get_cursor(0)')) @@ -427,7 +430,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :µ̳{1:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | + :µ̳{1:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | {3:-- TERMINAL --} | ]]) eq({6, 5}, eval('nvim_win_get_cursor(0)')) @@ -446,7 +449,7 @@ describe('buffer cursor position is correct in terminal without number column', end) describe('in a line with double-cell multibyte characters and no trailing spaces,', function() - skip(is_os('win'), "Encoding problem?") + if skip(is_os('win'), "Encoding problem?") then return end before_each(function() setup_ex_register('哦哦哦哦哦哦哦哦') @@ -460,7 +463,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :哦哦哦哦哦哦哦哦{1: } | + :哦哦哦哦哦哦哦哦{1:^ } | {3:-- TERMINAL --} | ]]) eq({6, 25}, eval('nvim_win_get_cursor(0)')) @@ -485,7 +488,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :哦哦哦哦哦哦{1:哦}哦 | + :哦哦哦哦哦哦{1:^哦}哦 | {3:-- TERMINAL --} | ]]) eq({6, 19}, eval('nvim_win_get_cursor(0)')) @@ -510,7 +513,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :哦{1:哦}哦哦哦哦哦哦 | + :哦{1:^哦}哦哦哦哦哦哦 | {3:-- TERMINAL --} | ]]) eq({6, 4}, eval('nvim_win_get_cursor(0)')) @@ -537,7 +540,7 @@ describe('buffer cursor position is correct in terminal without number column', | | Entering Ex mode. Type "visual" to go to Normal mode. | - :aaaaaaaa {1: } | + :aaaaaaaa {1:^ } | {3:-- TERMINAL --} | ]]) matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()')) @@ -564,13 +567,16 @@ describe('buffer cursor position is correct in terminal with number column', fun ..[[", "-u", "NONE", "-i", "NONE", "-E", "--cmd", "let @r = ']]..str..[['", ]] -- and don't always work ..[["--cmd", "cnoremap ", "--cmd", "cnoremap "]]..']', 70) + -- Also check for real cursor position, as it is used for stuff like input methods + screen._handle_busy_start = function() end + screen._handle_busy_stop = function() end screen:expect([[ {7: 1 } | {7: 2 } | {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:{1: } | + {7: 6 }:{1:^ } | {3:-- TERMINAL --} | ]]) end @@ -593,7 +599,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:aaaaaaaa{1: } | + {7: 6 }:aaaaaaaa{1:^ } | {3:-- TERMINAL --} | ]]) eq({6, 9}, eval('nvim_win_get_cursor(0)')) @@ -618,7 +624,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:aaaaaa{1:a}a | + {7: 6 }:aaaaaa{1:^a}a | {3:-- TERMINAL --} | ]]) eq({6, 7}, eval('nvim_win_get_cursor(0)')) @@ -643,7 +649,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:a{1:a}aaaaaa | + {7: 6 }:a{1:^a}aaaaaa | {3:-- TERMINAL --} | ]]) eq({6, 2}, eval('nvim_win_get_cursor(0)')) @@ -674,7 +680,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:µµµµµµµµ{1: } | + {7: 6 }:µµµµµµµµ{1:^ } | {3:-- TERMINAL --} | ]]) eq({6, 17}, eval('nvim_win_get_cursor(0)')) @@ -699,7 +705,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:µµµµµµ{1:µ}µ | + {7: 6 }:µµµµµµ{1:^µ}µ | {3:-- TERMINAL --} | ]]) eq({6, 13}, eval('nvim_win_get_cursor(0)')) @@ -724,7 +730,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:µ{1:µ}µµµµµµ | + {7: 6 }:µ{1:^µ}µµµµµµ | {3:-- TERMINAL --} | ]]) eq({6, 3}, eval('nvim_win_get_cursor(0)')) @@ -757,7 +763,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{1: } | + {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{1:^ } | {3:-- TERMINAL --} | ]]) eq({6, 33}, eval('nvim_win_get_cursor(0)')) @@ -782,7 +788,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳{1:µ̳}µ̳ | + {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳{1:^µ̳}µ̳ | {3:-- TERMINAL --} | ]]) eq({6, 25}, eval('nvim_win_get_cursor(0)')) @@ -807,7 +813,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:µ̳{1:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | + {7: 6 }:µ̳{1:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ | {3:-- TERMINAL --} | ]]) eq({6, 5}, eval('nvim_win_get_cursor(0)')) @@ -826,7 +832,7 @@ describe('buffer cursor position is correct in terminal with number column', fun end) describe('in a line with double-cell multibyte characters and no trailing spaces,', function() - skip(is_os('win'), "Encoding problem?") + if skip(is_os('win'), "Encoding problem?") then return end before_each(function() setup_ex_register('哦哦哦哦哦哦哦哦') @@ -840,7 +846,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:哦哦哦哦哦哦哦哦{1: } | + {7: 6 }:哦哦哦哦哦哦哦哦{1:^ } | {3:-- TERMINAL --} | ]]) eq({6, 25}, eval('nvim_win_get_cursor(0)')) @@ -865,7 +871,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:哦哦哦哦哦哦{1:哦}哦 | + {7: 6 }:哦哦哦哦哦哦{1:^哦}哦 | {3:-- TERMINAL --} | ]]) eq({6, 19}, eval('nvim_win_get_cursor(0)')) @@ -890,7 +896,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:哦{1:哦}哦哦哦哦哦哦 | + {7: 6 }:哦{1:^哦}哦哦哦哦哦哦 | {3:-- TERMINAL --} | ]]) eq({6, 4}, eval('nvim_win_get_cursor(0)')) @@ -917,7 +923,7 @@ describe('buffer cursor position is correct in terminal with number column', fun {7: 3 } | {7: 4 } | {7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. | - {7: 6 }:aaaaaaaa {1: } | + {7: 6 }:aaaaaaaa {1:^ } | {3:-- TERMINAL --} | ]]) matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()')) From 9f6fc24bcbb89d75074a42a242c9dfced4238512 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 23 Jul 2023 08:53:59 +0800 Subject: [PATCH 2/4] test: check that TextChangedT cannot delete terminal buffer --- test/functional/autocmd/termxx_spec.lua | 20 ++++++++++++++++++++ test/functional/terminal/buffer_spec.lua | 8 -------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua index a9980dda04..d8d4e5eac4 100644 --- a/test/functional/autocmd/termxx_spec.lua +++ b/test/functional/autocmd/termxx_spec.lua @@ -1,5 +1,6 @@ local luv = require('luv') local helpers = require('test.functional.helpers')(after_each) +local thelpers = require('test.functional.terminal.helpers') local clear, command, nvim, testprg = helpers.clear, helpers.command, helpers.nvim, helpers.testprg @@ -8,6 +9,7 @@ local eval, eq, neq, retry = local matches = helpers.matches local ok = helpers.ok local feed = helpers.feed +local meths = helpers.meths local pcall_err = helpers.pcall_err local assert_alive = helpers.assert_alive local skip = helpers.skip @@ -162,3 +164,21 @@ it('autocmd TermEnter, TermLeave', function() }, eval('g:evs')) end) + +describe('autocmd TextChangedT', function() + clear() + local screen = thelpers.screen_setup() + + it('works', function() + command('autocmd TextChangedT * ++once let g:called = 1') + thelpers.feed_data('a') + retry(nil, nil, function() eq(1, meths.get_var('called')) end) + end) + + it('cannot delete terminal buffer', function() + command([[autocmd TextChangedT * call nvim_input('') | bwipe!]]) + thelpers.feed_data('a') + screen:expect({any = 'E937: '}) + matches('^E937: Attempt to delete a buffer that is in use: term://', meths.get_vvar('errmsg')) + end) +end) diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index 46aa059d5a..689ec8b6b7 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -413,14 +413,6 @@ describe('on_lines does not emit out-of-bounds line indexes when', function() feed_command('bdelete!') eq('', exec_lua([[return _G.cb_error]])) end) - - it('runs TextChangedT event', function() - meths.set_var('called', 0) - command('autocmd TextChangedT * ++once let g:called = 1') - feed_command('terminal') - feed('iaa') - eq(1, meths.get_var('called')) - end) end) it('terminal truncates number of composing characters to 5', function() From d0a6c1437dc59b3c7c036b192a1bde0580d48073 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 23 Jul 2023 12:46:56 +0800 Subject: [PATCH 3/4] test: reduce flakiness Avoid consecutive RPC requests involving :startinsert or :stopinsert, because consecutive RPC requests may be processed together, before the :startinsert or :stopinsert takes effect. Also change some feed_command() to command() to make tests faster. --- test/functional/terminal/buffer_spec.lua | 10 ++-- test/functional/terminal/cursor_spec.lua | 5 +- test/functional/terminal/ex_terminal_spec.lua | 10 ++-- test/functional/terminal/helpers.lua | 9 ++-- test/functional/terminal/scrollback_spec.lua | 5 +- test/functional/terminal/tui_spec.lua | 53 ++++++++++--------- 6 files changed, 46 insertions(+), 46 deletions(-) diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index 689ec8b6b7..83d16d95f4 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -24,8 +24,7 @@ describe(':terminal buffer', function() before_each(function() clear() - feed_command('set modifiable swapfile undolevels=20') - poke_eventloop() + command('set modifiable swapfile undolevels=20') screen = thelpers.screen_setup() end) @@ -198,8 +197,7 @@ describe(':terminal buffer', function() it('handles loss of focus gracefully', function() -- Change the statusline to avoid printing the file name, which varies. - nvim('set_option', 'statusline', '==========') - feed_command('set laststatus=0') + nvim('set_option_value', 'statusline', '==========', {}) -- Save the buffer number of the terminal for later testing. local tbuf = eval('bufnr("%")') @@ -232,8 +230,6 @@ describe(':terminal buffer', function() neq(tbuf, eval('bufnr("%")')) feed_command('quit!') -- Should exit the new window, not the terminal. eq(tbuf, eval('bufnr("%")')) - - feed_command('set laststatus=1') -- Restore laststatus to the default. end) it('term_close() use-after-free #4393', function() @@ -432,7 +428,7 @@ describe('terminal input', function() _G.input_data = _G.input_data .. data end }) ]]) - command('startinsert') + feed('i') poke_eventloop() end) diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua index 47bc02373c..8285bcc26e 100644 --- a/test/functional/terminal/cursor_spec.lua +++ b/test/functional/terminal/cursor_spec.lua @@ -6,7 +6,7 @@ local testprg, command = helpers.testprg, helpers.command local nvim_prog = helpers.nvim_prog local eq, eval = helpers.eq, helpers.eval local matches = helpers.matches -local feed_command = helpers.feed_command +local poke_eventloop = helpers.poke_eventloop local hide_cursor = thelpers.hide_cursor local show_cursor = thelpers.show_cursor local is_os = helpers.is_os @@ -153,7 +153,8 @@ describe('cursor with customized highlighting', function() }) screen:attach({rgb=false}) command('call termopen(["'..testprg('tty-test')..'"])') - feed_command('startinsert') + feed('i') + poke_eventloop() end) it('overrides the default highlighting', function() diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua index 6b7e93a864..ebb0253caa 100644 --- a/test/functional/terminal/ex_terminal_spec.lua +++ b/test/functional/terminal/ex_terminal_spec.lua @@ -99,7 +99,7 @@ describe(':terminal', function() end) it('nvim_get_mode() in :terminal', function() - command(':terminal') + command('terminal') eq({ blocking=false, mode='nt' }, nvim('get_mode')) feed('i') eq({ blocking=false, mode='t' }, nvim('get_mode')) @@ -108,17 +108,19 @@ describe(':terminal', function() end) it(':stopinsert RPC request exits terminal-mode #7807', function() - command(':terminal') + command('terminal') feed('i[tui] insert-mode') eq({ blocking=false, mode='t' }, nvim('get_mode')) command('stopinsert') + feed('') -- Add input to separate two RPC requests eq({ blocking=false, mode='nt' }, nvim('get_mode')) end) it(':stopinsert in normal mode doesn\'t break insert mode #9889', function() - command(':terminal') + command('terminal') eq({ blocking=false, mode='nt' }, nvim('get_mode')) - command(':stopinsert') + command('stopinsert') + feed('') -- Add input to separate two RPC requests eq({ blocking=false, mode='nt' }, nvim('get_mode')) feed('a') eq({ blocking=false, mode='t' }, nvim('get_mode')) diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua index 7247361649..62d3dd67a3 100644 --- a/test/functional/terminal/helpers.lua +++ b/test/functional/terminal/helpers.lua @@ -5,7 +5,7 @@ local helpers = require('test.functional.helpers')(nil) local Screen = require('test.functional.ui.screen') local testprg = helpers.testprg local exec_lua = helpers.exec_lua -local feed_command, nvim = helpers.feed_command, helpers.nvim +local nvim = helpers.nvim local function feed_data(data) if type(data) == 'table' then @@ -82,15 +82,16 @@ local function screen_setup(extra_rows, command, cols, opts) screen:attach(opts or {rgb=false}) - feed_command('enew | call termopen('..command..')') + nvim('command', 'enew | call termopen('..command..')') nvim('input', '') local vim_errmsg = nvim('eval', 'v:errmsg') if vim_errmsg and "" ~= vim_errmsg then error(vim_errmsg) end - feed_command('setlocal scrollback=10') - feed_command('startinsert') + nvim('command', 'setlocal scrollback=10') + nvim('command', 'startinsert') + nvim('input', '') -- Add input to separate two RPC requests -- tty-test puts the terminal into raw mode and echoes input. Tests work by -- feeding termcodes to control the display and asserting by screen:expect. diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua index 5d967e0340..3fab74b911 100644 --- a/test/functional/terminal/scrollback_spec.lua +++ b/test/functional/terminal/scrollback_spec.lua @@ -2,7 +2,7 @@ local Screen = require('test.functional.ui.screen') local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf -local feed, testprg, feed_command = helpers.feed, helpers.testprg, helpers.feed_command +local feed, testprg = helpers.feed, helpers.testprg local eval = helpers.eval local command = helpers.command local matches = helpers.matches @@ -349,8 +349,7 @@ describe(':terminal prints more lines than the screen height and exits', functio clear() local screen = Screen.new(30, 7) screen:attach({rgb=false}) - feed_command(("call termopen(['%s', '10']) | startinsert"):format(testprg('tty-test'))) - poke_eventloop() + command(("call termopen(['%s', '10']) | startinsert"):format(testprg('tty-test'))) screen:expect([[ line6 | line7 | diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index dcf388e9aa..921ff29190 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -8,7 +8,6 @@ local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local Screen = require('test.functional.ui.screen') local eq = helpers.eq -local feed_command = helpers.feed_command local feed_data = thelpers.feed_data local clear = helpers.clear local command = helpers.command @@ -109,14 +108,14 @@ describe('TUI', function() end) it('accepts resize while pager is active', function() - child_session:request("nvim_exec", [[ - set more - func! ManyErr() - for i in range(20) - echoerr "FAIL ".i - endfor - endfunc - ]], false) + child_session:request('nvim_exec2', [[ + set more + func! ManyErr() + for i in range(20) + echoerr "FAIL ".i + endfor + endfunc + ]], {}) feed_data(':call ManyErr()\r') screen:expect{grid=[[ {8:Error detected while processing function ManyErr:} | @@ -240,7 +239,7 @@ describe('TUI', function() it('interprets leading byte as ALT modifier in normal-mode', function() local keys = 'dfghjkl' for c in keys:gmatch('.') do - feed_command('nnoremap ialt-'..c..'') + feed_data(':nnoremap ialt-'..c..'\r') feed_data('\027'..c) end screen:expect([[ @@ -280,9 +279,11 @@ describe('TUI', function() end) it('interprets [27u as ', function() - feed_command('nnoremap ') - feed_command('nnoremap AESC') - feed_command('nnoremap ; Asemicolon') + child_session:request('nvim_exec2', [[ + nnoremap + nnoremap AESC + nnoremap ; Asemicolon + ]], {}) feed_data('\027[27u;') screen:expect([[ ESCsemicolo{1:n} | @@ -330,11 +331,11 @@ describe('TUI', function() end) it('accepts mouse wheel events #19992', function() - child_session:request('nvim_exec', [[ + child_session:request('nvim_exec2', [[ set number nostartofline nowrap mousescroll=hor:1,ver:1 call setline(1, repeat([join(range(10), '----')], 10)) vsplit - ]], false) + ]], {}) screen:expect([[ {11: 1 }{1:0}----1----2----3----4│{11: 1 }0----1----2----3----| {11: 2 }0----1----2----3----4│{11: 2 }0----1----2----3----| @@ -660,11 +661,11 @@ describe('TUI', function() | {3:-- TERMINAL --} | ]]) - child_session:request('nvim_exec', [[ + child_session:request('nvim_exec2', [[ tab split tabnew highlight Tabline ctermbg=NONE ctermfg=NONE cterm=underline - ]], false) + ]], {}) screen:expect([[ {12: + [No Name] + [No Name] }{3: [No Name] }{1: }{12:X}| {1: } | @@ -719,7 +720,7 @@ describe('TUI', function() end) it('mouse events work with right-click menu', function() - child_session:request('nvim_exec', [[ + child_session:request('nvim_exec2', [[ call setline(1, 'popup menu test') set mouse=a mousemodel=popup @@ -729,7 +730,7 @@ describe('TUI', function() menu PopUp.baz :let g:menustr = 'baz' highlight Pmenu ctermbg=NONE ctermfg=NONE cterm=underline,reverse highlight PmenuSel ctermbg=NONE ctermfg=NONE cterm=underline,reverse,bold - ]], false) + ]], {}) meths.input_mouse('right', 'press', '', 0, 0, 4) screen:expect([[ {1:p}opup menu test | @@ -1583,11 +1584,11 @@ describe('TUI', function() it('no stack-use-after-scope with cursor color #22432', function() screen:set_option('rgb', true) command('set termguicolors') - child_session:request('nvim_exec', [[ + child_session:request('nvim_exec2', [[ set tgc hi Cursor guifg=Red guibg=Green set guicursor=n:block-Cursor/lCursor - ]], false) + ]], {}) screen:set_default_attr_ids({ [1] = {reverse = true}, [2] = {bold = true, foreground = Screen.colors.Blue}, @@ -1771,10 +1772,10 @@ describe('TUI FocusGained/FocusLost', function() {3:-- TERMINAL --} | ]]) child_session = helpers.connect(child_server) - child_session:request('nvim_exec', [[ + child_session:request('nvim_exec2', [[ autocmd FocusGained * echo 'gained' autocmd FocusLost * echo 'lost' - ]], false) + ]], {}) feed_data("\034\016") -- CTRL-\ CTRL-N end) @@ -1805,7 +1806,7 @@ describe('TUI FocusGained/FocusLost', function() end) it('in insert-mode', function() - feed_command('set noshowmode') + feed_data(':set noshowmode\r') feed_data('i') screen:expect{grid=[[ {1: } | @@ -1870,11 +1871,11 @@ describe('TUI FocusGained/FocusLost', function() -- Set up autocmds that modify the buffer, instead of just calling :echo. -- This is how we can test handling of focus gained/lost during cmdline-mode. -- See commit: 5cc87d4dabd02167117be7a978b5c8faaa975419. - child_session:request('nvim_exec', [[ + child_session:request('nvim_exec2', [[ autocmd! autocmd FocusLost * call append(line('$'), 'lost') autocmd FocusGained * call append(line('$'), 'gained') - ]], false) + ]], {}) retry(2, 3 * screen.timeout, function() -- Enter cmdline-mode. feed_data(':') From f33d49a7a792c66b341a664a4af05f1fd7ea1f5b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 28 Jul 2023 15:41:58 +0800 Subject: [PATCH 4/4] fix(inccommand): don't save information of a buffer twice Problem: 'inccommand' doesn't restore 'undolevels' properly for a buffer shown in multiple windows. Solution: Don't save information of a buffer twice. --- src/nvim/ex_getln.c | 29 +++++++++++++++----------- test/functional/ui/inccommand_spec.lua | 10 +++++---- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 97336a5fd5..4a5f3ad9f6 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2328,6 +2328,8 @@ static void cmdpreview_restore_undo(const CpUndoInfo *cp_undoinfo, buf_T *buf) static void cmdpreview_prepare(CpInfo *cpinfo) FUNC_ATTR_NONNULL_ALL { + PMap(ptr_t) saved_bufs = MAP_INIT; + kv_init(cpinfo->buf_info); kv_init(cpinfo->win_info); @@ -2339,19 +2341,19 @@ static void cmdpreview_prepare(CpInfo *cpinfo) continue; } - CpBufInfo cp_bufinfo; - cp_bufinfo.buf = buf; + if (!pmap_has(ptr_t)(&saved_bufs, buf)) { + CpBufInfo cp_bufinfo; + cp_bufinfo.buf = buf; + cp_bufinfo.save_b_p_ul = buf->b_p_ul; + cp_bufinfo.save_b_changed = buf->b_changed; + cp_bufinfo.save_changedtick = buf_get_changedtick(buf); + cmdpreview_save_undo(&cp_bufinfo.undo_info, buf); + kv_push(cpinfo->buf_info, cp_bufinfo); + pmap_put(ptr_t)(&saved_bufs, buf, NULL); - cp_bufinfo.save_b_p_ul = buf->b_p_ul; - cp_bufinfo.save_b_changed = buf->b_changed; - cp_bufinfo.save_changedtick = buf_get_changedtick(buf); - - cmdpreview_save_undo(&cp_bufinfo.undo_info, buf); - u_clearall(buf); - - kv_push(cpinfo->buf_info, cp_bufinfo); - - buf->b_p_ul = LONG_MAX; // Make sure we can undo all changes + u_clearall(buf); + buf->b_p_ul = LONG_MAX; // Make sure we can undo all changes + } CpWinInfo cp_wininfo; cp_wininfo.win = win; @@ -2370,6 +2372,8 @@ static void cmdpreview_prepare(CpInfo *cpinfo) win->w_p_cuc = false; // Disable 'cursorcolumn' so it doesn't mess up the highlights } + pmap_destroy(ptr_t)(&saved_bufs); + cpinfo->save_hls = p_hls; cpinfo->save_cmdmod = cmdmod; win_size_save(&cpinfo->save_view); @@ -2426,6 +2430,7 @@ static void cmdpreview_restore_state(CpInfo *cpinfo) // Clear preview highlights. extmark_clear(buf, (uint32_t)cmdpreview_ns, 0, 0, MAXLNUM, MAXCOL); } + for (size_t i = 0; i < cpinfo->win_info.size; i++) { CpWinInfo cp_wininfo = cpinfo->win_info.items[i]; win_T *win = cp_wininfo.win; diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 96634be327..7f05f0f901 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -2,7 +2,6 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear = helpers.clear local command = helpers.command -local curbufmeths = helpers.curbufmeths local eq = helpers.eq local eval = helpers.eval local feed_command = helpers.feed_command @@ -175,11 +174,14 @@ describe(":substitute, 'inccommand' preserves", function() it("'undolevels' (inccommand="..case..")", function() feed_command("set undolevels=139") feed_command("setlocal undolevels=34") + feed_command("split") -- Show the buffer in multiple windows feed_command("set inccommand=" .. case) insert("as") - feed(":%s/as/glork/") - eq(meths.get_option('undolevels'), 139) - eq(curbufmeths.get_option('undolevels'), 34) + feed(":%s/as/glork/") + poke_eventloop() + feed("") + eq(meths.get_option_value('undolevels', {scope='global'}), 139) + eq(meths.get_option_value('undolevels', {buf=0}), 34) end) end