" Tests for editing the command line. source check.vim source screendump.vim func Test_getcmdwintype() call feedkeys("q/:let a = getcmdwintype()\:q\", 'x!') call assert_equal('/', a) call feedkeys("q?:let a = getcmdwintype()\:q\", 'x!') call assert_equal('?', a) call feedkeys("q::let a = getcmdwintype()\:q\", 'x!') call assert_equal(':', a) call feedkeys(":\:let a = getcmdwintype()\:q\", 'x!') call assert_equal(':', a) call assert_equal('', getcmdwintype()) endfunc func Test_getcmdwin_autocmd() let s:seq = [] augroup CmdWin au WinEnter * call add(s:seq, 'WinEnter ' .. win_getid()) au WinLeave * call add(s:seq, 'WinLeave ' .. win_getid()) au BufEnter * call add(s:seq, 'BufEnter ' .. bufnr()) au BufLeave * call add(s:seq, 'BufLeave ' .. bufnr()) au CmdWinEnter * call add(s:seq, 'CmdWinEnter ' .. win_getid()) au CmdWinLeave * call add(s:seq, 'CmdWinLeave ' .. win_getid()) let org_winid = win_getid() let org_bufnr = bufnr() call feedkeys("q::let a = getcmdwintype()\:let s:cmd_winid = win_getid()\:let s:cmd_bufnr = bufnr()\:q\", 'x!') call assert_equal(':', a) call assert_equal([ \ 'WinLeave ' .. org_winid, \ 'WinEnter ' .. s:cmd_winid, \ 'BufLeave ' .. org_bufnr, \ 'BufEnter ' .. s:cmd_bufnr, \ 'CmdWinEnter ' .. s:cmd_winid, \ 'CmdWinLeave ' .. s:cmd_winid, \ 'BufLeave ' .. s:cmd_bufnr, \ 'WinLeave ' .. s:cmd_winid, \ 'WinEnter ' .. org_winid, \ 'BufEnter ' .. org_bufnr, \ ], s:seq) au! augroup END endfunc func Test_cmdwin_bug() let winid = win_getid() sp try call feedkeys("q::call win_gotoid(" .. winid .. ")\:q\", 'x!') catch /^Vim\%((\a\+)\)\=:E11/ endtry bw! endfunc func Test_cmdwin_restore() CheckScreendump let lines =<< trim [SCRIPT] augroup vimHints | au! | augroup END call setline(1, range(30)) 2split [SCRIPT] call writefile(lines, 'XTest_restore', 'D') let buf = RunVimInTerminal('-S XTest_restore', {'rows': 12}) call term_sendkeys(buf, "q:") call VerifyScreenDump(buf, 'Test_cmdwin_restore_1', {}) " normal restore call term_sendkeys(buf, ":q\") call VerifyScreenDump(buf, 'Test_cmdwin_restore_2', {}) " restore after setting 'lines' with one window call term_sendkeys(buf, ":close\") call term_sendkeys(buf, "q:") call term_sendkeys(buf, ":set lines=18\") call term_sendkeys(buf, ":q\") call VerifyScreenDump(buf, 'Test_cmdwin_restore_3', {}) " clean up call StopVimInTerminal(buf) endfunc func Test_cmdwin_no_terminal() CheckScreendump let buf = RunVimInTerminal('', {'rows': 12}) call term_sendkeys(buf, ":set cmdheight=2\") call term_sendkeys(buf, "q:") call term_sendkeys(buf, ":let buf = term_start(['/bin/echo'], #{hidden: 1})\") call VerifyScreenDump(buf, 'Test_cmdwin_no_terminal', {}) call term_sendkeys(buf, ":q\") call StopVimInTerminal(buf) endfunc func Test_cmdwin_wrong_command() CheckScreendump let buf = RunVimInTerminal('', {'rows': 12}) call term_sendkeys(buf, "q:") call term_sendkeys(buf, "als\") call term_sendkeys(buf, "\k") call VerifyScreenDump(buf, 'Test_cmdwin_wrong_command_1', {}) call term_sendkeys(buf, "\") call VerifyScreenDump(buf, 'Test_cmdwin_wrong_command_2', {}) call term_sendkeys(buf, ":q\") call StopVimInTerminal(buf) endfunc func Test_cmdwin_feedkeys() " This should not generate E488 call feedkeys("q:\", 'x') " Using feedkeys with q: only should automatically close the cmd window call feedkeys('q:', 'xt') call assert_equal(1, winnr('$')) call assert_equal('', getcmdwintype()) endfunc " Tests for the issues fixed in 7.4.441. " When 'cedit' is set to Ctrl-C, opening the command window hangs Vim func Test_cmdwin_cedit() exe "set cedit=\" normal! : call assert_equal(1, winnr('$')) let g:cmd_wintype = '' func CmdWinType() let g:cmd_wintype = getcmdwintype() let g:wintype = win_gettype() return '' endfunc call feedkeys("\a\=CmdWinType()\\") echo input('') call assert_equal('@', g:cmd_wintype) call assert_equal('command', g:wintype) set cedit&vim delfunc CmdWinType endfunc " Test for CmdwinEnter autocmd func Test_cmdwin_autocmd() augroup CmdWin au! autocmd BufLeave * if &buftype == '' | update | endif autocmd CmdwinEnter * startinsert augroup END call assert_fails('call feedkeys("q:xyz\", "xt")', 'E492:') call assert_equal('xyz', @:) augroup CmdWin au! augroup END augroup! CmdWin endfunc func Test_cmdwin_jump_to_win() call assert_fails('call feedkeys("q:\\\", "xt")', 'E11:') new set modified call assert_fails('call feedkeys("q/:qall\", "xt")', ['E37:', 'E162:']) close! call feedkeys("q/:close\", "xt") call assert_equal(1, winnr('$')) call feedkeys("q/:exit\", "xt") call assert_equal(1, winnr('$')) " opening command window twice should fail call assert_beeps('call feedkeys("q:q:\\", "xt")') call assert_equal(1, winnr('$')) endfunc func Test_cmdwin_tabpage() tabedit call assert_fails("silent norm q/g :I\", 'E11:') tabclose! endfunc func Test_cmdwin_interrupted_more_prompt() CheckScreendump " aborting the :smile output caused the cmdline window to use the current " buffer. let lines =<< trim [SCRIPT] au WinNew * smile [SCRIPT] call writefile(lines, 'XTest_cmdwin', 'D') let buf = RunVimInTerminal('-S XTest_cmdwin', {'rows': 18}) " open cmdwin call term_sendkeys(buf, "q:") call WaitForAssert({-> assert_match('-- More --', term_getline(buf, 18))}) " quit more prompt for :smile command call term_sendkeys(buf, "q") call WaitForAssert({-> assert_match('^$', term_getline(buf, 18))}) " execute a simple command call term_sendkeys(buf, "aecho 'done'\") call VerifyScreenDump(buf, 'Test_cmdwin_interrupted', {}) " clean up call StopVimInTerminal(buf) endfunc " Test for recursively getting multiple command line inputs func Test_cmdwin_multi_input() call feedkeys(":\=input('P: ')\\"cyan\\", 'xt') call assert_equal('"cyan', @:) endfunc " Test for normal mode commands not supported in the cmd window func Test_cmdwin_blocked_commands() call assert_fails('call feedkeys("q:\\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\\", "xt")', 'E11:') call assert_fails('call feedkeys("q:Q\", "xt")', 'E11:') call assert_fails('call feedkeys("q:Z\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\s\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\v\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\^\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\n\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\z\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\o\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\w\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\j\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\k\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\h\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\l\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\T\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\x\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\r\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\R\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\K\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\}\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\]\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\f\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\d\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\g\", "xt")', 'E11:') endfunc " Close the Cmd-line window in insert mode using CTRL-C func Test_cmdwin_insert_mode_close() %bw! let s = '' exe "normal q:a\let s='Hello'\" call assert_equal('Hello', s) call assert_equal(1, winnr('$')) endfunc func Test_cmdwin_ex_mode_with_modifier() " this was accessing memory after allocated text in Ex mode new call setline(1, ['some', 'text', 'lines']) silent! call feedkeys("gQnormal vq:atopleft\\\", 'xt') bwipe! endfunc func s:ComplInCmdwin_GlobalCompletion(a, l, p) return 'global' endfunc func s:ComplInCmdwin_LocalCompletion(a, l, p) return 'local' endfunc func Test_compl_in_cmdwin() set wildmenu wildchar= com! -nargs=1 -complete=command GetInput let input = com! -buffer TestCommand echo 'TestCommand' let w:test_winvar = 'winvar' let b:test_bufvar = 'bufvar' " User-defined commands let input = '' call feedkeys("q:iGetInput T\\\", 'tx!') call assert_equal('TestCommand', input) let input = '' call feedkeys("q::GetInput T\\:q\", 'tx!') call assert_equal('T', input) com! -nargs=1 -complete=var GetInput let input = " Window-local variables let input = '' call feedkeys("q:iGetInput w:test_\\\", 'tx!') call assert_equal('w:test_winvar', input) let input = '' call feedkeys("q::GetInput w:test_\\:q\", 'tx!') call assert_equal('w:test_', input) " Buffer-local variables let input = '' call feedkeys("q:iGetInput b:test_\\\", 'tx!') call assert_equal('b:test_bufvar', input) let input = '' call feedkeys("q::GetInput b:test_\\:q\", 'tx!') call assert_equal('b:test_', input) " Argument completion of buffer-local command func s:ComplInCmdwin_GlobalCompletionList(a, l, p) return ['global'] endfunc func s:ComplInCmdwin_LocalCompletionList(a, l, p) return ['local'] endfunc func s:ComplInCmdwin_CheckCompletion(arg) call assert_equal('local', a:arg) endfunc com! -nargs=1 -complete=custom,ComplInCmdwin_GlobalCompletion \ TestCommand call s:ComplInCmdwin_CheckCompletion() com! -buffer -nargs=1 -complete=custom,ComplInCmdwin_LocalCompletion \ TestCommand call s:ComplInCmdwin_CheckCompletion() call feedkeys("q:iTestCommand \\", 'tx!') com! -nargs=1 -complete=customlist,ComplInCmdwin_GlobalCompletionList \ TestCommand call s:ComplInCmdwin_CheckCompletion() com! -buffer -nargs=1 -complete=customlist,ComplInCmdwin_LocalCompletionList \ TestCommand call s:ComplInCmdwin_CheckCompletion() call feedkeys("q:iTestCommand \\", 'tx!') func! s:ComplInCmdwin_CheckCompletion(arg) call assert_equal('global', a:arg) endfunc new call feedkeys("q:iTestCommand \\", 'tx!') quit delfunc s:ComplInCmdwin_GlobalCompletion delfunc s:ComplInCmdwin_LocalCompletion delfunc s:ComplInCmdwin_GlobalCompletionList delfunc s:ComplInCmdwin_LocalCompletionList delfunc s:ComplInCmdwin_CheckCompletion delcom -buffer TestCommand delcom TestCommand delcom GetInput unlet w:test_winvar unlet b:test_bufvar set wildmenu& wildchar& endfunc func Test_cmdwin_cmd_completion() set wildmenu wildchar= com! -nargs=* -complete=command SomeOne echo 'one' com! -nargs=* -complete=command SomeTwo echo 'two' call feedkeys("q:aSome\\\"\", 'tx') call assert_equal('"SomeOne', @:) call feedkeys("q:aSome\\\\"\", 'tx') call assert_equal('"SomeTwo', @:) call feedkeys("q:aSome\\\\\"\", 'tx') call assert_equal('"SomeOne', @:) delcom SomeOne delcom SomeTwo set wildmenu& wildchar& endfunc func Test_cmdwin_ctrl_bsl() " Using CTRL-\ CTRL-N in cmd window should close the window call feedkeys("q:\\", 'xt') call assert_equal('', getcmdwintype()) endfunc func Test_cant_open_cmdwin_in_cmdwin() try call feedkeys("q:q::q\", "x!") catch let caught = v:exception endtry call assert_match('E1292:', caught) endfunc func Test_cmdwin_virtual_edit() enew! set ve=all cpo+=$ silent normal q/s set ve= cpo-=$ endfunc " Check that a :normal command can be used to stop Visual mode without side " effects. func Test_normal_escape() call feedkeys("q:i\" foo\:normal! \\\:\" bar\", 'ntx') call assert_equal('" bar', @:) endfunc " This was using a pointer to a freed buffer func Test_cmdwin_freed_buffer_ptr() " this does not work on MS-Windows because renaming an open file fails CheckNotMSWindows au BufEnter * next 0| file edit 0 silent! norm q/ au! BufEnter bwipe! endfunc " This was resulting in a window with negative width. " The test doesn't reproduce the illegal memory access though... func Test_cmdwin_split_often() let lines = &lines let columns = &columns set t_WS= try set encoding=iso8859 set ruler winsize 0 0 noremap 0 H sil norm 0000000q: catch /E36:/ endtry bwipe! set encoding=utf8 let &lines = lines let &columns = columns endfunc func Test_cmdwin_restore_heights() set showtabline=0 cmdheight=2 laststatus=0 call feedkeys("q::set cmdheight=1\:q\", 'ntx') call assert_equal(&lines - 1, winheight(0)) set showtabline=2 cmdheight=3 call feedkeys("q::set showtabline=0\:q\", 'ntx') call assert_equal(&lines - 3, winheight(0)) set cmdheight=1 laststatus=2 call feedkeys("q::set laststatus=0\:q\", 'ntx') call assert_equal(&lines - 1, winheight(0)) set laststatus=2 call feedkeys("q::set laststatus=1\:q\", 'ntx') call assert_equal(&lines - 1, winheight(0)) set laststatus=2 belowright vsplit wincmd _ let restcmds = winrestcmd() call feedkeys("q::set laststatus=1\:q\", 'ntx') " As we have 2 windows, &ls = 1 should still have a statusline on the last " window. As such, the number of available rows hasn't changed and the window " sizes should be restored. call assert_equal(restcmds, winrestcmd()) set cmdheight& showtabline& laststatus& endfunc func Test_cmdwin_temp_curwin() func CheckWraps(expect_wrap) setlocal textwidth=0 wrapmargin=1 call deletebufline('', 1, '$') let as = repeat('a', winwidth(0) - 2 - &wrapmargin) call setline(1, as .. ' b') normal! gww setlocal textwidth& wrapmargin& call assert_equal(a:expect_wrap ? [as, 'b'] : [as .. ' b'], getline(1, '$')) endfunc func CheckCmdWin() call assert_equal('command', win_gettype()) " textoff and &wrapmargin formatting considers the cmdwin_type char. call assert_equal(1, getwininfo(win_getid())[0].textoff) call CheckWraps(1) endfunc func CheckOtherWin() call assert_equal('', win_gettype()) call assert_equal(0, getwininfo(win_getid())[0].textoff) call CheckWraps(0) endfunc call feedkeys("q::call CheckCmdWin()\:call win_execute(win_getid(winnr('#')), 'call CheckOtherWin()')\:q", 'ntx') %bwipe! delfunc CheckWraps delfunc CheckCmdWin delfunc CheckOtherWin endfunc func Test_cmdwin_interrupted() func CheckInterrupted() call feedkeys("q::call assert_equal('', getcmdwintype())\:call assert_equal('', getcmdtype())\:q", 'ntx') endfunc augroup CmdWin " While opening the cmdwin's split: " Close the cmdwin's window. au WinEnter * ++once quit call CheckInterrupted() " Close the old window. au WinEnter * ++once execute winnr('#') 'quit' call CheckInterrupted() " Switch back to the old window. au WinEnter * ++once wincmd p call CheckInterrupted() " Change the old window's buffer. au WinEnter * ++once call win_execute(win_getid(winnr('#')), 'enew') call CheckInterrupted() " Using BufLeave autocmds as cmdwin restrictions do not apply to them when " fired from opening the cmdwin... " After opening the cmdwin's split, while creating the cmdwin's buffer: " Delete the cmdwin's buffer. au BufLeave * ++once bwipe call CheckInterrupted() " Close the cmdwin's window. au BufLeave * ++once quit call CheckInterrupted() " Close the old window. au BufLeave * ++once execute winnr('#') 'quit' call CheckInterrupted() " Switch to a different window. au BufLeave * ++once split call CheckInterrupted() " Change the old window's buffer. au BufLeave * ++once call win_execute(win_getid(winnr('#')), 'enew') call CheckInterrupted() " However, changing the current buffer is OK and does not interrupt. au BufLeave * ++once edit other call feedkeys("q::let t=getcmdwintype()\:let b=bufnr()\:clo", 'ntx') call assert_equal(':', t) call assert_equal(1, bufloaded('other')) call assert_notequal(b, bufnr('other')) augroup END " No autocmds should remain, but clear the augroup to be sure. augroup CmdWin au! augroup END %bwipe! delfunc CheckInterrupted endfunc func Test_cmdwin_existing_bufname() func CheckName() call assert_equal(1, getbufinfo('')[0].command) call assert_equal(0, getbufinfo('[Command Line]')[0].command) call assert_match('#a\s*"\[Command Line\]"', execute('ls')) call assert_match('%a\s*"\[Command Line\]"', execute('ls')) endfunc file [Command Line] call feedkeys("q::call CheckName()\:q\", 'ntx') 0file delfunc CheckName endfunc " vim: shiftwidth=2 sts=2 expandtab