Files
neovim/test/old/testdir/test_cmdwin.vim
zeertzjq 202e17deef vim-patch:9.2.0346: Wrong cursor position when entering command line window (#39072)
Problem:  Wrong cursor position when entering command line window
Solution: Add check_cursor() command to verify the cursor position
          (Hirohito Higashi).

When opening the command-line window with CTRL-F after typing a command
that fills the screen width, the cursor was placed past the end of the
line.  Add check_cursor() after setting State to MODE_NORMAL so the
cursor is adjusted to the last character.

Also fix the cmdwin prefix character (e.g. ':') being drawn on wrapped
continuation rows.  Draw an empty space instead so that the text
alignment is preserved.

closes: vim/vim#19964

c4fe1e958a

Cherry-pick Test_wildmenu_pum() changes from patch 9.1.1995.

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 18:22:05 +08:00

272 lines
7.5 KiB
VimL
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

" Tests for editing the command line.
source check.vim
source screendump.vim
func Test_cant_open_cmdwin_in_cmdwin()
try
call feedkeys("q:q::q\<CR>", "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\<Esc>:normal! \<C-V>\<Esc>\<CR>:\" bar\<CR>", '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\<CR>:q\<CR>", 'ntx')
call assert_equal(&lines - 1, winheight(0))
set showtabline=2 cmdheight=3
call feedkeys("q::set showtabline=0\<CR>:q\<CR>", 'ntx')
call assert_equal(&lines - 3, winheight(0))
set cmdheight=1 laststatus=2
call feedkeys("q::set laststatus=0\<CR>:q\<CR>", 'ntx')
call assert_equal(&lines - 1, winheight(0))
set laststatus=2
call feedkeys("q::set laststatus=1\<CR>:q\<CR>", 'ntx')
call assert_equal(&lines - 1, winheight(0))
set laststatus=2
belowright vsplit
wincmd _
let restcmds = winrestcmd()
call feedkeys("q::set laststatus=1\<CR>:q\<CR>", '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()\<CR>:call win_execute(win_getid(winnr('#')), 'call CheckOtherWin()')\<CR>:q<CR>", 'ntx')
%bwipe!
delfunc CheckWraps
delfunc CheckCmdWin
delfunc CheckOtherWin
endfunc
func Test_cmdwin_interrupted()
func CheckInterrupted()
call feedkeys("q::call assert_equal('', getcmdwintype())\<CR>:call assert_equal('', getcmdtype())\<CR>:q<CR>", '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()\<CR>:let b=bufnr()\<CR>:clo<CR>", '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()\<CR>:q\<CR>", 'ntx')
0file
delfunc CheckName
endfunc
func Test_cmdwin_showcmd()
CheckScreendump
let lines =<< trim [SCRIPT]
augroup vimHints | au! | augroup END
set showcmd
[SCRIPT]
call writefile(lines, 'XTest_cmdwin_showcmd', 'D')
let buf = RunVimInTerminal('-S XTest_cmdwin_showcmd', {'rows': 18})
for keys in ['q:', ":\<C-F>"]
call term_sendkeys(buf, keys)
call VerifyScreenDump(buf, 'Test_cmdwin_showcmd_1', {})
call term_sendkeys(buf, '"')
call WaitForAssert({-> assert_match('^: \+" *$', term_getline(buf, 18))})
call term_sendkeys(buf, 'x')
call WaitForAssert({-> assert_match('^: \+"x *$', term_getline(buf, 18))})
call term_sendkeys(buf, 'y')
call WaitForAssert({-> assert_match('^: \+"xy *$', term_getline(buf, 18))})
call term_sendkeys(buf, 'y')
call WaitForAssert({-> assert_match('^: \+$', term_getline(buf, 18))})
call term_sendkeys(buf, "\<C-C>\<C-C>")
call VerifyScreenDump(buf, 'Test_cmdwin_showcmd_2', {})
endfor
" clean up
call StopVimInTerminal(buf)
endfunc
func Test_cmdwin_cursor_position()
" When the cmdline fills the screen width exactly, pressing CTRL-F to open
" the cmdwin should place the cursor on the last character, not past it.
let cmd = 'echo "' .. repeat('a', &columns - 8) .. '"'
call assert_equal(&columns - 1, len(cmd))
let g:cmdwin_col = 0
let g:cmdwin_line = ''
call feedkeys(':' .. cmd .. "\<C-F>" ..
\ ":let g:cmdwin_col = col('.')\<CR>" ..
\ ":let g:cmdwin_line = getline('.')\<CR>" ..
\ ":q\<CR>", 'x!')
call assert_equal(len(cmd), g:cmdwin_col)
call assert_equal(cmd, g:cmdwin_line)
unlet g:cmdwin_col g:cmdwin_line
endfunc
func Test_cmdwin_no_prefix_on_wrapped_line()
CheckScreendump
let lines =<< trim END
augroup vimHints | au! | augroup END
END
call writefile(lines, 'Xcmdwin_wrap', 'D')
let buf = RunVimInTerminal('-S Xcmdwin_wrap', #{rows: 12, cols: 40})
let cmd = 'echo "' .. repeat('a', 40 - 8) .. '"XYZ'
call term_sendkeys(buf, ':' .. cmd .. "\<C-F>")
call TermWait(buf, 100)
call VerifyScreenDump(buf, 'Test_cmdwin_wrap_prefix', {})
call term_sendkeys(buf, ":q\<CR>")
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab