diff options
Diffstat (limited to 'test/functional')
36 files changed, 1638 insertions, 411 deletions
diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua index 933103046c..c4197f0b3e 100644 --- a/test/functional/api/highlight_spec.lua +++ b/test/functional/api/highlight_spec.lua @@ -34,6 +34,7 @@ describe('API: highlight',function() underdotted = true, underdashed = true, strikethrough = true, + nocombine = true, } before_each(function() @@ -55,7 +56,7 @@ describe('API: highlight',function() eq('Invalid highlight id: 30000', string.match(emsg, 'Invalid.*')) -- Test all highlight properties. - command('hi NewHighlight gui=underline,bold,undercurl,underdouble,underdotted,underdashed,italic,reverse,strikethrough') + command('hi NewHighlight gui=underline,bold,undercurl,underdouble,underdotted,underdashed,italic,reverse,strikethrough,nocombine') eq(expected_rgb2, nvim("get_hl_by_id", hl_id, true)) -- Test nil argument. @@ -136,10 +137,10 @@ describe('API: highlight',function() -- Test cterm & Normal values. #18024 (tail) & #18980 -- Ensure Normal, and groups that match Normal return their fg & bg cterm values meths.set_hl(0, 'Normal', {ctermfg = 17, ctermbg = 213}) - meths.set_hl(0, 'NotNormal', {ctermfg = 17, ctermbg = 213}) + meths.set_hl(0, 'NotNormal', {ctermfg = 17, ctermbg = 213, nocombine = true}) -- Note colors are "cterm" values, not rgb-as-ints eq({foreground = 17, background = 213}, nvim("get_hl_by_name", 'Normal', false)) - eq({foreground = 17, background = 213}, nvim("get_hl_by_name", 'NotNormal', false)) + eq({foreground = 17, background = 213, nocombine = true}, nvim("get_hl_by_name", 'NotNormal', false)) end) it('nvim_get_hl_id_by_name', function() @@ -214,6 +215,7 @@ describe("API: set highlight", function() reverse = true, undercurl = true, strikethrough = true, + nocombine = true, } } local highlight3_result_gui = { @@ -236,6 +238,7 @@ describe("API: set highlight", function() reverse = true, undercurl = true, strikethrough = true, + nocombine = true, } local function get_ns() @@ -290,7 +293,7 @@ describe("API: set highlight", function() exec_capture('highlight Test_hl')) meths.set_hl(0, 'Test_hl2', highlight3_config) - eq('Test_hl2 xxx cterm=undercurl,italic,reverse,strikethrough ctermfg=8 ctermbg=15 gui=bold,underline,undercurl,underdouble,underdotted,underdashed,italic,reverse,strikethrough guifg=#ff0000 guibg=#0032aa', + eq('Test_hl2 xxx cterm=undercurl,italic,reverse,strikethrough,nocombine ctermfg=8 ctermbg=15 gui=bold,underline,undercurl,underdouble,underdotted,underdashed,italic,reverse,strikethrough guifg=#ff0000 guibg=#0032aa', exec_capture('highlight Test_hl2')) -- Colors are stored with the name they are defined, but diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua index 6bc6651e04..eb2a467a8b 100644 --- a/test/functional/api/keymap_spec.lua +++ b/test/functional/api/keymap_spec.lua @@ -25,6 +25,7 @@ describe('nvim_get_keymap', function() local foo_bar_string = 'nnoremap foo bar' local foo_bar_map_table = { lhs='foo', + lhsraw='foo', script=0, silent=0, rhs='bar', @@ -56,6 +57,7 @@ describe('nvim_get_keymap', function() command('nnoremap foo_longer bar_longer') local foolong_bar_map_table = shallowcopy(foo_bar_map_table) foolong_bar_map_table['lhs'] = 'foo_longer' + foolong_bar_map_table['lhsraw'] = 'foo_longer' foolong_bar_map_table['rhs'] = 'bar_longer' eq({foolong_bar_map_table, foo_bar_map_table}, @@ -87,6 +89,7 @@ describe('nvim_get_keymap', function() command('nnoremap foo_longer bar_longer') local foolong_bar_map_table = shallowcopy(foo_bar_map_table) foolong_bar_map_table['lhs'] = 'foo_longer' + foolong_bar_map_table['lhsraw'] = 'foo_longer' foolong_bar_map_table['rhs'] = 'bar_longer' local buffer_table = shallowcopy(foo_bar_map_table) @@ -283,6 +286,16 @@ describe('nvim_get_keymap', function() command('onoremap \\<C-a><C-a><LT>C-a>\\ \\<C-b><C-b><LT>C-b>\\') command('onoremap <special> \\<C-c><C-c><LT>C-c>\\ \\<C-d><C-d><LT>C-d>\\') + -- wrapper around get_keymap() that drops "lhsraw" and "lhsrawalt" which are hard to check + local function get_keymap_noraw(...) + local ret = meths.get_keymap(...) + for _, item in ipairs(ret) do + item.lhsraw = nil + item.lhsrawalt = nil + end + return ret + end + for _, cmd in ipairs({ 'set cpo-=B', 'set cpo+=B', @@ -290,22 +303,23 @@ describe('nvim_get_keymap', function() command(cmd) eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'), cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n')}, - meths.get_keymap('n')) + get_keymap_noraw('n')) eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'), cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x')}, - meths.get_keymap('x')) + get_keymap_noraw('x')) eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'), cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's')}, - meths.get_keymap('s')) + get_keymap_noraw('s')) eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'), cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o')}, - meths.get_keymap('o')) + get_keymap_noraw('o')) end end) it('always uses space for space and bar for bar', function() local space_table = { lhs='| |', + lhsraw='| |', rhs='| |', mode='n', script=0, @@ -340,6 +354,7 @@ describe('nvim_get_keymap', function() mapargs[1].callback = nil eq({ lhs='asdf', + lhsraw='asdf', script=0, silent=0, expr=0, @@ -356,6 +371,7 @@ describe('nvim_get_keymap', function() meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"}) eq({ lhs='lhs', + lhsraw='lhs', rhs='rhs', script=0, silent=0, @@ -413,7 +429,11 @@ describe('nvim_set_keymap, nvim_del_keymap', function() -- Gets a maparg() dict from Nvim, if one exists. local function get_mapargs(mode, lhs) - return funcs.maparg(lhs, normalize_mapmode(mode), false, true) + local mapargs = funcs.maparg(lhs, normalize_mapmode(mode), false, true) + -- drop "lhsraw" and "lhsrawalt" which are hard to check + mapargs.lhsraw = nil + mapargs.lhsrawalt = nil + return mapargs end it('error on empty LHS', function() @@ -503,6 +523,11 @@ describe('nvim_set_keymap, nvim_del_keymap', function() pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {buffer = true})) end) + it('error when "replace_keycodes" is used without "expr"', function() + eq('"replace_keycodes" requires "expr"', + pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {replace_keycodes = true})) + end) + local optnames = {'nowait', 'silent', 'script', 'expr', 'unique'} for _, opt in ipairs(optnames) do -- note: need '%' to escape hyphens, which have special meaning in lua @@ -817,17 +842,39 @@ describe('nvim_set_keymap, nvim_del_keymap', function() local mapargs = funcs.maparg('asdf', 'n', false, true) assert(type(mapargs.callback) == 'number', 'callback is not luaref number') mapargs.callback = nil + mapargs.lhsraw = nil + mapargs.lhsrawalt = nil eq(generate_mapargs('n', 'asdf', nil, {sid=sid_lua}), mapargs) end) - it('can make lua expr mappings', function() + it('can make lua expr mappings replacing keycodes', function() exec_lua [[ - vim.api.nvim_set_keymap ('n', 'aa', '', {callback = function() return vim.api.nvim_replace_termcodes(':lua SomeValue = 99<cr>', true, false, true) end, expr = true }) + vim.api.nvim_set_keymap ('n', 'aa', '', {callback = function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, expr = true, replace_keycodes = true }) ]] feed('aa') - eq(99, exec_lua[[return SomeValue]]) + eq({'π<M-π>foo<'}, meths.buf_get_lines(0, 0, -1, false)) + end) + + it('can make lua expr mappings without replacing keycodes', function() + exec_lua [[ + vim.api.nvim_set_keymap ('i', 'aa', '', {callback = function() return '<space>' end, expr = true }) + ]] + + feed('iaa<esc>') + + eq({'<space>'}, meths.buf_get_lines(0, 0, -1, false)) + end) + + it('lua expr mapping returning nil is equivalent to returnig an empty string', function() + exec_lua [[ + vim.api.nvim_set_keymap ('i', 'aa', '', {callback = function() return nil end, expr = true }) + ]] + + feed('iaa<esc>') + + eq({''}, meths.buf_get_lines(0, 0, -1, false)) end) it('does not reset pum in lua mapping', function() @@ -1018,16 +1065,27 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() eq(1, exec_lua[[return GlobalCount]]) end) - it('can make lua expr mappings', function() + it('can make lua expr mappings replacing keycodes', function() exec_lua [[ - vim.api.nvim_buf_set_keymap (0, 'n', 'aa', '', {callback = function() return vim.api.nvim_replace_termcodes(':lua SomeValue = 99<cr>', true, false, true) end, expr = true }) + vim.api.nvim_buf_set_keymap (0, 'n', 'aa', '', {callback = function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, expr = true, replace_keycodes = true }) ]] feed('aa') - eq(99, exec_lua[[return SomeValue ]]) + eq({'π<M-π>foo<'}, meths.buf_get_lines(0, 0, -1, false)) + end) + + it('can make lua expr mappings without replacing keycodes', function() + exec_lua [[ + vim.api.nvim_buf_set_keymap (0, 'i', 'aa', '', {callback = function() return '<space>' end, expr = true }) + ]] + + feed('iaa<esc>') + + eq({'<space>'}, meths.buf_get_lines(0, 0, -1, false)) end) + it('can overwrite lua mappings', function() eq(0, exec_lua [[ GlobalCount = 0 diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 3724dbf820..17de6730fb 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3733,6 +3733,12 @@ describe('API', function() eq("", meths.cmd({ cmd = "Foo", bang = false }, { output = true })) end) it('works with modifiers', function() + -- with :silent output is still captured + eq('1', + meths.cmd({ cmd = 'echomsg', args = { '1' }, mods = { silent = true } }, + { output = true })) + -- with :silent message isn't added to message history + eq('', meths.cmd({ cmd = 'messages' }, { output = true })) meths.create_user_command("Foo", 'set verbose', {}) eq(" verbose=1", meths.cmd({ cmd = "Foo", mods = { verbose = 1 } }, { output = true })) eq(0, meths.get_option_value("verbose", {})) diff --git a/test/functional/editor/mark_spec.lua b/test/functional/editor/mark_spec.lua index 1eb76aa628..2440867c6e 100644 --- a/test/functional/editor/mark_spec.lua +++ b/test/functional/editor/mark_spec.lua @@ -157,6 +157,13 @@ describe('named marks', function() os.remove(file1) end) + it("errors when using a mark in another buffer in command range", function() + feed('ifoo<Esc>mA') + command('enew') + feed('ibar<Esc>') + eq('Vim(print):E20: Mark not set', pcall_err(command, [['Aprint]])) + end) + it("leave a context mark when moving with '", function() command("edit " .. file1) feed("llmamA") diff --git a/test/functional/editor/meta_key_spec.lua b/test/functional/editor/meta_key_spec.lua index 23964ca10f..825b20138a 100644 --- a/test/functional/editor/meta_key_spec.lua +++ b/test/functional/editor/meta_key_spec.lua @@ -91,7 +91,7 @@ describe('meta-keys #8226 #13042', function() command('tnoremap <A-j> alt-j') feed('i<M-l> xxx <A-j>') eq('meta-l xxx alt-j', exec_lua([[return _G.input_data]])) - -- Unmapped ALT-chord is sent to terminal as-is. #16220 + -- Unmapped ALT-chord is sent to terminal as-is. #16202 #16220 exec_lua([[_G.input_data = '']]) command('tunmap <M-l>') feed('<M-l>') diff --git a/test/functional/editor/put_spec.lua b/test/functional/editor/put_spec.lua index cc9fce8f67..5050edff5c 100644 --- a/test/functional/editor/put_spec.lua +++ b/test/functional/editor/put_spec.lua @@ -879,9 +879,13 @@ describe('put command', function() ine of words 2]], curbuf_contents()) end) - local function bell_test(actions, should_ring) - local screen = Screen.new() + local screen + setup(function() + screen = Screen.new() screen:attach() + end) + + local function bell_test(actions, should_ring) if should_ring then -- check bell is not set by nvim before the action screen:sleep(50) @@ -899,7 +903,6 @@ describe('put command', function() end end end, unchanged=(not should_ring)} - screen:detach() end it('should not ring the bell with gp at end of line', function() diff --git a/test/functional/editor/tabpage_spec.lua b/test/functional/editor/tabpage_spec.lua index 3b2c1db350..7dd0b9f154 100644 --- a/test/functional/editor/tabpage_spec.lua +++ b/test/functional/editor/tabpage_spec.lua @@ -1,4 +1,5 @@ local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') local clear = helpers.clear local command = helpers.command @@ -53,6 +54,46 @@ describe('tabpage', function() neq(999, eval('g:win_closed')) end) + it('switching tabpage after setting laststatus=3 #19591', function() + local screen = Screen.new(40, 8) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, + [1] = {bold = true, reverse = true}, -- StatusLine + [2] = {reverse = true}, -- StatusLineNC, TabLineFill + [3] = {bold = true}, -- TabLineSel + [4] = {background = Screen.colors.LightGrey, underline = true}, -- TabLine + [5] = {bold = true, foreground = Screen.colors.Magenta}, + }) + screen:attach() + + command('tabnew') + command('tabprev') + command('set laststatus=3') + command('tabnext') + feed('<C-G>') + screen:expect([[ + {4: [No Name] }{3: [No Name] }{2: }{4:X}| + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {1:[No Name] }| + "[No Name]" --No lines in buffer-- | + ]]) + command('vnew') + screen:expect([[ + {4: [No Name] }{3: }{5:2}{3: [No Name] }{2: }{4:X}| + ^ │ | + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {1:[No Name] }| + "[No Name]" --No lines in buffer-- | + ]]) + end) + it(":tabmove handles modifiers and addr", function() command('tabnew | tabnew | tabnew') eq(4, funcs.nvim_tabpage_get_number(0)) diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua index 1553de4432..ee8da2932d 100644 --- a/test/functional/ex_cmds/mksession_spec.lua +++ b/test/functional/ex_cmds/mksession_spec.lua @@ -14,7 +14,6 @@ local pesc = helpers.pesc local rmdir = helpers.rmdir local sleep = helpers.sleep local meths = helpers.meths -local expect_exit = helpers.expect_exit local file_prefix = 'Xtest-functional-ex_cmds-mksession_spec' @@ -42,18 +41,85 @@ describe(':mksession', function() command('split') command('terminal') command('split') - command('mksession '..session_file) + command('mksession ' .. session_file) + command('%bwipeout!') -- Create a new test instance of Nvim. - expect_exit(command, 'qall!') clear() -- Restore session. - command('source '..session_file) + command('source ' .. session_file) eq(funcs.winbufnr(1), funcs.winbufnr(2)) neq(funcs.winbufnr(1), funcs.winbufnr(3)) end) + -- common testing procedure for testing "sessionoptions-=terminal" + local function test_terminal_session_disabled(expected_buf_count) + command('set sessionoptions-=terminal') + + command('mksession ' .. session_file) + + -- Create a new test instance of Nvim. + clear() + + -- Restore session. + command('source ' .. session_file) + + eq(expected_buf_count, #meths.list_bufs()) + end + + it( + 'do not restore :terminal if not set in sessionoptions, terminal in current window #13078', + function() + local tmpfile_base = file_prefix .. '-tmpfile' + command('edit ' .. tmpfile_base) + command('terminal') + + local buf_count = #meths.list_bufs() + eq(2, buf_count) + + eq('terminal', meths.buf_get_option(0, 'buftype')) + + test_terminal_session_disabled(2) + + -- no terminal should be set. As a side effect we end up with a blank buffer + eq('', meths.buf_get_option(meths.list_bufs()[1], 'buftype')) + eq('', meths.buf_get_option(meths.list_bufs()[2], 'buftype')) + end + ) + + it('do not restore :terminal if not set in sessionoptions, terminal hidden #13078', function() + command('terminal') + local terminal_bufnr = meths.get_current_buf() + + local tmpfile_base = file_prefix .. '-tmpfile' + -- make terminal hidden by opening a new file + command('edit ' .. tmpfile_base .. '1') + + local buf_count = #meths.list_bufs() + eq(2, buf_count) + + eq(1, funcs.getbufinfo(terminal_bufnr)[1].hidden) + + test_terminal_session_disabled(1) + + -- no terminal should exist here + neq('', meths.buf_get_name(meths.list_bufs()[1])) + end) + + it('do not restore :terminal if not set in sessionoptions, only buffer #13078', function() + command('terminal') + eq('terminal', meths.buf_get_option(0, 'buftype')) + + local buf_count = #meths.list_bufs() + eq(1, buf_count) + + test_terminal_session_disabled(1) + + -- no terminal should be set + eq('', meths.buf_get_option(0, 'buftype')) + end) + it('restores tab-local working directories', function() local tmpfile_base = file_prefix .. '-tmpfile' local cwd_dir = funcs.getcwd() @@ -103,28 +169,27 @@ describe(':mksession', function() it('restores CWD for :terminal buffers #11288', function() local cwd_dir = funcs.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '') - cwd_dir = cwd_dir:gsub([[\]], '/') -- :mksession always uses unix slashes. - local session_path = cwd_dir..'/'..session_file + cwd_dir = cwd_dir:gsub([[\]], '/') -- :mksession always uses unix slashes. + local session_path = cwd_dir .. '/' .. session_file - command('cd '..tab_dir) + command('cd ' .. tab_dir) command('terminal') - command('cd '..cwd_dir) - command('mksession '..session_path) - command('bdelete!') + command('cd ' .. cwd_dir) + command('mksession ' .. session_path) + command('%bwipeout!') if iswin() then - sleep(100) -- Make sure all child processes have exited. + sleep(100) -- Make sure all child processes have exited. end - expect_exit(command, 'qall!') -- Create a new test instance of Nvim. clear() - command('silent source '..session_path) + command('silent source ' .. session_path) - local expected_cwd = cwd_dir..'/'..tab_dir - matches('^term://'..pesc(expected_cwd)..'//%d+:', funcs.expand('%')) - command('bdelete!') + local expected_cwd = cwd_dir .. '/' .. tab_dir + matches('^term://' .. pesc(expected_cwd) .. '//%d+:', funcs.expand('%')) + command('%bwipeout!') if iswin() then - sleep(100) -- Make sure all child processes have exited. + sleep(100) -- Make sure all child processes have exited. end end) @@ -136,10 +201,10 @@ describe(':mksession', function() local screen local cwd_dir = funcs.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '') - local session_path = cwd_dir..'/'..session_file + local session_path = cwd_dir .. '/' .. session_file screen = Screen.new(50, 6) - screen:attach({rgb=false}) + screen:attach({ rgb = false }) local expected_screen = [[ ^/ | | @@ -155,15 +220,15 @@ describe(':mksession', function() -- Verify that the terminal's working directory is "/". screen:expect(expected_screen) - command('cd '..cwd_dir) - command('mksession '..session_path) - expect_exit(command, 'qall!') + command('cd ' .. cwd_dir) + command('mksession ' .. session_path) + command('%bwipeout!') -- Create a new test instance of Nvim. clear() screen = Screen.new(50, 6) - screen:attach({rgb=false}) - command('silent source '..session_path) + screen:attach({ rgb = false }) + command('silent source ' .. session_path) -- Verify that the terminal's working directory is "/". screen:expect(expected_screen) @@ -181,7 +246,7 @@ describe(':mksession', function() height = 3, row = 0, col = 1, - style = 'minimal' + style = 'minimal', } meths.open_win(buf, false, config) local cmdheight = meths.get_option('cmdheight') diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua index 0dc0c8c2db..aa47198f7a 100644 --- a/test/functional/fixtures/fake-lsp-server.lua +++ b/test/functional/fixtures/fake-lsp-server.lua @@ -67,10 +67,12 @@ local function expect_notification(method, params, ...) local message = read_message() assert_eq(method, message.method, ..., "expect_notification", "method") - assert_eq(params, message.params, - ..., "expect_notification", method, "params") - assert_eq({jsonrpc = "2.0"; method=method, params=params}, message, - ..., "expect_notification", "message") + if params then + assert_eq(params, message.params, + ..., "expect_notification", method, "params") + assert_eq({jsonrpc = "2.0"; method=method, params=params}, message, + ..., "expect_notification", "message") + end end local function expect_request(method, handler, ...) @@ -257,6 +259,26 @@ function tests.basic_check_capabilities() } end +function tests.text_document_save_did_open() + skeleton { + on_init = function() + return { + capabilities = { + textDocumentSync = { + save = true + } + } + } + end; + body = function() + notify('start') + expect_notification('textDocument/didOpen') + expect_notification('textDocument/didSave') + notify('shutdown') + end; + } +end + function tests.text_document_sync_save_bool() skeleton { on_init = function() diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 0c616e73fb..8c5a60657a 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -271,10 +271,22 @@ function module.command(cmd) end --- use for commands which expect nvim to quit -function module.expect_exit(...) - eq("EOF was received from Nvim. Likely the Nvim process crashed.", - module.pcall_err(...)) +-- Use for commands which expect nvim to quit. +-- The first argument can also be a timeout. +function module.expect_exit(fn_or_timeout, ...) + local eof_err_msg = 'EOF was received from Nvim. Likely the Nvim process crashed.' + if type(fn_or_timeout) == 'function' then + eq(eof_err_msg, module.pcall_err(fn_or_timeout, ...)) + else + eq(eof_err_msg, module.pcall_err(function(timeout, fn, ...) + fn(...) + while session:next_message(timeout) do + end + if session.eof_err then + error(session.eof_err[2]) + end + end, fn_or_timeout, ...)) + end end -- Evaluates a VimL expression. diff --git a/test/functional/legacy/075_maparg_spec.lua b/test/functional/legacy/075_maparg_spec.lua deleted file mode 100644 index ad6c190104..0000000000 --- a/test/functional/legacy/075_maparg_spec.lua +++ /dev/null @@ -1,59 +0,0 @@ --- Tests for maparg(). --- Also test utf8 map with a 0x80 byte. - -local helpers = require('test.functional.helpers')(after_each) -local clear, feed = helpers.clear, helpers.feed -local command, expect = helpers.command, helpers.expect -local poke_eventloop = helpers.poke_eventloop - -describe('maparg()', function() - setup(clear) - - it('is working', function() - command('set cpo-=<') - - -- Test maparg() with a string result - command('map foo<C-V> is<F4>foo') - command('vnoremap <script> <buffer> <expr> <silent> bar isbar') - command([[call append('$', maparg('foo<C-V>'))]]) - command([[call append('$', string(maparg('foo<C-V>', '', 0, 1)))]]) - command([[call append('$', string(maparg('bar', '', 0, 1)))]]) - command('map <buffer> <nowait> foo bar') - command([[call append('$', string(maparg('foo', '', 0, 1)))]]) - command('map abc x<char-114>x') - command([[call append('$', maparg('abc'))]]) - command('map abc y<S-char-114>y') - command([[call append('$', maparg('abc'))]]) - feed('Go<esc>:<cr>') - poke_eventloop() - - -- Outside of the range, minimum - command('inoremap <Char-0x1040> a') - command([[execute "normal a\u1040\<Esc>"]]) - - -- Inside of the range, minimum - command('inoremap <Char-0x103f> b') - command([[execute "normal a\u103f\<Esc>"]]) - - -- Inside of the range, maximum - command('inoremap <Char-0xf03f> c') - command([[execute "normal a\uf03f\<Esc>"]]) - - -- Outside of the range, maximum - command('inoremap <Char-0xf040> d') - command([[execute "normal a\uf040\<Esc>"]]) - - -- Remove empty line - command('1d') - - -- Assert buffer contents. - expect([[ - is<F4>foo - {'lnum': 0, 'script': 0, 'silent': 0, 'noremap': 0, 'lhs': 'foo<C-V>', 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': 0, 'rhs': 'is<F4>foo', 'buffer': 0} - {'lnum': 0, 'script': 1, 'silent': 1, 'noremap': 1, 'lhs': 'bar', 'mode': 'v', 'nowait': 0, 'expr': 1, 'sid': 0, 'rhs': 'isbar', 'buffer': 1} - {'lnum': 0, 'script': 0, 'silent': 0, 'noremap': 0, 'lhs': 'foo', 'mode': ' ', 'nowait': 1, 'expr': 0, 'sid': 0, 'rhs': 'bar', 'buffer': 1} - xrx - yRy - abcd]]) - end) -end) diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua index 8379e426e0..f90da16d7b 100644 --- a/test/functional/legacy/arglist_spec.lua +++ b/test/functional/legacy/arglist_spec.lua @@ -4,6 +4,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, command, eq = helpers.clear, helpers.command, helpers.eq local eval, exc_exec, neq = helpers.eval, helpers.exc_exec, helpers.neq +local expect_exit = helpers.expect_exit local feed = helpers.feed local pcall_err = helpers.pcall_err @@ -275,6 +276,6 @@ describe('argument list commands', function() 2 more files to edit. Quit anyway? | [Y]es, (N)o: ^ | ]]) - feed('Y') + expect_exit(100, feed, 'Y') end) end) diff --git a/test/functional/legacy/cmdline_spec.lua b/test/functional/legacy/cmdline_spec.lua index d8d849271b..cf02636890 100644 --- a/test/functional/legacy/cmdline_spec.lua +++ b/test/functional/legacy/cmdline_spec.lua @@ -3,11 +3,12 @@ local Screen = require('test.functional.ui.screen') local clear = helpers.clear local feed = helpers.feed local feed_command = helpers.feed_command -local source = helpers.source +local exec = helpers.exec describe('cmdline', function() before_each(clear) + -- oldtest: Test_cmdlineclear_tabenter() it('is cleared when switching tabs', function() local screen = Screen.new(30, 10) screen:attach() @@ -91,10 +92,11 @@ describe('cmdline', function() ]]) end) + -- oldtest: Test_verbose_option() it('prints every executed Ex command if verbose >= 16', function() local screen = Screen.new(60, 12) screen:attach() - source([[ + exec([[ command DoSomething echo 'hello' |set ts=4 |let v = '123' |echo v call feedkeys("\r", 't') " for the hit-enter prompt set verbose=20 @@ -115,4 +117,27 @@ describe('cmdline', function() Press ENTER or type command to continue^ | ]]) end) + + -- oldtest: Test_cmdline_redraw_tabline() + it('tabline is redrawn on entering cmdline', function() + local screen = Screen.new(30, 6) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText + [1] = {reverse = true}, -- TabLineFill + }) + screen:attach() + exec([[ + set showtabline=2 + autocmd CmdlineEnter * set tabline=foo + ]]) + feed(':') + screen:expect([[ + {1:foo }| + | + {0:~ }| + {0:~ }| + {0:~ }| + :^ | + ]]) + end) end) diff --git a/test/functional/legacy/ex_mode_spec.lua b/test/functional/legacy/ex_mode_spec.lua index 98f113bbd0..a8f54c6939 100644 --- a/test/functional/legacy/ex_mode_spec.lua +++ b/test/functional/legacy/ex_mode_spec.lua @@ -6,6 +6,7 @@ local eq = helpers.eq local eval = helpers.eval local feed = helpers.feed local meths = helpers.meths +local sleep = helpers.sleep before_each(clear) @@ -122,4 +123,54 @@ describe('Ex mode', function() | ]]) end) + + it('pressing Ctrl-C in :append inside a loop in Ex mode does not hang', function() + local screen = Screen.new(60, 6) + screen:set_default_attr_ids({ + [0] = {bold = true, reverse = true}, -- MsgSeparator + [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText + }) + screen:attach() + feed('gQ') + feed('for i in range(1)<CR>') + feed('append<CR>') + screen:expect([[ + {0: }| + Entering Ex mode. Type "visual" to go to Normal mode. | + :for i in range(1) | + | + : append | + ^ | + ]]) + feed('<C-C>') + sleep(10) -- Wait for input to be flushed + feed('foo<CR>') + screen:expect([[ + Entering Ex mode. Type "visual" to go to Normal mode. | + :for i in range(1) | + | + : append | + foo | + ^ | + ]]) + feed('.<CR>') + screen:expect([[ + :for i in range(1) | + | + : append | + foo | + . | + : ^ | + ]]) + feed('endfor<CR>') + feed('vi<CR>') + screen:expect([[ + ^foo | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) + end) end) diff --git a/test/functional/legacy/excmd_spec.lua b/test/functional/legacy/excmd_spec.lua index 6b3b265579..65957d85de 100644 --- a/test/functional/legacy/excmd_spec.lua +++ b/test/functional/legacy/excmd_spec.lua @@ -2,10 +2,13 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear = helpers.clear local command = helpers.command +local exec = helpers.exec local exec_lua = helpers.exec_lua +local expect_exit = helpers.expect_exit local feed = helpers.feed +local funcs = helpers.funcs +local iswin = helpers.iswin local meths = helpers.meths -local poke_eventloop = helpers.poke_eventloop local read_file = helpers.read_file local source = helpers.source local eq = helpers.eq @@ -37,152 +40,484 @@ describe('Ex command', function() end) end) -it(':confirm command dialog', function() +describe(':confirm command dialog', function() local screen local function start_new() clear() - screen = Screen.new(60, 20) + screen = Screen.new(75, 20) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText + [1] = {bold = true, reverse = true}, -- StatusLine, MsgSeparator + [2] = {reverse = true}, -- StatusLineNC + [3] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg + }) screen:attach() end - write_file('foo', 'foo1\n') - write_file('bar', 'bar1\n') - - -- Test for saving all the modified buffers - start_new() - command("set nomore") - command("new foo") - command("call setline(1, 'foo2')") - command("new bar") - command("call setline(1, 'bar2')") - command("wincmd b") - feed(':confirm qall\n') - screen:expect([[ - bar2 | - ~ | - ~ | - ~ | - ~ | - ~ | - bar [+] | - foo2 | - ~ | - ~ | - ~ | - ~ | - foo [+] | - | - ~ | - ~ | - | - :confirm qall | - Save changes to "bar"? | - [Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: ^ | - ]]) - feed('A') - poke_eventloop() - - eq('foo2\n', read_file('foo')) - eq('bar2\n', read_file('bar')) - - -- Test for discarding all the changes to modified buffers - start_new() - command("set nomore") - command("new foo") - command("call setline(1, 'foo3')") - command("new bar") - command("call setline(1, 'bar3')") - command("wincmd b") - feed(':confirm qall\n') - screen:expect([[ - bar3 | - ~ | - ~ | - ~ | - ~ | - ~ | - bar [+] | - foo3 | - ~ | - ~ | - ~ | - ~ | - foo [+] | - | - ~ | - ~ | - | - :confirm qall | - Save changes to "bar"? | - [Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: ^ | - ]]) - feed('D') - poke_eventloop() - - eq('foo2\n', read_file('foo')) - eq('bar2\n', read_file('bar')) - - -- Test for saving and discarding changes to some buffers - start_new() - command("set nomore") - command("new foo") - command("call setline(1, 'foo4')") - command("new bar") - command("call setline(1, 'bar4')") - command("wincmd b") - feed(':confirm qall\n') - screen:expect([[ - bar4 | - ~ | - ~ | - ~ | - ~ | - ~ | - bar [+] | - foo4 | - ~ | - ~ | - ~ | - ~ | - foo [+] | - | - ~ | - ~ | - | - :confirm qall | - Save changes to "bar"? | - [Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: ^ | - ]]) - feed('N') - screen:expect([[ - bar4 | - ~ | - ~ | - ~ | - ~ | - ~ | - bar [+] | - foo4 | - ~ | - ~ | - ~ | - ~ | - foo [+] | - | - | - :confirm qall | - Save changes to "bar"? | - | - Save changes to "foo"? | - [Y]es, (N)o, (C)ancel: ^ | - ]]) - feed('Y') - poke_eventloop() - - eq('foo4\n', read_file('foo')) - eq('bar2\n', read_file('bar')) - - os.remove('foo') - os.remove('bar') + -- Test for the :confirm command dialog + -- oldtest: Test_confirm_cmd() + it('works', function() + write_file('Xfoo', 'foo1\n') + write_file('Xbar', 'bar1\n') + + -- Test for saving all the modified buffers + start_new() + exec([[ + set nomore + new Xfoo + call setline(1, 'foo2') + new Xbar + call setline(1, 'bar2') + wincmd b + ]]) + feed(':confirm qall\n') + screen:expect([[ + bar2 | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {2:Xbar [+] }| + foo2 | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {2:Xfoo [+] }| + | + {0:~ }| + {0:~ }| + {1: }| + :confirm qall | + {3:Save changes to "Xbar"?} | + {3:[Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: }^ | + ]]) + expect_exit(100, feed, 'A') + + eq('foo2\n', read_file('Xfoo')) + eq('bar2\n', read_file('Xbar')) + + -- Test for discarding all the changes to modified buffers + start_new() + exec([[ + set nomore + new Xfoo + call setline(1, 'foo3') + new Xbar + call setline(1, 'bar3') + wincmd b + ]]) + feed(':confirm qall\n') + screen:expect([[ + bar3 | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {2:Xbar [+] }| + foo3 | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {2:Xfoo [+] }| + | + {0:~ }| + {0:~ }| + {1: }| + :confirm qall | + {3:Save changes to "Xbar"?} | + {3:[Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: }^ | + ]]) + expect_exit(100, feed, 'D') + + eq('foo2\n', read_file('Xfoo')) + eq('bar2\n', read_file('Xbar')) + + -- Test for saving and discarding changes to some buffers + start_new() + exec([[ + set nomore + new Xfoo + call setline(1, 'foo4') + new Xbar + call setline(1, 'bar4') + wincmd b + ]]) + feed(':confirm qall\n') + screen:expect([[ + bar4 | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {2:Xbar [+] }| + foo4 | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {2:Xfoo [+] }| + | + {0:~ }| + {0:~ }| + {1: }| + :confirm qall | + {3:Save changes to "Xbar"?} | + {3:[Y]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: }^ | + ]]) + feed('N') + screen:expect([[ + bar4 | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {2:Xbar [+] }| + foo4 | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {2:Xfoo [+] }| + | + {1: }| + :confirm qall | + {3:Save changes to "Xbar"?} | + | + {3:Save changes to "Xfoo"?} | + {3:[Y]es, (N)o, (C)ancel: }^ | + ]]) + expect_exit(100, feed, 'Y') + + eq('foo4\n', read_file('Xfoo')) + eq('bar2\n', read_file('Xbar')) + + os.remove('Xfoo') + os.remove('Xbar') + end) + + -- oldtest: Test_confirm_cmd_cancel() + it('can be cancelled', function() + -- Test for closing a window with a modified buffer + start_new() + screen:try_resize(75, 10) + exec([[ + set nohidden nomore + new + call setline(1, 'abc') + ]]) + feed(':confirm close\n') + screen:expect([[ + abc | + {0:~ }| + {0:~ }| + {0:~ }| + {1:[No Name] [+] }| + | + {1: }| + :confirm close | + {3:Save changes to "Untitled"?} | + {3:[Y]es, (N)o, (C)ancel: }^ | + ]]) + feed('C') + screen:expect([[ + ^abc | + {0:~ }| + {0:~ }| + {0:~ }| + {1:[No Name] [+] }| + | + {0:~ }| + {0:~ }| + {2:[No Name] }| + | + ]]) + feed(':confirm close\n') + screen:expect([[ + abc | + {0:~ }| + {0:~ }| + {0:~ }| + {1:[No Name] [+] }| + | + {1: }| + :confirm close | + {3:Save changes to "Untitled"?} | + {3:[Y]es, (N)o, (C)ancel: }^ | + ]]) + feed('N') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end) + + -- oldtest: Test_confirm_q_wq() + it('works with :q and :wq', function() + write_file('Xfoo', 'foo') + start_new() + screen:try_resize(75, 8) + exec([[ + set hidden nomore + call setline(1, 'abc') + edit Xfoo + set nofixendofline + ]]) + feed(':confirm q\n') + screen:expect([[ + foo | + {0:~ }| + {0:~ }| + {0:~ }| + {1: }| + :confirm q | + {3:Save changes to "Untitled"?} | + {3:[Y]es, (N)o, (C)ancel: }^ | + ]]) + feed('C') + screen:expect([[ + ^abc | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + + command('edit Xfoo') + feed(':confirm wq\n') + screen:expect([[ + foo | + {0:~ }| + {0:~ }| + {0:~ }| + {1: }| + "Xfoo" [noeol] 1L, 3B written | + {3:Save changes to "Untitled"?} | + {3:[Y]es, (N)o, (C)ancel: }^ | + ]]) + feed('C') + screen:expect([[ + ^abc | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + "Xfoo" [noeol] 1L, 3B written | + ]]) + + os.remove('Xfoo') + end) + + -- oldtest: Test_confirm_write_ro() + it('works when writing a read-only file', function() + write_file('Xconfirm_write_ro', 'foo\n') + start_new() + screen:try_resize(75, 8) + exec([[ + set ruler + set nobackup ff=unix cmdheight=2 + edit Xconfirm_write_ro + norm Abar + ]]) + + -- Try to write with 'ro' option. + feed(':set ro | confirm w\n') + screen:expect([[ + foobar | + {0:~ }| + {0:~ }| + {1: }| + :set ro | confirm w | + {3:'readonly' option is set for "Xconfirm_write_ro".} | + {3:Do you wish to write anyway?} | + {3:(Y)es, [N]o: }^ | + ]]) + feed('N') + screen:expect([[ + fooba^r | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + 1,6 All | + ]]) + eq('foo\n', read_file('Xconfirm_write_ro')) + + feed(':confirm w\n') + screen:expect([[ + foobar | + {0:~ }| + {0:~ }| + {1: }| + :confirm w | + {3:'readonly' option is set for "Xconfirm_write_ro".} | + {3:Do you wish to write anyway?} | + {3:(Y)es, [N]o: }^ | + ]]) + feed('Y') + if iswin() then + screen:expect([[ + foobar | + {0:~ }| + {1: }| + :confirm w | + {3:'readonly' option is set for "Xconfirm_write_ro".} | + {3:Do you wish to write anyway?} | + "Xconfirm_write_ro" [unix] 1L, 7B written | + {3:Press ENTER or type command to continue}^ | + ]]) + else + screen:expect([[ + foobar | + {0:~ }| + {1: }| + :confirm w | + {3:'readonly' option is set for "Xconfirm_write_ro".} | + {3:Do you wish to write anyway?} | + "Xconfirm_write_ro" 1L, 7B written | + {3:Press ENTER or type command to continue}^ | + ]]) + end + eq('foobar\n', read_file('Xconfirm_write_ro')) + feed('<CR>') -- suppress hit-enter prompt + + -- Try to write with read-only file permissions. + funcs.setfperm('Xconfirm_write_ro', 'r--r--r--') + feed(':set noro | silent undo | confirm w\n') + screen:expect([[ + foobar | + {0:~ }| + {1: }| + :set noro | silent undo | confirm w | + {3:File permissions of "Xconfirm_write_ro" are read-only.} | + {3:It may still be possible to write it.} | + {3:Do you wish to try?} | + {3:(Y)es, [N]o: }^ | + ]]) + feed('Y') + if iswin() then + screen:expect([[ + foobar | + {1: }| + :set noro | silent undo | confirm w | + {3:File permissions of "Xconfirm_write_ro" are read-only.} | + {3:It may still be possible to write it.} | + {3:Do you wish to try?} | + "Xconfirm_write_ro" [unix] 1L, 4B written | + {3:Press ENTER or type command to continue}^ | + ]]) + else + screen:expect([[ + foobar | + {1: }| + :set noro | silent undo | confirm w | + {3:File permissions of "Xconfirm_write_ro" are read-only.} | + {3:It may still be possible to write it.} | + {3:Do you wish to try?} | + "Xconfirm_write_ro" 1L, 4B written | + {3:Press ENTER or type command to continue}^ | + ]]) + end + eq('foo\n', read_file('Xconfirm_write_ro')) + feed('<CR>') -- suppress hit-enter prompt + + os.remove('Xconfirm_write_ro') + end) + + -- oldtest: Test_confirm_write_partial_file() + it('works when writing a partial file', function() + write_file('Xwrite_partial', 'a\nb\nc\nd\n') + start_new() + screen:try_resize(75, 8) + exec([[ + set ruler + set nobackup ff=unix cmdheight=2 + edit Xwrite_partial + ]]) + + feed(':confirm 2,3w\n') + screen:expect([[ + a | + b | + c | + d | + {1: }| + :confirm 2,3w | + {3:Write partial file?} | + {3:(Y)es, [N]o: }^ | + ]]) + feed('N') + screen:expect([[ + ^a | + b | + c | + d | + {0:~ }| + {0:~ }| + | + 1,1 All | + ]]) + eq('a\nb\nc\nd\n', read_file('Xwrite_partial')) + os.remove('Xwrite_partial') + + feed(':confirm 2,3w\n') + screen:expect([[ + a | + b | + c | + d | + {1: }| + :confirm 2,3w | + {3:Write partial file?} | + {3:(Y)es, [N]o: }^ | + ]]) + feed('Y') + if iswin() then + screen:expect([[ + a | + b | + c | + {1: }| + :confirm 2,3w | + {3:Write partial file?} | + "Xwrite_partial" [New][unix] 2L, 4B written | + {3:Press ENTER or type command to continue}^ | + ]]) + else + screen:expect([[ + a | + b | + c | + {1: }| + :confirm 2,3w | + {3:Write partial file?} | + "Xwrite_partial" [New] 2L, 4B written | + {3:Press ENTER or type command to continue}^ | + ]]) + end + eq('b\nc\n', read_file('Xwrite_partial')) + + os.remove('Xwrite_partial') + end) end) diff --git a/test/functional/legacy/global_spec.lua b/test/functional/legacy/global_spec.lua new file mode 100644 index 0000000000..9f4528530c --- /dev/null +++ b/test/functional/legacy/global_spec.lua @@ -0,0 +1,51 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear = helpers.clear +local exec = helpers.exec +local feed = helpers.feed +local sleep = helpers.sleep + +before_each(clear) + +describe(':global', function() + -- oldtest: Test_interrupt_global() + it('can be interrupted using Ctrl-C in cmdline mode vim-patch:9.0.0082', function() + local screen = Screen.new(75, 6) + screen:set_default_attr_ids({ + [0] = {bold = true, reverse = true}, -- MsgSeparator + [1] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg + }) + screen:attach() + + exec([[ + set nohlsearch noincsearch + cnoremap ; <Cmd>sleep 10<CR> + call setline(1, repeat(['foo'], 5)) + ]]) + + feed(':g/foo/norm :<C-V>;<CR>') + sleep(10) -- Wait for :sleep to start + feed('<C-C>') + screen:expect([[ + ^foo | + foo | + foo | + foo | + foo | + {1:Interrupted} | + ]]) + + -- Also test in Ex mode + feed('gQg/foo/norm :<C-V>;<CR>') + sleep(10) -- Wait for :sleep to start + feed('<C-C>') + screen:expect([[ + {0: }| + Entering Ex mode. Type "visual" to go to Normal mode. | + :g/foo/norm :; | + | + {1:Interrupted} | + :^ | + ]]) + end) +end) diff --git a/test/functional/legacy/messages_spec.lua b/test/functional/legacy/messages_spec.lua index b296ac909d..51c2406933 100644 --- a/test/functional/legacy/messages_spec.lua +++ b/test/functional/legacy/messages_spec.lua @@ -27,7 +27,16 @@ describe('messages', function() it('works', function() command('call setline(1, range(1, 100))') - feed(':%p#\n') + feed(':%pfoo<C-H><C-H><C-H>#') + screen:expect([[ + 1 | + 2 | + 3 | + 4 | + 5 | + :%p#^ | + ]]) + feed('\n') screen:expect([[ {2: 1 }1 | {2: 2 }2 | @@ -199,11 +208,11 @@ describe('messages', function() -- Up all the way with 'g'. feed('g') screen:expect([[ + :%p# | {2: 1 }1 | {2: 2 }2 | {2: 3 }3 | {2: 4 }4 | - {2: 5 }5 | {1:-- More --}^ | ]]) @@ -241,6 +250,18 @@ describe('messages', function() {1:Press ENTER or type command to continue}^ | ]]) + -- A command line that doesn't print text is appended to scrollback, + -- even if it invokes a nested command line. + feed([[:<C-R>=':'<CR>:<CR>g<lt>]]) + screen:expect([[ + {2: 97 }97 | + {2: 98 }98 | + {2: 99 }99 | + {2:100 }100 | + ::: | + {1:Press ENTER or type command to continue}^ | + ]]) + feed(':%p#\n') screen:expect([[ {2: 1 }1 | diff --git a/test/functional/legacy/syn_attr_spec.lua b/test/functional/legacy/syn_attr_spec.lua new file mode 100644 index 0000000000..06e8427e27 --- /dev/null +++ b/test/functional/legacy/syn_attr_spec.lua @@ -0,0 +1,60 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear = helpers.clear +local command = helpers.command +local eq = helpers.eq +local eval = helpers.eval + +before_each(clear) + +-- oldtest: Test_missing_attr() +it('synIDattr() works', function() + local bool_attrs = { + 'bold', + 'italic', + 'reverse', + 'standout', + 'underline', + 'undercurl', + 'underdouble', + 'underdotted', + 'underdashed', + 'strikethrough', + 'nocombine', + } + + command('hi Mine cterm=NONE gui=NONE') + eq('Mine', eval([[synIDattr(hlID("Mine"), "name")]])) + for _, mode in ipairs({'cterm', 'gui'}) do + eq('', eval(([[synIDattr("Mine"->hlID(), "bg", '%s')]]):format(mode))) + eq('', eval(([[synIDattr("Mine"->hlID(), "fg", '%s')]]):format(mode))) + eq('', eval(([[synIDattr("Mine"->hlID(), "sp", '%s')]]):format(mode))) + for _, attr in ipairs(bool_attrs) do + eq('', eval(([[synIDattr(hlID("Mine"), "%s", '%s')]]):format(attr, mode))) + eq('', eval(([[synIDattr(hlID("Mine"), "%s", '%s')]]):format(attr, mode))) + eq('', eval(([[synIDattr(hlID("Mine"), "%s", '%s')]]):format(attr, mode))) + end + eq('', eval(([[synIDattr(hlID("Mine"), "inverse", '%s')]]):format(mode))) + end + + for i, attr1 in ipairs(bool_attrs) do + local attr2 = bool_attrs[i - 1] or bool_attrs[#bool_attrs] + + command(('hi Mine cterm=%s gui=%s'):format(attr1, attr2)) + eq('1', eval(([[synIDattr(hlID("Mine"), "%s", 'cterm')]]):format(attr1))) + eq('', eval(([[synIDattr(hlID("Mine"), "%s", 'cterm')]]):format(attr2))) + eq('', eval(([[synIDattr("Mine"->hlID(), "%s", 'gui')]]):format(attr1))) + eq('1', eval(([[synIDattr("Mine"->hlID(), "%s", 'gui')]]):format(attr2))) + + command(('hi Mine cterm=%s gui=%s'):format(attr2, attr1)) + eq('', eval(([[synIDattr("Mine"->hlID(), "%s", 'cterm')]]):format(attr1))) + eq('1', eval(([[synIDattr("Mine"->hlID(), "%s", 'cterm')]]):format(attr2))) + eq('1', eval(([[synIDattr(hlID("Mine"), "%s", 'gui')]]):format(attr1))) + eq('', eval(([[synIDattr(hlID("Mine"), "%s", 'gui')]]):format(attr2))) + end + + command('hi Mine cterm=reverse gui=inverse') + eq('1', eval([[synIDattr(hlID("Mine"), "reverse", 'cterm')]])) + eq('1', eval([[synIDattr(hlID("Mine"), "inverse", 'cterm')]])) + eq('1', eval([[synIDattr(hlID("Mine"), "reverse", 'gui')]])) + eq('1', eval([[synIDattr(hlID("Mine"), "inverse", 'gui')]])) +end) diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 883e0e373b..2b249b7a69 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -2148,6 +2148,13 @@ describe('lua stdlib', function() ]] eq('2', funcs.luaeval "BUF") eq(2, funcs.luaeval "#vim.api.nvim_list_bufs()") + + -- vim.cmd can be indexed with a command name + exec_lua [[ + vim.cmd.let 'g:var = 2' + ]] + + eq(2, funcs.luaeval "vim.g.var") end) it('vim.regex', function() @@ -2493,6 +2500,41 @@ describe('lua stdlib', function() eq(false, pcall_result) end) + + describe('returns -2 when interrupted', function() + before_each(function() + local channel = meths.get_api_info()[1] + meths.set_var('channel', channel) + end) + + it('without callback', function() + exec_lua([[ + function _G.Wait() + vim.rpcnotify(vim.g.channel, 'ready') + local _, interrupted = vim.wait(4000) + vim.rpcnotify(vim.g.channel, 'wait', interrupted) + end + ]]) + feed(':lua _G.Wait()<CR>') + eq({'notification', 'ready', {}}, next_msg(500)) + feed('<C-C>') + eq({'notification', 'wait', {-2}}, next_msg(500)) + end) + + it('with callback', function() + exec_lua([[ + function _G.Wait() + vim.rpcnotify(vim.g.channel, 'ready') + local _, interrupted = vim.wait(4000, function() end) + vim.rpcnotify(vim.g.channel, 'wait', interrupted) + end + ]]) + feed(':lua _G.Wait()<CR>') + eq({'notification', 'ready', {}}, next_msg(500)) + feed('<C-C>') + eq({'notification', 'wait', {-2}}, next_msg(500)) + end) + end) end) it('vim.notify_once', function() @@ -2750,12 +2792,12 @@ describe('vim.keymap', function() it('can make an expr mapping', function() exec_lua [[ - vim.keymap.set('n', 'aa', function() return ':lua SomeValue = 99<cr>' end, {expr = true}) + vim.keymap.set('n', 'aa', function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, {expr = true}) ]] feed('aa') - eq(99, exec_lua[[return SomeValue]]) + eq({'π<M-π>foo<'}, meths.buf_get_lines(0, 0, -1, false)) end) it('can overwrite a mapping', function() diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index c166982052..cd7415de90 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -535,6 +535,46 @@ describe('LSP', function() } end) + it('saveas sends didOpen if filename changed', function() + local expected_handlers = { + { NIL, {}, { method = 'shutdown', client_id = 1 } }, + { NIL, {}, { method = 'start', client_id = 1 } }, + } + local client + test_rpc_server({ + test_name = 'text_document_save_did_open', + on_init = function(c) + client = c + end, + on_exit = function(code, signal) + eq(0, code, 'exit code') + eq(0, signal, 'exit signal') + end, + on_handler = function(err, result, ctx) + eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler') + if ctx.method == 'start' then + local tmpfile_old = helpers.tmpname() + local tmpfile_new = helpers.tmpname() + os.remove(tmpfile_new) + exec_lua( + [=[ + local oldname, newname = ... + BUFFER = vim.api.nvim_get_current_buf() + vim.api.nvim_buf_set_name(BUFFER, oldname) + vim.api.nvim_buf_set_lines(BUFFER, 0, -1, true, {"help me"}) + lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID) + vim.api.nvim_buf_call(BUFFER, function() vim.cmd('saveas ' .. newname) end) + ]=], + tmpfile_old, + tmpfile_new + ) + else + client.stop() + end + end, + }) + end) + it('BufWritePost sends didSave including text if server capability is set', function() local expected_handlers = { {NIL, {}, {method="shutdown", client_id=1}}; diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index 1cef771f0d..23430a620b 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -5,12 +5,15 @@ local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim local poke_eventloop = helpers.poke_eventloop local eval, feed_command, source = helpers.eval, helpers.feed_command, helpers.source local eq, neq = helpers.eq, helpers.neq +local meths = helpers.meths +local retry = helpers.retry local write_file = helpers.write_file local command = helpers.command local exc_exec = helpers.exc_exec local matches = helpers.matches local exec_lua = helpers.exec_lua local sleep = helpers.sleep +local funcs = helpers.funcs describe(':terminal buffer', function() local screen @@ -298,6 +301,44 @@ describe(':terminal buffer', function() feed_command('put a') -- register a is empty helpers.assert_alive() end) + + it([[can use temporary normal mode <c-\><c-o>]], function() + eq('t', funcs.mode(1)) + feed [[<c-\><c-o>]] + screen:expect{grid=[[ + tty ready | + {2:^ } | + | + | + | + | + {3:-- (terminal) --} | + ]]} + eq('ntT', funcs.mode(1)) + + feed [[:let g:x = 17]] + screen:expect{grid=[[ + tty ready | + {2: } | + | + | + | + | + :let g:x = 17^ | + ]]} + + feed [[<cr>]] + screen:expect{grid=[[ + tty ready | + {1: } | + | + | + | + | + {3:-- TERMINAL --} | + ]]} + eq('t', funcs.mode(1)) + end) end) describe('No heap-buffer-overflow when using', function() @@ -364,3 +405,11 @@ describe('on_lines does not emit out-of-bounds line indexes when', function() eq('', exec_lua([[return _G.cb_error]])) end) end) + +it('terminal truncates number of composing characters to 5', function() + clear() + local chan = meths.open_term(0, {}) + local composing = ('a̳'):sub(2) + meths.chan_send(chan, 'a' .. composing:rep(8)) + retry(nil, nil, function() eq('a' .. composing:rep(5), meths.get_current_line()) end) +end) diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index dd88379344..eee759d2be 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -144,10 +144,9 @@ describe('TUI', function() {3:-- TERMINAL --} | ]]} - -- TODO(bfredl): messes up the output (just like vim does). feed_data('g') screen:expect{grid=[[ - ) | + :call ManyErr() | {8:Error detected while processing function ManyErr:} | {11:line 2:} | {10:-- More --}{1: } | @@ -156,7 +155,7 @@ describe('TUI', function() screen:try_resize(50,10) screen:expect{grid=[[ - ) | + :call ManyErr() | {8:Error detected while processing function ManyErr:} | {11:line 2:} | {8:FAIL 0} | @@ -436,8 +435,11 @@ describe('TUI', function() | {3:-- TERMINAL --} | ]]) - feed_data(':tab split\r:tabnew\r') - feed_data(':highlight Tabline ctermbg=NONE ctermfg=NONE cterm=underline\r') + child_session:request('nvim_command', [[ + tab split + tabnew + highlight Tabline ctermbg=NONE ctermfg=NONE cterm=underline + ]]) local attrs = screen:get_default_attr_ids() attrs[11] = {underline = true} screen:expect([[ diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index eb0a14da31..db13647cc6 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -96,119 +96,6 @@ local function test_cmdline(linegrid) ]]} end) - describe("redraws statusline on entering", function() - before_each(function() - command('set laststatus=2') - command('set statusline=%{mode()}') - end) - - it('from normal mode', function() - screen:expect{grid=[[ - ^ | - {1:~ }| - {1:~ }| - {3:n }| - | - ]]} - - feed(':') - screen:expect{grid=[[ - ^ | - {1:~ }| - {1:~ }| - {3:c }| - | - ]], cmdline={{ - firstc = ":", - content = {{""}}, - pos = 0, - }}} - end) - - it('from normal mode when : is mapped', function() - command('nnoremap ; :') - - screen:expect{grid=[[ - ^ | - {1:~ }| - {1:~ }| - {3:n }| - | - ]]} - - feed(';') - screen:expect{grid=[[ - ^ | - {1:~ }| - {1:~ }| - {3:c }| - | - ]], cmdline={{ - firstc = ":", - content = {{""}}, - pos = 0, - }}} - end) - - it('but not with scrolled messages', function() - screen:try_resize(35,10) - feed(':echoerr doesnotexist<cr>') - screen:expect{grid=[[ - | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {3: }| - {4:E121: Undefined variable: doesnotex}| - {4:ist} | - {5:Press ENTER or type command to cont}| - {5:inue}^ | - ]]} - feed(':echoerr doesnotexist<cr>') - screen:expect{grid=[[ - | - {1:~ }| - {3: }| - {4:E121: Undefined variable: doesnotex}| - {4:ist} | - {5:Press ENTER or type command to cont}| - {4:E121: Undefined variable: doesnotex}| - {4:ist} | - {5:Press ENTER or type command to cont}| - {5:inue}^ | - ]]} - - feed(':echoerr doesnotexist<cr>') - screen:expect{grid=[[ - {4:E121: Undefined variable: doesnotex}| - {4:ist} | - {5:Press ENTER or type command to cont}| - {4:E121: Undefined variable: doesnotex}| - {4:ist} | - {5:Press ENTER or type command to cont}| - {4:E121: Undefined variable: doesnotex}| - {4:ist} | - {5:Press ENTER or type command to cont}| - {5:inue}^ | - ]]} - - feed('<cr>') - screen:expect{grid=[[ - ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {3:n }| - | - ]]} - end) - end) - it("works with input()", function() feed(':call input("input", "default")<cr>') screen:expect{grid=[[ @@ -883,6 +770,154 @@ describe('cmdline redraw', function() end) end) +describe('statusline is redrawn on entering cmdline', function() + local screen + + before_each(function() + clear() + screen = new_screen() + command('set laststatus=2') + end) + + it('from normal mode', function() + command('set statusline=%{mode()}') + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {3:n }| + | + ]]} + + feed(':') + screen:expect{grid=[[ + | + {1:~ }| + {1:~ }| + {3:c }| + :^ | + ]]} + end) + + it('from normal mode when : is mapped', function() + command('set statusline=%{mode()}') + command('nnoremap ; :') + + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {3:n }| + | + ]]} + + feed(';') + screen:expect{grid=[[ + | + {1:~ }| + {1:~ }| + {3:c }| + :^ | + ]]} + end) + + it('but not with scrolled messages', function() + command('set statusline=%{mode()}') + screen:try_resize(35,10) + feed(':echoerr doesnotexist<cr>') + screen:expect{grid=[[ + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {3: }| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {5:inue}^ | + ]]} + feed(':echoerr doesnotexist<cr>') + screen:expect{grid=[[ + | + {1:~ }| + {3: }| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {5:inue}^ | + ]]} + + feed(':echoerr doesnotexist<cr>') + screen:expect{grid=[[ + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {5:inue}^ | + ]]} + + feed('<cr>') + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {3:n }| + | + ]]} + end) + + describe('if custom statusline is set by', function() + before_each(function() + command('set statusline=') + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {3:[No Name] }| + | + ]]} + end) + + it('CmdlineEnter autocommand', function() + command('autocmd CmdlineEnter * set statusline=command') + feed(':') + screen:expect{grid=[[ + | + {1:~ }| + {1:~ }| + {3:command }| + :^ | + ]]} + end) + + it('ModeChanged autocommand', function() + command('autocmd ModeChanged *:c set statusline=command') + feed(':') + screen:expect{grid=[[ + | + {1:~ }| + {1:~ }| + {3:command }| + :^ | + ]]} + end) + end) +end) + describe("cmdline height", function() it("does not crash resized screen #14263", function() clear() @@ -1068,7 +1103,7 @@ describe('cmdheight=0', function() ~ | ~ | ~ | - ~ | + recording @q | ]], showmode={}} feed('q') screen:expect{grid=[[ diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua index a1423c98a8..03cd4bfd06 100644 --- a/test/functional/ui/cursor_spec.lua +++ b/test/functional/ui/cursor_spec.lua @@ -215,7 +215,7 @@ describe('ui/cursor', function() m.hl_id = 60 m.attr = {background = Screen.colors.DarkGray} end - if m.id_lm then m.id_lm = 65 end + if m.id_lm then m.id_lm = 61 end end -- Assert the new expectation. diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua index 5d056cd6c3..36dc5addcd 100644 --- a/test/functional/ui/diff_spec.lua +++ b/test/functional/ui/diff_spec.lua @@ -6,6 +6,7 @@ local clear = helpers.clear local command = helpers.command local insert = helpers.insert local write_file = helpers.write_file +local dedent = helpers.dedent local exec = helpers.exec describe('Diff mode screen', function() @@ -985,6 +986,93 @@ int main(int argc, char **argv) ]]) end) end) + + -- oldtest: Test_diff_scroll() + -- This was scrolling for 'cursorbind' but 'scrollbind' is more important + it('scrolling works correctly vim-patch:8.2.5155', function() + screen:try_resize(40, 12) + write_file(fname, dedent([[ + line 1 + line 2 + line 3 + line 4 + + // Common block + // one + // containing + // four lines + + // Common block + // two + // containing + // four lines]]), false) + write_file(fname_2, dedent([[ + line 1 + line 2 + line 3 + line 4 + + Lorem + ipsum + dolor + sit + amet, + consectetur + adipiscing + elit. + Etiam + luctus + lectus + sodales, + dictum + + // Common block + // one + // containing + // four lines + + Vestibulum + tincidunt + aliquet + nulla. + + // Common block + // two + // containing + // four lines]]), false) + reread() + + feed('<C-W><C-W>jjjj') + screen:expect([[ + {1: }line 1 │{1: }line 1 | + {1: }line 2 │{1: }line 2 | + {1: }line 3 │{1: }line 3 | + {1: }line 4 │{1: }line 4 | + {1: } │{1: }^ | + {1: }{2:-----------------}│{1: }{4:Lorem }| + {1: }{2:-----------------}│{1: }{4:ipsum }| + {1: }{2:-----------------}│{1: }{4:dolor }| + {1: }{2:-----------------}│{1: }{4:sit }| + {1: }{2:-----------------}│{1: }{4:amet, }| + {3:<nal-diff-screen-1 }{7:<al-diff-screen-1.2 }| + :e | + ]]) + feed('j') + screen:expect([[ + {1: }line 1 │{1: }line 1 | + {1: }line 2 │{1: }line 2 | + {1: }line 3 │{1: }line 3 | + {1: }line 4 │{1: }line 4 | + {1: } │{1: } | + {1: }{2:-----------------}│{1: }{4:^Lorem }| + {1: }{2:-----------------}│{1: }{4:ipsum }| + {1: }{2:-----------------}│{1: }{4:dolor }| + {1: }{2:-----------------}│{1: }{4:sit }| + {1: }{2:-----------------}│{1: }{4:amet, }| + {3:<nal-diff-screen-1 }{7:<al-diff-screen-1.2 }| + :e | + ]]) + end) end) it('win_update redraws lines properly', function() @@ -1227,6 +1315,7 @@ it('Align the filler lines when changing text in diff mode', function() ]]} end) +-- oldtest: Test_diff_binary() it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', function() clear() local screen = Screen.new(40, 20) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 50247ed214..5967b630f6 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -18,6 +18,7 @@ local run = helpers.run local pcall_err = helpers.pcall_err local tbl_contains = global_helpers.tbl_contains local curbuf, curwin, curtab = helpers.curbuf, helpers.curwin, helpers.curtab +local NIL = helpers.NIL describe('float window', function() before_each(function() @@ -420,6 +421,15 @@ describe('float window', function() eq(winids, eval('winids')) end) + it("no segfault when setting minimal style after clearing local 'fillchars' #19510", function() + local float_opts = {relative = 'editor', row = 1, col = 1, width = 1, height = 1} + local float_win = meths.open_win(0, true, float_opts) + meths.win_set_option(float_win, 'fillchars', NIL) + float_opts.style = 'minimal' + meths.win_set_config(float_win, float_opts) + assert_alive() + end) + describe('with only one tabpage,', function() local float_opts = {relative = 'editor', row = 1, col = 1, width = 1, height = 1} local old_buf, old_win diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index 394f2f5f49..c79fc2989c 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -1818,6 +1818,83 @@ describe("folded lines", function() ]]) end end) + + it('fold text is shown when text has been scrolled to the right #19123', function() + insert(content1) + command('set number nowrap') + command('3,4fold') + feed('gg') + if multigrid then + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + {8: 1 }^This is a | + {8: 2 }valid English | + {8: 3 }{5:+-- 2 lines: sentence composed by·······}| + {8: 5 }in his cave. | + {8: 6 } | + {1:~ }| + {1:~ }| + ## grid 3 + | + ]]) + else + screen:expect([[ + {8: 1 }^This is a | + {8: 2 }valid English | + {8: 3 }{5:+-- 2 lines: sentence composed by·······}| + {8: 5 }in his cave. | + {8: 6 } | + {1:~ }| + {1:~ }| + | + ]]) + end + + feed('zl') + if multigrid then + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + {8: 1 }^his is a | + {8: 2 }alid English | + {8: 3 }{5:+-- 2 lines: sentence composed by·······}| + {8: 5 }n his cave. | + {8: 6 } | + {1:~ }| + {1:~ }| + ## grid 3 + | + ]]) + else + screen:expect([[ + {8: 1 }^his is a | + {8: 2 }alid English | + {8: 3 }{5:+-- 2 lines: sentence composed by·······}| + {8: 5 }n his cave. | + {8: 6 } | + {1:~ }| + {1:~ }| + | + ]]) + end + end) end describe("with ext_multigrid", function() diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 00f126a1f2..e7eaedba2d 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -1854,7 +1854,7 @@ aliquip ex ea commodo consequat.]]) feed('k') screen:expect{grid=[[ - {7:0}{8: }{7:)}{8: }| + {7:0}{8: }| {9:1}{10: }| {9:2}{10: }| {9:3}{10: }| @@ -1943,6 +1943,7 @@ aliquip ex ea commodo consequat.]]) -- text is not reflown; existing lines get cut screen:try_resize(30, 12) screen:expect{grid=[[ + :lua error(_G.x) | {2:E5108: Error executing lua [st}| {2:":lua"]:1: Lorem ipsum dolor s}| {2:et, consectetur} | @@ -1953,7 +1954,6 @@ aliquip ex ea commodo consequat.]]) | | | - | {4:-- More --}^ | ]]} @@ -1961,6 +1961,22 @@ aliquip ex ea commodo consequat.]]) -- wrapped at the new screen size. feed('<cr>') screen:expect{grid=[[ + {2:E5108: Error executing lua [st}| + {2:":lua"]:1: Lorem ipsum dolor s}| + {2:et, consectetur} | + {2:adipisicing elit, sed do eiusm}| + {2:mpore} | + {2:incididunt ut labore et dolore}| + {2:a aliqua.} | + {2:Ut enim ad minim veniam, quis }| + {2:nostrud xercitation} | + {2:ullamco laboris nisi ut} | + {2:aliquip ex ea commodo consequa}| + {4:-- More --}^ | + ]]} + + feed('<cr>') + screen:expect{grid=[[ {2:":lua"]:1: Lorem ipsum dolor s}| {2:et, consectetur} | {2:adipisicing elit, sed do eiusm}| diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index 69b0d1ecec..e389b7ab89 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -1572,22 +1572,22 @@ describe('ui/mouse/input', function() meths.input_mouse('left', 'release', '', 0, 0, 0) end) - it('scroll keys are not translated into multiclicks #6211 #6989', function() + it('scroll keys are not translated into multiclicks and can be mapped #6211 #6989', function() meths.set_var('mouse_up', 0) meths.set_var('mouse_up2', 0) - meths.set_var('mouse_up3', 0) - meths.set_var('mouse_up4', 0) command('nnoremap <ScrollWheelUp> <Cmd>let g:mouse_up += 1<CR>') command('nnoremap <2-ScrollWheelUp> <Cmd>let g:mouse_up2 += 1<CR>') - command('nnoremap <3-ScrollWheelUp> <Cmd>let g:mouse_up3 += 1<CR>') - command('nnoremap <4-ScrollWheelUp> <Cmd>let g:mouse_up4 += 1<CR>') - meths.input_mouse('wheel', 'up', '', 0, 0, 0) - meths.input_mouse('wheel', 'up', '', 0, 0, 0) + feed('<ScrollWheelUp><0,0>') + feed('<ScrollWheelUp><0,0>') meths.input_mouse('wheel', 'up', '', 0, 0, 0) meths.input_mouse('wheel', 'up', '', 0, 0, 0) eq(4, meths.get_var('mouse_up')) eq(0, meths.get_var('mouse_up2')) - eq(0, meths.get_var('mouse_up3')) - eq(0, meths.get_var('mouse_up4')) + end) + + it('feeding <MouseMove> does not use uninitialized memory #19480', function() + feed('<MouseMove>') + helpers.poke_eventloop() + helpers.assert_alive() end) end) diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua index c2b0bcdb64..8d7c404637 100644 --- a/test/functional/ui/options_spec.lua +++ b/test/functional/ui/options_spec.lua @@ -51,7 +51,7 @@ describe('UI receives option updates', function() end) it('on attach #11372', function() - clear() + clear{args_rm={'--headless'}} local evs = {} screen = Screen.new(20,5) -- Override mouse_on/mouse_off handlers. @@ -88,6 +88,13 @@ describe('UI receives option updates', function() eq(expected, screen.options) end) + command("set pumblend=50") + expected.pumblend = 50 + screen:expect(function() + eq(expected, screen.options) + end) + + -- check handling of out-of-bounds value command("set pumblend=-1") expected.pumblend = 0 screen:expect(function() diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua index 1e1066d48a..69a2d2f4ed 100644 --- a/test/functional/ui/statusline_spec.lua +++ b/test/functional/ui/statusline_spec.lua @@ -1,5 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') +local assert_alive = helpers.assert_alive local clear = helpers.clear local command = helpers.command local feed = helpers.feed @@ -20,11 +21,9 @@ describe('statusline clicks', function() command('set laststatus=2 mousemodel=extend') exec([=[ function! MyClickFunc(minwid, clicks, button, mods) - let mods = trim(a:mods) - if mods ==# '' - let g:testvar = printf("%d %d %s", a:minwid, a:clicks, a:button) - else - let g:testvar = printf("%d %d %s %s", a:minwid, a:clicks, a:button, mods) + let g:testvar = printf("%d %d %s", a:minwid, a:clicks, a:button) + if a:mods !=# ' ' + let g:testvar ..= '(' .. a:mods .. ')' endif endfunction ]=]) @@ -34,8 +33,20 @@ describe('statusline clicks', function() meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T') meths.input_mouse('left', 'press', '', 0, 6, 17) eq('0 1 l', eval("g:testvar")) + meths.input_mouse('left', 'press', '', 0, 6, 17) + eq('0 2 l', eval("g:testvar")) + meths.input_mouse('left', 'press', '', 0, 6, 17) + eq('0 3 l', eval("g:testvar")) + meths.input_mouse('left', 'press', '', 0, 6, 17) + eq('0 4 l', eval("g:testvar")) meths.input_mouse('right', 'press', '', 0, 6, 17) eq('0 1 r', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 6, 17) + eq('0 2 r', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 6, 17) + eq('0 3 r', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 6, 17) + eq('0 4 r', eval("g:testvar")) end) it('works for winbar', function() @@ -98,12 +109,60 @@ describe('statusline clicks', function() eq('0 2 r', eval("g:testvar")) end) - it("click works with modifiers #18994", function() + it("works with modifiers #18994", function() meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T') - meths.input_mouse('right', 'press', 's', 0, 6, 17) - eq('0 1 r s', eval("g:testvar")) - meths.input_mouse('left', 'press', 's', 0, 6, 17) - eq('0 1 l s', eval("g:testvar")) + -- Note: alternate between left and right mouse buttons to avoid triggering multiclicks + meths.input_mouse('left', 'press', 'S', 0, 6, 17) + eq('0 1 l(s )', eval("g:testvar")) + meths.input_mouse('right', 'press', 'S', 0, 6, 17) + eq('0 1 r(s )', eval("g:testvar")) + meths.input_mouse('left', 'press', 'A', 0, 6, 17) + eq('0 1 l( a )', eval("g:testvar")) + meths.input_mouse('right', 'press', 'A', 0, 6, 17) + eq('0 1 r( a )', eval("g:testvar")) + meths.input_mouse('left', 'press', 'AS', 0, 6, 17) + eq('0 1 l(s a )', eval("g:testvar")) + meths.input_mouse('right', 'press', 'AS', 0, 6, 17) + eq('0 1 r(s a )', eval("g:testvar")) + meths.input_mouse('left', 'press', 'T', 0, 6, 17) + eq('0 1 l( m)', eval("g:testvar")) + meths.input_mouse('right', 'press', 'T', 0, 6, 17) + eq('0 1 r( m)', eval("g:testvar")) + meths.input_mouse('left', 'press', 'TS', 0, 6, 17) + eq('0 1 l(s m)', eval("g:testvar")) + meths.input_mouse('right', 'press', 'TS', 0, 6, 17) + eq('0 1 r(s m)', eval("g:testvar")) + meths.input_mouse('left', 'press', 'C', 0, 6, 17) + eq('0 1 l( c )', eval("g:testvar")) + -- <C-RightMouse> is for tag jump + end) + + it("works for global statusline with vertical splits #19186", function() + command('set laststatus=3') + meths.set_option('statusline', '%0@MyClickFunc@Clicky stuff%T %= %0@MyClickFunc@Clicky stuff%T') + command('vsplit') + screen:expect([[ + ^ │ | + ~ │~ | + ~ │~ | + ~ │~ | + ~ │~ | + ~ │~ | + Clicky stuff Clicky stuff| + | + ]]) + + -- clickable area on the right + meths.input_mouse('left', 'press', '', 0, 6, 35) + eq('0 1 l', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 6, 35) + eq('0 1 r', eval("g:testvar")) + + -- clickable area on the left + meths.input_mouse('left', 'press', '', 0, 6, 5) + eq('0 1 l', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 6, 5) + eq('0 1 r', eval("g:testvar")) end) end) @@ -340,3 +399,11 @@ describe('global statusline', function() eq(1, meths.get_option('cmdheight')) end) end) + +it('statusline does not crash if it has Arabic characters #19447', function() + clear() + meths.set_option('statusline', 'غً') + meths.set_option('laststatus', 2) + command('redraw!') + assert_alive() +end) diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua index 92a6ab2e84..60fa10da87 100644 --- a/test/functional/ui/winbar_spec.lua +++ b/test/functional/ui/winbar_spec.lua @@ -578,3 +578,48 @@ describe('winbar', function() eq('Vim(set):E36: Not enough room', pcall_err(command, 'set winbar=test')) end) end) + +it('local winbar works with tabs', function() + clear() + local screen = Screen.new(60, 13) + screen:attach() + screen:set_default_attr_ids({ + [1] = {bold = true}, + [2] = {reverse = true}, + [3] = {bold = true, foreground = Screen.colors.Blue}, + [4] = {underline = true, background = Screen.colors.LightGray} + }) + meths.set_option_value('winbar', 'foo', { scope = 'local', win = 0 }) + command('tabnew') + screen:expect([[ + {4: [No Name] }{1: [No Name] }{2: }{4:X}| + ^ | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]) + command('tabnext') + screen:expect{grid=[[ + {1: [No Name] }{4: [No Name] }{2: }{4:X}| + {1:foo }| + ^ | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]} +end) diff --git a/test/functional/vimscript/buf_functions_spec.lua b/test/functional/vimscript/buf_functions_spec.lua index e957e5f5af..b521620320 100644 --- a/test/functional/vimscript/buf_functions_spec.lua +++ b/test/functional/vimscript/buf_functions_spec.lua @@ -303,4 +303,8 @@ describe('setbufvar() function', function() pcall_err(funcs.setbufvar, 1, 'changedtick', true)) eq(2, funcs.getbufvar(1, 'changedtick')) end) + it('throws error when setting a string option to a boolean value vim-patch:9.0.0090', function() + eq('Vim:E928: String required', + pcall_err(funcs.setbufvar, '', '&errorformat', true)) + end) end) diff --git a/test/functional/vimscript/let_spec.lua b/test/functional/vimscript/let_spec.lua index ca1b5e8907..86905199a8 100644 --- a/test/functional/vimscript/let_spec.lua +++ b/test/functional/vimscript/let_spec.lua @@ -7,6 +7,7 @@ local eval = helpers.eval local meths = helpers.meths local exec = helpers.exec local exec_capture = helpers.exec_capture +local expect_exit = helpers.expect_exit local source = helpers.source local testprg = helpers.testprg @@ -28,7 +29,7 @@ describe(':let', function() it(":unlet self-referencing node in a List graph #6070", function() -- :unlet-ing a self-referencing List must not allow GC on indirectly -- referenced in-scope Lists. Before #6070 this caused use-after-free. - source([=[ + expect_exit(100, source, [=[ let [l1, l2] = [[], []] echo 'l1:' . id(l1) echo 'l2:' . id(l2) diff --git a/test/functional/vimscript/map_functions_spec.lua b/test/functional/vimscript/map_functions_spec.lua index 275c72d212..aa64006de0 100644 --- a/test/functional/vimscript/map_functions_spec.lua +++ b/test/functional/vimscript/map_functions_spec.lua @@ -3,7 +3,10 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq local eval = helpers.eval +local expect = helpers.expect +local feed = helpers.feed local funcs = helpers.funcs +local meths = helpers.meths local nvim = helpers.nvim local source = helpers.source local command = helpers.command @@ -13,6 +16,7 @@ describe('maparg()', function() local foo_bar_map_table = { lhs='foo', + lhsraw='foo', script=0, silent=0, rhs='bar', @@ -141,6 +145,7 @@ describe('maparg()', function() local function acmap(lhs, rhs) return { lhs = ac(lhs), + lhsraw = ac(lhs), rhs = ac(rhs), buffer = 0, @@ -161,3 +166,32 @@ describe('maparg()', function() eq(acmap('e`', 'f`'), funcs.maparg(ac('e`'), 'n', 0, 1)) end) end) + +describe('mapset()', function() + before_each(clear) + + it('can restore mapping description from the dict returned by maparg()', function() + meths.set_keymap('n', 'lhs', 'rhs', {desc = 'map description'}) + eq('\nn lhs rhs\n map description', + helpers.exec_capture("nmap lhs")) + local mapargs = funcs.maparg('lhs', 'n', false, true) + meths.del_keymap('n', 'lhs') + eq('\nNo mapping found', helpers.exec_capture("nmap lhs")) + funcs.mapset('n', false, mapargs) + eq('\nn lhs rhs\n map description', + helpers.exec_capture("nmap lhs")) + end) + + it('can restore "replace_keycodes" from the dict returned by maparg()', function() + meths.set_keymap('i', 'foo', [['<l' .. 't>']], {expr = true, replace_keycodes = true}) + feed('Afoo') + expect('<') + local mapargs = funcs.maparg('foo', 'i', false, true) + meths.set_keymap('i', 'foo', [['<l' .. 't>']], {expr = true}) + feed('foo') + expect('<<lt>') + funcs.mapset('i', false, mapargs) + feed('foo') + expect('<<lt><') + end) +end) diff --git a/test/functional/vimscript/system_spec.lua b/test/functional/vimscript/system_spec.lua index c915556c57..a778e2f435 100644 --- a/test/functional/vimscript/system_spec.lua +++ b/test/functional/vimscript/system_spec.lua @@ -630,7 +630,7 @@ end) describe('shell :!', function() before_each(clear) - it(':{range}! with powershell filter/redirect #16271', function() + it(':{range}! with powershell filter/redirect #16271 #19250', function() local screen = Screen.new(500, 8) screen:attach() local found = helpers.set_shell_powershell(true) @@ -639,18 +639,25 @@ describe('shell :!', function() 1 4 2]]) - feed(':4verbose %!sort<cr>') - screen:expect{ - any=[[Executing command: .?Start%-Process sort %-RedirectStandardInput .* %-RedirectStandardOutput .* %-NoNewWindow %-Wait]] - } + if iswin() then + feed(':4verbose %!sort /R<cr>') + screen:expect{ + any=[[Executing command: .?Start%-Process sort %-ArgumentList "/R" %-RedirectStandardInput .* %-RedirectStandardOutput .* %-NoNewWindow %-Wait]] + } + else + feed(':4verbose %!sort -r<cr>') + screen:expect{ + any=[[Executing command: .?Start%-Process sort %-ArgumentList "%-r" %-RedirectStandardInput .* %-RedirectStandardOutput .* %-NoNewWindow %-Wait]] + } + end feed('<CR>') if found then -- Not using fake powershell, so we can test the result. expect([[ - 1 - 2 + 4 3 - 4]]) + 2 + 1]]) end end) end) |