diff options
Diffstat (limited to 'test/functional/ex_cmds')
-rw-r--r-- | test/functional/ex_cmds/cd_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/ex_cmds/cmd_map_spec.lua | 96 | ||||
-rw-r--r-- | test/functional/ex_cmds/ctrl_c_spec.lua | 60 | ||||
-rw-r--r-- | test/functional/ex_cmds/drop_spec.lua | 32 | ||||
-rw-r--r-- | test/functional/ex_cmds/echo_spec.lua | 14 | ||||
-rw-r--r-- | test/functional/ex_cmds/ls_spec.lua | 4 | ||||
-rw-r--r-- | test/functional/ex_cmds/make_spec.lua | 6 | ||||
-rw-r--r-- | test/functional/ex_cmds/map_spec.lua | 233 | ||||
-rw-r--r-- | test/functional/ex_cmds/menu_spec.lua | 3 | ||||
-rw-r--r-- | test/functional/ex_cmds/mksession_spec.lua | 109 | ||||
-rw-r--r-- | test/functional/ex_cmds/normal_spec.lua | 27 | ||||
-rw-r--r-- | test/functional/ex_cmds/quickfix_commands_spec.lua | 13 | ||||
-rw-r--r-- | test/functional/ex_cmds/script_spec.lua | 16 | ||||
-rw-r--r-- | test/functional/ex_cmds/sign_spec.lua | 9 | ||||
-rw-r--r-- | test/functional/ex_cmds/source_spec.lua | 20 | ||||
-rw-r--r-- | test/functional/ex_cmds/swapfile_preserve_recover_spec.lua | 3 | ||||
-rw-r--r-- | test/functional/ex_cmds/verbose_spec.lua | 168 |
17 files changed, 680 insertions, 135 deletions
diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua index f9cce0deb6..42a811f5da 100644 --- a/test/functional/ex_cmds/cd_spec.lua +++ b/test/functional/ex_cmds/cd_spec.lua @@ -173,7 +173,7 @@ for _, cmd in ipairs {'cd', 'chdir'} do -- Change tab-local working directory and verify it is different command('silent t' .. cmd .. ' ' .. directories.tab) eq(globalDir .. pathsep .. directories.tab, cwd()) - eq(cwd(), tcwd()) -- working directory maches tab directory + eq(cwd(), tcwd()) -- working directory matches tab directory eq(1, tlwd()) eq(cwd(), wcwd()) -- still no window-directory eq(0, wlwd()) diff --git a/test/functional/ex_cmds/cmd_map_spec.lua b/test/functional/ex_cmds/cmd_map_spec.lua index 0b2190bbcf..919d167712 100644 --- a/test/functional/ex_cmds/cmd_map_spec.lua +++ b/test/functional/ex_cmds/cmd_map_spec.lua @@ -1,21 +1,23 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear -local feed_command = helpers.feed_command local feed = helpers.feed local eq = helpers.eq local expect = helpers.expect local eval = helpers.eval local funcs = helpers.funcs local insert = helpers.insert +local write_file = helpers.write_file local exc_exec = helpers.exc_exec -local source = helpers.source +local command = helpers.command local Screen = require('test.functional.ui.screen') describe('mappings with <Cmd>', function() local screen + local tmpfile = 'X_ex_cmds_cmd_map' + local function cmdmap(lhs, rhs) - feed_command('noremap '..lhs..' <Cmd>'..rhs..'<cr>') - feed_command('noremap! '..lhs..' <Cmd>'..rhs..'<cr>') + command('noremap '..lhs..' <Cmd>'..rhs..'<cr>') + command('noremap! '..lhs..' <Cmd>'..rhs..'<cr>') end before_each(function() @@ -39,7 +41,7 @@ describe('mappings with <Cmd>', function() cmdmap('<F4>', 'normal! ww') cmdmap('<F5>', 'normal! "ay') cmdmap('<F6>', 'throw "very error"') - feed_command([[ + command([[ function! TextObj() if mode() !=# "v" normal! v @@ -55,11 +57,15 @@ describe('mappings with <Cmd>', function() feed('gg') cmdmap('<F8>', 'startinsert') cmdmap('<F9>', 'stopinsert') - feed_command("abbr foo <Cmd>let g:y = 17<cr>bar") + command("abbr foo <Cmd>let g:y = 17<cr>bar") + end) + + after_each(function() + os.remove(tmpfile) end) it('can be displayed', function() - feed_command('map <F3>') + command('map <F3>') screen:expect([[ ^some short lines | of test text | @@ -73,8 +79,8 @@ describe('mappings with <Cmd>', function() end) it('handles invalid mappings', function() - feed_command('let x = 0') - feed_command('noremap <F3> <Cmd><Cmd>let x = 1<cr>') + command('let x = 0') + command('noremap <F3> <Cmd><Cmd>let x = 1<cr>') feed('<F3>') screen:expect([[ ^some short lines | @@ -87,7 +93,7 @@ describe('mappings with <Cmd>', function() {2:E5521: <Cmd> mapping must end with <CR> before second <Cmd>} | ]]) - feed_command('noremap <F3> <Cmd><F3>let x = 2<cr>') + command('noremap <F3> <Cmd>let x = 3') feed('<F3>') screen:expect([[ ^some short lines | @@ -97,22 +103,50 @@ describe('mappings with <Cmd>', function() {1:~ }| {1:~ }| {1:~ }| - {2:E5522: <Cmd> mapping must not include <F3> key} | + {2:E5520: <Cmd> mapping must end with <CR>} | ]]) + eq(0, eval('x')) + end) - feed_command('noremap <F3> <Cmd>let x = 3') + it('allows special keys and modifiers', function() + command('noremap <F3> <Cmd>normal! <Down><CR>') feed('<F3>') screen:expect([[ - ^some short lines | - of test text | + some short lines | + ^of test text | {1:~ }| {1:~ }| {1:~ }| {1:~ }| {1:~ }| - {2:E5520: <Cmd> mapping must end with <CR>} | + | ]]) - eq(0, eval('x')) + + command('noremap <F3> <Cmd>normal! <C-Right><CR>') + feed('<F3>') + screen:expect([[ + some short lines | + of ^test text | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) + end) + + it('handles string containing K_SPECIAL (0x80) bytes correctly', function() + command([[noremap <F3> <Cmd>let g:str = 'foo…bar'<CR>]]) + feed('<F3>') + eq('foo…bar', eval('g:str')) + local str = eval([["foo\<D-…>bar"]]) + command([[noremap <F3> <Cmd>let g:str = ']]..str..[['<CR>]]) + feed('<F3>') + eq(str, eval('g:str')) + command([[noremap <F3> <Cmd>let g:str = 'foo<D-…>bar'<CR>]]) + feed('<F3>') + eq(str, eval('g:str')) end) it('works in various modes and sees correct `mode()` value', function() @@ -137,7 +171,7 @@ describe('mappings with <Cmd>', function() eq('n', eval('mode(1)')) -- select mode mapping - feed_command('snoremap <F3> <Cmd>let m = mode(1)<cr>') + command('snoremap <F3> <Cmd>let m = mode(1)<cr>') feed('gh<F3>') eq('s', eval('m')) -- didn't leave select mode @@ -184,8 +218,8 @@ describe('mappings with <Cmd>', function() eq('n', eval('mode(1)')) -- terminal mode - feed_command('tnoremap <F3> <Cmd>let m = mode(1)<cr>') - feed_command('split | terminal') + command('tnoremap <F3> <Cmd>let m = mode(1)<cr>') + command('split | terminal') feed('i') eq('t', eval('mode(1)')) feed('<F3>') @@ -264,11 +298,11 @@ describe('mappings with <Cmd>', function() end) it('works in :normal command', function() - feed_command('noremap ,x <Cmd>call append(1, "xx")\\| call append(1, "aa")<cr>') - feed_command('noremap ,f <Cmd>nosuchcommand<cr>') - feed_command('noremap ,e <Cmd>throw "very error"\\| call append(1, "yy")<cr>') - feed_command('noremap ,m <Cmd>echoerr "The message."\\| call append(1, "zz")<cr>') - feed_command('noremap ,w <Cmd>for i in range(5)\\|if i==1\\|echoerr "Err"\\|endif\\|call append(1, i)\\|endfor<cr>') + command('noremap ,x <Cmd>call append(1, "xx")\\| call append(1, "aa")<cr>') + command('noremap ,f <Cmd>nosuchcommand<cr>') + command('noremap ,e <Cmd>throw "very error"\\| call append(1, "yy")<cr>') + command('noremap ,m <Cmd>echoerr "The message."\\| call append(1, "zz")<cr>') + command('noremap ,w <Cmd>for i in range(5)\\|if i==1\\|echoerr "Err"\\|endif\\|call append(1, i)\\|endfor<cr>') feed(":normal ,x<cr>") screen:expect([[ @@ -297,7 +331,7 @@ describe('mappings with <Cmd>', function() :normal ,x | ]]) - feed_command(':%d') + command(':%d') eq('Vim(echoerr):Err', exc_exec("normal ,w")) screen:expect([[ ^ | @@ -310,8 +344,8 @@ describe('mappings with <Cmd>', function() --No lines in buffer-- | ]]) - feed_command(':%d') - feed_command(':normal ,w') + command(':%d') + feed(':normal ,w<cr>') screen:expect([[ ^ | 4 | @@ -401,8 +435,8 @@ describe('mappings with <Cmd>', function() end) it('works in select mode', function() - feed_command('snoremap <F1> <cmd>throw "very error"<cr>') - feed_command('snoremap <F2> <cmd>normal! <c-g>"by<cr>') + command('snoremap <F1> <cmd>throw "very error"<cr>') + command('snoremap <F2> <cmd>normal! <c-g>"by<cr>') -- can extend select mode feed('gh<F4>') screen:expect([[ @@ -830,12 +864,14 @@ describe('mappings with <Cmd>', function() end) it("works with <SID> mappings", function() - source([[ + command('new!') + write_file(tmpfile, [[ map <f2> <Cmd>call <SID>do_it()<Cr> function! s:do_it() let g:x = 10 endfunction ]]) + command('source '..tmpfile) feed('<f2>') eq('', eval('v:errmsg')) eq(10, eval('g:x')) diff --git a/test/functional/ex_cmds/ctrl_c_spec.lua b/test/functional/ex_cmds/ctrl_c_spec.lua deleted file mode 100644 index f65d9f0d01..0000000000 --- a/test/functional/ex_cmds/ctrl_c_spec.lua +++ /dev/null @@ -1,60 +0,0 @@ -local helpers = require('test.functional.helpers')(after_each) -local Screen = require('test.functional.ui.screen') -local clear, feed, source = helpers.clear, helpers.feed, helpers.source -local command = helpers.command - -describe("CTRL-C (mapped)", function() - before_each(function() - clear() - end) - - it("interrupts :global", function() - -- Crashes luajit. - if helpers.skip_fragile(pending, - helpers.isCI('travis') or helpers.isCI('appveyor')) then - return - end - - source([[ - set nomore nohlsearch undolevels=-1 - nnoremap <C-C> <NOP> - ]]) - - command("silent edit! test/functional/fixtures/bigfile.txt") - local screen = Screen.new(52, 6) - screen:attach() - screen:set_default_attr_ids({ - [0] = {foreground = Screen.colors.White, - background = Screen.colors.Red}, - [1] = {bold = true, - foreground = Screen.colors.SeaGreen} - }) - - screen:expect([[ - ^0000;<control>;Cc;0;BN;;;;;N;NULL;;;; | - 0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;; | - 0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; | - 0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; | - 0004;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;;| - | - ]]) - - local function test_ctrl_c(ms) - feed(":global/^/p<CR>") - screen:sleep(ms) - feed("<C-C>") - screen:expect{any="Interrupt"} - end - - -- The test is time-sensitive. Try different sleep values. - local ms_values = {100, 1000, 10000} - for i, ms in ipairs(ms_values) do - if i < #ms_values then - local status, _ = pcall(test_ctrl_c, ms) - if status then break end - else -- Call the last attempt directly. - test_ctrl_c(ms) - end - end - end) -end) diff --git a/test/functional/ex_cmds/drop_spec.lua b/test/functional/ex_cmds/drop_spec.lua index 9d84a2d4f6..2537ab9cdc 100644 --- a/test/functional/ex_cmds/drop_spec.lua +++ b/test/functional/ex_cmds/drop_spec.lua @@ -41,14 +41,14 @@ describe(":drop", function() feed_command("edit tmp2") feed_command("drop tmp1") screen:expect([[ - {2:│}^ | - {0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }| + │^ | + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| {2:tmp2 }{1:tmp1 }| :drop tmp1 | ]]) @@ -62,14 +62,14 @@ describe(":drop", function() feed("iABC<esc>") feed_command("drop tmp3") screen:expect([[ - ^ {2:│} | - {0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }| - {1:tmp3 }{2:│}{0:~ }| - ABC {2:│}{0:~ }| - {0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }| + ^ │ | + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {1:tmp3 }│{0:~ }| + ABC │{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| {2:tmp2 [+] tmp1 }| "tmp3" [New] | ]]) diff --git a/test/functional/ex_cmds/echo_spec.lua b/test/functional/ex_cmds/echo_spec.lua index d320425de1..a6be04138b 100644 --- a/test/functional/ex_cmds/echo_spec.lua +++ b/test/functional/ex_cmds/echo_spec.lua @@ -181,9 +181,9 @@ describe(':echo :echon :echomsg :echoerr', function() end) it('dumps references to script functions', function() - eq('<SNR>2_Test2', eval('String(Test2_f)')) - eq("function('<SNR>2_Test2')", eval('StringMsg(Test2_f)')) - eq("function('<SNR>2_Test2')", eval('StringErr(Test2_f)')) + eq('<SNR>1_Test2', eval('String(Test2_f)')) + eq("function('<SNR>1_Test2')", eval('StringMsg(Test2_f)')) + eq("function('<SNR>1_Test2')", eval('StringErr(Test2_f)')) end) it('dump references to lambdas', function() @@ -205,11 +205,11 @@ describe(':echo :echon :echomsg :echoerr', function() it('dumps automatically created partials', function() assert_same_echo_dump( - "function('<SNR>2_Test2', {'f': function('<SNR>2_Test2')})", + "function('<SNR>1_Test2', {'f': function('<SNR>1_Test2')})", '{"f": Test2_f}.f', true) assert_same_echo_dump( - "function('<SNR>2_Test2', [1], {'f': function('<SNR>2_Test2', [1])})", + "function('<SNR>1_Test2', [1], {'f': function('<SNR>1_Test2', [1])})", '{"f": function(Test2_f, [1])}.f', true) end) @@ -227,7 +227,7 @@ describe(':echo :echon :echomsg :echoerr', function() function() meths.set_var('d', {v=true}) eq(dedent([[ - {'p': function('<SNR>2_Test2', {...@0}), 'f': function('<SNR>2_Test2'), 'v': v:true}]]), + {'p': function('<SNR>1_Test2', {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]]), exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))')) end) @@ -264,7 +264,7 @@ describe(':echo :echon :echomsg :echoerr', function() eval('add(l, function("Test1", l))') eval('add(l, function("Test1", d))') eq(dedent([=[ - {'p': function('<SNR>2_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>2_Test2'), 'v': v:true}]=]), + {'p': function('<SNR>1_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]=]), exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))')) end) end) diff --git a/test/functional/ex_cmds/ls_spec.lua b/test/functional/ex_cmds/ls_spec.lua index 9853084c47..2583d80269 100644 --- a/test/functional/ex_cmds/ls_spec.lua +++ b/test/functional/ex_cmds/ls_spec.lua @@ -5,7 +5,7 @@ local eq = helpers.eq local eval = helpers.eval local feed = helpers.feed local nvim = helpers.nvim -local nvim_dir = helpers.nvim_dir +local testprg = helpers.testprg local retry = helpers.retry describe(':ls', function() @@ -14,7 +14,7 @@ describe(':ls', function() end) it('R, F for :terminal buffers', function() - nvim('set_option', 'shell', string.format('"%s" INTERACT', nvim_dir..'/shell-test')) + nvim('set_option', 'shell', string.format('"%s" INTERACT', testprg('shell-test'))) command('edit foo') command('set hidden') diff --git a/test/functional/ex_cmds/make_spec.lua b/test/functional/ex_cmds/make_spec.lua index 3b4d22ab38..bf585ee44c 100644 --- a/test/functional/ex_cmds/make_spec.lua +++ b/test/functional/ex_cmds/make_spec.lua @@ -4,7 +4,7 @@ local eval = helpers.eval local has_powershell = helpers.has_powershell local matches = helpers.matches local nvim = helpers.nvim -local nvim_dir = helpers.nvim_dir +local testprg = helpers.testprg describe(':make', function() clear() @@ -22,7 +22,7 @@ describe(':make', function() end) it('captures stderr & non zero exit code #14349', function () - nvim('set_option', 'makeprg', nvim_dir..'/shell-test foo') + nvim('set_option', 'makeprg', testprg('shell-test')..' foo') local out = eval('execute("make")') -- Make program exit code correctly captured matches('\nshell returned 3', out) @@ -31,7 +31,7 @@ describe(':make', function() end) it('captures stderr & zero exit code #14349', function () - nvim('set_option', 'makeprg', nvim_dir..'/shell-test') + nvim('set_option', 'makeprg', testprg('shell-test')) local out = eval('execute("make")') -- Ensure there are no "shell returned X" messages between -- command and last line (indicating zero exit) diff --git a/test/functional/ex_cmds/map_spec.lua b/test/functional/ex_cmds/map_spec.lua index 84d5bc2335..c6bdd017bd 100644 --- a/test/functional/ex_cmds/map_spec.lua +++ b/test/functional/ex_cmds/map_spec.lua @@ -1,11 +1,15 @@ local helpers = require("test.functional.helpers")(after_each) +local Screen = require('test.functional.ui.screen') local eq = helpers.eq +local exec = helpers.exec local feed = helpers.feed local meths = helpers.meths local clear = helpers.clear local command = helpers.command local expect = helpers.expect +local insert = helpers.insert +local eval = helpers.eval describe(':*map', function() before_each(clear) @@ -25,4 +29,233 @@ describe(':*map', function() feed('i-<M-">-') expect('-foo-') end) + + it('shows <nop> as mapping rhs', function() + command('nmap asdf <Nop>') + eq([[ + +n asdf <Nop>]], + helpers.exec_capture('nmap asdf')) + end) + + it('mappings with description can be filtered', function() + meths.set_keymap('n', 'asdf1', 'qwert', {desc='do the one thing'}) + meths.set_keymap('n', 'asdf2', 'qwert', {desc='doesnot really do anything'}) + meths.set_keymap('n', 'asdf3', 'qwert', {desc='do the other thing'}) + eq([[ + +n asdf3 qwert + do the other thing +n asdf1 qwert + do the one thing]], + helpers.exec_capture('filter the nmap')) + end) + + it('<Plug> mappings ignore nore', function() + command('let x = 0') + eq(0, meths.eval('x')) + command [[ + nnoremap <Plug>(Increase_x) <cmd>let x+=1<cr> + nmap increase_x_remap <Plug>(Increase_x) + nnoremap increase_x_noremap <Plug>(Increase_x) + ]] + feed('increase_x_remap') + eq(1, meths.eval('x')) + feed('increase_x_noremap') + eq(2, meths.eval('x')) + end) + + it("Doesn't auto ignore nore for keys before or after <Plug> mapping", function() + command('let x = 0') + eq(0, meths.eval('x')) + command [[ + nnoremap x <nop> + nnoremap <Plug>(Increase_x) <cmd>let x+=1<cr> + nmap increase_x_remap x<Plug>(Increase_x)x + nnoremap increase_x_noremap x<Plug>(Increase_x)x + ]] + insert("Some text") + eq('Some text', eval("getline('.')")) + + feed('increase_x_remap') + eq(1, meths.eval('x')) + eq('Some text', eval("getline('.')")) + feed('increase_x_noremap') + eq(2, meths.eval('x')) + eq('Some te', eval("getline('.')")) + end) +end) + +describe('Screen', function() + local screen + before_each(function() + clear() + screen = Screen.new(20, 5) + screen:attach() + end) + + it('cursor is restored after :map <expr> which calls input()', function() + command('map <expr> x input("> ")') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]]) + feed('x') + screen:expect([[ + | + ~ | + ~ | + ~ | + > ^ | + ]]) + feed('\n') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + > | + ]]) + end) + + it('cursor is restored after :imap <expr> which calls input()', function() + command('imap <expr> x input("> ")') + feed('i') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + -- INSERT -- | + ]]) + feed('x') + screen:expect([[ + | + ~ | + ~ | + ~ | + > ^ | + ]]) + feed('\n') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + > | + ]]) + end) + + it('cursor position does not move after empty-string :cmap <expr> #19046', function() + command([[cnoremap <expr> <F2> '']]) + feed(':<F2>') + screen:expect([[ + | + ~ | + ~ | + ~ | + :^ | + ]]) + end) + + it('cursor is restored after :map <expr> which redraws statusline vim-patch:8.1.2336', function() + exec([[ + call setline(1, ['one', 'two', 'three']) + 2 + set ls=2 + hi! link StatusLine ErrorMsg + noremap <expr> <C-B> Func() + func Func() + let g:on = !get(g:, 'on', 0) + redraws + return '' + endfunc + func Status() + return get(g:, 'on', 0) ? '[on]' : '' + endfunc + set stl=%{Status()} + ]]) + feed('<C-B>') + screen:expect([[ + one | + ^two | + three | + [on] | + | + ]]) + end) + + it('error in :nmap <expr> does not mess up display vim-patch:4.2.4338', function() + screen:try_resize(40, 5) + command('nmap <expr> <F2> execute("throw 42")') + feed('<F2>') + screen:expect([[ + | + | + Error detected while processing : | + E605: Exception not caught: 42 | + Press ENTER or type command to continue^ | + ]]) + feed('<CR>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]]) + end) + + it('error in :cmap <expr> handled correctly vim-patch:4.2.4338', function() + screen:try_resize(40, 5) + command('cmap <expr> <F2> execute("throw 42")') + feed(':echo "foo') + screen:expect([[ + | + ~ | + ~ | + ~ | + :echo "foo^ | + ]]) + feed('<F2>') + screen:expect([[ + | + :echo "foo | + Error detected while processing : | + E605: Exception not caught: 42 | + :echo "foo^ | + ]]) + feed('"') + screen:expect([[ + | + :echo "foo | + Error detected while processing : | + E605: Exception not caught: 42 | + :echo "foo"^ | + ]]) + feed('\n') + screen:expect([[ + :echo "foo | + Error detected while processing : | + E605: Exception not caught: 42 | + foo | + Press ENTER or type command to continue^ | + ]]) + end) + + it('listing mappings clears command line vim-patch:8.2.4401', function() + screen:try_resize(40, 5) + command('nmap a b') + feed(': nmap a<CR>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + n a b | + ]]) + end) end) diff --git a/test/functional/ex_cmds/menu_spec.lua b/test/functional/ex_cmds/menu_spec.lua index 0cd32df27c..b9ed32c328 100644 --- a/test/functional/ex_cmds/menu_spec.lua +++ b/test/functional/ex_cmds/menu_spec.lua @@ -64,6 +64,8 @@ describe('menu_get', function() before_each(function() clear() command([=[ + aunmenu * + nnoremenu &Test.Test inormal<ESC> inoremenu Test.Test insert vnoremenu Test.Test x @@ -396,6 +398,7 @@ describe('menu_get', function() before_each(function() clear() + command('aunmenu *') end) it('returns <keycode> representation of special keys', function() diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua index 09eaa36686..1553de4432 100644 --- a/test/functional/ex_cmds/mksession_spec.lua +++ b/test/functional/ex_cmds/mksession_spec.lua @@ -1,14 +1,20 @@ local lfs = require('lfs') local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') local clear = helpers.clear local command = helpers.command local get_pathsep = helpers.get_pathsep +local iswin = helpers.iswin local eq = helpers.eq +local neq = helpers.neq local funcs = helpers.funcs local matches = helpers.matches 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' @@ -30,7 +36,8 @@ describe(':mksession', function() -- If the same :terminal is displayed in multiple windows, :mksession -- should restore it as such. - -- Create two windows showing the same :terminal buffer. + -- Create three windows: first two from top show same terminal, third - + -- another one (created earlier). command('terminal') command('split') command('terminal') @@ -38,13 +45,13 @@ describe(':mksession', function() command('mksession '..session_file) -- Create a new test instance of Nvim. - command('qall!') + expect_exit(command, 'qall!') clear() -- Restore session. command('source '..session_file) - eq({2,2,4}, - {funcs.winbufnr(1), funcs.winbufnr(2), funcs.winbufnr(3)}) + eq(funcs.winbufnr(1), funcs.winbufnr(2)) + neq(funcs.winbufnr(1), funcs.winbufnr(3)) end) it('restores tab-local working directories', function() @@ -91,12 +98,7 @@ describe(':mksession', function() command('tabnext 1') eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '1', funcs.expand('%:p')) command('tabnext 2') - -- :mksession stores paths using unix slashes, but Nvim doesn't adjust these - -- for absolute paths in all cases yet. Absolute paths are used in the - -- session file after :tcd, so we need to expect unix slashes here for now - -- eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', funcs.expand('%:p')) - eq(cwd_dir:gsub([[\]], '/') .. '/' .. tmpfile_base .. '2', - funcs.expand('%:p')) + eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', funcs.expand('%:p')) end) it('restores CWD for :terminal buffers #11288', function() @@ -105,10 +107,14 @@ describe(':mksession', function() local session_path = cwd_dir..'/'..session_file command('cd '..tab_dir) - command('terminal echo $PWD') + command('terminal') command('cd '..cwd_dir) command('mksession '..session_path) - command('qall!') + command('bdelete!') + if iswin() then + sleep(100) -- Make sure all child processes have exited. + end + expect_exit(command, 'qall!') -- Create a new test instance of Nvim. clear() @@ -116,6 +122,83 @@ describe(':mksession', function() local expected_cwd = cwd_dir..'/'..tab_dir matches('^term://'..pesc(expected_cwd)..'//%d+:', funcs.expand('%')) - command('qall!') + command('bdelete!') + if iswin() then + sleep(100) -- Make sure all child processes have exited. + end + end) + + it('restores CWD for :terminal buffer at root directory #16988', function() + if iswin() then + pending('N/A for Windows') + return + end + + local screen + local cwd_dir = funcs.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '') + local session_path = cwd_dir..'/'..session_file + + screen = Screen.new(50, 6) + screen:attach({rgb=false}) + local expected_screen = [[ + ^/ | + | + [Process exited 0] | + | + | + | + ]] + + command('cd /') + command('terminal echo $PWD') + + -- Verify that the terminal's working directory is "/". + screen:expect(expected_screen) + + command('cd '..cwd_dir) + command('mksession '..session_path) + expect_exit(command, 'qall!') + + -- Create a new test instance of Nvim. + clear() + screen = Screen.new(50, 6) + screen:attach({rgb=false}) + command('silent source '..session_path) + + -- Verify that the terminal's working directory is "/". + screen:expect(expected_screen) + end) + + it('restores a session when there is a float #18432', function() + local tmpfile = file_prefix .. '-tmpfile-float' + + command('edit ' .. tmpfile) + local buf = meths.create_buf(false, true) + local config = { + relative = 'editor', + focusable = false, + width = 10, + height = 3, + row = 0, + col = 1, + style = 'minimal' + } + meths.open_win(buf, false, config) + local cmdheight = meths.get_option('cmdheight') + command('mksession ' .. session_file) + + -- Create a new test instance of Nvim. + clear() + + command('source ' .. session_file) + + eq(tmpfile, funcs.expand('%')) + -- Check that there is only a single window, which indicates the floating + -- window was not restored. + eq(1, funcs.winnr('$')) + -- The command-line height should remain the same as it was. + eq(cmdheight, meths.get_option('cmdheight')) + + os.remove(tmpfile) end) end) diff --git a/test/functional/ex_cmds/normal_spec.lua b/test/functional/ex_cmds/normal_spec.lua new file mode 100644 index 0000000000..f6e7dd2b3a --- /dev/null +++ b/test/functional/ex_cmds/normal_spec.lua @@ -0,0 +1,27 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear = helpers.clear +local command = helpers.command +local feed = helpers.feed +local expect = helpers.expect +local eq = helpers.eq +local eval = helpers.eval + +before_each(clear) + +describe(':normal', function() + it('can get out of Insert mode if called from Ex mode #17924', function() + feed('gQnormal! Ifoo<CR>') + expect('foo') + end) + + it('normal! does not execute command in Ex mode when running out of characters', function() + command('let g:var = 0') + command('normal! gQlet g:var = 1') + eq(0, eval('g:var')) + end) + + it('normal! gQinsert does not hang #17980', function() + command('normal! gQinsert') + expect('') + end) +end) diff --git a/test/functional/ex_cmds/quickfix_commands_spec.lua b/test/functional/ex_cmds/quickfix_commands_spec.lua index c956a2df2d..94b7fa1a84 100644 --- a/test/functional/ex_cmds/quickfix_commands_spec.lua +++ b/test/functional/ex_cmds/quickfix_commands_spec.lua @@ -109,4 +109,17 @@ describe('quickfix', function() ]]) eq({0, 6, 1, 0, 1}, funcs.getcurpos()) end) + + it('BufAdd does not cause E16 when reusing quickfix buffer #18135', function() + local file = file_base .. '_reuse_qfbuf_BufAdd' + write_file(file, ('\n'):rep(100) .. 'foo') + source([[ + set grepprg=internal + autocmd BufAdd * call and(0, 0) + autocmd QuickFixCmdPost grep ++nested cclose | cwindow + ]]) + command('grep foo ' .. file) + command('grep foo ' .. file) + os.remove(file) + end) end) diff --git a/test/functional/ex_cmds/script_spec.lua b/test/functional/ex_cmds/script_spec.lua index 0a772c559b..bf69ada820 100644 --- a/test/functional/ex_cmds/script_spec.lua +++ b/test/functional/ex_cmds/script_spec.lua @@ -2,18 +2,30 @@ local helpers = require('test.functional.helpers')(after_each) local eq = helpers.eq local neq = helpers.neq +local command = helpers.command +local write_file = helpers.write_file local meths = helpers.meths local clear = helpers.clear local dedent = helpers.dedent -local source = helpers.source local exc_exec = helpers.exc_exec local missing_provider = helpers.missing_provider +local tmpfile = 'X_ex_cmds_script' + before_each(clear) +local function source(code) + write_file(tmpfile, code) + command('source '..tmpfile) +end + describe('script_get-based command', function() local garbage = ')}{+*({}]*[;(+}{&[]}{*])(' + after_each(function() + os.remove(tmpfile) + end) + local function test_garbage_exec(cmd, check_neq) describe(cmd, function() it('works correctly when skipping oneline variant', function() @@ -62,10 +74,10 @@ describe('script_get-based command', function() -- Provider-based scripts test_garbage_exec('ruby', not missing_provider('ruby')) - test_garbage_exec('python', not missing_provider('python')) test_garbage_exec('python3', not missing_provider('python3')) -- Missing scripts + test_garbage_exec('python', false) test_garbage_exec('tcl', false) test_garbage_exec('mzscheme', false) test_garbage_exec('perl', false) diff --git a/test/functional/ex_cmds/sign_spec.lua b/test/functional/ex_cmds/sign_spec.lua index 891cfe1670..f280a45174 100644 --- a/test/functional/ex_cmds/sign_spec.lua +++ b/test/functional/ex_cmds/sign_spec.lua @@ -1,5 +1,5 @@ local helpers = require('test.functional.helpers')(after_each) -local clear, nvim, eq = helpers.clear, helpers.nvim, helpers.eq +local clear, nvim, eq, assert_alive = helpers.clear, helpers.nvim, helpers.eq, helpers.assert_alive describe('sign', function() before_each(clear) @@ -21,4 +21,11 @@ describe('sign', function() end) end) end) + + describe('define {id}', function() + it ('does not leak memory when specifying multiple times the same argument', function() + nvim('command', 'sign define Foo culhl=Normal culhl=Normal') + assert_alive() + end) + end) end) diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua index fa650d611b..13a40fcc53 100644 --- a/test/functional/ex_cmds/source_spec.lua +++ b/test/functional/ex_cmds/source_spec.lua @@ -19,6 +19,26 @@ describe(':source', function() clear() end) + it('sourcing a file that is deleted and recreated is consistent vim-patch:8.1.0151', function() + local test_file = 'Xfile.vim' + local other_file = 'Xfoobar' + local script = [[ + func Func() + endfunc + ]] + write_file(test_file, script) + command('source ' .. test_file) + os.remove(test_file) + write_file(test_file, script) + command('source ' .. test_file) + os.remove(test_file) + write_file(other_file, '') + write_file(test_file, script) + command('source ' .. test_file) + os.remove(other_file) + os.remove(test_file) + end) + it('current buffer', function() insert([[ let a = 2 diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua index d91feb4bc1..4d984af41e 100644 --- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua +++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua @@ -10,6 +10,7 @@ local feed = helpers.feed local nvim_prog = helpers.nvim_prog local ok = helpers.ok local rmdir = helpers.rmdir +local os_kill = helpers.os_kill local set_session = helpers.set_session local spawn = helpers.spawn local nvim_async = helpers.nvim_async @@ -62,6 +63,7 @@ describe(':preserve', function() local swappath1 = eval('g:swapname') + os_kill(eval('getpid()')) -- Start another Nvim instance. local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'}, true) @@ -122,6 +124,7 @@ describe('swapfile detection', function() feed('isometext<esc>') command('preserve') + os_kill(eval('getpid()')) -- Start another Nvim instance. local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'}, true) diff --git a/test/functional/ex_cmds/verbose_spec.lua b/test/functional/ex_cmds/verbose_spec.lua new file mode 100644 index 0000000000..e6f67ef18e --- /dev/null +++ b/test/functional/ex_cmds/verbose_spec.lua @@ -0,0 +1,168 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local eq = helpers.eq +local exec = helpers.exec +local exec_capture = helpers.exec_capture +local write_file = helpers.write_file +local call_viml_function = helpers.meths.call_function + +describe('lua :verbose', function() + local script_location, script_file + -- All test cases below use the same nvim instance. + setup(function() + clear{args={'-V1'}} + script_file = 'test_verbose.lua' + local current_dir = call_viml_function('getcwd', {}) + current_dir = call_viml_function('fnamemodify', {current_dir, ':~'}) + script_location = table.concat{current_dir, helpers.get_pathsep(), script_file} + + write_file(script_file, [[ +vim.api.nvim_set_option('hlsearch', false) +vim.bo.expandtab = true +vim.opt.number = true +vim.api.nvim_set_keymap('n', '<leader>key1', ':echo "test"<cr>', {noremap = true}) +vim.keymap.set('n', '<leader>key2', ':echo "test"<cr>') + +vim.api.nvim_exec("augroup test_group\ + autocmd!\ + autocmd FileType c setl cindent\ + augroup END\ + ", false) + +vim.api.nvim_command("command Bdelete :bd") +vim.api.nvim_create_user_command("TestCommand", ":echo 'Hello'", {}) + +vim.api.nvim_exec ("\ +function Close_Window() abort\ + wincmd -\ +endfunction\ +", false) + +local ret = vim.api.nvim_exec ("\ +function! s:return80()\ + return 80\ +endfunction\ +let &tw = s:return80()\ +", true) +]]) + exec(':source '..script_file) + end) + + teardown(function() + os.remove(script_file) + end) + + it('"Last set" for option set by Lua', function() + local result = exec_capture(':verbose set hlsearch?') + eq(string.format([[ +nohlsearch + Last set from %s line 1]], + script_location), result) + end) + + it('"Last set" for option set by vim.o', function() + local result = exec_capture(':verbose set expandtab?') + eq(string.format([[ + expandtab + Last set from %s line 2]], + script_location), result) + end) + + it('"Last set" for option set by vim.opt', function() + local result = exec_capture(':verbose set number?') + eq(string.format([[ + number + Last set from %s line 3]], + script_location), result) + end) + + it('"Last set" for keymap set by Lua', function() + local result = exec_capture(':verbose map <leader>key1') + eq(string.format([[ + +n \key1 * :echo "test"<CR> + Last set from %s line 4]], + script_location), result) + end) + + it('"Last set" for keymap set by vim.keymap', function() + local result = exec_capture(':verbose map <leader>key2') + eq(string.format([[ + +n \key2 * :echo "test"<CR> + Last set from %s line 5]], + script_location), result) + end) + + it('"Last set" for autocmd by vim.api.nvim_exec', function() + local result = exec_capture(':verbose autocmd test_group Filetype c') + eq(string.format([[ +--- Autocommands --- +test_group FileType + c setl cindent + Last set from %s line 7]], + script_location), result) + end) + + it('"Last set" for command defined by nvim_command', function() + local result = exec_capture(':verbose command Bdelete') + eq(string.format([[ + Name Args Address Complete Definition + Bdelete 0 :bd + Last set from %s line 13]], + script_location), result) + end) + + it('"Last set" for command defined by nvim_create_user_command', function() + local result = exec_capture(':verbose command TestCommand') + eq(string.format([[ + Name Args Address Complete Definition + TestCommand 0 :echo 'Hello' + Last set from %s line 14]], + script_location), result) + end) + + it('"Last set for function', function() + local result = exec_capture(':verbose function Close_Window') + eq(string.format([[ + function Close_Window() abort + Last set from %s line 16 +1 wincmd - + endfunction]], + script_location), result) + end) + + it('"Last set" works with anonymous sid', function() + local result = exec_capture(':verbose set tw?') + eq(string.format([[ + textwidth=80 + Last set from %s line 22]], + script_location), result) + end) +end) + +describe('lua verbose:', function() + local script_file + + setup(function() + clear() + script_file = 'test_luafile.lua' + write_file(script_file, [[ + vim.api.nvim_set_option('hlsearch', false) + ]]) + exec(':source '..script_file) + end) + + teardown(function() + os.remove(script_file) + end) + + it('is disabled when verbose = 0', function() + local result = exec_capture(':verbose set hlsearch?') + eq([[ +nohlsearch + Last set from Lua]], result) + end) +end) + |