Mercurial > vim
view src/testdir/test_edit.vim @ 29841:b37b74ea8dee v9.0.0259
patch 9.0.0259: crash with mouse click when not initialized
Commit: https://github.com/vim/vim/commit/80525751c5ce9ed82c41d83faf9ef38667bf61b1
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Aug 24 19:27:45 2022 +0100
patch 9.0.0259: crash with mouse click when not initialized
Problem: Crash with mouse click when not initialized.
Solution: Check TabPageIdxs[] is not NULL.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 24 Aug 2022 20:30:03 +0200 |
parents | 2a327999c05c |
children | d891115c0aea |
line wrap: on
line source
" Test for edit functions if exists("+t_kD") let &t_kD="[3;*~" endif source check.vim " Needed for testing basic rightleft: Test_edit_rightleft source view_util.vim " Needs to come first until the bug in getchar() is " fixed: https://groups.google.com/d/msg/vim_dev/fXL9yme4H4c/bOR-U6_bAQAJ func Test_edit_00b() new call setline(1, ['abc ']) inoreabbr <buffer> h here some more call cursor(1, 4) " <c-l> expands the abbreviation and ends insertmode call feedkeys(":set im\<cr> h\<c-l>:set noim\<cr>", 'tix') call assert_equal(['abc here some more '], getline(1,'$')) iunabbr <buffer> h bw! endfunc func Test_edit_01() " set for Travis CI? " set nocp noesckeys new " 1) empty buffer call assert_equal([''], getline(1,'$')) " 2) delete in an empty line call feedkeys("i\<del>\<esc>", 'tnix') call assert_equal([''], getline(1,'$')) %d " 3) delete one character call setline(1, 'a') call feedkeys("i\<del>\<esc>", 'tnix') call assert_equal([''], getline(1,'$')) %d " 4) delete a multibyte character call setline(1, "\u0401") call feedkeys("i\<del>\<esc>", 'tnix') call assert_equal([''], getline(1,'$')) %d " 5.1) delete linebreak with 'bs' option containing eol let _bs=&bs set bs=eol call setline(1, ["abc def", "ghi jkl"]) call cursor(1, 1) call feedkeys("A\<del>\<esc>", 'tnix') call assert_equal(['abc defghi jkl'], getline(1, 2)) %d " 5.2) delete linebreak with backspace option w/out eol set bs= call setline(1, ["abc def", "ghi jkl"]) call cursor(1, 1) call feedkeys("A\<del>\<esc>", 'tnix') call assert_equal(["abc def", "ghi jkl"], getline(1, 2)) let &bs=_bs bw! endfunc func Test_edit_02() " Change cursor position in InsertCharPre command new call setline(1, 'abc') call cursor(1, 1) fu! DoIt(...) call cursor(1, 4) if len(a:000) let v:char=a:1 endif endfu au InsertCharPre <buffer> :call DoIt('y') call feedkeys("ix\<esc>", 'tnix') call assert_equal(['abcy'], getline(1, '$')) " Setting <Enter> in InsertCharPre au! InsertCharPre <buffer> :call DoIt("\n") call setline(1, 'abc') call cursor(1, 1) call feedkeys("ix\<esc>", 'tnix') call assert_equal(['abc', ''], getline(1, '$')) %d au! InsertCharPre " Change cursor position in InsertEnter command " 1) when setting v:char, keeps changed cursor position au! InsertEnter <buffer> :call DoIt('y') call setline(1, 'abc') call cursor(1, 1) call feedkeys("ix\<esc>", 'tnix') call assert_equal(['abxc'], getline(1, '$')) " 2) when not setting v:char, restores changed cursor position au! InsertEnter <buffer> :call DoIt() call setline(1, 'abc') call cursor(1, 1) call feedkeys("ix\<esc>", 'tnix') call assert_equal(['xabc'], getline(1, '$')) au! InsertEnter delfu DoIt bw! endfunc func Test_edit_03() " Change cursor after <c-o> command to end of line new call setline(1, 'abc') call cursor(1, 1) call feedkeys("i\<c-o>$y\<esc>", 'tnix') call assert_equal(['abcy'], getline(1, '$')) %d call setline(1, 'abc') call cursor(1, 1) call feedkeys("i\<c-o>80|y\<esc>", 'tnix') call assert_equal(['abcy'], getline(1, '$')) %d call setline(1, 'abc') call feedkeys("Ad\<c-o>:s/$/efg/\<cr>hij", 'tnix') call assert_equal(['hijabcdefg'], getline(1, '$')) bw! endfunc func Test_edit_04() " test for :stopinsert new call setline(1, 'abc') call cursor(1, 1) call feedkeys("i\<c-o>:stopinsert\<cr>$", 'tnix') call feedkeys("aX\<esc>", 'tnix') call assert_equal(['abcX'], getline(1, '$')) %d bw! endfunc func Test_edit_05() " test for folds being opened new call setline(1, ['abcX', 'abcX', 'zzzZ']) call cursor(1, 1) set foldmethod=manual foldopen+=insert " create fold for those two lines norm! Vjzf call feedkeys("$ay\<esc>", 'tnix') call assert_equal(['abcXy', 'abcX', 'zzzZ'], getline(1, '$')) %d call setline(1, ['abcX', 'abcX', 'zzzZ']) call cursor(1, 1) set foldmethod=manual foldopen-=insert " create fold for those two lines norm! Vjzf call feedkeys("$ay\<esc>", 'tnix') call assert_equal(['abcXy', 'abcX', 'zzzZ'], getline(1, '$')) %d bw! endfunc func Test_edit_06() " Test in diff mode CheckFeature diff CheckExecutable diff new call setline(1, ['abc', 'xxx', 'yyy']) vnew call setline(1, ['abc', 'zzz', 'xxx', 'yyy']) wincmd p diffthis wincmd p diffthis wincmd p call cursor(2, 1) norm! zt call feedkeys("Ozzz\<esc>", 'tnix') call assert_equal(['abc', 'zzz', 'xxx', 'yyy'], getline(1,'$')) bw! bw! endfunc func Test_edit_07() " 1) Test with completion <c-l> when popupmenu is visible new call setline(1, 'J') func! ListMonths() call complete(col('.')-1, ['January', 'February', 'March', \ 'April', 'May', 'June', 'July', 'August', 'September', \ 'October', 'November', 'December']) return '' endfunc inoremap <buffer> <F5> <C-R>=ListMonths()<CR> call feedkeys("A\<f5>\<c-p>". repeat("\<down>", 6)."\<c-l>\<down>\<c-l>\<cr>", 'tx') call assert_equal(['July'], getline(1,'$')) " 1) Test completion when InsertCharPre kicks in %d call setline(1, 'J') fu! DoIt() if v:char=='u' let v:char='an' endif endfu au InsertCharPre <buffer> :call DoIt() call feedkeys("A\<f5>\<c-p>u\<cr>\<c-l>\<cr>", 'tx') call assert_equal(["Jan\<c-l>",''], 1->getline('$')) %d call setline(1, 'J') call feedkeys("A\<f5>\<c-p>u\<down>\<c-l>\<cr>", 'tx') call assert_equal(["January"], 1->getline('$')) delfu ListMonths delfu DoIt iunmap <buffer> <f5> bw! endfunc func Test_edit_08() " reset insertmode from i_ctrl-r_= let g:bufnr = bufnr('%') new call setline(1, ['abc']) call cursor(1, 4) call feedkeys(":set im\<cr>ZZZ\<c-r>=setbufvar(g:bufnr,'&im', 0)\<cr>",'tnix') call assert_equal(['abZZZc'], getline(1,'$')) call assert_equal([0, 1, 1, 0], getpos('.')) call assert_false(0, '&im') bw! unlet g:bufnr endfunc func Test_edit_09() " test i_CTRL-\ combinations new call setline(1, ['abc', 'def', 'ghi']) call cursor(1, 1) " 1) CTRL-\ CTLR-N call feedkeys(":set im\<cr>\<c-\>\<c-n>ccABC\<c-l>", 'txin') call assert_equal(['ABC', 'def', 'ghi'], getline(1,'$')) call setline(1, ['ABC', 'def', 'ghi']) " 2) CTRL-\ CTLR-G call feedkeys("j0\<c-\>\<c-g>ZZZ\<cr>\<c-l>", 'txin') call assert_equal(['ABC', 'ZZZ', 'def', 'ghi'], getline(1,'$')) call feedkeys("I\<c-\>\<c-g>YYY\<c-l>", 'txin') call assert_equal(['ABC', 'ZZZ', 'YYYdef', 'ghi'], getline(1,'$')) set noinsertmode " 3) CTRL-\ CTRL-O call setline(1, ['ABC', 'ZZZ', 'def', 'ghi']) call cursor(1, 1) call feedkeys("A\<c-o>ix", 'txin') call assert_equal(['ABxC', 'ZZZ', 'def', 'ghi'], getline(1,'$')) call feedkeys("A\<c-\>\<c-o>ix", 'txin') call assert_equal(['ABxCx', 'ZZZ', 'def', 'ghi'], getline(1,'$')) " 4) CTRL-\ a (should be inserted literally, not special after <c-\> call setline(1, ['ABC', 'ZZZ', 'def', 'ghi']) call cursor(1, 1) call feedkeys("A\<c-\>a", 'txin') call assert_equal(["ABC\<c-\>a", 'ZZZ', 'def', 'ghi'], getline(1, '$')) bw! endfunc func Test_edit_11() " Test that indenting kicks in new set cindent call setline(1, ['{', '', '']) call cursor(2, 1) call feedkeys("i\<c-f>int c;\<esc>", 'tnix') call cursor(3, 1) call feedkeys("\<Insert>/* comment */", 'tnix') call assert_equal(['{', "\<tab>int c;", "/* comment */"], getline(1, '$')) " added changed cindentkeys slightly set cindent cinkeys+=*/ call setline(1, ['{', '', '']) call cursor(2, 1) call feedkeys("i\<c-f>int c;\<esc>", 'tnix') call cursor(3, 1) call feedkeys("i/* comment */", 'tnix') call assert_equal(['{', "\<tab>int c;", "\<tab>/* comment */"], getline(1, '$')) set cindent cinkeys+==end call feedkeys("oend\<cr>\<esc>", 'tnix') call assert_equal(['{', "\<tab>int c;", "\<tab>/* comment */", "\tend", ''], getline(1, '$')) set cinkeys-==end %d " Use indentexpr instead of cindenting func! Do_Indent() if v:lnum == 3 return 3*shiftwidth() else return 2*shiftwidth() endif endfunc setl indentexpr=Do_Indent() indentkeys+=*/ call setline(1, ['{', '', '']) call cursor(2, 1) call feedkeys("i\<c-f>int c;\<esc>", 'tnix') call cursor(3, 1) call feedkeys("i/* comment */", 'tnix') call assert_equal(['{', "\<tab>\<tab>int c;", "\<tab>\<tab>\<tab>/* comment */"], getline(1, '$')) set cinkeys&vim indentkeys&vim set nocindent indentexpr= delfu Do_Indent bw! endfunc func Test_edit_11_indentexpr() " Test that indenting kicks in new " Use indentexpr instead of cindenting func! Do_Indent() let pline=prevnonblank(v:lnum) if empty(getline(v:lnum)) if getline(pline) =~ 'if\|then' return shiftwidth() else return 0 endif else return 0 endif endfunc setl indentexpr=Do_Indent() indentkeys+=0=then,0=fi call setline(1, ['if [ $this ]']) call cursor(1, 1) call feedkeys("othen\<cr>that\<cr>fi", 'tnix') call assert_equal(['if [ $this ]', "then", "\<tab>that", "fi"], getline(1, '$')) set cinkeys&vim indentkeys&vim set nocindent indentexpr= delfu Do_Indent " Using a script-local function func s:NewIndentExpr() endfunc set indentexpr=s:NewIndentExpr() call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr) set indentexpr=<SID>NewIndentExpr() call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr) set indentexpr& bw! endfunc " Test changing indent in replace mode func Test_edit_12() new call setline(1, ["\tabc", "\tdef"]) call cursor(2, 4) call feedkeys("R^\<c-d>", 'tnix') call assert_equal(["\tabc", "def"], getline(1, '$')) call assert_equal([0, 2, 2, 0], '.'->getpos()) %d call setline(1, ["\tabc", "\t\tdef"]) call cursor(2, 2) call feedkeys("R^\<c-d>", 'tnix') call assert_equal(["\tabc", "def"], getline(1, '$')) call assert_equal([0, 2, 1, 0], getpos('.')) %d call setline(1, ["\tabc", "\t\tdef"]) call cursor(2, 2) call feedkeys("R\<c-t>", 'tnix') call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$')) call assert_equal([0, 2, 2, 0], getpos('.')) bw! 10vnew call setline(1, ["\tabc", "\t\tdef"]) call cursor(2, 2) call feedkeys("R\<c-t>", 'tnix') call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$')) call assert_equal([0, 2, 2, 0], getpos('.')) %d set sw=4 call setline(1, ["\tabc", "\t\tdef"]) call cursor(2, 2) call feedkeys("R\<c-t>\<c-t>", 'tnix') call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$')) call assert_equal([0, 2, 2, 0], getpos('.')) %d call setline(1, ["\tabc", "\t\tdef"]) call cursor(2, 2) call feedkeys("R\<c-t>\<c-t>", 'tnix') call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$')) call assert_equal([0, 2, 2, 0], getpos('.')) set sw& " In replace mode, after hitting enter in a line with tab characters, " pressing backspace should restore the tab characters. %d setlocal autoindent backspace=2 call setline(1, "\tone\t\ttwo") exe "normal ggRred\<CR>six" .. repeat("\<BS>", 8) call assert_equal(["\tone\t\ttwo"], getline(1, '$')) bw! endfunc func Test_edit_13() " Test smartindenting new set smartindent autoindent call setline(1, ["\tabc"]) call feedkeys("A {\<cr>more\<cr>}\<esc>", 'tnix') call assert_equal(["\tabc {", "\t\tmore", "\t}"], getline(1, '$')) set smartindent& autoindent& bwipe! " Test autoindent removing indent of blank line. new call setline(1, ' foo bar baz') set autoindent exe "normal 0eea\<CR>\<CR>\<Esc>" call assert_equal(" foo bar", getline(1)) call assert_equal("", getline(2)) call assert_equal(" baz", getline(3)) set autoindent& " pressing <C-U> to erase line should keep the indent with 'autoindent' set backspace=2 autoindent %d exe "normal i\tone\<CR>three\<C-U>two" call assert_equal(["\tone", "\ttwo"], getline(1, '$')) set backspace& autoindent& bwipe! endfunc " Test for autoindent removing indent when insert mode is stopped. Some parts " of the code is exercised only when interactive mode is used. So use Vim in a " terminal. func Test_autoindent_remove_indent() CheckRunVimInTerminal let buf = RunVimInTerminal('-N Xfile', {'rows': 6, 'cols' : 20}) call TermWait(buf) call term_sendkeys(buf, ":set autoindent\n") " leaving insert mode in a new line with indent added by autoindent, should " remove the indent. call term_sendkeys(buf, "i\<Tab>foo\<CR>\<Esc>") " Need to delay for some time, otherwise the code in getchar.c will not be " exercised. call TermWait(buf, 50) " when a line is wrapped and the cursor is at the start of the second line, " leaving insert mode, should move the cursor back to the first line. call term_sendkeys(buf, "o" .. repeat('x', 20) .. "\<Esc>") " Need to delay for some time, otherwise the code in getchar.c will not be " exercised. call TermWait(buf, 50) call term_sendkeys(buf, ":w\n") call TermWait(buf) call StopVimInTerminal(buf) call assert_equal(["\tfoo", '', repeat('x', 20)], readfile('Xfile')) call delete('Xfile') endfunc func Test_edit_CR() " Test for <CR> in insert mode " basically only in quickfix mode it's tested, the rest " has been taken care of by other tests CheckFeature quickfix botright new call writefile(range(1, 10), 'Xqflist.txt') call setqflist([{'filename': 'Xqflist.txt', 'lnum': 2}]) copen set modifiable call feedkeys("A\<cr>", 'tnix') call assert_equal('Xqflist.txt', bufname('')) call assert_equal(2, line('.')) cclose botright new call setloclist(0, [{'filename': 'Xqflist.txt', 'lnum': 10}]) lopen set modifiable call feedkeys("A\<cr>", 'tnix') call assert_equal('Xqflist.txt', bufname('')) call assert_equal(10, line('.')) call feedkeys("A\<Enter>", 'tnix') call feedkeys("A\<kEnter>", 'tnix') call feedkeys("A\n", 'tnix') call feedkeys("A\r", 'tnix') call assert_equal(map(range(1, 10), 'string(v:val)') + ['', '', '', ''], getline(1, '$')) bw! lclose call delete('Xqflist.txt') endfunc func Test_edit_CTRL_() CheckFeature rightleft " disabled for Windows builds, why? CheckNotMSWindows let _encoding=&encoding set encoding=utf-8 " Test for CTRL-_ new call setline(1, ['abc']) call cursor(1, 1) call feedkeys("i\<c-_>xyz\<esc>", 'tnix') call assert_equal(["\<C-_>xyzabc"], getline(1, '$')) call assert_false(&revins) set ari call setline(1, ['abc']) call cursor(1, 1) call feedkeys("i\<c-_>xyz\<esc>", 'tnix') call assert_equal(["æèñabc"], getline(1, '$')) call assert_true(&revins) call setline(1, ['abc']) call cursor(1, 1) call feedkeys("i\<c-_>xyz\<esc>", 'tnix') call assert_equal(["xyzabc"], getline(1, '$')) call assert_false(&revins) set noari let &encoding=_encoding bw! endfunc " needs to come first, to have the @. register empty func Test_edit_00a_CTRL_A() " Test pressing CTRL-A new call setline(1, repeat([''], 5)) call cursor(1, 1) try call feedkeys("A\<NUL>", 'tnix') catch /^Vim\%((\a\+)\)\=:E29/ call assert_true(1, 'E29 error caught') endtry call cursor(1, 1) call feedkeys("Afoobar \<esc>", 'tnix') call cursor(2, 1) call feedkeys("A\<c-a>more\<esc>", 'tnix') call cursor(3, 1) call feedkeys("A\<NUL>and more\<esc>", 'tnix') call assert_equal(['foobar ', 'foobar more', 'foobar morend more', '', ''], getline(1, '$')) bw! endfunc func Test_edit_CTRL_EY() " Ctrl-E/ Ctrl-Y in insert mode completion to scroll 10new call setline(1, range(1, 100)) call cursor(30, 1) norm! z. call feedkeys("A\<c-x>\<c-e>\<c-e>\<c-e>\<c-e>\<c-e>", 'tnix') call assert_equal(30, winsaveview()['topline']) call assert_equal([0, 30, 2, 0], getpos('.')) call feedkeys("A\<c-x>\<c-e>\<c-e>\<c-e>\<c-e>\<c-e>", 'tnix') call feedkeys("A\<c-x>".repeat("\<c-y>", 10), 'tnix') call assert_equal(21, winsaveview()['topline']) call assert_equal([0, 30, 2, 0], getpos('.')) bw! endfunc func Test_edit_CTRL_G() new call setline(1, ['foobar', 'foobar', 'foobar']) call cursor(2, 4) call feedkeys("ioooooooo\<c-g>k\<c-r>.\<esc>", 'tnix') call assert_equal(['foooooooooobar', 'foooooooooobar', 'foobar'], getline(1, '$')) call assert_equal([0, 1, 11, 0], getpos('.')) call feedkeys("i\<c-g>k\<esc>", 'tnix') call assert_equal([0, 1, 10, 0], getpos('.')) call cursor(2, 4) call feedkeys("i\<c-g>jzzzz\<esc>", 'tnix') call assert_equal(['foooooooooobar', 'foooooooooobar', 'foozzzzbar'], getline(1, '$')) call assert_equal([0, 3, 7, 0], getpos('.')) call feedkeys("i\<c-g>j\<esc>", 'tnix') call assert_equal([0, 3, 6, 0], getpos('.')) bw! endfunc func Test_edit_CTRL_I() " Tab in completion mode let path=expand("%:p:h") new call setline(1, [path. "/", '']) call feedkeys("Arunt\<c-x>\<c-f>\<tab>\<cr>\<esc>", 'tnix') call assert_match('runtest\.vim', getline(1)) %d call writefile(['one', 'two', 'three'], 'Xinclude.txt') let include='#include Xinclude.txt' call setline(1, [include, '']) call cursor(2, 1) call feedkeys("A\<c-x>\<tab>\<cr>\<esc>", 'tnix') call assert_equal([include, 'one', ''], getline(1, '$')) call feedkeys("2ggC\<c-x>\<tab>\<down>\<cr>\<esc>", 'tnix') call assert_equal([include, 'two', ''], getline(1, '$')) call feedkeys("2ggC\<c-x>\<tab>\<down>\<down>\<cr>\<esc>", 'tnix') call assert_equal([include, 'three', ''], getline(1, '$')) call feedkeys("2ggC\<c-x>\<tab>\<down>\<down>\<down>\<cr>\<esc>", 'tnix') call assert_equal([include, '', ''], getline(1, '$')) call delete("Xinclude.txt") bw! endfunc func Test_edit_CTRL_K() " Test pressing CTRL-K (basically only dictionary completion and digraphs " the rest is already covered call writefile(['A', 'AA', 'AAA', 'AAAA'], 'Xdictionary.txt') set dictionary=Xdictionary.txt new call setline(1, 'A') call cursor(1, 1) call feedkeys("A\<c-x>\<c-k>\<cr>\<esc>", 'tnix') call assert_equal(['AA', ''], getline(1, '$')) %d call setline(1, 'A') call cursor(1, 1) call feedkeys("A\<c-x>\<c-k>\<down>\<cr>\<esc>", 'tnix') call assert_equal(['AAA'], getline(1, '$')) %d call setline(1, 'A') call cursor(1, 1) call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<cr>\<esc>", 'tnix') call assert_equal(['AAAA'], getline(1, '$')) %d call setline(1, 'A') call cursor(1, 1) call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<down>\<cr>\<esc>", 'tnix') call assert_equal(['A'], getline(1, '$')) %d call setline(1, 'A') call cursor(1, 1) call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<down>\<down>\<cr>\<esc>", 'tnix') call assert_equal(['AA'], getline(1, '$')) " press an unexpected key after dictionary completion %d call setline(1, 'A') call cursor(1, 1) call feedkeys("A\<c-x>\<c-k>\<c-]>\<cr>\<esc>", 'tnix') call assert_equal(['AA', ''], getline(1, '$')) %d call setline(1, 'A') call cursor(1, 1) call feedkeys("A\<c-x>\<c-k>\<c-s>\<cr>\<esc>", 'tnix') call assert_equal(["AA\<c-s>", ''], getline(1, '$')) %d call setline(1, 'A') call cursor(1, 1) call feedkeys("A\<c-x>\<c-k>\<c-f>\<cr>\<esc>", 'tnix') call assert_equal(["AA\<c-f>", ''], getline(1, '$')) set dictionary= %d call setline(1, 'A') call cursor(1, 1) let v:testing = 1 try call feedkeys("A\<c-x>\<c-k>\<esc>", 'tnix') catch " error sleeps 2 seconds, when v:testing is not set let v:testing = 0 endtry call delete('Xdictionary.txt') call test_override("char_avail", 1) set showcmd %d call feedkeys("A\<c-k>a:\<esc>", 'tnix') call assert_equal(['ä'], getline(1, '$')) call test_override("char_avail", 0) set noshowcmd bw! endfunc func Test_edit_CTRL_L() " Test Ctrl-X Ctrl-L (line completion) new set complete=. call setline(1, ['one', 'two', 'three', '', '', '', '']) call cursor(4, 1) call feedkeys("A\<c-x>\<c-l>\<esc>", 'tnix') call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$')) call feedkeys("cct\<c-x>\<c-l>\<c-n>\<esc>", 'tnix') call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$')) call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<esc>", 'tnix') call assert_equal(['one', 'two', 'three', 'two', '', '', ''], getline(1, '$')) call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<c-n>\<esc>", 'tnix') call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$')) call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<c-n>\<c-n>\<esc>", 'tnix') call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$')) call feedkeys("cct\<c-x>\<c-l>\<c-p>\<esc>", 'tnix') call assert_equal(['one', 'two', 'three', 'two', '', '', ''], getline(1, '$')) call feedkeys("cct\<c-x>\<c-l>\<c-p>\<c-p>\<esc>", 'tnix') call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$')) call feedkeys("cct\<c-x>\<c-l>\<c-p>\<c-p>\<c-p>\<esc>", 'tnix') call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$')) set complete= call cursor(5, 1) call feedkeys("A\<c-x>\<c-l>\<c-p>\<c-n>\<esc>", 'tnix') call assert_equal(['one', 'two', 'three', 'three', "\<c-l>\<c-p>\<c-n>", '', ''], getline(1, '$')) set complete& %d if has("conceal") && has("syntax") call setline(1, ['foo', 'bar', 'foobar']) call test_override("char_avail", 1) set conceallevel=2 concealcursor=n syn on syn match ErrorMsg "^bar" call matchadd("Conceal", 'oo', 10, -1, {'conceal': 'X'}) func! DoIt() let g:change=1 endfunc au! TextChangedI <buffer> :call DoIt() call cursor(2, 1) call assert_false(exists("g:change")) call feedkeys("A \<esc>", 'tnix') call assert_equal(['foo', 'bar ', 'foobar'], getline(1, '$')) call assert_equal(1, g:change) call test_override("char_avail", 0) call clearmatches() syn off au! TextChangedI delfu DoIt unlet! g:change endif bw! endfunc func Test_edit_CTRL_N() " Check keyword completion for e in ['latin1', 'utf-8'] exe 'set encoding=' .. e new set complete=. call setline(1, ['INFER', 'loWER', '', '', ]) call cursor(3, 1) call feedkeys("Ai\<c-n>\<cr>\<esc>", "tnix") call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['INFER', 'loWER', 'i', 'LO', '', ''], getline(1, '$'), e) %d call setline(1, ['INFER', 'loWER', '', '', ]) call cursor(3, 1) set ignorecase infercase call feedkeys("Ii\<c-n>\<cr>\<esc>", "tnix") call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['INFER', 'loWER', 'infer', 'LOWER', '', ''], getline(1, '$'), e) set noignorecase noinfercase %d call setline(1, ['one word', 'two word']) exe "normal! Goo\<C-P>\<C-X>\<C-P>" call assert_equal('one word', getline(3)) %d set complete& bw! endfor endfunc func Test_edit_CTRL_O() " Check for CTRL-O in insert mode new inoreabbr <buffer> h here some more call setline(1, ['abc', 'def']) call cursor(1, 1) " Ctrl-O after an abbreviation exe "norm A h\<c-o>:set nu\<cr> text" call assert_equal(['abc here some more text', 'def'], getline(1, '$')) call assert_true(&nu) set nonu iunabbr <buffer> h " Ctrl-O at end of line with 've'=onemore call cursor(1, 1) call feedkeys("A\<c-o>:let g:a=getpos('.')\<cr>\<esc>", 'tnix') call assert_equal([0, 1, 23, 0], g:a) call cursor(1, 1) set ve=onemore call feedkeys("A\<c-o>:let g:a=getpos('.')\<cr>\<esc>", 'tnix') call assert_equal([0, 1, 24, 0], g:a) set ve= unlet! g:a bw! endfunc func Test_edit_CTRL_R() " Insert Register new call test_override("ALL", 1) set showcmd call feedkeys("AFOOBAR eins zwei\<esc>", 'tnix') call feedkeys("O\<c-r>.", 'tnix') call feedkeys("O\<c-r>=10*500\<cr>\<esc>", 'tnix') call feedkeys("O\<c-r>=getreg('=', 1)\<cr>\<esc>", 'tnix') call assert_equal(["getreg('=', 1)", '5000', "FOOBAR eins zwei", "FOOBAR eins zwei"], getline(1, '$')) call test_override("ALL", 0) set noshowcmd bw! endfunc func Test_edit_CTRL_S() " Test pressing CTRL-S (basically only spellfile completion) " the rest is already covered new if !has("spell") call setline(1, 'vim') call feedkeys("A\<c-x>ss\<cr>\<esc>", 'tnix') call assert_equal(['vims', ''], getline(1, '$')) bw! return endif call setline(1, 'vim') " spell option not yet set try call feedkeys("A\<c-x>\<c-s>\<cr>\<esc>", 'tnix') catch /^Vim\%((\a\+)\)\=:E756/ call assert_true(1, 'error caught') endtry call assert_equal(['vim', ''], getline(1, '$')) %d setl spell spelllang=en call setline(1, 'vim') call cursor(1, 1) call feedkeys("A\<c-x>\<c-s>\<cr>\<esc>", 'tnix') call assert_equal(['Vim', ''], getline(1, '$')) %d call setline(1, 'vim') call cursor(1, 1) call feedkeys("A\<c-x>\<c-s>\<down>\<cr>\<esc>", 'tnix') call assert_equal(['Aim'], getline(1, '$')) %d call setline(1, 'vim') call cursor(1, 1) call feedkeys("A\<c-x>\<c-s>\<c-p>\<cr>\<esc>", 'tnix') call assert_equal(['vim', ''], getline(1, '$')) %d " empty buffer call cursor(1, 1) call feedkeys("A\<c-x>\<c-s>\<c-p>\<cr>\<esc>", 'tnix') call assert_equal(['', ''], getline(1, '$')) setl nospell bw! endfunc func Test_edit_CTRL_T() " Check for CTRL-T and CTRL-X CTRL-T in insert mode " 1) increase indent new call setline(1, "abc") call cursor(1, 1) call feedkeys("A\<c-t>xyz", 'tnix') call assert_equal(["\<tab>abcxyz"], getline(1, '$')) " 2) also when paste option is set set paste call setline(1, "abc") call cursor(1, 1) call feedkeys("A\<c-t>xyz", 'tnix') call assert_equal(["\<tab>abcxyz"], getline(1, '$')) set nopaste " CTRL-X CTRL-T (thesaurus complete) call writefile(['angry furious mad enraged'], 'Xthesaurus') set thesaurus=Xthesaurus call setline(1, 'mad') call cursor(1, 1) call feedkeys("A\<c-x>\<c-t>\<cr>\<esc>", 'tnix') call assert_equal(['mad', ''], getline(1, '$')) %d call setline(1, 'mad') call cursor(1, 1) call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['angry', ''], getline(1, '$')) %d call setline(1, 'mad') call cursor(1, 1) call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['furious', ''], getline(1, '$')) %d call setline(1, 'mad') call cursor(1, 1) call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['enraged', ''], getline(1, '$')) %d call setline(1, 'mad') call cursor(1, 1) call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['mad', ''], getline(1, '$')) %d call setline(1, 'mad') call cursor(1, 1) call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['mad', ''], getline(1, '$')) " Using <c-p> <c-n> when 'complete' is empty set complete= %d call setline(1, 'mad') call cursor(1, 1) call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['angry', ''], getline(1, '$')) %d call setline(1, 'mad') call cursor(1, 1) call feedkeys("A\<c-x>\<c-t>\<c-p>\<cr>\<esc>", 'tnix') call assert_equal(['mad', ''], getline(1, '$')) set complete& set thesaurus= %d call setline(1, 'mad') call cursor(1, 1) let v:testing = 1 try call feedkeys("A\<c-x>\<c-t>\<esc>", 'tnix') catch " error sleeps 2 seconds, when v:testing is not set let v:testing = 0 endtry call assert_equal(['mad'], getline(1, '$')) call delete('Xthesaurus') bw! endfunc " Test thesaurus completion with different encodings func Test_thesaurus_complete_with_encoding() call writefile(['angry furious mad enraged'], 'Xthesaurus') set thesaurus=Xthesaurus for e in ['latin1', 'utf-8'] exe 'set encoding=' .. e new call setline(1, 'mad') call cursor(1, 1) call feedkeys("A\<c-x>\<c-t>\<cr>\<esc>", 'tnix') call assert_equal(['mad', ''], getline(1, '$')) bw! endfor set thesaurus= call delete('Xthesaurus') endfunc " Test 'thesaurusfunc' func MyThesaurus(findstart, base) let mythesaurus = [ \ #{word: "happy", \ synonyms: "cheerful,blissful,flying high,looking good,peppy"}, \ #{word: "kind", \ synonyms: "amiable,bleeding-heart,heart in right place"}] if a:findstart " locate the start of the word let line = getline('.') let start = col('.') - 1 while start > 0 && line[start - 1] =~ '\a' let start -= 1 endwhile return start else " find strings matching with "a:base" let res = [] for w in mythesaurus if w.word =~ '^' . a:base call add(res, w.word) call extend(res, split(w.synonyms, ",")) endif endfor return res endif endfunc func Test_thesaurus_func() new set thesaurus=notused set thesaurusfunc=NotUsed setlocal thesaurusfunc=MyThesaurus call setline(1, "an ki") call cursor(1, 1) call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['an amiable', ''], getline(1, '$')) setlocal thesaurusfunc=NonExistingFunc call assert_fails("normal $a\<C-X>\<C-T>", 'E117:') setlocal thesaurusfunc= set thesaurusfunc=NonExistingFunc call assert_fails("normal $a\<C-X>\<C-T>", 'E117:') %bw! set thesaurusfunc= set thesaurus= endfunc func Test_edit_CTRL_U() " Test 'completefunc' new " -1, -2 and -3 are special return values let g:special=0 fun! CompleteMonths(findstart, base) if a:findstart " locate the start of the word return g:special else " find months matching with "a:base" let res = [] for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec") if m =~ '^\c'.a:base call add(res, {'word': m, 'abbr': m.' Month', 'icase': 0}) endif endfor return {'words': res, 'refresh': 'always'} endif endfun set completefunc=CompleteMonths call setline(1, ['', '']) call cursor(1, 1) call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix') call assert_equal(['X', '', ''], getline(1, '$')) %d let g:special=-1 call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix') call assert_equal(['XJan', ''], getline(1, '$')) %d let g:special=-2 call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix') call assert_equal(['X', ''], getline(1, '$')) %d let g:special=-3 call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix') call assert_equal(['X', ''], getline(1, '$')) %d let g:special=0 call feedkeys("AM\<c-x>\<c-u>\<cr>\<esc>", 'tnix') call assert_equal(['Mar', ''], getline(1, '$')) %d call feedkeys("AM\<c-x>\<c-u>\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['May', ''], getline(1, '$')) %d call feedkeys("AM\<c-x>\<c-u>\<c-n>\<c-n>\<cr>\<esc>", 'tnix') call assert_equal(['M', ''], getline(1, '$')) delfu CompleteMonths %d try call feedkeys("A\<c-x>\<c-u>", 'tnix') call assert_fails(1, 'unknown completion function') catch /^Vim\%((\a\+)\)\=:E117/ call assert_true(1, 'E117 error caught') endtry set completefunc= bw! endfunc func Test_edit_completefunc_delete() func CompleteFunc(findstart, base) if a:findstart == 1 return col('.') - 1 endif normal dd return ['a', 'b'] endfunc new set completefunc=CompleteFunc call setline(1, ['', 'abcd', '']) 2d call assert_fails("normal 2G$a\<C-X>\<C-U>", 'E565:') bwipe! endfunc func Test_edit_CTRL_Z() " Ctrl-Z when insertmode is not set inserts it literally new call setline(1, 'abc') call feedkeys("A\<c-z>\<esc>", 'tnix') call assert_equal(["abc\<c-z>"], getline(1,'$')) bw! " TODO: How to Test Ctrl-Z in insert mode, e.g. suspend? endfunc func Test_edit_DROP() CheckFeature dnd new call setline(1, ['abc def ghi']) call cursor(1, 1) try call feedkeys("i\<Drop>\<Esc>", 'tnix') call assert_fails(1, 'Invalid register name') catch /^Vim\%((\a\+)\)\=:E353/ call assert_true(1, 'error caught') endtry bw! endfunc func Test_edit_CTRL_V() new call setline(1, ['abc']) call cursor(2, 1) " force some redraws set showmode showcmd call test_override('char_avail', 1) call feedkeys("A\<c-v>\<c-n>\<c-v>\<c-l>\<c-v>\<c-b>\<esc>", 'tnix') call assert_equal(["abc\x0e\x0c\x02"], getline(1, '$')) if has("rightleft") && exists("+rl") set rl call setline(1, ['abc']) call cursor(2, 1) call feedkeys("A\<c-v>\<c-n>\<c-v>\<c-l>\<c-v>\<c-b>\<esc>", 'tnix') call assert_equal(["abc\x0e\x0c\x02"], getline(1, '$')) set norl endif set noshowmode showcmd call test_override('char_avail', 0) " No modifiers should be applied to the char typed using i_CTRL-V_digit. call feedkeys(":append\<CR>\<C-V>76c\<C-V>76\<C-F2>\<C-V>u3c0j\<C-V>u3c0\<M-F3>\<CR>.\<CR>", 'tnix') call assert_equal('LcL<C-F2>πjπ<M-F3>', getline(2)) if has('osx') " A char with a modifier should not be a valid char for i_CTRL-V_digit. call feedkeys("o\<C-V>\<D-j>\<C-V>\<D-1>\<C-V>\<D-o>\<C-V>\<D-x>\<C-V>\<D-u>", 'tnix') call assert_equal('<D-j><D-1><D-o><D-x><D-u>', getline(3)) endif bw! endfunc func Test_edit_F1() CheckFeature quickfix " Pressing <f1> new call feedkeys(":set im\<cr>\<f1>\<c-l>", 'tnix') set noinsertmode call assert_equal('help', &buftype) bw bw endfunc func Test_edit_F21() " Pressing <f21> " sends a netbeans command CheckFeature netbeans_intg new " I have no idea what this is supposed to do :) call feedkeys("A\<F21>\<F1>\<esc>", 'tnix') bw endfunc func Test_edit_HOME_END() " Test Home/End Keys new set foldopen+=hor call setline(1, ['abc', 'def']) call cursor(1, 1) call feedkeys("AX\<Home>Y\<esc>", 'tnix') call cursor(2, 1) call feedkeys("iZ\<End>Y\<esc>", 'tnix') call assert_equal(['YabcX', 'ZdefY'], getline(1, '$')) set foldopen-=hor bw! endfunc func Test_edit_INS() " Test for Pressing <Insert> new call setline(1, ['abc', 'def']) call cursor(1, 1) call feedkeys("i\<Insert>ZYX>", 'tnix') call assert_equal(['ZYX>', 'def'], getline(1, '$')) call setline(1, ['abc', 'def']) call cursor(1, 1) call feedkeys("i\<Insert>Z\<Insert>YX>", 'tnix') call assert_equal(['ZYX>bc', 'def'], getline(1, '$')) bw! endfunc func Test_edit_LEFT_RIGHT() " Left, Shift-Left, Right, Shift-Right new call setline(1, ['abc def ghi', 'ABC DEF GHI', 'ZZZ YYY XXX']) let _ww=&ww set ww= call cursor(2, 1) call feedkeys("i\<left>\<esc>", 'tnix') call assert_equal([0, 2, 1, 0], getpos('.')) " Is this a bug, <s-left> does not respect whichwrap option call feedkeys("i\<s-left>\<esc>", 'tnix') call assert_equal([0, 1, 8, 0], getpos('.')) call feedkeys("i". repeat("\<s-left>", 3). "\<esc>", 'tnix') call assert_equal([0, 1, 1, 0], getpos('.')) call feedkeys("i\<right>\<esc>", 'tnix') call assert_equal([0, 1, 1, 0], getpos('.')) call feedkeys("i\<right>\<right>\<esc>", 'tnix') call assert_equal([0, 1, 2, 0], getpos('.')) call feedkeys("A\<right>\<esc>", 'tnix') call assert_equal([0, 1, 11, 0], getpos('.')) call feedkeys("A\<s-right>\<esc>", 'tnix') call assert_equal([0, 2, 1, 0], getpos('.')) call feedkeys("i\<s-right>\<esc>", 'tnix') call assert_equal([0, 2, 4, 0], getpos('.')) call cursor(3, 11) call feedkeys("A\<right>\<esc>", 'tnix') call feedkeys("A\<s-right>\<esc>", 'tnix') call assert_equal([0, 3, 11, 0], getpos('.')) call cursor(2, 11) " <S-Right> does not respect 'whichwrap' option call feedkeys("A\<s-right>\<esc>", 'tnix') call assert_equal([0, 3, 1, 0], getpos('.')) " Check motion when 'whichwrap' contains cursor keys for insert mode set ww+=[,] call cursor(2, 1) call feedkeys("i\<left>\<esc>", 'tnix') call assert_equal([0, 1, 11, 0], getpos('.')) call cursor(2, 11) call feedkeys("A\<right>\<esc>", 'tnix') call assert_equal([0, 3, 1, 0], getpos('.')) call cursor(2, 11) call feedkeys("A\<s-right>\<esc>", 'tnix') call assert_equal([0, 3, 1, 0], getpos('.')) let &ww = _ww bw! endfunc func Test_edit_MOUSE() " This is a simple test, since we not really using the mouse here CheckFeature mouse 10new call setline(1, range(1, 100)) call cursor(1, 1) call assert_equal(1, line('w0')) call assert_equal(10, line('w$')) set mouse=a " One scroll event moves three lines. call feedkeys("A\<ScrollWheelDown>\<esc>", 'tnix') call assert_equal(4, line('w0')) call assert_equal(13, line('w$')) " This should move by one page down. call feedkeys("A\<S-ScrollWheelDown>\<esc>", 'tnix') call assert_equal(14, line('w0')) set nostartofline " Another page down. call feedkeys("A\<C-ScrollWheelDown>\<esc>", 'tnix') call assert_equal(24, line('w0')) call assert_equal([0, 24, 2, 0], getpos('.')) call test_setmouse(4, 3) call feedkeys("A\<LeftMouse>\<esc>", 'tnix') call assert_equal([0, 27, 2, 0], getpos('.')) set mousemodel=extend call test_setmouse(5, 3) call feedkeys("A\<RightMouse>\<esc>\<esc>", 'tnix') call assert_equal([0, 28, 2, 0], getpos('.')) set mousemodel& call cursor(1, 100) norm! zt " this should move by a screen up, but when the test " is run, it moves up to the top of the buffer... call feedkeys("A\<ScrollWheelUp>\<esc>", 'tnix') call assert_equal([0, 1, 1, 0], getpos('.')) call cursor(1, 30) norm! zt call feedkeys("A\<S-ScrollWheelUp>\<esc>", 'tnix') call assert_equal([0, 1, 1, 0], getpos('.')) call cursor(1, 30) norm! zt call feedkeys("A\<C-ScrollWheelUp>\<esc>", 'tnix') call assert_equal([0, 1, 1, 0], getpos('.')) %d call setline(1, repeat(["12345678901234567890"], 100)) call cursor(2, 1) call feedkeys("A\<ScrollWheelRight>\<esc>", 'tnix') call assert_equal([0, 2, 20, 0], getpos('.')) call feedkeys("A\<ScrollWheelLeft>\<esc>", 'tnix') call assert_equal([0, 2, 20, 0], getpos('.')) call feedkeys("A\<S-ScrollWheelRight>\<esc>", 'tnix') call assert_equal([0, 2, 20, 0], getpos('.')) call feedkeys("A\<S-ScrollWheelLeft>\<esc>", 'tnix') call assert_equal([0, 2, 20, 0], getpos('.')) call feedkeys("A\<C-ScrollWheelRight>\<esc>", 'tnix') call assert_equal([0, 2, 20, 0], getpos('.')) call feedkeys("A\<C-ScrollWheelLeft>\<esc>", 'tnix') call assert_equal([0, 2, 20, 0], getpos('.')) set mouse& startofline bw! endfunc func Test_edit_PAGEUP_PAGEDOWN() 10new call setline(1, repeat(['abc def ghi'], 30)) call cursor(1, 1) call feedkeys("i\<PageDown>\<esc>", 'tnix') call assert_equal([0, 9, 1, 0], getpos('.')) call feedkeys("i\<PageDown>\<esc>", 'tnix') call assert_equal([0, 17, 1, 0], getpos('.')) call feedkeys("i\<PageDown>\<esc>", 'tnix') call assert_equal([0, 25, 1, 0], getpos('.')) call feedkeys("i\<PageDown>\<esc>", 'tnix') call assert_equal([0, 30, 1, 0], getpos('.')) call feedkeys("i\<PageDown>\<esc>", 'tnix') call assert_equal([0, 30, 1, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 29, 1, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 21, 1, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 13, 1, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 5, 1, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 5, 11, 0], getpos('.')) " <S-Up> is the same as <PageUp> " <S-Down> is the same as <PageDown> call cursor(1, 1) call feedkeys("i\<S-Down>\<esc>", 'tnix') call assert_equal([0, 9, 1, 0], getpos('.')) call feedkeys("i\<S-Down>\<esc>", 'tnix') call assert_equal([0, 17, 1, 0], getpos('.')) call feedkeys("i\<S-Down>\<esc>", 'tnix') call assert_equal([0, 25, 1, 0], getpos('.')) call feedkeys("i\<S-Down>\<esc>", 'tnix') call assert_equal([0, 30, 1, 0], getpos('.')) call feedkeys("i\<S-Down>\<esc>", 'tnix') call assert_equal([0, 30, 1, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 29, 1, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 21, 1, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 13, 1, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 5, 1, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 5, 11, 0], getpos('.')) set nostartofline call cursor(30, 11) norm! zt call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 29, 11, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 21, 11, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 13, 11, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 5, 11, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 5, 11, 0], getpos('.')) call cursor(1, 1) call feedkeys("A\<PageDown>\<esc>", 'tnix') call assert_equal([0, 9, 11, 0], getpos('.')) call feedkeys("A\<PageDown>\<esc>", 'tnix') call assert_equal([0, 17, 11, 0], getpos('.')) call feedkeys("A\<PageDown>\<esc>", 'tnix') call assert_equal([0, 25, 11, 0], getpos('.')) call feedkeys("A\<PageDown>\<esc>", 'tnix') call assert_equal([0, 30, 11, 0], getpos('.')) call feedkeys("A\<PageDown>\<esc>", 'tnix') call assert_equal([0, 30, 11, 0], getpos('.')) " <S-Up> is the same as <PageUp> " <S-Down> is the same as <PageDown> call cursor(30, 11) norm! zt call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 29, 11, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 21, 11, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 13, 11, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 5, 11, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 5, 11, 0], getpos('.')) call cursor(1, 1) call feedkeys("A\<S-Down>\<esc>", 'tnix') call assert_equal([0, 9, 11, 0], getpos('.')) call feedkeys("A\<S-Down>\<esc>", 'tnix') call assert_equal([0, 17, 11, 0], getpos('.')) call feedkeys("A\<S-Down>\<esc>", 'tnix') call assert_equal([0, 25, 11, 0], getpos('.')) call feedkeys("A\<S-Down>\<esc>", 'tnix') call assert_equal([0, 30, 11, 0], getpos('.')) call feedkeys("A\<S-Down>\<esc>", 'tnix') call assert_equal([0, 30, 11, 0], getpos('.')) bw! endfunc func Test_edit_forbidden() new " 1) edit in the sandbox is not allowed call setline(1, 'a') com! Sandbox :sandbox call feedkeys("i\<del>\<esc>", 'tnix') call assert_fails(':Sandbox', 'E48:') com! Sandbox :sandbox exe "norm! i\<del>" call assert_fails(':Sandbox', 'E48:') delcom Sandbox call assert_equal(['a'], getline(1,'$')) " 2) edit with textlock set fu! DoIt() call feedkeys("i\<del>\<esc>", 'tnix') endfu au InsertCharPre <buffer> :call DoIt() try call feedkeys("ix\<esc>", 'tnix') call assert_fails(1, 'textlock') catch /^Vim\%((\a\+)\)\=:E565/ " catch E565: not allowed here endtry " TODO: Might be a bug: should x really be inserted here call assert_equal(['xa'], getline(1, '$')) delfu DoIt try call feedkeys("ix\<esc>", 'tnix') call assert_fails(1, 'unknown function') catch /^Vim\%((\a\+)\)\=:E117/ " catch E117: unknown function endtry au! InsertCharPre " 3) edit when completion is shown fun! Complete(findstart, base) if a:findstart return col('.') else call feedkeys("i\<del>\<esc>", 'tnix') return [] endif endfun set completefunc=Complete try call feedkeys("i\<c-x>\<c-u>\<esc>", 'tnix') call assert_fails(1, 'change in complete function') catch /^Vim\%((\a\+)\)\=:E565/ " catch E565 endtry delfu Complete set completefunc= if has("rightleft") && exists("+fkmap") " 4) 'R' when 'fkmap' and 'revins' is set. set revins fkmap try normal Ri call assert_fails(1, "R with 'fkmap' and 'ri' set") catch finally set norevins nofkmap endtry endif bw! endfunc func Test_edit_rightleft() " Cursor in rightleft mode moves differently CheckFeature rightleft call NewWindow(10, 20) call setline(1, ['abc', 'def', 'ghi']) call cursor(1, 2) set rightleft " Screen looks as expected let lines = ScreenLines([1, 4], winwidth(0)) let expect = [ \" cba", \" fed", \" ihg", \" ~"] call assert_equal(join(expect, "\n"), join(lines, "\n")) " 2) right moves to the left call feedkeys("i\<right>\<esc>x", 'txin') call assert_equal(['bc', 'def', 'ghi'], getline(1,'$')) call cursor(1, 2) call feedkeys("i\<s-right>\<esc>", 'txin') call cursor(1, 2) call feedkeys("i\<c-right>\<esc>", 'txin') " Screen looks as expected let lines = ScreenLines([1, 4], winwidth(0)) let expect = [ \" cb", \" fed", \" ihg", \" ~"] call assert_equal(join(expect, "\n"), join(lines, "\n")) " 2) left moves to the right call setline(1, ['abc', 'def', 'ghi']) call cursor(1, 2) call feedkeys("i\<left>\<esc>x", 'txin') call assert_equal(['ac', 'def', 'ghi'], getline(1,'$')) call cursor(1, 2) call feedkeys("i\<s-left>\<esc>", 'txin') call cursor(1, 2) call feedkeys("i\<c-left>\<esc>", 'txin') " Screen looks as expected let lines = ScreenLines([1, 4], winwidth(0)) let expect = [ \" ca", \" fed", \" ihg", \" ~"] call assert_equal(join(expect, "\n"), join(lines, "\n")) %d _ call test_override('redraw_flag', 1) call test_override('char_avail', 1) call feedkeys("a\<C-V>x41", "xt") redraw! call assert_equal(repeat(' ', 19) .. 'A', Screenline(1)) call test_override('ALL', 0) set norightleft bw! endfunc func Test_edit_complete_very_long_name() " Long directory names only work on Unix. CheckUnix let dirname = getcwd() . "/Xdir" let longdirname = dirname . repeat('/' . repeat('d', 255), 4) try call mkdir(longdirname, 'p') catch /E739:/ " Long directory name probably not supported. call delete(dirname, 'rf') return endtry " Try to get the Vim window position before setting 'columns', so that we can " move the window back to where it was. let winposx = getwinposx() let winposy = getwinposy() if winposx >= 0 && winposy >= 0 && !has('gui_running') " We did get the window position, but xterm may report the wrong numbers. " Move the window to the reported position and compute any offset. exe 'winpos ' . winposx . ' ' . winposy sleep 100m let x = getwinposx() if x >= 0 let winposx += winposx - x endif let y = getwinposy() if y >= 0 let winposy += winposy - y endif endif let save_columns = &columns " Need at least about 1100 columns to reproduce the problem. set columns=2000 set noswapfile let longfilename = longdirname . '/' . repeat('a', 255) call writefile(['Totum', 'Table'], longfilename) new exe "next Xfile " . longfilename exe "normal iT\<C-N>" bwipe! exe 'bwipe! ' . longfilename call delete(dirname, 'rf') let &columns = save_columns if winposx >= 0 && winposy >= 0 exe 'winpos ' . winposx . ' ' . winposy endif set swapfile& endfunc func Test_edit_backtick() next a\`b c call assert_equal('a`b', expand('%')) next call assert_equal('c', expand('%')) call assert_equal('a\`b c', expand('##')) endfunc func Test_edit_quit() edit foo.txt split new call setline(1, 'hello') 3wincmd w redraw! call assert_fails('1q', 'E37:') bwipe! foo.txt only endfunc func Test_edit_alt() " Keeping the cursor line didn't happen when the first line has indent. new call setline(1, [' one', 'two', 'three']) w XAltFile $ call assert_equal(3, line('.')) e Xother e # call assert_equal(3, line('.')) bwipe XAltFile call delete('XAltFile') endfunc func Test_edit_InsertLeave() new au InsertLeavePre * let g:did_au_pre = 1 au InsertLeave * let g:did_au = 1 let g:did_au_pre = 0 let g:did_au = 0 call feedkeys("afoo\<Esc>", 'tx') call assert_equal(1, g:did_au_pre) call assert_equal(1, g:did_au) call assert_equal('foo', getline(1)) let g:did_au_pre = 0 let g:did_au = 0 call feedkeys("Sbar\<C-C>", 'tx') call assert_equal(1, g:did_au_pre) call assert_equal(0, g:did_au) call assert_equal('bar', getline(1)) inoremap x xx<Esc> let g:did_au_pre = 0 let g:did_au = 0 call feedkeys("Saax", 'tx') call assert_equal(1, g:did_au_pre) call assert_equal(1, g:did_au) call assert_equal('aaxx', getline(1)) inoremap x xx<C-C> let g:did_au_pre = 0 let g:did_au = 0 call feedkeys("Sbbx", 'tx') call assert_equal(1, g:did_au_pre) call assert_equal(0, g:did_au) call assert_equal('bbxx', getline(1)) bwipe! au! InsertLeave InsertLeavePre iunmap x endfunc func Test_edit_InsertLeave_undo() new XtestUndo set undofile au InsertLeave * wall exe "normal ofoo\<Esc>" call assert_equal(2, line('$')) normal u call assert_equal(1, line('$')) bwipe! au! InsertLeave call delete('XtestUndo') call delete(undofile('XtestUndo')) set undofile& endfunc " Test for inserting characters using CTRL-V followed by a number. func Test_edit_special_chars() new let t = "o\<C-V>65\<C-V>x42\<C-V>o103 \<C-V>33a\<C-V>xfg\<C-V>o78\<Esc>" exe "normal " . t call assert_equal("ABC !a\<C-O>g\<C-G>8", getline(2)) close! endfunc func Test_edit_startinsert() new set backspace+=start call setline(1, 'foobar') call feedkeys("A\<C-U>\<Esc>", 'xt') call assert_equal('', getline(1)) call setline(1, 'foobar') call feedkeys(":startinsert!\<CR>\<C-U>\<Esc>", 'xt') call assert_equal('', getline(1)) set backspace& bwipe! endfunc " Test for :startreplace and :startgreplace func Test_edit_startreplace() new call setline(1, 'abc') call feedkeys("l:startreplace\<CR>xyz\e", 'xt') call assert_equal('axyz', getline(1)) call feedkeys("0:startreplace!\<CR>abc\e", 'xt') call assert_equal('axyzabc', getline(1)) call setline(1, "a\tb") call feedkeys("0l:startgreplace\<CR>xyz\e", 'xt') call assert_equal("axyz\tb", getline(1)) call feedkeys("0i\<C-R>=execute('startreplace')\<CR>12\e", 'xt') call assert_equal("12axyz\tb", getline(1)) close! endfunc func Test_edit_noesckeys() CheckNotGui new " <Left> moves cursor when 'esckeys' is set exe "set t_kl=\<Esc>OD" set esckeys call feedkeys("axyz\<Esc>ODX", "xt") call assert_equal("xyXz", getline(1)) " <Left> exits Insert mode when 'esckeys' is off set noesckeys call setline(1, '') call feedkeys("axyz\<Esc>ODX", "xt") call assert_equal(["DX", "xyz"], getline(1, 2)) bwipe! set esckeys endfunc " Test for running an invalid ex command in insert mode using CTRL-O func Test_edit_ctrl_o_invalid_cmd() new set showmode showcmd " Avoid a sleep of 3 seconds. Zero might have side effects. call test_override('ui_delay', 50) let caught_e492 = 0 try call feedkeys("i\<C-O>:invalid\<CR>abc\<Esc>", "xt") catch /E492:/ let caught_e492 = 1 endtry call assert_equal(1, caught_e492) call assert_equal('abc', getline(1)) set showmode& showcmd& call test_override('ui_delay', 0) close! endfunc " Test for editing a file with a very long name func Test_edit_illegal_filename() CheckEnglish new redir => msg exe 'edit ' . repeat('f', 5000) redir END call assert_match("Illegal file name$", split(msg, "\n")[0]) close! endfunc " Test for editing a directory func Test_edit_is_a_directory() CheckEnglish let dirname = getcwd() . "/Xdir" call mkdir(dirname, 'p') new redir => msg exe 'edit' dirname redir END call assert_match("is a directory$", split(msg, "\n")[0]) bwipe! let dirname .= '/' new redir => msg exe 'edit' dirname redir END call assert_match("is a directory$", split(msg, "\n")[0]) bwipe! call delete(dirname, 'rf') endfunc " Test for editing a file using invalid file encoding func Test_edit_invalid_encoding() CheckEnglish call writefile([], 'Xfile') redir => msg new ++enc=axbyc Xfile redir END call assert_match('\[NOT converted\]', msg) call delete('Xfile') close! endfunc " Test for the "charconvert" option func Test_edit_charconvert() CheckEnglish call writefile(['one', 'two'], 'Xfile') " set 'charconvert' to a non-existing function set charconvert=NonExitingFunc() new let caught_e117 = v:false try redir => msg edit ++enc=axbyc Xfile catch /E117:/ let caught_e117 = v:true finally redir END endtry call assert_true(caught_e117) call assert_equal(['one', 'two'], getline(1, '$')) call assert_match("Conversion with 'charconvert' failed", msg) close! set charconvert& " 'charconvert' function doesn't create a output file func Cconv1() endfunc set charconvert=Cconv1() new redir => msg edit ++enc=axbyc Xfile redir END call assert_equal(['one', 'two'], getline(1, '$')) call assert_match("can't read output of 'charconvert'", msg) close! delfunc Cconv1 set charconvert& " 'charconvert' function to convert to upper case func Cconv2() let data = readfile(v:fname_in) call map(data, 'toupper(v:val)') call writefile(data, v:fname_out) endfunc set charconvert=Cconv2() new Xfile write ++enc=ucase Xfile1 call assert_equal(['ONE', 'TWO'], readfile('Xfile1')) call delete('Xfile1') close! delfunc Cconv2 set charconvert& " 'charconvert' function removes the input file func Cconv3() call delete(v:fname_in) endfunc set charconvert=Cconv3() new call assert_fails('edit ++enc=lcase Xfile', 'E202:') call assert_equal([''], getline(1, '$')) close! delfunc Cconv3 set charconvert& call delete('Xfile') endfunc " Test for editing a file without read permission func Test_edit_file_no_read_perm() CheckUnix CheckNotRoot call writefile(['one', 'two'], 'Xfile') call setfperm('Xfile', '-w-------') new redir => msg edit Xfile redir END call assert_equal(1, &readonly) call assert_equal([''], getline(1, '$')) call assert_match('\[Permission Denied\]', msg) close! call delete('Xfile') endfunc " Using :edit without leaving 'insertmode' should not cause Insert mode to be " re-entered immediately after <C-L> func Test_edit_insertmode_ex_edit() CheckRunVimInTerminal let lines =<< trim END set insertmode noruler inoremap <C-B> <Cmd>edit Xfoo<CR> END call writefile(lines, 'Xtest_edit_insertmode_ex_edit') let buf = RunVimInTerminal('-S Xtest_edit_insertmode_ex_edit', #{rows: 6}) " Somehow this can be very slow with valgrind. A separate TermWait() works " better than a longer time with WaitForAssert() (why?) call TermWait(buf, 1000) call WaitForAssert({-> assert_match('^-- INSERT --\s*$', term_getline(buf, 6))}) call term_sendkeys(buf, "\<C-B>\<C-L>") call WaitForAssert({-> assert_notmatch('^-- INSERT --\s*$', term_getline(buf, 6))}) " clean up call StopVimInTerminal(buf) call delete('Xtest_edit_insertmode_ex_edit') endfunc " Pressing escape in 'insertmode' should beep " FIXME: Execute this later, when using valgrind it makes the next test " Test_edit_insertmode_ex_edit() fail. func Test_z_edit_insertmode_esc_beeps() new set insertmode call assert_beeps("call feedkeys(\"one\<Esc>\", 'xt')") set insertmode& " unsupported "CTRL-G l" command should beep in insert mode. call assert_beeps("normal i\<C-G>l") bwipe! endfunc " Test for 'hkmap' and 'hkmapp' func Test_edit_hkmap() CheckFeature rightleft if has('win32') && !has('gui') throw 'Skipped: fails on the MS-Windows terminal version' endif new set revins hkmap let str = 'abcdefghijklmnopqrstuvwxyz' let str ..= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' let str ..= '`/'',.;' call feedkeys('i' .. str, 'xt') let expected = "óõú,.;" let expected ..= "ZYXWVUTSRQPONMLKJIHGFEDCBA" let expected ..= "æèñ'äåàãø/ôíîöêìçïéòë÷âáðù" call assert_equal(expected, getline(1)) %d set revins hkmap hkmapp let str = 'abcdefghijklmnopqrstuvwxyz' let str ..= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' call feedkeys('i' .. str, 'xt') let expected = "õYXWVUTSRQóOïíLKJIHGFEDêBA" let expected ..= "öòXùåèúæø'ôñðîì÷çéäâóǟãëáà" call assert_equal(expected, getline(1)) set revins& hkmap& hkmapp& close! endfunc " Test for 'allowrevins' and using CTRL-_ in insert mode func Test_edit_allowrevins() CheckFeature rightleft new set allowrevins call feedkeys("iABC\<C-_>DEF\<C-_>GHI", 'xt') call assert_equal('ABCFEDGHI', getline(1)) set allowrevins& close! endfunc " Test for inserting a register in insert mode using CTRL-R func Test_edit_insert_reg() new let g:Line = '' func SaveFirstLine() let g:Line = Screenline(1) return 'r' endfunc inoremap <expr> <buffer> <F2> SaveFirstLine() call test_override('redraw_flag', 1) call test_override('char_avail', 1) let @r = 'sample' call feedkeys("a\<C-R>=SaveFirstLine()\<CR>", "xt") call assert_equal('"', g:Line) call test_override('ALL', 0) close! endfunc " When a character is inserted at the last position of the last line in a " window, the window contents should be scrolled one line up. If the top line " is part of a fold, then the entire fold should be scrolled up. func Test_edit_lastline_scroll() new let h = winheight(0) let lines = ['one', 'two', 'three'] let lines += repeat(['vim'], h - 4) call setline(1, lines) call setline(h, repeat('x', winwidth(0) - 1)) call feedkeys("GAx", 'xt') redraw! call assert_equal(h - 1, winline()) call assert_equal(2, line('w0')) " scroll with a fold 1,2fold normal gg call setline(h + 1, repeat('x', winwidth(0) - 1)) call feedkeys("GAx", 'xt') redraw! call assert_equal(h - 1, winline()) call assert_equal(3, line('w0')) close! endfunc func Test_edit_browse() " in the GUI this opens a file picker, we only test the terminal behavior CheckNotGui " ":browse xxx" checks for the FileExplorer augroup and assumes editing "." " works then. augroup FileExplorer au! augroup END " When the USE_FNAME_CASE is defined this used to cause a crash. browse enew bwipe! browse split bwipe! endfunc func Test_read_invalid() set encoding=latin1 " This was not properly checking for going past the end. call assert_fails('r`=', 'E484') set encoding=utf-8 endfunc " Test for the 'revins' option func Test_edit_revins() CheckFeature rightleft new set revins exe "normal! ione\ttwo three" call assert_equal("eerht owt\teno", getline(1)) call setline(1, "one\ttwo three") normal! gg$bi a call assert_equal("one\ttwo a three", getline(1)) exe "normal! $bi\<BS>\<BS>" call assert_equal("one\ttwo a ree", getline(1)) exe "normal! 0wi\<C-W>" call assert_equal("one\t a ree", getline(1)) exe "normal! 0wi\<C-U>" call assert_equal("one\t ", getline(1)) " newline in insert mode starts at the end of the line call setline(1, 'one two three') exe "normal! wi\nfour" call assert_equal(['one two three', 'ruof'], getline(1, '$')) set revins& bw! endfunc " Test for getting the character of the line below after "p" func Test_edit_put_CTRL_E() set encoding=latin1 new let @" = '' sil! norm orggRx sil! norm pr call assert_equal(['r', 'r'], getline(1, 2)) bwipe! set encoding=utf-8 endfunc " Test toggling of input method. See :help i_CTRL-^ func Test_edit_CTRL_hat() CheckFeature xim " FIXME: test fails with Motif GUI. " test also fails when running in the GUI. CheckFeature gui_gtk CheckNotGui new call assert_equal(0, &iminsert) call feedkeys("i\<C-^>", 'xt') call assert_equal(2, &iminsert) call feedkeys("i\<C-^>", 'xt') call assert_equal(0, &iminsert) bwipe! endfunc " Weird long file name was going over the end of NameBuff func Test_edit_overlong_file_name() CheckUnix file 0000000000000000000000000000 file %%%%%%%%%%%%%%%%%%%%%%%%%% file %%%%%% set readonly set ls=2 redraw! set noreadonly ls& bwipe! endfunc func Test_edit_shift_bs() CheckMSWindows " FIXME: this works interactively, but the test fails throw 'Skipped: Shift-Backspace Test not working correctly :(' " Need to run this in Win32 Terminal, do not use CheckRunVimInTerminal if !has("terminal") return endif " Shift Backspace should work like Backspace in insert mode let lines =<< trim END call setline(1, ['abc']) END call writefile(lines, 'Xtest_edit_shift_bs') let buf = RunVimInTerminal('-S Xtest_edit_shift_bs', #{rows: 3}) call term_sendkeys(buf, "A\<S-BS>-\<esc>") call TermWait(buf, 50) call assert_equal('ab-', term_getline(buf, 1)) " clean up call StopVimInTerminal(buf) call delete('Xtest_edit_shift_bs') endfunc " vim: shiftwidth=2 sts=2 expandtab