From aed8ce9da277f5ecffe968b324f242c41c3b752a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 10:50:31 +0200 Subject: Adding upstream version 2:9.0.1378. Signed-off-by: Daniel Baumann --- src/testdir/test_edit.vim | 2109 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2109 insertions(+) create mode 100644 src/testdir/test_edit.vim (limited to 'src/testdir/test_edit.vim') diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim new file mode 100644 index 0000000..79e3c3f --- /dev/null +++ b/src/testdir/test_edit.vim @@ -0,0 +1,2109 @@ +" 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 h here some more + call cursor(1, 4) + " expands the abbreviation and ends insertmode + call feedkeys(":set im\ h\:set noim\", 'tix') + call assert_equal(['abc here some more '], getline(1,'$')) + iunabbr 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\\", 'tnix') + call assert_equal([''], getline(1,'$')) + %d + " 3) delete one character + call setline(1, 'a') + call feedkeys("i\\", 'tnix') + call assert_equal([''], getline(1,'$')) + %d + " 4) delete a multibyte character + call setline(1, "\u0401") + call feedkeys("i\\", '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\\", '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\\", '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 :call DoIt('y') + call feedkeys("ix\", 'tnix') + call assert_equal(['abcy'], getline(1, '$')) + " Setting in InsertCharPre + au! InsertCharPre :call DoIt("\n") + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("ix\", '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 :call DoIt('y') + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("ix\", 'tnix') + call assert_equal(['abxc'], getline(1, '$')) + " 2) when not setting v:char, restores changed cursor position + au! InsertEnter :call DoIt() + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("ix\", 'tnix') + call assert_equal(['xabc'], getline(1, '$')) + au! InsertEnter + delfu DoIt + bw! +endfunc + +func Test_edit_03() + " Change cursor after command to end of line + new + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("i\$y\", 'tnix') + call assert_equal(['abcy'], getline(1, '$')) + %d + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("i\80|y\", 'tnix') + call assert_equal(['abcy'], getline(1, '$')) + %d + call setline(1, 'abc') + call feedkeys("Ad\:s/$/efg/\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\:stopinsert\$", 'tnix') + call feedkeys("aX\", '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\", '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\", '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\", 'tnix') + call assert_equal(['abc', 'zzz', 'xxx', 'yyy'], getline(1,'$')) + bw! + bw! +endfunc + +func Test_edit_07() + " 1) Test with completion 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 =ListMonths() + + call feedkeys("A\\". repeat("\", 6)."\\\\", '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 :call DoIt() + call feedkeys("A\\u\\\", 'tx') + call assert_equal(["Jan\",''], 1->getline('$')) + %d + call setline(1, 'J') + call feedkeys("A\\u\\\", 'tx') + call assert_equal(["January"], 1->getline('$')) + + delfu ListMonths + delfu DoIt + iunmap + 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\ZZZ\=setbufvar(g:bufnr,'&im', 0)\",'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\\\ccABC\", 'txin') + call assert_equal(['ABC', 'def', 'ghi'], getline(1,'$')) + call setline(1, ['ABC', 'def', 'ghi']) + " 2) CTRL-\ CTLR-G + call feedkeys("j0\\ZZZ\\", 'txin') + call assert_equal(['ABC', 'ZZZ', 'def', 'ghi'], getline(1,'$')) + call feedkeys("I\\YYY\", '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\ix", 'txin') + call assert_equal(['ABxC', 'ZZZ', 'def', 'ghi'], getline(1,'$')) + call feedkeys("A\\ix", 'txin') + call assert_equal(['ABxCx', 'ZZZ', 'def', 'ghi'], getline(1,'$')) + " 4) CTRL-\ a (should be inserted literally, not special after + call setline(1, ['ABC', 'ZZZ', 'def', 'ghi']) + call cursor(1, 1) + call feedkeys("A\a", 'txin') + call assert_equal(["ABC\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\int c;\", 'tnix') + call cursor(3, 1) + call feedkeys("\/* comment */", 'tnix') + call assert_equal(['{', "\int c;", "/* comment */"], getline(1, '$')) + " added changed cindentkeys slightly + set cindent cinkeys+=*/ + call setline(1, ['{', '', '']) + call cursor(2, 1) + call feedkeys("i\int c;\", 'tnix') + call cursor(3, 1) + call feedkeys("i/* comment */", 'tnix') + call assert_equal(['{', "\int c;", "\/* comment */"], getline(1, '$')) + set cindent cinkeys+==end + call feedkeys("oend\\", 'tnix') + call assert_equal(['{', "\int c;", "\/* 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\int c;\", 'tnix') + call cursor(3, 1) + call feedkeys("i/* comment */", 'tnix') + call assert_equal(['{', "\\int c;", "\\\/* 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\that\fi", 'tnix') + call assert_equal(['if [ $this ]', "then", "\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('') .. 'NewIndentExpr()', &indentexpr) + call assert_equal(expand('') .. 'NewIndentExpr()', &g:indentexpr) + set indentexpr=NewIndentExpr() + call assert_equal(expand('') .. 'NewIndentExpr()', &indentexpr) + call assert_equal(expand('') .. 'NewIndentExpr()', &g:indentexpr) + setlocal indentexpr= + setglobal indentexpr=s:NewIndentExpr() + call assert_equal(expand('') .. 'NewIndentExpr()', &g:indentexpr) + call assert_equal('', &indentexpr) + new + call assert_equal(expand('') .. 'NewIndentExpr()', &indentexpr) + bw! + setglobal indentexpr=NewIndentExpr() + call assert_equal(expand('') .. 'NewIndentExpr()', &g:indentexpr) + call assert_equal('', &indentexpr) + new + call assert_equal(expand('') .. 'NewIndentExpr()', &indentexpr) + bw! + 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^\", '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^\", '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\", '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\", '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\\", '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\\", '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\six" .. repeat("\", 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 {\more\}\", '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\\\" + call assert_equal(" foo bar", getline(1)) + call assert_equal("", getline(2)) + call assert_equal(" baz", getline(3)) + set autoindent& + + " pressing to erase line should keep the indent with 'autoindent' + set backspace=2 autoindent + %d + exe "normal i\tone\three\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 Xarifile', {'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\foo\\") + " 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) .. "\") + " 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('Xarifile')) + call delete('Xarifile') +endfunc + +func Test_edit_CR() + " Test for 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', 'D') + call setqflist([{'filename': 'Xqflist.txt', 'lnum': 2}]) + copen + set modifiable + call feedkeys("A\", '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\", 'tnix') + call assert_equal('Xqflist.txt', bufname('')) + call assert_equal(10, line('.')) + call feedkeys("A\", 'tnix') + call feedkeys("A\", '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 +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\xyz\", 'tnix') + call assert_equal(["\xyzabc"], getline(1, '$')) + call assert_false(&revins) + set ari + call setline(1, ['abc']) + call cursor(1, 1) + call feedkeys("i\xyz\", 'tnix') + call assert_equal(["æèñabc"], getline(1, '$')) + call assert_true(&revins) + call setline(1, ['abc']) + call cursor(1, 1) + call feedkeys("i\xyz\", '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\", 'tnix') + catch /^Vim\%((\a\+)\)\=:E29/ + call assert_true(1, 'E29 error caught') + endtry + call cursor(1, 1) + call feedkeys("Afoobar \", 'tnix') + call cursor(2, 1) + call feedkeys("A\more\", 'tnix') + call cursor(3, 1) + call feedkeys("A\and more\", '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\\\\\\", 'tnix') + call assert_equal(30, winsaveview()['topline']) + call assert_equal([0, 30, 2, 0], getpos('.')) + call feedkeys("A\\\\\\", 'tnix') + call feedkeys("A\".repeat("\", 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\k\.\", 'tnix') + call assert_equal(['foooooooooobar', 'foooooooooobar', 'foobar'], getline(1, '$')) + call assert_equal([0, 1, 11, 0], getpos('.')) + call feedkeys("i\k\", 'tnix') + call assert_equal([0, 1, 10, 0], getpos('.')) + call cursor(2, 4) + call feedkeys("i\jzzzz\", 'tnix') + call assert_equal(['foooooooooobar', 'foooooooooobar', 'foozzzzbar'], getline(1, '$')) + call assert_equal([0, 3, 7, 0], getpos('.')) + call feedkeys("i\j\", 'tnix') + call assert_equal([0, 3, 6, 0], getpos('.')) + call assert_nobeep("normal! i\\") + bw! +endfunc + +func Test_edit_CTRL_I() + " Tab in completion mode + let path=expand("%:p:h") + new + call setline(1, [path. "/", '']) + call feedkeys("Arunt\\\\\", 'tnix') + call assert_match('runtest\.vim', getline(1)) + %d + call writefile(['one', 'two', 'three'], 'Xinclude.txt', 'D') + let include='#include Xinclude.txt' + call setline(1, [include, '']) + call cursor(2, 1) + call feedkeys("A\\\\", 'tnix') + call assert_equal([include, 'one', ''], getline(1, '$')) + call feedkeys("2ggC\\\\\", 'tnix') + call assert_equal([include, 'two', ''], getline(1, '$')) + call feedkeys("2ggC\\\\\\", 'tnix') + call assert_equal([include, 'three', ''], getline(1, '$')) + call feedkeys("2ggC\\\\\\\", 'tnix') + call assert_equal([include, '', ''], getline(1, '$')) + 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', 'D') + set dictionary=Xdictionary.txt + new + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\\\\", 'tnix') + call assert_equal(['AA', ''], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\\\\\", 'tnix') + call assert_equal(['AAA'], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\\\\\\", 'tnix') + call assert_equal(['AAAA'], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\\\\\\\", 'tnix') + call assert_equal(['A'], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\\\\\\\\", '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\\\\\", 'tnix') + call assert_equal(['AA', ''], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\\\\\", 'tnix') + call assert_equal(["AA\", ''], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\\\\\", 'tnix') + call assert_equal(["AA\", ''], getline(1, '$')) + + set dictionary= + %d + call setline(1, 'A') + call cursor(1, 1) + let v:testing = 1 + try + call feedkeys("A\\\", 'tnix') + catch + " error sleeps 2 seconds, when v:testing is not set + let v:testing = 0 + endtry + + call test_override("char_avail", 1) + set showcmd + %d + call feedkeys("A\a:\", '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\\\", 'tnix') + call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$')) + call feedkeys("cct\\\\", 'tnix') + call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$')) + call feedkeys("cct\\\\\", 'tnix') + call assert_equal(['one', 'two', 'three', 'two', '', '', ''], getline(1, '$')) + call feedkeys("cct\\\\\\", 'tnix') + call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$')) + call feedkeys("cct\\\\\\\", 'tnix') + call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$')) + call feedkeys("cct\\\\", 'tnix') + call assert_equal(['one', 'two', 'three', 'two', '', '', ''], getline(1, '$')) + call feedkeys("cct\\\\\", 'tnix') + call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$')) + call feedkeys("cct\\\\\\", 'tnix') + call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$')) + set complete= + call cursor(5, 1) + call feedkeys("A\\\\\", 'tnix') + call assert_equal(['one', 'two', 'three', 'three', "\\\", '', ''], 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 :call DoIt() + + call cursor(2, 1) + call assert_false(exists("g:change")) + call feedkeys("A \", '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\\\", "tnix") + call feedkeys("ILO\\\", '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\\\", "tnix") + call feedkeys("ILO\\\", '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\\\" + 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 h here some more + call setline(1, ['abc', 'def']) + call cursor(1, 1) + " Ctrl-O after an abbreviation + exe "norm A h\:set nu\ text" + call assert_equal(['abc here some more text', 'def'], getline(1, '$')) + call assert_true(&nu) + set nonu + iunabbr h + " Ctrl-O at end of line with 've'=onemore + call cursor(1, 1) + call feedkeys("A\:let g:a=getpos('.')\\", 'tnix') + call assert_equal([0, 1, 23, 0], g:a) + call cursor(1, 1) + set ve=onemore + call feedkeys("A\:let g:a=getpos('.')\\", '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\", 'tnix') + call feedkeys("O\.", 'tnix') + call feedkeys("O\=10*500\\", 'tnix') + call feedkeys("O\=getreg('=', 1)\\", '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\ss\\", 'tnix') + call assert_equal(['vims', ''], getline(1, '$')) + bw! + return + endif + call setline(1, 'vim') + " spell option not yet set + try + call feedkeys("A\\\\", '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\\\\", 'tnix') + call assert_equal(['Vim', ''], getline(1, '$')) + %d + call setline(1, 'vim') + call cursor(1, 1) + call feedkeys("A\\\\\", 'tnix') + call assert_equal(['Aim'], getline(1, '$')) + %d + call setline(1, 'vim') + call cursor(1, 1) + call feedkeys("A\\\\\", 'tnix') + call assert_equal(['vim', ''], getline(1, '$')) + %d + " empty buffer + call cursor(1, 1) + call feedkeys("A\\\\\", '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\xyz", 'tnix') + call assert_equal(["\abcxyz"], getline(1, '$')) + " 2) also when paste option is set + set paste + call setline(1, "abc") + call cursor(1, 1) + call feedkeys("A\xyz", 'tnix') + call assert_equal(["\abcxyz"], getline(1, '$')) + set nopaste + " CTRL-X CTRL-T (thesaurus complete) + call writefile(['angry furious mad enraged'], 'Xthesaurus', 'D') + set thesaurus=Xthesaurus + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\\\\", 'tnix') + call assert_equal(['mad', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\\\\\", 'tnix') + call assert_equal(['angry', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\\\\\\", 'tnix') + call assert_equal(['furious', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\\\\\\\", 'tnix') + call assert_equal(['enraged', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\\\\\\\\", 'tnix') + call assert_equal(['mad', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\\\\\\\\\", 'tnix') + call assert_equal(['mad', ''], getline(1, '$')) + " Using when 'complete' is empty + set complete= + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\\\\\", 'tnix') + call assert_equal(['angry', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\\\\\", '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\\\", 'tnix') + catch + " error sleeps 2 seconds, when v:testing is not set + let v:testing = 0 + endtry + call assert_equal(['mad'], getline(1, '$')) + bw! +endfunc + +" Test thesaurus completion with different encodings +func Test_thesaurus_complete_with_encoding() + call writefile(['angry furious mad enraged'], 'Xthesaurus', 'D') + 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\\\\", 'tnix') + call assert_equal(['mad', ''], getline(1, '$')) + bw! + endfor + set thesaurus= +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\\\\\", 'tnix') + call assert_equal(['an amiable', ''], getline(1, '$')) + + setlocal thesaurusfunc=NonExistingFunc + call assert_fails("normal $a\\", 'E117:') + + setlocal thesaurusfunc= + set thesaurusfunc=NonExistingFunc + call assert_fails("normal $a\\", '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\\\\", 'tnix') + call assert_equal(['X', '', ''], getline(1, '$')) + %d + let g:special=-1 + call feedkeys("AX\\\\", 'tnix') + call assert_equal(['XJan', ''], getline(1, '$')) + %d + let g:special=-2 + call feedkeys("AX\\\\", 'tnix') + call assert_equal(['X', ''], getline(1, '$')) + %d + let g:special=-3 + call feedkeys("AX\\\\", 'tnix') + call assert_equal(['X', ''], getline(1, '$')) + %d + let g:special=0 + call feedkeys("AM\\\\", 'tnix') + call assert_equal(['Mar', ''], getline(1, '$')) + %d + call feedkeys("AM\\\\\", 'tnix') + call assert_equal(['May', ''], getline(1, '$')) + %d + call feedkeys("AM\\\\\\", 'tnix') + call assert_equal(['M', ''], getline(1, '$')) + delfu CompleteMonths + %d + try + call feedkeys("A\\", '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\\", '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\\", 'tnix') + call assert_equal(["abc\"], 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\\", '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\\\\\\\", '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\\\\\\\", '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\\76c\76\\u3c0j\u3c0\\.\", 'tnix') + call assert_equal('LcLπjπ', getline(2)) + + if has('osx') + " A char with a modifier should not be a valid char for i_CTRL-V_digit. + call feedkeys("o\\\\\\\\\\", 'tnix') + call assert_equal('', getline(3)) + endif + + bw! +endfunc + +func Test_edit_F1() + CheckFeature quickfix + + " Pressing + new + call feedkeys(":set im\\\", 'tnix') + set noinsertmode + call assert_equal('help', &buftype) + bw + bw +endfunc + +func Test_edit_F21() + " Pressing + " sends a netbeans command + CheckFeature netbeans_intg + new + " I have no idea what this is supposed to do :) + call feedkeys("A\\\", '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\Y\", 'tnix') + call cursor(2, 1) + call feedkeys("iZ\Y\", 'tnix') + call assert_equal(['YabcX', 'ZdefY'], getline(1, '$')) + + set foldopen-=hor + bw! +endfunc + +func Test_edit_INS() + " Test for Pressing + new + call setline(1, ['abc', 'def']) + call cursor(1, 1) + call feedkeys("i\ZYX>", 'tnix') + call assert_equal(['ZYX>', 'def'], getline(1, '$')) + call setline(1, ['abc', 'def']) + call cursor(1, 1) + call feedkeys("i\Z\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\\", 'tnix') + call assert_equal([0, 2, 1, 0], getpos('.')) + " Is this a bug, does not respect whichwrap option + call feedkeys("i\\", 'tnix') + call assert_equal([0, 1, 8, 0], getpos('.')) + call feedkeys("i". repeat("\", 3). "\", 'tnix') + call assert_equal([0, 1, 1, 0], getpos('.')) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 1, 1, 0], getpos('.')) + call feedkeys("i\\\", 'tnix') + call assert_equal([0, 1, 2, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 1, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 2, 1, 0], getpos('.')) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 2, 4, 0], getpos('.')) + call cursor(3, 11) + call feedkeys("A\\", 'tnix') + call feedkeys("A\\", 'tnix') + call assert_equal([0, 3, 11, 0], getpos('.')) + call cursor(2, 11) + " does not respect 'whichwrap' option + call feedkeys("A\\", '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\\", 'tnix') + call assert_equal([0, 1, 11, 0], getpos('.')) + call cursor(2, 11) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 3, 1, 0], getpos('.')) + call cursor(2, 11) + call feedkeys("A\\", '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\\", 'tnix') + call assert_equal(4, line('w0')) + call assert_equal(13, line('w$')) + " This should move by one page down. + call feedkeys("A\\", 'tnix') + call assert_equal(14, line('w0')) + set nostartofline + " Another page down. + call feedkeys("A\\", 'tnix') + call assert_equal(24, line('w0')) + + call assert_equal([0, 24, 2, 0], getpos('.')) + call test_setmouse(4, 3) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 27, 2, 0], getpos('.')) + set mousemodel=extend + call test_setmouse(5, 3) + call feedkeys("A\\\", '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\\", 'tnix') + call assert_equal([0, 1, 1, 0], getpos('.')) + call cursor(1, 30) + norm! zt + call feedkeys("A\\", 'tnix') + call assert_equal([0, 1, 1, 0], getpos('.')) + call cursor(1, 30) + norm! zt + call feedkeys("A\\", 'tnix') + call assert_equal([0, 1, 1, 0], getpos('.')) + %d + call setline(1, repeat(["12345678901234567890"], 100)) + call cursor(2, 1) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + call feedkeys("A\\", '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\\", 'tnix') + call assert_equal([0, 9, 1, 0], getpos('.')) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 17, 1, 0], getpos('.')) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 25, 1, 0], getpos('.')) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 30, 1, 0], getpos('.')) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 30, 1, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 29, 1, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 21, 1, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 13, 1, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 5, 1, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + " is the same as + " is the same as + call cursor(1, 1) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 9, 1, 0], getpos('.')) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 17, 1, 0], getpos('.')) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 25, 1, 0], getpos('.')) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 30, 1, 0], getpos('.')) + call feedkeys("i\\", 'tnix') + call assert_equal([0, 30, 1, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 29, 1, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 21, 1, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 13, 1, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 5, 1, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + set nostartofline + call cursor(30, 11) + norm! zt + call feedkeys("A\\", 'tnix') + call assert_equal([0, 29, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 21, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 13, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + call cursor(1, 1) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 9, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 17, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 25, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 30, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 30, 11, 0], getpos('.')) + " is the same as + " is the same as + call cursor(30, 11) + norm! zt + call feedkeys("A\\", 'tnix') + call assert_equal([0, 29, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 21, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 13, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + call cursor(1, 1) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 9, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 17, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 25, 11, 0], getpos('.')) + call feedkeys("A\\", 'tnix') + call assert_equal([0, 30, 11, 0], getpos('.')) + call feedkeys("A\\", '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\\", 'tnix') + call assert_fails(':Sandbox', 'E48:') + com! Sandbox :sandbox exe "norm! i\" + call assert_fails(':Sandbox', 'E48:') + delcom Sandbox + call assert_equal(['a'], getline(1,'$')) + + " 2) edit with textlock set + fu! DoIt() + call feedkeys("i\\", 'tnix') + endfu + au InsertCharPre :call DoIt() + try + call feedkeys("ix\", '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\", '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\\", 'tnix') + return [] + endif + endfun + set completefunc=Complete + try + call feedkeys("i\\\", '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\\x", 'txin') + call assert_equal(['bc', 'def', 'ghi'], getline(1,'$')) + call cursor(1, 2) + call feedkeys("i\\", 'txin') + call cursor(1, 2) + call feedkeys("i\\", '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\\x", 'txin') + call assert_equal(['ac', 'def', 'ghi'], getline(1,'$')) + call cursor(1, 2) + call feedkeys("i\\", 'txin') + call cursor(1, 2) + call feedkeys("i\\", '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\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() . "/Xlongdir" + let longdirname = dirname . repeat('/' . repeat('d', 255), 4) + try + call mkdir(longdirname, 'pR') + 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 Xnofile " . longfilename + exe "normal iT\" + + bwipe! + exe 'bwipe! ' . longfilename + 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\", '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\", '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 + 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 + 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\" + 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\65\x42\o103 \33a\xfg\o78\" + + exe "normal " . t + call assert_equal("ABC !a\g\8", getline(2)) + + close! +endfunc + +func Test_edit_startinsert() + new + set backspace+=start + call setline(1, 'foobar') + call feedkeys("A\\", 'xt') + call assert_equal('', getline(1)) + + call setline(1, 'foobar') + call feedkeys(":startinsert!\\\", '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\xyz\e", 'xt') + call assert_equal('axyz', getline(1)) + call feedkeys("0:startreplace!\abc\e", 'xt') + call assert_equal('axyzabc', getline(1)) + call setline(1, "a\tb") + call feedkeys("0l:startgreplace\xyz\e", 'xt') + call assert_equal("axyz\tb", getline(1)) + call feedkeys("0i\=execute('startreplace')\12\e", 'xt') + call assert_equal("12axyz\tb", getline(1)) + close! +endfunc + +func Test_edit_noesckeys() + CheckNotGui + new + + " moves cursor when 'esckeys' is set + exe "set t_kl=\OD" + set esckeys + call feedkeys("axyz\ODX", "xt") + call assert_equal("xyXz", getline(1)) + + " exits Insert mode when 'esckeys' is off + set noesckeys + call setline(1, '') + call feedkeys("axyz\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\:invalid\abc\", "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() . "/Xeditdir" + 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([], 'Xinvfile', 'D') + redir => msg + new ++enc=axbyc Xinvfile + redir END + call assert_match('\[NOT converted\]', msg) + close! +endfunc + +" Test for the "charconvert" option +func Test_edit_charconvert() + CheckEnglish + call writefile(['one', 'two'], 'Xccfile', 'D') + + " set 'charconvert' to a non-existing function + set charconvert=NonExitingFunc() + new + let caught_e117 = v:false + try + redir => msg + edit ++enc=axbyc Xccfile + 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 Xccfile + 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 Xccfile + write ++enc=ucase Xccfile1 + call assert_equal(['ONE', 'TWO'], readfile('Xccfile1')) + call delete('Xccfile1') + 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 Xccfile', 'E202:') + call assert_equal([''], getline(1, '$')) + close! + delfunc Cconv3 + set charconvert& +endfunc + +" Test for editing a file without read permission +func Test_edit_file_no_read_perm() + CheckUnix + CheckNotRoot + + call writefile(['one', 'two'], 'Xnrpfile', 'D') + call setfperm('Xnrpfile', '-w-------') + new + redir => msg + edit Xnrpfile + redir END + call assert_equal(1, &readonly) + call assert_equal([''], getline(1, '$')) + call assert_match('\[Permission Denied\]', msg) + close! +endfunc + +" Using :edit without leaving 'insertmode' should not cause Insert mode to be +" re-entered immediately after +func Test_edit_insertmode_ex_edit() + CheckRunVimInTerminal + + let lines =<< trim END + set insertmode noruler + inoremap edit Xfoo + END + call writefile(lines, 'Xtest_edit_insertmode_ex_edit', 'D') + + let buf = RunVimInTerminal('-S Xtest_edit_insertmode_ex_edit', #{rows: 6, wait_for_ruler: 0}) + " Somehow when using valgrind "INSERT" does not show up unless we send + " something to the terminal. + for i in range(30) + if term_getline(buf, 6) =~ 'INSERT' + break + endif + call term_sendkeys(buf, "-") + sleep 100m + endfor + call WaitForAssert({-> assert_match('^-- INSERT --\s*$', term_getline(buf, 6))}) + call term_sendkeys(buf, "\\") + call WaitForAssert({-> assert_notmatch('^-- INSERT --\s*$', term_getline(buf, 6))}) + + " clean up + call StopVimInTerminal(buf) +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\\", 'xt')") + set insertmode& + " unsupported "CTRL-G l" command should beep in insert mode. + call assert_beeps("normal i\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\DEF\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 SaveFirstLine() + call test_override('redraw_flag', 1) + call test_override('char_avail', 1) + let @r = 'sample' + call feedkeys("a\=SaveFirstLine()\", "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\\" + call assert_equal("one\ttwo a ree", getline(1)) + exe "normal! 0wi\" + call assert_equal("one\t a ree", getline(1)) + exe "normal! 0wi\" + 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\", 'xt') + call assert_equal(2, &iminsert) + call feedkeys("i\", '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', 'D') + + let buf = RunVimInTerminal('-S Xtest_edit_shift_bs', #{rows: 3}) + call term_sendkeys(buf, "A\-\") + call TermWait(buf, 50) + call assert_equal('ab-', term_getline(buf, 1)) + + " clean up + call StopVimInTerminal(buf) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab -- cgit v1.2.3