neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

test_edit.vim (73671B)


      1 " Test for edit functions
      2 
      3 if exists("+t_kD")
      4  let &t_kD="[3;*~"
      5 endif
      6 
      7 source check.vim
      8 source screendump.vim
      9 source view_util.vim
     10 
     11 " Needs to come first until the bug in getchar() is
     12 " fixed: https://groups.google.com/d/msg/vim_dev/fXL9yme4H4c/bOR-U6_bAQAJ
     13 func Test_edit_00b()
     14  new
     15  call setline(1, ['abc '])
     16  inoreabbr <buffer> h here some more
     17  call cursor(1, 4)
     18  " <esc> expands the abbreviation and ends insert mode
     19  " call feedkeys(":set im\<cr> h\<c-l>:set noim\<cr>", 'tix')
     20  call feedkeys("i h\<esc>", 'tix')
     21  call assert_equal(['abc here some more '], getline(1,'$'))
     22  iunabbr <buffer> h
     23  bw!
     24 endfunc
     25 
     26 func Test_edit_01()
     27  " set for Travis CI?
     28  "  set nocp noesckeys
     29  new
     30  " 1) empty buffer
     31  call assert_equal([''], getline(1,'$'))
     32  " 2) delete in an empty line
     33  call feedkeys("i\<del>\<esc>", 'tnix')
     34  call assert_equal([''], getline(1,'$'))
     35  %d
     36  " 3) delete one character
     37  call setline(1, 'a')
     38  call feedkeys("i\<del>\<esc>", 'tnix')
     39  call assert_equal([''], getline(1,'$'))
     40  %d
     41  " 4) delete a multibyte character
     42  call setline(1, "\u0401")
     43  call feedkeys("i\<del>\<esc>", 'tnix')
     44  call assert_equal([''], getline(1,'$'))
     45  %d
     46  " 5.1) delete linebreak with 'bs' option containing eol
     47  let _bs=&bs
     48  set bs=eol
     49  call setline(1, ["abc def", "ghi jkl"])
     50  call cursor(1, 1)
     51  call feedkeys("A\<del>\<esc>", 'tnix')
     52  call assert_equal(['abc defghi jkl'], getline(1, 2))
     53  %d
     54  " 5.2) delete linebreak with backspace option w/out eol
     55  set bs=
     56  call setline(1, ["abc def", "ghi jkl"])
     57  call cursor(1, 1)
     58  call feedkeys("A\<del>\<esc>", 'tnix')
     59  call assert_equal(["abc def", "ghi jkl"], getline(1, 2))
     60  let &bs=_bs
     61  bw!
     62 endfunc
     63 
     64 func Test_edit_02()
     65  " Change cursor position in InsertCharPre command
     66  new
     67  call setline(1, 'abc')
     68  call cursor(1, 1)
     69  fu! DoIt(...)
     70    call cursor(1, 4)
     71    if len(a:000)
     72      let v:char=a:1
     73    endif
     74  endfu
     75  au InsertCharPre <buffer> :call DoIt('y')
     76  call feedkeys("ix\<esc>", 'tnix')
     77  call assert_equal(['abcy'], getline(1, '$'))
     78  " Setting <Enter> in InsertCharPre
     79  au! InsertCharPre <buffer> :call DoIt("\n")
     80  call setline(1, 'abc')
     81  call cursor(1, 1)
     82  call feedkeys("ix\<esc>", 'tnix')
     83  call assert_equal(['abc', ''], getline(1, '$'))
     84  %d
     85  au! InsertCharPre
     86  " Change cursor position in InsertEnter command
     87  " 1) when setting v:char, keeps changed cursor position
     88  au! InsertEnter <buffer> :call DoIt('y')
     89  call setline(1, 'abc')
     90  call cursor(1, 1)
     91  call feedkeys("ix\<esc>", 'tnix')
     92  call assert_equal(['abxc'], getline(1, '$'))
     93  " 2) when not setting v:char, restores changed cursor position
     94  au! InsertEnter <buffer> :call DoIt()
     95  call setline(1, 'abc')
     96  call cursor(1, 1)
     97  call feedkeys("ix\<esc>", 'tnix')
     98  call assert_equal(['xabc'], getline(1, '$'))
     99  au! InsertEnter
    100  delfu DoIt
    101  bw!
    102 endfunc
    103 
    104 func Test_edit_03()
    105  " Change cursor after <c-o> command to end of line
    106  new
    107  call setline(1, 'abc')
    108  call cursor(1, 1)
    109  call feedkeys("i\<c-o>$y\<esc>", 'tnix')
    110  call assert_equal(['abcy'], getline(1, '$'))
    111  %d
    112  call setline(1, 'abc')
    113  call cursor(1, 1)
    114  call feedkeys("i\<c-o>80|y\<esc>", 'tnix')
    115  call assert_equal(['abcy'], getline(1, '$'))
    116  %d
    117  call setline(1, 'abc')
    118  call feedkeys("Ad\<c-o>:s/$/efg/\<cr>hij", 'tnix')
    119  call assert_equal(['hijabcdefg'], getline(1, '$'))
    120  bw!
    121 endfunc
    122 
    123 func Test_edit_04()
    124  " test for :stopinsert
    125  new
    126  call setline(1, 'abc')
    127  call cursor(1, 1)
    128  call feedkeys("i\<c-o>:stopinsert\<cr>$", 'tnix')
    129  call feedkeys("aX\<esc>", 'tnix')
    130  call assert_equal(['abcX'], getline(1, '$'))
    131  %d
    132  bw!
    133 endfunc
    134 
    135 func Test_edit_05()
    136  " test for folds being opened
    137  new
    138  call setline(1, ['abcX', 'abcX', 'zzzZ'])
    139  call cursor(1, 1)
    140  set foldmethod=manual foldopen+=insert
    141  " create fold for those two lines
    142  norm! Vjzf
    143  call feedkeys("$ay\<esc>", 'tnix')
    144  call assert_equal(['abcXy', 'abcX', 'zzzZ'], getline(1, '$'))
    145  %d
    146  call setline(1, ['abcX', 'abcX', 'zzzZ'])
    147  call cursor(1, 1)
    148  set foldmethod=manual foldopen-=insert
    149  " create fold for those two lines
    150  norm! Vjzf
    151  call feedkeys("$ay\<esc>", 'tnix')
    152  call assert_equal(['abcXy', 'abcX', 'zzzZ'], getline(1, '$'))
    153  %d
    154  bw!
    155 endfunc
    156 
    157 func Test_edit_06()
    158  " Test in diff mode
    159  if !has("diff") || !executable("diff")
    160    return
    161  endif
    162  new
    163  call setline(1, ['abc', 'xxx', 'yyy'])
    164  vnew
    165  call setline(1, ['abc', 'zzz', 'xxx', 'yyy'])
    166  wincmd p
    167  diffthis
    168  wincmd p
    169  diffthis
    170  wincmd p
    171  call cursor(2, 1)
    172  norm! zt
    173  call feedkeys("Ozzz\<esc>", 'tnix')
    174  call assert_equal(['abc', 'zzz', 'xxx', 'yyy'], getline(1,'$'))
    175  bw!
    176  bw!
    177 endfunc
    178 
    179 func Test_edit_07()
    180  " 1) Test with completion <c-l> when popupmenu is visible
    181  new
    182  call setline(1, 'J')
    183 
    184  func! ListMonths()
    185    call complete(col('.')-1, ['January', 'February', 'March',
    186    \ 'April', 'May', 'June', 'July', 'August', 'September',
    187    \ 'October', 'November', 'December'])
    188    return ''
    189  endfunc
    190  inoremap <buffer> <F5> <C-R>=ListMonths()<CR>
    191 
    192  call feedkeys("A\<f5>\<c-p>". repeat("\<down>", 6)."\<c-l>\<down>\<c-l>\<cr>", 'tx')
    193  call assert_equal(['July'], getline(1,'$'))
    194  " 1) Test completion when InsertCharPre kicks in
    195  %d
    196  call setline(1, 'J')
    197  fu! DoIt()
    198    if v:char=='u'
    199      let v:char='an'
    200    endif
    201  endfu
    202  au InsertCharPre <buffer> :call DoIt()
    203  call feedkeys("A\<f5>\<c-p>u\<C-Y>\<c-l>\<cr>", 'tx')
    204  call assert_equal(["Jan\<c-l>",''], 1->getline('$'))
    205  %d
    206  call setline(1, 'J')
    207  call feedkeys("A\<f5>\<c-p>u\<down>\<c-l>\<cr>", 'tx')
    208  call assert_equal(["January"], 1->getline('$'))
    209 
    210  delfu ListMonths
    211  delfu DoIt
    212  iunmap <buffer> <f5>
    213  bw!
    214 endfunc
    215 
    216 func Test_edit_08()
    217  throw 'skipped: moved to test/functional/legacy/edit_spec.lua'
    218  " reset insertmode from i_ctrl-r_=
    219  let g:bufnr = bufnr('%')
    220  new
    221  call setline(1, ['abc'])
    222  call cursor(1, 4)
    223  call feedkeys(":set im\<cr>ZZZ\<c-r>=setbufvar(g:bufnr,'&im', 0)\<cr>",'tnix')
    224  call assert_equal(['abZZZc'], getline(1,'$'))
    225  call assert_equal([0, 1, 1, 0], getpos('.'))
    226  call assert_false(0, '&im')
    227  bw!
    228  unlet g:bufnr
    229 endfunc
    230 
    231 func Test_edit_09()
    232  " test i_CTRL-\ combinations
    233  new
    234  call setline(1, ['abc', 'def', 'ghi'])
    235  call cursor(1, 1)
    236  " 1) CTRL-\ CTLR-N
    237  " call feedkeys(":set im\<cr>\<c-\>\<c-n>ccABC\<c-l>", 'txin')
    238  call feedkeys("i\<c-\>\<c-n>ccABC\<esc>", 'txin')
    239  call assert_equal(['ABC', 'def', 'ghi'], getline(1,'$'))
    240  call setline(1, ['ABC', 'def', 'ghi'])
    241  " 2) CTRL-\ CTLR-G
    242  " CTRL-\ CTRL-G goes to Insert mode when 'insertmode' is set, but
    243  " 'insertmode' is now removed so skip this test
    244  " call feedkeys("j0\<c-\>\<c-g>ZZZ\<cr>\<esc>", 'txin')
    245  " call assert_equal(['ABC', 'ZZZ', 'def', 'ghi'], getline(1,'$'))
    246  " call feedkeys("I\<c-\>\<c-g>YYY\<c-l>", 'txin')
    247  " call assert_equal(['ABC', 'ZZZ', 'YYYdef', 'ghi'], getline(1,'$'))
    248  " set noinsertmode
    249  " 3) CTRL-\ CTRL-O
    250  call setline(1, ['ABC', 'ZZZ', 'def', 'ghi'])
    251  call cursor(1, 1)
    252  call feedkeys("A\<c-o>ix", 'txin')
    253  call assert_equal(['ABxC', 'ZZZ', 'def', 'ghi'], getline(1,'$'))
    254  call feedkeys("A\<c-\>\<c-o>ix", 'txin')
    255  call assert_equal(['ABxCx', 'ZZZ', 'def', 'ghi'], getline(1,'$'))
    256  " 4) CTRL-\ a (should be inserted literally, not special after <c-\>
    257  call setline(1, ['ABC', 'ZZZ', 'def', 'ghi'])
    258  call cursor(1, 1)
    259  call feedkeys("A\<c-\>a", 'txin')
    260  call assert_equal(["ABC\<c-\>a", 'ZZZ', 'def', 'ghi'], getline(1, '$'))
    261  bw!
    262 endfunc
    263 
    264 func Test_edit_11()
    265  " Test that indenting kicks in
    266  new
    267  set cindent
    268  call setline(1, ['{', '', ''])
    269  call cursor(2, 1)
    270  call feedkeys("i\<c-f>int c;\<esc>", 'tnix')
    271  call cursor(3, 1)
    272  call feedkeys("\<Insert>/* comment */", 'tnix')
    273  call assert_equal(['{', "\<tab>int c;", "/* comment */"], getline(1, '$'))
    274  " added changed cindentkeys slightly
    275  set cindent cinkeys+=*/
    276  call setline(1, ['{', '', ''])
    277  call cursor(2, 1)
    278  call feedkeys("i\<c-f>int c;\<esc>", 'tnix')
    279  call cursor(3, 1)
    280  call feedkeys("i/* comment */", 'tnix')
    281  call assert_equal(['{', "\<tab>int c;", "\<tab>/* comment */"], getline(1, '$'))
    282  set cindent cinkeys+==end
    283  call feedkeys("oend\<cr>\<esc>", 'tnix')
    284  call assert_equal(['{', "\<tab>int c;", "\<tab>/* comment */", "\tend", ''], getline(1, '$'))
    285  set cinkeys-==end
    286  %d
    287  " Use indentexpr instead of cindenting
    288  func! Do_Indent()
    289    if v:lnum == 3
    290      return 3*shiftwidth()
    291    else
    292      return 2*shiftwidth()
    293    endif
    294  endfunc
    295  setl indentexpr=Do_Indent() indentkeys+=*/
    296  call setline(1, ['{', '', ''])
    297  call cursor(2, 1)
    298  call feedkeys("i\<c-f>int c;\<esc>", 'tnix')
    299  call cursor(3, 1)
    300  call feedkeys("i/* comment */", 'tnix')
    301  call assert_equal(['{', "\<tab>\<tab>int c;", "\<tab>\<tab>\<tab>/* comment */"], getline(1, '$'))
    302  set cinkeys&vim indentkeys&vim
    303  set nocindent indentexpr=
    304  delfu Do_Indent
    305  bw!
    306 endfunc
    307 
    308 func Test_edit_11_indentexpr()
    309  " Test that indenting kicks in
    310  new
    311  " Use indentexpr instead of cindenting
    312  func! Do_Indent()
    313    let pline=prevnonblank(v:lnum)
    314    if empty(getline(v:lnum))
    315      if getline(pline) =~ 'if\|then'
    316        return shiftwidth()
    317      else
    318        return 0
    319      endif
    320    else
    321        return 0
    322    endif
    323  endfunc
    324  setl indentexpr=Do_Indent() indentkeys+=0=then,0=fi
    325  call setline(1, ['if [ $this ]'])
    326  call cursor(1, 1)
    327  call feedkeys("othen\<cr>that\<cr>fi", 'tnix')
    328  call assert_equal(['if [ $this ]', "then", "\<tab>that", "fi"], getline(1, '$'))
    329  set cinkeys&vim indentkeys&vim
    330  set nocindent indentexpr=
    331  delfu Do_Indent
    332 
    333  " Using a script-local function
    334  func s:NewIndentExpr()
    335  endfunc
    336  set indentexpr=s:NewIndentExpr()
    337  call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
    338  call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
    339  set indentexpr=<SID>NewIndentExpr()
    340  call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
    341  call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
    342  setlocal indentexpr=
    343  setglobal indentexpr=s:NewIndentExpr()
    344  call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
    345  call assert_equal('', &indentexpr)
    346  new
    347  call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
    348  bw!
    349  setglobal indentexpr=<SID>NewIndentExpr()
    350  call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
    351  call assert_equal('', &indentexpr)
    352  new
    353  call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
    354  bw!
    355  set indentexpr&
    356 
    357  bw!
    358 endfunc
    359 
    360 " Test changing indent in replace mode
    361 func Test_edit_12()
    362  new
    363  call setline(1, ["\tabc", "\tdef"])
    364  call cursor(2, 4)
    365  call feedkeys("R^\<c-d>", 'tnix')
    366  call assert_equal(["\tabc", "def"], getline(1, '$'))
    367  call assert_equal([0, 2, 2, 0], '.'->getpos())
    368  %d
    369  call setline(1, ["\tabc", "\t\tdef"])
    370  call cursor(2, 2)
    371  call feedkeys("R^\<c-d>", 'tnix')
    372  call assert_equal(["\tabc", "def"], getline(1, '$'))
    373  call assert_equal([0, 2, 1, 0], getpos('.'))
    374  %d
    375  call setline(1, ["\tabc", "\t\tdef"])
    376  call cursor(2, 2)
    377  call feedkeys("R\<c-t>", 'tnix')
    378  call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$'))
    379  call assert_equal([0, 2, 2, 0], getpos('.'))
    380  bw!
    381  10vnew
    382  call setline(1, ["\tabc", "\t\tdef"])
    383  call cursor(2, 2)
    384  call feedkeys("R\<c-t>", 'tnix')
    385  call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$'))
    386  call assert_equal([0, 2, 2, 0], getpos('.'))
    387  %d
    388  set sw=4
    389  call setline(1, ["\tabc", "\t\tdef"])
    390  call cursor(2, 2)
    391  call feedkeys("R\<c-t>\<c-t>", 'tnix')
    392  call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$'))
    393  call assert_equal([0, 2, 2, 0], getpos('.'))
    394  %d
    395  call setline(1, ["\tabc", "\t\tdef"])
    396  call cursor(2, 2)
    397  call feedkeys("R\<c-t>\<c-t>", 'tnix')
    398  call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$'))
    399  call assert_equal([0, 2, 2, 0], getpos('.'))
    400  set sw&
    401 
    402  " In replace mode, after hitting enter in a line with tab characters,
    403  " pressing backspace should restore the tab characters.
    404  %d
    405  setlocal autoindent backspace=2
    406  call setline(1, "\tone\t\ttwo")
    407  exe "normal ggRred\<CR>six" .. repeat("\<BS>", 8)
    408  call assert_equal(["\tone\t\ttwo"], getline(1, '$'))
    409  bw!
    410 endfunc
    411 
    412 func Test_edit_13()
    413  " Test smartindenting
    414  new
    415  set smartindent autoindent
    416  call setline(1, ["\tabc"])
    417  call feedkeys("A {\<cr>more\<cr>}\<esc>", 'tnix')
    418  call assert_equal(["\tabc {", "\t\tmore", "\t}"], getline(1, '$'))
    419  set smartindent& autoindent&
    420  bwipe!
    421 
    422  " Test autoindent removing indent of blank line.
    423  new
    424  call setline(1, '    foo bar baz')
    425  set autoindent
    426  exe "normal 0eea\<CR>\<CR>\<Esc>"
    427  call assert_equal("    foo bar", getline(1))
    428  call assert_equal("", getline(2))
    429  call assert_equal("    baz", getline(3))
    430  set autoindent&
    431 
    432  " pressing <C-U> to erase line should keep the indent with 'autoindent'
    433  set backspace=2 autoindent
    434  %d
    435  exe "normal i\tone\<CR>three\<C-U>two"
    436  call assert_equal(["\tone", "\ttwo"], getline(1, '$'))
    437  set backspace& autoindent&
    438 
    439  bwipe!
    440 endfunc
    441 
    442 " Test for autoindent removing indent when insert mode is stopped.  Some parts
    443 " of the code is exercised only when interactive mode is used. So use Vim in a
    444 " terminal.
    445 func Test_autoindent_remove_indent()
    446  CheckRunVimInTerminal
    447  let buf = RunVimInTerminal('-N Xarifile', {'rows': 6, 'cols' : 20})
    448  call TermWait(buf)
    449  call term_sendkeys(buf, ":set autoindent\n")
    450  " leaving insert mode in a new line with indent added by autoindent, should
    451  " remove the indent.
    452  call term_sendkeys(buf, "i\<Tab>foo\<CR>\<Esc>")
    453  " Need to delay for some time, otherwise the code in getchar.c will not be
    454  " exercised.
    455  call TermWait(buf, 50)
    456  " when a line is wrapped and the cursor is at the start of the second line,
    457  " leaving insert mode, should move the cursor back to the first line.
    458  call term_sendkeys(buf, "o" .. repeat('x', 20) .. "\<Esc>")
    459  " Need to delay for some time, otherwise the code in getchar.c will not be
    460  " exercised.
    461  call TermWait(buf, 50)
    462  call term_sendkeys(buf, ":w\n")
    463  call TermWait(buf)
    464  call StopVimInTerminal(buf)
    465  call assert_equal(["\tfoo", '', repeat('x', 20)], readfile('Xarifile'))
    466  call delete('Xarifile')
    467 endfunc
    468 
    469 " Test for autoindent removing indent when insert mode is stopped and
    470 " autocomplete is enabled.  Some parts of the code is exercised only when
    471 " interactive mode is used. So use Vim in a terminal.
    472 func Test_autoindent_remove_indent_with_autocomplete()
    473  CheckRunVimInTerminal
    474  let buf = RunVimInTerminal('-N Xarifile', {'rows': 6, 'cols' : 20})
    475  call TermWait(buf)
    476  call term_sendkeys(buf, ":set autoindent autocomplete\n")
    477  " leaving insert mode in a new line with indent added by autoindent, should
    478  " remove the indent.
    479  call term_sendkeys(buf, "i\<Tab>foo\<CR>\<Esc>")
    480  " Need to delay for some time, otherwise the code in getchar.c will not be
    481  " exercised.
    482  call TermWait(buf, 50)
    483  " when a line is wrapped and the cursor is at the start of the second line,
    484  " leaving insert mode, should move the cursor back to the first line.
    485  call term_sendkeys(buf, "o" .. repeat('x', 20) .. "\<Esc>")
    486  " Need to delay for some time, otherwise the code in getchar.c will not be
    487  " exercised.
    488  call TermWait(buf, 50)
    489  call term_sendkeys(buf, ":w\n")
    490  call TermWait(buf)
    491  call StopVimInTerminal(buf)
    492  call assert_equal(["\tfoo", '', repeat('x', 20)], readfile('Xarifile'))
    493  call delete('Xarifile')
    494 endfunc
    495 
    496 func Test_edit_esc_after_CR_autoindent()
    497  new
    498  setlocal autoindent
    499  autocmd InsertLeavePre * let g:prev_cursor = getpos('.')
    500 
    501  call setline(1, 'foobar')
    502  exe "normal! $hi\<CR>\<Esc>"
    503  call assert_equal(['foob', 'ar'], getline(1, '$'))
    504  call assert_equal([0, 2, 1, 0], getpos('.'))
    505  call assert_equal([0, 2, 1, 0], getpos("'^"))
    506  call assert_equal([0, 2, 1, 0], g:prev_cursor)
    507  %d
    508 
    509  call setline(1, 'foobar')
    510  exe "normal! $i\<CR>\<Esc>"
    511  call assert_equal(['fooba', 'r'], getline(1, '$'))
    512  call assert_equal([0, 2, 1, 0], getpos('.'))
    513  call assert_equal([0, 2, 1, 0], getpos("'^"))
    514  call assert_equal([0, 2, 1, 0], g:prev_cursor)
    515  %d
    516 
    517  call setline(1, 'foobar')
    518  exe "normal! A\<CR>\<Esc>"
    519  call assert_equal(['foobar', ''], getline(1, '$'))
    520  call assert_equal([0, 2, 1, 0], getpos('.'))
    521  call assert_equal([0, 2, 1, 0], getpos("'^"))
    522  call assert_equal([0, 2, 1, 0], g:prev_cursor)
    523  %d
    524 
    525  call setline(1, '  foobar')
    526  exe "normal! $hi\<CR>\<Esc>"
    527  call assert_equal(['  foob', '  ar'], getline(1, '$'))
    528  call assert_equal([0, 2, 2, 0], getpos('.'))
    529  call assert_equal([0, 2, 3, 0], getpos("'^"))
    530  call assert_equal([0, 2, 3, 0], g:prev_cursor)
    531  %d
    532 
    533  call setline(1, '  foobar')
    534  exe "normal! $i\<CR>\<Esc>"
    535  call assert_equal(['  fooba', '  r'], getline(1, '$'))
    536  call assert_equal([0, 2, 2, 0], getpos('.'))
    537  call assert_equal([0, 2, 3, 0], getpos("'^"))
    538  call assert_equal([0, 2, 3, 0], g:prev_cursor)
    539  %d
    540 
    541  call setline(1, '  foobar')
    542  exe "normal! A\<CR>\<Esc>"
    543  call assert_equal(['  foobar', ''], getline(1, '$'))
    544  call assert_equal([0, 2, 1, 0], getpos('.'))
    545  call assert_equal([0, 2, 1, 0], getpos("'^"))
    546  call assert_equal([0, 2, 1, 0], g:prev_cursor)
    547  %d
    548 
    549  autocmd! InsertLeavePre
    550  unlet g:prev_cursor
    551  bwipe!
    552 endfunc
    553 
    554 func Test_edit_CR()
    555  " Test for <CR> in insert mode
    556  " basically only in quickfix mode it's tested, the rest
    557  " has been taken care of by other tests
    558  CheckFeature quickfix
    559  botright new
    560  call writefile(range(1, 10), 'Xqflist.txt', 'D')
    561  call setqflist([{'filename': 'Xqflist.txt', 'lnum': 2}])
    562  copen
    563  set modifiable
    564  call feedkeys("A\<cr>", 'tnix')
    565  call assert_equal('Xqflist.txt', bufname(''))
    566  call assert_equal(2, line('.'))
    567  cclose
    568  botright new
    569  call setloclist(0, [{'filename': 'Xqflist.txt', 'lnum': 10}])
    570  lopen
    571  set modifiable
    572  call feedkeys("A\<cr>", 'tnix')
    573  call assert_equal('Xqflist.txt', bufname(''))
    574  call assert_equal(10, line('.'))
    575  call feedkeys("A\<Enter>", 'tnix')
    576  call feedkeys("A\<kEnter>", 'tnix')
    577  call feedkeys("A\n", 'tnix')
    578  call feedkeys("A\r", 'tnix')
    579  call assert_equal(map(range(1, 10), 'string(v:val)') + ['', '', '', ''], getline(1, '$'))
    580 
    581  bw!
    582  lclose
    583 endfunc
    584 
    585 func Test_edit_CTRL_()
    586  CheckFeature rightleft
    587  " disabled for Windows builds, why?
    588  CheckNotMSWindows
    589  let _encoding=&encoding
    590  set encoding=utf-8
    591  " Test for CTRL-_
    592  new
    593  call setline(1, ['abc'])
    594  call cursor(1, 1)
    595  call feedkeys("i\<c-_>xyz\<esc>", 'tnix')
    596  call assert_equal(["\<C-_>xyzabc"], getline(1, '$'))
    597  call assert_false(&revins)
    598  set ari
    599  call setline(1, ['abc'])
    600  call cursor(1, 1)
    601  call feedkeys("i\<c-_>xyz\<esc>", 'tnix')
    602  " call assert_equal(["æèñabc"], getline(1, '$'))
    603  call assert_equal(["zyxabc"], getline(1, '$'))
    604  call assert_true(&revins)
    605  call setline(1, ['abc'])
    606  call cursor(1, 1)
    607  call feedkeys("i\<c-_>xyz\<esc>", 'tnix')
    608  call assert_equal(["xyzabc"], getline(1, '$'))
    609  call assert_false(&revins)
    610  set noari
    611  let &encoding=_encoding
    612  bw!
    613 endfunc
    614 
    615 " needs to come first, to have the @. register empty
    616 func Test_edit_00a_CTRL_A()
    617  " Test pressing CTRL-A
    618  new
    619  call setline(1, repeat([''], 5))
    620  call cursor(1, 1)
    621  try
    622    call feedkeys("A\<NUL>", 'tnix')
    623  catch /^Vim\%((\a\+)\)\=:E29/
    624    call assert_true(1, 'E29 error caught')
    625  endtry
    626  call cursor(1, 1)
    627  call feedkeys("Afoobar \<esc>", 'tnix')
    628  call cursor(2, 1)
    629  call feedkeys("A\<c-a>more\<esc>", 'tnix')
    630  call cursor(3, 1)
    631  call feedkeys("A\<NUL>and more\<esc>", 'tnix')
    632  call assert_equal(['foobar ', 'foobar more', 'foobar morend more', '', ''], getline(1, '$'))
    633  bw!
    634 endfunc
    635 
    636 func Test_edit_CTRL_EY()
    637  " Ctrl-E/ Ctrl-Y in insert mode completion to scroll
    638  10new
    639  call setline(1, range(1, 100))
    640  call cursor(30, 1)
    641  norm! z.
    642  call feedkeys("A\<c-x>\<c-e>\<c-e>\<c-e>\<c-e>\<c-e>", 'tnix')
    643  call assert_equal(30, winsaveview()['topline'])
    644  call assert_equal([0, 30, 2, 0], getpos('.'))
    645  call feedkeys("A\<c-x>\<c-e>\<c-e>\<c-e>\<c-e>\<c-e>", 'tnix')
    646  call feedkeys("A\<c-x>".repeat("\<c-y>", 10), 'tnix')
    647  call assert_equal(21, winsaveview()['topline'])
    648  call assert_equal([0, 30, 2, 0], getpos('.'))
    649  bw!
    650 endfunc
    651 
    652 func Test_edit_CTRL_G()
    653  new
    654  call setline(1, ['foobar', 'foobar', 'foobar'])
    655  call cursor(2, 4)
    656  call feedkeys("ioooooooo\<c-g>k\<c-r>.\<esc>", 'tnix')
    657  call assert_equal(['foooooooooobar', 'foooooooooobar', 'foobar'], getline(1, '$'))
    658  call assert_equal([0, 1, 11, 0], getpos('.'))
    659  call feedkeys("i\<c-g>k\<esc>", 'tnix')
    660  call assert_equal([0, 1, 10, 0], getpos('.'))
    661  call cursor(2, 4)
    662  call feedkeys("i\<c-g>jzzzz\<esc>", 'tnix')
    663  call assert_equal(['foooooooooobar', 'foooooooooobar', 'foozzzzbar'], getline(1, '$'))
    664  call assert_equal([0, 3, 7, 0], getpos('.'))
    665  call feedkeys("i\<c-g>j\<esc>", 'tnix')
    666  call assert_equal([0, 3, 6, 0], getpos('.'))
    667  call assert_nobeep("normal! i\<c-g>\<esc>")
    668  bw!
    669 endfunc
    670 
    671 func Test_edit_CTRL_I()
    672  " Tab in completion mode
    673  let path=expand("%:p:h")
    674  new
    675  call setline(1, [path. "/", ''])
    676  call feedkeys("Arunt\<c-x>\<c-f>\<tab>\<cr>\<esc>", 'tnix')
    677  call assert_match('runtest\.vim', getline(1))
    678  %d
    679  call writefile(['one', 'two', 'three'], 'Xinclude.txt', 'D')
    680  let include='#include Xinclude.txt'
    681  call setline(1, [include, ''])
    682  call cursor(2, 1)
    683  call feedkeys("A\<c-x>\<tab>\<cr>\<esc>", 'tnix')
    684  call assert_equal([include, 'one', ''], getline(1, '$'))
    685  call feedkeys("2ggC\<c-x>\<tab>\<down>\<cr>\<esc>", 'tnix')
    686  call assert_equal([include, 'two', ''], getline(1, '$'))
    687  call feedkeys("2ggC\<c-x>\<tab>\<down>\<down>\<cr>\<esc>", 'tnix')
    688  call assert_equal([include, 'three', ''], getline(1, '$'))
    689  call feedkeys("2ggC\<c-x>\<tab>\<down>\<down>\<down>\<cr>\<esc>", 'tnix')
    690  call assert_equal([include, '', ''], getline(1, '$'))
    691  bw!
    692 endfunc
    693 
    694 func Test_edit_CTRL_K()
    695  " Test pressing CTRL-K (basically only dictionary completion and digraphs
    696  " the rest is already covered
    697  call writefile(['A', 'AA', 'AAA', 'AAAA'], 'Xdictionary.txt', 'D')
    698  set dictionary=Xdictionary.txt
    699  new
    700  call setline(1, 'A')
    701  call cursor(1, 1)
    702  call feedkeys("A\<c-x>\<c-k>\<cr>\<esc>", 'tnix')
    703  call assert_equal(['AA', ''], getline(1, '$'))
    704  %d
    705  call setline(1, 'A')
    706  call cursor(1, 1)
    707  call feedkeys("A\<c-x>\<c-k>\<down>\<cr>\<esc>", 'tnix')
    708  call assert_equal(['AAA'], getline(1, '$'))
    709  %d
    710  call setline(1, 'A')
    711  call cursor(1, 1)
    712  call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<cr>\<esc>", 'tnix')
    713  call assert_equal(['AAAA'], getline(1, '$'))
    714  %d
    715  call setline(1, 'A')
    716  call cursor(1, 1)
    717  call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<down>\<cr>\<esc>", 'tnix')
    718  call assert_equal(['A'], getline(1, '$'))
    719  %d
    720  call setline(1, 'A')
    721  call cursor(1, 1)
    722  call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<down>\<down>\<cr>\<esc>", 'tnix')
    723  call assert_equal(['AA'], getline(1, '$'))
    724 
    725  " press an unexpected key after dictionary completion
    726  %d
    727  call setline(1, 'A')
    728  call cursor(1, 1)
    729  call feedkeys("A\<c-x>\<c-k>\<c-]>\<cr>\<esc>", 'tnix')
    730  call assert_equal(['AA', ''], getline(1, '$'))
    731  %d
    732  call setline(1, 'A')
    733  call cursor(1, 1)
    734  call feedkeys("A\<c-x>\<c-k>\<c-s>\<cr>\<esc>", 'tnix')
    735  call assert_equal(["AA\<c-s>", ''], getline(1, '$'))
    736  %d
    737  call setline(1, 'A')
    738  call cursor(1, 1)
    739  call feedkeys("A\<c-x>\<c-k>\<c-f>\<cr>\<esc>", 'tnix')
    740  call assert_equal(["AA\<c-f>", ''], getline(1, '$'))
    741 
    742  set dictionary=
    743  %d
    744  call setline(1, 'A')
    745  call cursor(1, 1)
    746  try
    747    call feedkeys("A\<c-x>\<c-k>\<esc>", 'tnix')
    748  catch
    749  endtry
    750 
    751  call Ntest_override("char_avail", 1)
    752  set showcmd
    753  %d
    754  call feedkeys("A\<c-k>a:\<esc>", 'tnix')
    755  call assert_equal(['ä'], getline(1, '$'))
    756  call Ntest_override("char_avail", 0)
    757  set noshowcmd
    758 
    759  bw!
    760 endfunc
    761 
    762 func Test_edit_CTRL_L()
    763  " Test Ctrl-X Ctrl-L (line completion)
    764  new
    765  set complete=.
    766  call setline(1, ['one', 'two', 'three', '', '', '', ''])
    767  call cursor(4, 1)
    768  call feedkeys("A\<c-x>\<c-l>\<esc>", 'tnix')
    769  call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$'))
    770  call feedkeys("cct\<c-x>\<c-l>\<c-n>\<esc>", 'tnix')
    771  call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$'))
    772  call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<esc>", 'tnix')
    773  call assert_equal(['one', 'two', 'three', 'two', '', '', ''], getline(1, '$'))
    774  call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<c-n>\<esc>", 'tnix')
    775  call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$'))
    776  call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<c-n>\<c-n>\<esc>", 'tnix')
    777  call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$'))
    778  call feedkeys("cct\<c-x>\<c-l>\<c-p>\<esc>", 'tnix')
    779  call assert_equal(['one', 'two', 'three', 'two', '', '', ''], getline(1, '$'))
    780  call feedkeys("cct\<c-x>\<c-l>\<c-p>\<c-p>\<esc>", 'tnix')
    781  call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$'))
    782  call feedkeys("cct\<c-x>\<c-l>\<c-p>\<c-p>\<c-p>\<esc>", 'tnix')
    783  call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$'))
    784  set complete=
    785  call cursor(5, 1)
    786  call feedkeys("A\<c-x>\<c-l>\<c-p>\<c-n>\<esc>", 'tnix')
    787  call assert_equal(['one', 'two', 'three', 'three', "\<c-l>\<c-p>\<c-n>", '', ''], getline(1, '$'))
    788  set complete&
    789  %d
    790  if has("conceal") && has("syntax")
    791    call setline(1, ['foo', 'bar', 'foobar'])
    792    call Ntest_override("char_avail", 1)
    793    set conceallevel=2 concealcursor=n
    794    syn on
    795    syn match ErrorMsg "^bar"
    796    call matchadd("Conceal", 'oo', 10, -1, {'conceal': 'X'})
    797    func! DoIt()
    798      let g:change=1
    799    endfunc
    800    au! TextChangedI <buffer> :call DoIt()
    801 
    802    call cursor(2, 1)
    803    call assert_false(exists("g:change"))
    804    call feedkeys("A \<esc>", 'tnix')
    805    call assert_equal(['foo', 'bar ', 'foobar'], getline(1, '$'))
    806    call assert_equal(1, g:change)
    807 
    808    call Ntest_override("char_avail", 0)
    809    call clearmatches()
    810    syn off
    811    au! TextChangedI
    812    delfu DoIt
    813    unlet! g:change
    814  endif
    815  bw!
    816 endfunc
    817 
    818 func Test_edit_CTRL_N()
    819  " Check keyword completion
    820  " for e in ['latin1', 'utf-8']
    821  for e in ['utf-8']
    822    exe 'set encoding=' .. e
    823    new
    824    set complete=.
    825    call setline(1, ['INFER', 'loWER', '', '', ])
    826    call cursor(3, 1)
    827    call feedkeys("Ai\<c-n>\<cr>\<esc>", "tnix")
    828    call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix')
    829    call assert_equal(['INFER', 'loWER', 'i', 'LO', '', ''], getline(1, '$'), e)
    830    %d
    831    call setline(1, ['INFER', 'loWER', '', '', ])
    832    call cursor(3, 1)
    833    set ignorecase infercase
    834    call feedkeys("Ii\<c-n>\<cr>\<esc>", "tnix")
    835    call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix')
    836    call assert_equal(['INFER', 'loWER', 'infer', 'LOWER', '', ''], getline(1, '$'), e)
    837    set noignorecase noinfercase
    838    %d
    839    call setline(1, ['one word', 'two word'])
    840    exe "normal! Goo\<C-P>\<C-X>\<C-P>"
    841    call assert_equal('one word', getline(3))
    842    %d
    843    set complete&
    844    bw!
    845  endfor
    846 endfunc
    847 
    848 func Test_edit_CTRL_O()
    849  " Check for CTRL-O in insert mode
    850  new
    851  inoreabbr <buffer> h here some more
    852  call setline(1, ['abc', 'def'])
    853  call cursor(1, 1)
    854  " Ctrl-O after an abbreviation
    855  exe "norm A h\<c-o>:set nu\<cr> text"
    856  call assert_equal(['abc here some more text', 'def'], getline(1, '$'))
    857  call assert_true(&nu)
    858  set nonu
    859  iunabbr <buffer> h
    860  " Ctrl-O at end of line with 've'=onemore
    861  call cursor(1, 1)
    862  call feedkeys("A\<c-o>:let g:a=getpos('.')\<cr>\<esc>", 'tnix')
    863  call assert_equal([0, 1, 23, 0], g:a)
    864  call cursor(1, 1)
    865  set ve=onemore
    866  call feedkeys("A\<c-o>:let g:a=getpos('.')\<cr>\<esc>", 'tnix')
    867  call assert_equal([0, 1, 24, 0], g:a)
    868  set ve=
    869  unlet! g:a
    870  bw!
    871 endfunc
    872 
    873 func Test_edit_CTRL_R()
    874  " Insert Register
    875  new
    876  " call test_override("ALL", 1)
    877  set showcmd
    878  call feedkeys("AFOOBAR eins zwei\<esc>", 'tnix')
    879  call feedkeys("O\<c-r>.", 'tnix')
    880  call feedkeys("O\<c-r>=10*500\<cr>\<esc>", 'tnix')
    881  call feedkeys("O\<c-r>=getreg('=', 1)\<cr>\<esc>", 'tnix')
    882  call assert_equal(["getreg('=', 1)", '5000', "FOOBAR eins zwei", "FOOBAR eins zwei"], getline(1, '$'))
    883  " call test_override("ALL", 0)
    884  set noshowcmd
    885  bw!
    886 endfunc
    887 
    888 func Test_edit_CTRL_S()
    889  " Test pressing CTRL-S (basically only spellfile completion)
    890  " the rest is already covered
    891  new
    892  if !has("spell")
    893    call setline(1, 'vim')
    894    call feedkeys("A\<c-x>ss\<cr>\<esc>", 'tnix')
    895    call assert_equal(['vims', ''], getline(1, '$'))
    896    bw!
    897    return
    898  endif
    899  call setline(1, 'vim')
    900  " spell option not yet set
    901  try
    902    call feedkeys("A\<c-x>\<c-s>\<cr>\<esc>", 'tnix')
    903  catch /^Vim\%((\a\+)\)\=:E756/
    904    call assert_true(1, 'error caught')
    905  endtry
    906  call assert_equal(['vim', ''], getline(1, '$'))
    907  %d
    908  setl spell spelllang=en
    909  call setline(1, 'vim')
    910  call cursor(1, 1)
    911  call feedkeys("A\<c-x>\<c-s>\<cr>\<esc>", 'tnix')
    912  call assert_equal(['Vim', ''], getline(1, '$'))
    913  %d
    914  call setline(1, 'vim')
    915  call cursor(1, 1)
    916  call feedkeys("A\<c-x>\<c-s>\<down>\<cr>\<esc>", 'tnix')
    917  call assert_equal(['Aim'], getline(1, '$'))
    918  %d
    919  call setline(1, 'vim')
    920  call cursor(1, 1)
    921  call feedkeys("A\<c-x>\<c-s>\<c-p>\<cr>\<esc>", 'tnix')
    922  call assert_equal(['vim', ''], getline(1, '$'))
    923  %d
    924  " empty buffer
    925  call cursor(1, 1)
    926  call feedkeys("A\<c-x>\<c-s>\<c-p>\<cr>\<esc>", 'tnix')
    927  call assert_equal(['', ''], getline(1, '$'))
    928  setl nospell
    929  bw!
    930 endfunc
    931 
    932 func Edit_CTRL_T()
    933  " Check for CTRL-T and CTRL-X CTRL-T in insert mode
    934  " 1) increase indent
    935  new
    936  call setline(1, "abc")
    937  call cursor(1, 1)
    938  call feedkeys("A\<c-t>xyz", 'tnix')
    939  call assert_equal(["\<tab>abcxyz"], getline(1, '$'))
    940  " 2) also when paste option is set
    941  set paste
    942  call setline(1, "abc")
    943  call cursor(1, 1)
    944  call feedkeys("A\<c-t>xyz", 'tnix')
    945  call assert_equal(["\<tab>abcxyz"], getline(1, '$'))
    946  set nopaste
    947  " CTRL-X CTRL-T (thesaurus complete)
    948  call writefile(['angry furious mad enraged'], 'Xthesaurus', 'D')
    949  set thesaurus=Xthesaurus
    950  call setline(1, 'mad')
    951  call cursor(1, 1)
    952  call feedkeys("A\<c-x>\<c-t>\<cr>\<esc>", 'tnix')
    953  call assert_equal(['mad', ''], getline(1, '$'))
    954  %d
    955  call setline(1, 'mad')
    956  call cursor(1, 1)
    957  call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix')
    958  call assert_equal(['angry', ''], getline(1, '$'))
    959  %d
    960  call setline(1, 'mad')
    961  call cursor(1, 1)
    962  call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<cr>\<esc>", 'tnix')
    963  call assert_equal(['furious', ''], getline(1, '$'))
    964  %d
    965  call setline(1, 'mad')
    966  call cursor(1, 1)
    967  call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix')
    968  call assert_equal(['enraged', ''], getline(1, '$'))
    969  %d
    970  call setline(1, 'mad')
    971  call cursor(1, 1)
    972  call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix')
    973  call assert_equal(['mad', ''], getline(1, '$'))
    974  %d
    975  call setline(1, 'mad')
    976  call cursor(1, 1)
    977  call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix')
    978  call assert_equal(['mad', ''], getline(1, '$'))
    979  " Using <c-p> <c-n> when 'complete' is empty
    980  set complete=
    981  %d
    982  call setline(1, 'mad')
    983  call cursor(1, 1)
    984  call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix')
    985  call assert_equal(['angry', ''], getline(1, '$'))
    986  %d
    987  call setline(1, 'mad')
    988  call cursor(1, 1)
    989  call feedkeys("A\<c-x>\<c-t>\<c-p>\<cr>\<esc>", 'tnix')
    990  call assert_equal(['mad', ''], getline(1, '$'))
    991  set complete&
    992 
    993  set thesaurus=
    994  %d
    995  call setline(1, 'mad')
    996  call cursor(1, 1)
    997  try
    998    call feedkeys("A\<c-x>\<c-t>\<esc>", 'tnix')
    999  catch
   1000  endtry
   1001  call assert_equal(['mad'], getline(1, '$'))
   1002  bw!
   1003 endfunc
   1004 
   1005 func Test_edit_CTRL_T()
   1006  call Edit_CTRL_T()
   1007  set completeopt+=fuzzy
   1008  call Edit_CTRL_T()
   1009  set completeopt&
   1010 endfunc
   1011 
   1012 func Test_edit_CTRL_T_longest()
   1013  " CTRL-X CTRL-T (thesaurus complete) with 'longest' should not insert
   1014  " longest match
   1015  set completeopt+=longest
   1016  new
   1017  call writefile(['angry furious mad madder maddest'], 'Xthesaurus', 'D')
   1018  set thesaurus=Xthesaurus
   1019  call setline(1, 'mad')
   1020  call cursor(1, 1)
   1021  call feedkeys("A\<c-x>\<c-t>\<cr>\<esc>", 'tnix')
   1022  call assert_equal(['mad', ''], getline(1, '$'))
   1023  bw!
   1024  set thesaurus=
   1025  set completeopt&
   1026 endfunc
   1027 
   1028 " Test thesaurus completion with different encodings
   1029 func Test_thesaurus_complete_with_encoding()
   1030  call writefile(['angry furious mad enraged'], 'Xthesaurus', 'D')
   1031  set thesaurus=Xthesaurus
   1032  " for e in ['latin1', 'utf-8']
   1033  for e in ['utf-8']
   1034    exe 'set encoding=' .. e
   1035    new
   1036    call setline(1, 'mad')
   1037    call cursor(1, 1)
   1038    call feedkeys("A\<c-x>\<c-t>\<cr>\<esc>", 'tnix')
   1039    call assert_equal(['mad', ''], getline(1, '$'))
   1040    bw!
   1041  endfor
   1042  set thesaurus=
   1043 endfunc
   1044 
   1045 " Test 'thesaurusfunc'
   1046 func MyThesaurus(findstart, base)
   1047  let mythesaurus = [
   1048        \ #{word: "happy",
   1049        \   synonyms: "cheerful,blissful,flying high,looking good,peppy"},
   1050        \ #{word: "kind",
   1051        \   synonyms: "amiable,bleeding-heart,heart in right place"}]
   1052  if a:findstart
   1053    " locate the start of the word
   1054    let line = getline('.')
   1055    let start = col('.') - 1
   1056    while start > 0 && line[start - 1] =~ '\a'
   1057      let start -= 1
   1058    endwhile
   1059    return start
   1060  else
   1061    " find strings matching with "a:base"
   1062    let res = []
   1063    for w in mythesaurus
   1064      if w.word =~ '^' . a:base
   1065        call add(res, w.word)
   1066        call extend(res, split(w.synonyms, ","))
   1067      endif
   1068    endfor
   1069    return res
   1070  endif
   1071 endfunc
   1072 
   1073 func Test_thesaurus_func()
   1074  new
   1075  set thesaurus=notused
   1076  set thesaurusfunc=NotUsed
   1077  setlocal thesaurusfunc=MyThesaurus
   1078  call setline(1, "an ki")
   1079  call cursor(1, 1)
   1080  call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix')
   1081  call assert_equal(['an amiable', ''], getline(1, '$'))
   1082 
   1083  setlocal thesaurusfunc=NonExistingFunc
   1084  call assert_fails("normal $a\<C-X>\<C-T>", 'E117:')
   1085 
   1086  setlocal thesaurusfunc=
   1087  set thesaurusfunc=NonExistingFunc
   1088  call assert_fails("normal $a\<C-X>\<C-T>", 'E117:')
   1089  %bw!
   1090 
   1091  set thesaurusfunc=
   1092  set thesaurus=
   1093 endfunc
   1094 
   1095 func Test_edit_CTRL_U()
   1096  " Test 'completefunc'
   1097  new
   1098  " -1, -2 and -3 are special return values
   1099  let g:special=0
   1100  fun! CompleteMonths(findstart, base)
   1101    if a:findstart
   1102      " locate the start of the word
   1103      return g:special
   1104    else
   1105      " find months matching with "a:base"
   1106      let res = []
   1107      for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")
   1108        if m =~ '^\c'.a:base
   1109          call add(res, {'word': m, 'abbr': m.' Month', 'icase': 0})
   1110        endif
   1111      endfor
   1112      return {'words': res, 'refresh': 'always'}
   1113    endif
   1114  endfun
   1115  set completefunc=CompleteMonths
   1116  call setline(1, ['', ''])
   1117  call cursor(1, 1)
   1118  call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix')
   1119  call assert_equal(['X', '', ''], getline(1, '$'))
   1120  %d
   1121  let g:special=-1
   1122  call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix')
   1123  call assert_equal(['XJan', ''], getline(1, '$'))
   1124  %d
   1125  let g:special=-2
   1126  call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix')
   1127  call assert_equal(['X', ''], getline(1, '$'))
   1128  %d
   1129  let g:special=-3
   1130  call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix')
   1131  call assert_equal(['X', ''], getline(1, '$'))
   1132  %d
   1133  let g:special=0
   1134  call feedkeys("AM\<c-x>\<c-u>\<cr>\<esc>", 'tnix')
   1135  call assert_equal(['Mar', ''], getline(1, '$'))
   1136  %d
   1137  call feedkeys("AM\<c-x>\<c-u>\<c-n>\<cr>\<esc>", 'tnix')
   1138  call assert_equal(['May', ''], getline(1, '$'))
   1139  %d
   1140  call feedkeys("AM\<c-x>\<c-u>\<c-n>\<c-n>\<cr>\<esc>", 'tnix')
   1141  call assert_equal(['M', ''], getline(1, '$'))
   1142  delfu CompleteMonths
   1143  %d
   1144  try
   1145    call feedkeys("A\<c-x>\<c-u>", 'tnix')
   1146    call assert_fails(1, 'unknown completion function')
   1147  catch /^Vim\%((\a\+)\)\=:E117/
   1148    call assert_true(1, 'E117 error caught')
   1149  endtry
   1150  set completefunc=
   1151  bw!
   1152 endfunc
   1153 
   1154 func Test_edit_completefunc_delete()
   1155  func CompleteFunc(findstart, base)
   1156    if a:findstart == 1
   1157      return col('.') - 1
   1158    endif
   1159    normal dd
   1160    return ['a', 'b']
   1161  endfunc
   1162  new
   1163  set completefunc=CompleteFunc
   1164  call setline(1, ['', 'abcd', ''])
   1165  2d
   1166  call assert_fails("normal 2G$a\<C-X>\<C-U>", 'E565:')
   1167  bwipe!
   1168 endfunc
   1169 
   1170 func Test_edit_CTRL_Z()
   1171  " Ctrl-Z when insertmode is not set inserts it literally
   1172  new
   1173  call setline(1, 'abc')
   1174  call feedkeys("A\<c-z>\<esc>", 'tnix')
   1175  call assert_equal(["abc\<c-z>"], getline(1,'$'))
   1176  bw!
   1177  " TODO: How to Test Ctrl-Z in insert mode, e.g. suspend?
   1178 endfunc
   1179 
   1180 func Test_edit_DROP()
   1181  if !has("dnd")
   1182    return
   1183  endif
   1184  new
   1185  call setline(1, ['abc def ghi'])
   1186  call cursor(1, 1)
   1187  try
   1188    call feedkeys("i\<Drop>\<Esc>", 'tnix')
   1189    call assert_fails(1, 'Invalid register name')
   1190  catch /^Vim\%((\a\+)\)\=:E353/
   1191    call assert_true(1, 'error caught')
   1192  endtry
   1193  bw!
   1194 endfunc
   1195 
   1196 func Test_edit_CTRL_V()
   1197  new
   1198  call setline(1, ['abc'])
   1199  call cursor(2, 1)
   1200 
   1201  " force some redraws
   1202  set showmode showcmd
   1203  call Ntest_override('char_avail', 1)
   1204 
   1205  call feedkeys("A\<c-v>\<c-n>\<c-v>\<c-l>\<c-v>\<c-b>\<esc>", 'tnix')
   1206  call assert_equal(["abc\x0e\x0c\x02"], getline(1, '$'))
   1207 
   1208  if has("rightleft") && exists("+rl")
   1209    set rl
   1210    call setline(1, ['abc'])
   1211    call cursor(2, 1)
   1212    call feedkeys("A\<c-v>\<c-n>\<c-v>\<c-l>\<c-v>\<c-b>\<esc>", 'tnix')
   1213    call assert_equal(["abc\x0e\x0c\x02"], getline(1, '$'))
   1214    set norl
   1215  endif
   1216 
   1217  set noshowmode showcmd
   1218  call Ntest_override('char_avail', 0)
   1219 
   1220  " No modifiers should be applied to the char typed using i_CTRL-V_digit.
   1221  call feedkeys(":append\<CR>\<C-V>76c\<C-V>76\<C-F2>\<C-V>u3c0j\<C-V>u3c0\<M-F3>\<CR>.\<CR>", 'tnix')
   1222  call assert_equal('LcL<C-F2>πjπ<M-F3>', getline(2))
   1223 
   1224  if has('osx')
   1225    " A char with a modifier should not be a valid char for i_CTRL-V_digit.
   1226    call feedkeys("o\<C-V>\<D-j>\<C-V>\<D-1>\<C-V>\<D-o>\<C-V>\<D-x>\<C-V>\<D-u>", 'tnix')
   1227    call assert_equal('<D-j><D-1><D-o><D-x><D-u>', getline(3))
   1228  endif
   1229 
   1230  bw!
   1231 endfunc
   1232 
   1233 func Test_edit_F1()
   1234  CheckFeature quickfix
   1235 
   1236  " Pressing <f1>
   1237  new
   1238  " call feedkeys(":set im\<cr>\<f1>\<c-l>", 'tnix')
   1239  call feedkeys("i\<f1>\<esc>", 'tnix')
   1240  set noinsertmode
   1241  call assert_equal('help', &buftype)
   1242  bw
   1243  bw
   1244 endfunc
   1245 
   1246 func Test_edit_F21()
   1247  " Pressing <f21>
   1248  " sends a netbeans command
   1249  if has("netbeans_intg")
   1250    new
   1251    " I have no idea what this is supposed to do :)
   1252    call feedkeys("A\<F21>\<F1>\<esc>", 'tnix')
   1253    bw
   1254  endif
   1255 endfunc
   1256 
   1257 func Test_edit_HOME_END()
   1258  " Test Home/End Keys
   1259  new
   1260  set foldopen+=hor
   1261  call setline(1, ['abc', 'def'])
   1262  call cursor(1, 1)
   1263  call feedkeys("AX\<Home>Y\<esc>", 'tnix')
   1264  call cursor(2, 1)
   1265  call feedkeys("iZ\<End>Y\<esc>", 'tnix')
   1266  call assert_equal(['YabcX', 'ZdefY'], getline(1, '$'))
   1267 
   1268  set foldopen-=hor
   1269  bw!
   1270 endfunc
   1271 
   1272 func Test_edit_INS()
   1273  " Test for Pressing <Insert>
   1274  new
   1275  call setline(1, ['abc', 'def'])
   1276  call cursor(1, 1)
   1277  call feedkeys("i\<Insert>ZYX>", 'tnix')
   1278  call assert_equal(['ZYX>', 'def'], getline(1, '$'))
   1279  call setline(1, ['abc', 'def'])
   1280  call cursor(1, 1)
   1281  call feedkeys("i\<Insert>Z\<Insert>YX>", 'tnix')
   1282  call assert_equal(['ZYX>bc', 'def'], getline(1, '$'))
   1283  bw!
   1284 endfunc
   1285 
   1286 func Test_edit_LEFT_RIGHT()
   1287  " Left, Shift-Left, Right, Shift-Right
   1288  new
   1289  call setline(1, ['abc def ghi', 'ABC DEF GHI', 'ZZZ YYY XXX'])
   1290  let _ww=&ww
   1291  set ww=
   1292  call cursor(2, 1)
   1293  call feedkeys("i\<left>\<esc>", 'tnix')
   1294  call assert_equal([0, 2, 1, 0], getpos('.'))
   1295  " Is this a bug, <s-left> does not respect whichwrap option
   1296  call feedkeys("i\<s-left>\<esc>", 'tnix')
   1297  call assert_equal([0, 1, 8, 0], getpos('.'))
   1298  call feedkeys("i". repeat("\<s-left>", 3). "\<esc>", 'tnix')
   1299  call assert_equal([0, 1, 1, 0], getpos('.'))
   1300  call feedkeys("i\<right>\<esc>", 'tnix')
   1301  call assert_equal([0, 1, 1, 0], getpos('.'))
   1302  call feedkeys("i\<right>\<right>\<esc>", 'tnix')
   1303  call assert_equal([0, 1, 2, 0], getpos('.'))
   1304  call feedkeys("A\<right>\<esc>", 'tnix')
   1305  call assert_equal([0, 1, 11, 0], getpos('.'))
   1306  call feedkeys("A\<s-right>\<esc>", 'tnix')
   1307  call assert_equal([0, 2, 1, 0], getpos('.'))
   1308  call feedkeys("i\<s-right>\<esc>", 'tnix')
   1309  call assert_equal([0, 2, 4, 0], getpos('.'))
   1310  call cursor(3, 11)
   1311  call feedkeys("A\<right>\<esc>", 'tnix')
   1312  call feedkeys("A\<s-right>\<esc>", 'tnix')
   1313  call assert_equal([0, 3, 11, 0], getpos('.'))
   1314  call cursor(2, 11)
   1315  " <S-Right> does not respect 'whichwrap' option
   1316  call feedkeys("A\<s-right>\<esc>", 'tnix')
   1317  call assert_equal([0, 3, 1, 0], getpos('.'))
   1318  " Check motion when 'whichwrap' contains cursor keys for insert mode
   1319  set ww+=[,]
   1320  call cursor(2, 1)
   1321  call feedkeys("i\<left>\<esc>", 'tnix')
   1322  call assert_equal([0, 1, 11, 0], getpos('.'))
   1323  call cursor(2, 11)
   1324  call feedkeys("A\<right>\<esc>", 'tnix')
   1325  call assert_equal([0, 3, 1, 0], getpos('.'))
   1326  call cursor(2, 11)
   1327  call feedkeys("A\<s-right>\<esc>", 'tnix')
   1328  call assert_equal([0, 3, 1, 0], getpos('.'))
   1329  let &ww = _ww
   1330  bw!
   1331 endfunc
   1332 
   1333 func Test_edit_MOUSE()
   1334  " This is a simple test, since we're not really using the mouse here
   1335  CheckFeature mouse
   1336  10new
   1337  call setline(1, range(1, 100))
   1338  call cursor(1, 1)
   1339  call assert_equal(1, line('w0'))
   1340  call assert_equal(10, line('w$'))
   1341  set mouse=a
   1342  " One scroll event moves three lines.
   1343  call feedkeys("A\<ScrollWheelDown>\<esc>", 'tnix')
   1344  call assert_equal(4, line('w0'))
   1345  call assert_equal(13, line('w$'))
   1346  " This should move by one page down.
   1347  call feedkeys("A\<S-ScrollWheelDown>\<esc>", 'tnix')
   1348  call assert_equal(14, line('w0'))
   1349  set nostartofline
   1350  " Another page down.
   1351  call feedkeys("A\<C-ScrollWheelDown>\<esc>", 'tnix')
   1352  call assert_equal(24, line('w0'))
   1353 
   1354  call assert_equal([0, 24, 2, 0], getpos('.'))
   1355  call Ntest_setmouse(4, 3)
   1356  call feedkeys("A\<LeftMouse>\<esc>", 'tnix')
   1357  call assert_equal([0, 27, 2, 0], getpos('.'))
   1358  set mousemodel=extend
   1359  call Ntest_setmouse(5, 3)
   1360  call feedkeys("A\<RightMouse>\<esc>\<esc>", 'tnix')
   1361  call assert_equal([0, 28, 2, 0], getpos('.'))
   1362  set mousemodel&
   1363  call cursor(1, 100)
   1364  norm! zt
   1365  " this should move by a screen up, but when the test
   1366  " is run, it moves up to the top of the buffer...
   1367  call feedkeys("A\<ScrollWheelUp>\<esc>", 'tnix')
   1368  call assert_equal([0, 1, 1, 0], getpos('.'))
   1369  call cursor(1, 30)
   1370  norm! zt
   1371  call feedkeys("A\<S-ScrollWheelUp>\<esc>", 'tnix')
   1372  call assert_equal([0, 1, 1, 0], getpos('.'))
   1373  call cursor(1, 30)
   1374  norm! zt
   1375  call feedkeys("A\<C-ScrollWheelUp>\<esc>", 'tnix')
   1376  call assert_equal([0, 1, 1, 0], getpos('.'))
   1377  %d
   1378  call setline(1, repeat(["12345678901234567890"], 100))
   1379  call cursor(2, 1)
   1380  call feedkeys("A\<ScrollWheelRight>\<esc>", 'tnix')
   1381  call assert_equal([0, 2, 20, 0], getpos('.'))
   1382  call feedkeys("A\<ScrollWheelLeft>\<esc>", 'tnix')
   1383  call assert_equal([0, 2, 20, 0], getpos('.'))
   1384  call feedkeys("A\<S-ScrollWheelRight>\<esc>", 'tnix')
   1385  call assert_equal([0, 2, 20, 0], getpos('.'))
   1386  call feedkeys("A\<S-ScrollWheelLeft>\<esc>", 'tnix')
   1387  call assert_equal([0, 2, 20, 0], getpos('.'))
   1388  call feedkeys("A\<C-ScrollWheelRight>\<esc>", 'tnix')
   1389  call assert_equal([0, 2, 20, 0], getpos('.'))
   1390  call feedkeys("A\<C-ScrollWheelLeft>\<esc>", 'tnix')
   1391  call assert_equal([0, 2, 20, 0], getpos('.'))
   1392  set mouse& startofline
   1393  bw!
   1394 endfunc
   1395 
   1396 func Test_edit_PAGEUP_PAGEDOWN()
   1397  10new
   1398  call setline(1, repeat(['abc def ghi'], 30))
   1399  call cursor(1, 1)
   1400  call assert_nobeep('call feedkeys("i\<PageDown>\<esc>", "tnix")')
   1401  call assert_equal([0, 9, 1, 0], getpos('.'))
   1402  call assert_nobeep('call feedkeys("i\<PageDown>\<esc>", "tnix")')
   1403  call assert_equal([0, 17, 1, 0], getpos('.'))
   1404  call assert_nobeep('call feedkeys("i\<PageDown>\<esc>", "tnix")')
   1405  call assert_equal([0, 25, 1, 0], getpos('.'))
   1406  call assert_nobeep('call feedkeys("i\<PageDown>\<esc>", "tnix")')
   1407  call assert_equal([0, 30, 1, 0], getpos('.'))
   1408  call assert_beeps('call feedkeys("i\<PageDown>\<esc>", "tnix")')
   1409  call assert_equal([0, 30, 1, 0], getpos('.'))
   1410  call assert_nobeep('call feedkeys("A\<PageUp>\<esc>", "tnix")')
   1411  call assert_equal([0, 29, 1, 0], getpos('.'))
   1412  call assert_nobeep('call feedkeys("A\<PageUp>\<esc>", "tnix")')
   1413  call assert_equal([0, 21, 1, 0], getpos('.'))
   1414  call assert_nobeep('call feedkeys("A\<PageUp>\<esc>", "tnix")')
   1415  call assert_equal([0, 13, 1, 0], getpos('.'))
   1416  call assert_nobeep('call feedkeys("A\<PageUp>\<esc>", "tnix")')
   1417  call assert_equal([0, 10, 1, 0], getpos('.'))
   1418  call assert_beeps('call feedkeys("A\<PageUp>\<esc>", "tnix")')
   1419  call assert_equal([0, 10, 11, 0], getpos('.'))
   1420  " <S-Up> is the same as <PageUp>
   1421  " <S-Down> is the same as <PageDown>
   1422  call cursor(1, 1)
   1423  call assert_nobeep('call feedkeys("i\<S-Down>\<esc>", "tnix")')
   1424  call assert_equal([0, 9, 1, 0], getpos('.'))
   1425  call assert_nobeep('call feedkeys("i\<S-Down>\<esc>", "tnix")')
   1426  call assert_equal([0, 17, 1, 0], getpos('.'))
   1427  call assert_nobeep('call feedkeys("i\<S-Down>\<esc>", "tnix")')
   1428  call assert_equal([0, 25, 1, 0], getpos('.'))
   1429  call assert_nobeep('call feedkeys("i\<S-Down>\<esc>", "tnix")')
   1430  call assert_equal([0, 30, 1, 0], getpos('.'))
   1431  call assert_beeps('call feedkeys("i\<S-Down>\<esc>", "tnix")')
   1432  call assert_equal([0, 30, 1, 0], getpos('.'))
   1433  call assert_nobeep('call feedkeys("A\<S-Up>\<esc>", "tnix")')
   1434  call assert_equal([0, 29, 1, 0], getpos('.'))
   1435  call assert_nobeep('call feedkeys("A\<S-Up>\<esc>", "tnix")')
   1436  call assert_equal([0, 21, 1, 0], getpos('.'))
   1437  call assert_nobeep('call feedkeys("A\<S-Up>\<esc>", "tnix")')
   1438  call assert_equal([0, 13, 1, 0], getpos('.'))
   1439  call assert_nobeep('call feedkeys("A\<S-Up>\<esc>", "tnix")')
   1440  call assert_equal([0, 10, 1, 0], getpos('.'))
   1441  call assert_beeps('call feedkeys("A\<S-Up>\<esc>", "tnix")')
   1442  call assert_equal([0, 10, 11, 0], getpos('.'))
   1443  set nostartofline
   1444  call cursor(30, 11)
   1445  norm! zt
   1446  call assert_nobeep('call feedkeys("A\<PageUp>\<esc>", "tnix")')
   1447  call assert_equal([0, 29, 11, 0], getpos('.'))
   1448  call assert_nobeep('call feedkeys("A\<PageUp>\<esc>", "tnix")')
   1449  call assert_equal([0, 21, 11, 0], getpos('.'))
   1450  call assert_nobeep('call feedkeys("A\<PageUp>\<esc>", "tnix")')
   1451  call assert_equal([0, 13, 11, 0], getpos('.'))
   1452  call assert_nobeep('call feedkeys("A\<PageUp>\<esc>", "tnix")')
   1453  call assert_equal([0, 10, 11, 0], getpos('.'))
   1454  call assert_beeps('call feedkeys("A\<PageUp>\<esc>", "tnix")')
   1455  call assert_equal([0, 10, 11, 0], getpos('.'))
   1456  call cursor(1, 1)
   1457  call assert_nobeep('call feedkeys("A\<PageDown>\<esc>", "tnix")')
   1458  call assert_equal([0, 9, 11, 0], getpos('.'))
   1459  call assert_nobeep('call feedkeys("A\<PageDown>\<esc>", "tnix")')
   1460  call assert_equal([0, 17, 11, 0], getpos('.'))
   1461  call assert_nobeep('call feedkeys("A\<PageDown>\<esc>", "tnix")')
   1462  call assert_equal([0, 25, 11, 0], getpos('.'))
   1463  call assert_nobeep('call feedkeys("A\<PageDown>\<esc>", "tnix")')
   1464  call assert_equal([0, 30, 11, 0], getpos('.'))
   1465  call assert_beeps('call feedkeys("A\<PageDown>\<esc>", "tnix")')
   1466  call assert_equal([0, 30, 11, 0], getpos('.'))
   1467  " <S-Up> is the same as <PageUp>
   1468  " <S-Down> is the same as <PageDown>
   1469  call cursor(30, 11)
   1470  norm! zt
   1471  call assert_nobeep('call feedkeys("A\<S-Up>\<esc>", "tnix")')
   1472  call assert_equal([0, 29, 11, 0], getpos('.'))
   1473  call assert_nobeep('call feedkeys("A\<S-Up>\<esc>", "tnix")')
   1474  call assert_equal([0, 21, 11, 0], getpos('.'))
   1475  call assert_nobeep('call feedkeys("A\<S-Up>\<esc>", "tnix")')
   1476  call assert_equal([0, 13, 11, 0], getpos('.'))
   1477  call assert_nobeep('call feedkeys("A\<S-Up>\<esc>", "tnix")')
   1478  call assert_equal([0, 10, 11, 0], getpos('.'))
   1479  call assert_beeps('call feedkeys("A\<S-Up>\<esc>", "tnix")')
   1480  call assert_equal([0, 10, 11, 0], getpos('.'))
   1481  call cursor(1, 1)
   1482  call assert_nobeep('call feedkeys("A\<S-Down>\<esc>", "tnix")')
   1483  call assert_equal([0, 9, 11, 0], getpos('.'))
   1484  call assert_nobeep('call feedkeys("A\<S-Down>\<esc>", "tnix")')
   1485  call assert_equal([0, 17, 11, 0], getpos('.'))
   1486  call assert_nobeep('call feedkeys("A\<S-Down>\<esc>", "tnix")')
   1487  call assert_equal([0, 25, 11, 0], getpos('.'))
   1488  call assert_nobeep('call feedkeys("A\<S-Down>\<esc>", "tnix")')
   1489  call assert_equal([0, 30, 11, 0], getpos('.'))
   1490  call assert_beeps('call feedkeys("A\<S-Down>\<esc>", "tnix")')
   1491  call assert_equal([0, 30, 11, 0], getpos('.'))
   1492  bw!
   1493 endfunc
   1494 
   1495 func Test_edit_forbidden()
   1496  new
   1497  " 1) edit in the sandbox is not allowed
   1498  call setline(1, 'a')
   1499  com! Sandbox :sandbox call feedkeys("i\<del>\<esc>", 'tnix')
   1500  call assert_fails(':Sandbox', 'E48:')
   1501  com! Sandbox :sandbox exe "norm! i\<del>"
   1502  call assert_fails(':Sandbox', 'E48:')
   1503  delcom Sandbox
   1504  call assert_equal(['a'], getline(1,'$'))
   1505 
   1506  " 2) edit with textlock set
   1507  fu! DoIt()
   1508    call feedkeys("i\<del>\<esc>", 'tnix')
   1509  endfu
   1510  au InsertCharPre <buffer> :call DoIt()
   1511  try
   1512    call feedkeys("ix\<esc>", 'tnix')
   1513    call assert_fails(1, 'textlock')
   1514  catch /^Vim\%((\a\+)\)\=:E565/ " catch E565: not allowed here
   1515  endtry
   1516  " TODO: Might be a bug: should x really be inserted here
   1517  call assert_equal(['xa'], getline(1, '$'))
   1518  delfu DoIt
   1519  try
   1520    call feedkeys("ix\<esc>", 'tnix')
   1521    call assert_fails(1, 'unknown function')
   1522  catch /^Vim\%((\a\+)\)\=:E117/ " catch E117: unknown function
   1523  endtry
   1524  au! InsertCharPre
   1525 
   1526  " 3) edit when completion is shown
   1527  fun! Complete(findstart, base)
   1528    if a:findstart
   1529      return col('.')
   1530    else
   1531      call feedkeys("i\<del>\<esc>", 'tnix')
   1532      return []
   1533    endif
   1534  endfun
   1535  set completefunc=Complete
   1536  try
   1537    call feedkeys("i\<c-x>\<c-u>\<esc>", 'tnix')
   1538    call assert_fails(1, 'change in complete function')
   1539  catch /^Vim\%((\a\+)\)\=:E565/ " catch E565
   1540  endtry
   1541  delfu Complete
   1542  set completefunc=
   1543 
   1544  if has("rightleft") && exists("+fkmap")
   1545    " 4) 'R' when 'fkmap' and 'revins' is set.
   1546    set revins fkmap
   1547    try
   1548      normal Ri
   1549      call assert_fails(1, "R with 'fkmap' and 'ri' set")
   1550    catch
   1551    finally
   1552      set norevins nofkmap
   1553    endtry
   1554  endif
   1555  bw!
   1556 endfunc
   1557 
   1558 func Test_edit_rightleft()
   1559  " Cursor in rightleft mode moves differently
   1560  CheckFeature rightleft
   1561  call NewWindow(10, 20)
   1562  call setline(1, ['abc', 'def', 'ghi'])
   1563  call cursor(1, 2)
   1564  set rightleft
   1565  " Screen looks as expected
   1566  let lines = ScreenLines([1, 4], winwidth(0))
   1567  let expect = [
   1568        \"                 cba",
   1569        \"                 fed",
   1570        \"                 ihg",
   1571        \"                   ~"]
   1572  call assert_equal(join(expect, "\n"), join(lines, "\n"))
   1573  " 2) right moves to the left
   1574  call feedkeys("i\<right>\<esc>x", 'txin')
   1575  call assert_equal(['bc', 'def', 'ghi'], getline(1,'$'))
   1576  call cursor(1, 2)
   1577  call feedkeys("i\<s-right>\<esc>", 'txin')
   1578  call cursor(1, 2)
   1579  call feedkeys("i\<c-right>\<esc>", 'txin')
   1580  " Screen looks as expected
   1581  let lines = ScreenLines([1, 4], winwidth(0))
   1582  let expect = [
   1583        \"                  cb",
   1584        \"                 fed",
   1585        \"                 ihg",
   1586        \"                   ~"]
   1587  call assert_equal(join(expect, "\n"), join(lines, "\n"))
   1588  " 2) left moves to the right
   1589  call setline(1, ['abc', 'def', 'ghi'])
   1590  call cursor(1, 2)
   1591  call feedkeys("i\<left>\<esc>x", 'txin')
   1592  call assert_equal(['ac', 'def', 'ghi'], getline(1,'$'))
   1593  call cursor(1, 2)
   1594  call feedkeys("i\<s-left>\<esc>", 'txin')
   1595  call cursor(1, 2)
   1596  call feedkeys("i\<c-left>\<esc>", 'txin')
   1597  " Screen looks as expected
   1598  let lines = ScreenLines([1, 4], winwidth(0))
   1599  let expect = [
   1600        \"                  ca",
   1601        \"                 fed",
   1602        \"                 ihg",
   1603        \"                   ~"]
   1604  call assert_equal(join(expect, "\n"), join(lines, "\n"))
   1605  %d _
   1606  " call test_override('redraw_flag', 1)
   1607  " call test_override('char_avail', 1)
   1608  call feedkeys("a\<C-V>x41", "xt")
   1609  redraw!
   1610  call assert_equal(repeat(' ', 19) .. 'A', Screenline(1))
   1611  " call test_override('ALL', 0)
   1612  set norightleft
   1613  bw!
   1614 endfunc
   1615 
   1616 func Test_edit_complete_very_long_name()
   1617  " Long directory names only work on Unix.
   1618  CheckUnix
   1619 
   1620  let dirname = getcwd() . "/Xlongdir"
   1621  let longdirname = dirname . repeat('/' . repeat('d', 255), 4)
   1622  try
   1623    call mkdir(longdirname, 'pR')
   1624  catch /E739:/
   1625    " Long directory name probably not supported.
   1626    call delete(dirname, 'rf')
   1627    return
   1628  endtry
   1629 
   1630  " Try to get the Vim window position before setting 'columns', so that we can
   1631  " move the window back to where it was.
   1632  let winposx = getwinposx()
   1633  let winposy = getwinposy()
   1634 
   1635  if winposx >= 0 && winposy >= 0 && !has('gui_running')
   1636    " We did get the window position, but xterm may report the wrong numbers.
   1637    " Move the window to the reported position and compute any offset.
   1638    exe 'winpos ' . winposx . ' ' . winposy
   1639    sleep 100m
   1640    let x = getwinposx()
   1641    if x >= 0
   1642      let winposx += winposx - x
   1643    endif
   1644    let y = getwinposy()
   1645    if y >= 0
   1646      let winposy += winposy - y
   1647    endif
   1648  endif
   1649 
   1650  let save_columns = &columns
   1651  " Need at least about 1100 columns to reproduce the problem.
   1652  set columns=2000
   1653  set noswapfile
   1654 
   1655  let longfilename = longdirname . '/' . repeat('a', 255)
   1656  call writefile(['Totum', 'Table'], longfilename)
   1657  new
   1658  exe "next Xnofile " . longfilename
   1659  exe "normal iT\<C-N>"
   1660 
   1661  bwipe!
   1662  exe 'bwipe! ' . longfilename
   1663  let &columns = save_columns
   1664  if winposx >= 0 && winposy >= 0
   1665    exe 'winpos ' . winposx . ' ' . winposy
   1666  endif
   1667  set swapfile&
   1668 endfunc
   1669 
   1670 func Test_edit_backtick()
   1671  next a\`b c
   1672  call assert_equal('a`b', expand('%'))
   1673  next
   1674  call assert_equal('c', expand('%'))
   1675  call assert_equal('a\`b c', expand('##'))
   1676 endfunc
   1677 
   1678 func Test_edit_quit()
   1679  edit foo.txt
   1680  split
   1681  new
   1682  call setline(1, 'hello')
   1683  3wincmd w
   1684  redraw!
   1685  call assert_fails('1q', 'E37:')
   1686  bwipe! foo.txt
   1687  only
   1688 endfunc
   1689 
   1690 func Test_edit_alt()
   1691  " Keeping the cursor line didn't happen when the first line has indent.
   1692  new
   1693  call setline(1, ['  one', 'two', 'three'])
   1694  w XAltFile
   1695  $
   1696  call assert_equal(3, line('.'))
   1697  e Xother
   1698  e #
   1699  call assert_equal(3, line('.'))
   1700 
   1701  bwipe XAltFile
   1702  call delete('XAltFile')
   1703 endfunc
   1704 
   1705 func Test_edit_InsertLeave()
   1706  new
   1707  au InsertLeavePre * let g:did_au_pre = 1
   1708  au InsertLeave * let g:did_au = 1
   1709  let g:did_au_pre = 0
   1710  let g:did_au = 0
   1711  call feedkeys("afoo\<Esc>", 'tx')
   1712  call assert_equal(1, g:did_au_pre)
   1713  call assert_equal(1, g:did_au)
   1714  call assert_equal('foo', getline(1))
   1715 
   1716  let g:did_au_pre = 0
   1717  let g:did_au = 0
   1718  call feedkeys("Sbar\<C-C>", 'tx')
   1719  call assert_equal(1, g:did_au_pre)
   1720  call assert_equal(0, g:did_au)
   1721  call assert_equal('bar', getline(1))
   1722 
   1723  inoremap x xx<Esc>
   1724  let g:did_au_pre = 0
   1725  let g:did_au = 0
   1726  call feedkeys("Saax", 'tx')
   1727  call assert_equal(1, g:did_au_pre)
   1728  call assert_equal(1, g:did_au)
   1729  call assert_equal('aaxx', getline(1))
   1730 
   1731  inoremap x xx<C-C>
   1732  let g:did_au_pre = 0
   1733  let g:did_au = 0
   1734  call feedkeys("Sbbx", 'tx')
   1735  call assert_equal(1, g:did_au_pre)
   1736  call assert_equal(0, g:did_au)
   1737  call assert_equal('bbxx', getline(1))
   1738 
   1739  bwipe!
   1740  au! InsertLeave InsertLeavePre
   1741  iunmap x
   1742 endfunc
   1743 
   1744 func Test_edit_InsertLeave_undo()
   1745  new XtestUndo
   1746  set undofile
   1747  au InsertLeave * wall
   1748  exe "normal ofoo\<Esc>"
   1749  call assert_equal(2, line('$'))
   1750  normal u
   1751  call assert_equal(1, line('$'))
   1752 
   1753  bwipe!
   1754  au! InsertLeave
   1755  call delete('XtestUndo')
   1756  call delete(undofile('XtestUndo'))
   1757  set undofile&
   1758 endfunc
   1759 
   1760 " Test for inserting characters using CTRL-V followed by a number.
   1761 func Test_edit_special_chars()
   1762  new
   1763 
   1764  let t = "o\<C-V>65\<C-V>x42\<C-V>o103 \<C-V>33a\<C-V>xfg\<C-V>o78\<Esc>"
   1765 
   1766  exe "normal " . t
   1767  call assert_equal("ABC !a\<C-O>g\<C-G>8", getline(2))
   1768 
   1769  bw!
   1770 endfunc
   1771 
   1772 func Test_edit_startinsert()
   1773  new
   1774  set backspace+=start
   1775  call setline(1, 'foobar')
   1776  call feedkeys("A\<C-U>\<Esc>", 'xt')
   1777  call assert_equal('', getline(1))
   1778 
   1779  call setline(1, 'foobar')
   1780  call feedkeys(":startinsert!\<CR>\<C-U>\<Esc>", 'xt')
   1781  call assert_equal('', getline(1))
   1782 
   1783  set backspace&
   1784  bwipe!
   1785 endfunc
   1786 
   1787 " Test for :startreplace and :startgreplace
   1788 func Test_edit_startreplace()
   1789  new
   1790  call setline(1, 'abc')
   1791  call feedkeys("l:startreplace\<CR>xyz\e", 'xt')
   1792  call assert_equal('axyz', getline(1))
   1793  call feedkeys("0:startreplace!\<CR>abc\e", 'xt')
   1794  call assert_equal('axyzabc', getline(1))
   1795  call setline(1, "a\tb")
   1796  call feedkeys("0l:startgreplace\<CR>xyz\e", 'xt')
   1797  call assert_equal("axyz\tb", getline(1))
   1798  call feedkeys("0i\<C-R>=execute('startreplace')\<CR>12\e", 'xt')
   1799  call assert_equal("12axyz\tb", getline(1))
   1800  bw!
   1801 endfunc
   1802 
   1803 func Test_edit_noesckeys()
   1804  CheckNotGui
   1805  new
   1806 
   1807  " <Left> moves cursor when 'esckeys' is set
   1808  exe "set t_kl=\<Esc>OD"
   1809  " set esckeys
   1810  call feedkeys("axyz\<Esc>ODX", "xt")
   1811  " call assert_equal("xyXz", getline(1))
   1812 
   1813  " <Left> exits Insert mode when 'esckeys' is off
   1814  " set noesckeys
   1815  call setline(1, '')
   1816  call feedkeys("axyz\<Esc>ODX", "xt")
   1817  call assert_equal(["DX", "xyz"], getline(1, 2))
   1818 
   1819  bwipe!
   1820  " set esckeys
   1821 endfunc
   1822 
   1823 " Test for running an invalid ex command in insert mode using CTRL-O
   1824 func Test_edit_ctrl_o_invalid_cmd()
   1825  new
   1826  set showmode showcmd
   1827  " Avoid a sleep of 3 seconds. Zero might have side effects.
   1828  " call test_override('ui_delay', 50)
   1829  let caught_e492 = 0
   1830  try
   1831    call feedkeys("i\<C-O>:invalid\<CR>abc\<Esc>", "xt")
   1832  catch /E492:/
   1833    let caught_e492 = 1
   1834  endtry
   1835  call assert_equal(1, caught_e492)
   1836  call assert_equal('abc', getline(1))
   1837  set showmode& showcmd&
   1838  " call test_override('ui_delay', 0)
   1839  bw!
   1840 endfunc
   1841 
   1842 " Test for editing a file with a very long name
   1843 func Test_edit_illegal_filename()
   1844  CheckEnglish
   1845  new
   1846  redir => msg
   1847  exe 'edit ' . repeat('f', 5000)
   1848  redir END
   1849  call assert_match("Illegal file name$", split(msg, "\n")[0])
   1850  close!
   1851 endfunc
   1852 
   1853 " Test for editing a directory
   1854 func Test_edit_is_a_directory()
   1855  CheckEnglish
   1856  let dirname = getcwd() . "/Xeditdir"
   1857  call mkdir(dirname, 'p')
   1858 
   1859  new
   1860  redir => msg
   1861  exe 'edit' dirname
   1862  redir END
   1863  call assert_match("is a directory$", split(msg, "\n")[0])
   1864  bwipe!
   1865 
   1866  let dirname .= '/'
   1867 
   1868  new
   1869  redir => msg
   1870  exe 'edit' dirname
   1871  redir END
   1872  call assert_match("is a directory$", split(msg, "\n")[0])
   1873  bwipe!
   1874 
   1875  call delete(dirname, 'rf')
   1876 endfunc
   1877 
   1878 " Test for editing a file using invalid file encoding
   1879 func Test_edit_invalid_encoding()
   1880  CheckEnglish
   1881  call writefile([], 'Xinvfile', 'D')
   1882  redir => msg
   1883  new ++enc=axbyc Xinvfile
   1884  redir END
   1885  call assert_match('\[NOT converted\]', msg)
   1886  close!
   1887 endfunc
   1888 
   1889 " Test for the "charconvert" option
   1890 func Test_edit_charconvert()
   1891  CheckEnglish
   1892  call writefile(['one', 'two'], 'Xccfile', 'D')
   1893 
   1894  " set 'charconvert' to a non-existing function
   1895  set charconvert=NonExitingFunc()
   1896  new
   1897  let caught_e117 = v:false
   1898  try
   1899    redir => msg
   1900    edit ++enc=axbyc Xccfile
   1901  catch /E117:/
   1902    let caught_e117 = v:true
   1903  finally
   1904    redir END
   1905  endtry
   1906  call assert_true(caught_e117)
   1907  call assert_equal(['one', 'two'], getline(1, '$'))
   1908  call assert_match("Conversion with 'charconvert' failed", msg)
   1909  close!
   1910  set charconvert&
   1911 
   1912  " 'charconvert' function doesn't create an output file
   1913  func Cconv1()
   1914  endfunc
   1915  set charconvert=Cconv1()
   1916  new
   1917  redir => msg
   1918  edit ++enc=axbyc Xccfile
   1919  redir END
   1920  call assert_equal(['one', 'two'], getline(1, '$'))
   1921  call assert_match("can't read output of 'charconvert'", msg)
   1922  close!
   1923  delfunc Cconv1
   1924  set charconvert&
   1925 
   1926  " 'charconvert' function to convert to upper case
   1927  func Cconv2()
   1928    let data = readfile(v:fname_in)
   1929    call map(data, 'toupper(v:val)')
   1930    call writefile(data, v:fname_out)
   1931  endfunc
   1932  set charconvert=Cconv2()
   1933  new Xccfile
   1934  write ++enc=ucase Xccfile1
   1935  call assert_equal(['ONE', 'TWO'], readfile('Xccfile1'))
   1936  call delete('Xccfile1')
   1937  close!
   1938  delfunc Cconv2
   1939  set charconvert&
   1940 
   1941  " 'charconvert' function removes the input file
   1942  func Cconv3()
   1943    call delete(v:fname_in)
   1944  endfunc
   1945  set charconvert=Cconv3()
   1946  new
   1947  call assert_fails('edit ++enc=lcase Xccfile', 'E202:')
   1948  call assert_equal([''], getline(1, '$'))
   1949  close!
   1950  delfunc Cconv3
   1951  set charconvert&
   1952 endfunc
   1953 
   1954 " Test for editing a file without read permission
   1955 func Test_edit_file_no_read_perm()
   1956  CheckUnix
   1957  CheckNotRoot
   1958 
   1959  call writefile(['one', 'two'], 'Xnrpfile', 'D')
   1960  call setfperm('Xnrpfile', '-w-------')
   1961  new
   1962  redir => msg
   1963  edit Xnrpfile
   1964  redir END
   1965  call assert_equal(1, &readonly)
   1966  call assert_equal([''], getline(1, '$'))
   1967  call assert_match('\[Permission Denied\]', msg)
   1968  close!
   1969 endfunc
   1970 
   1971 " Using :edit without leaving 'insertmode' should not cause Insert mode to be
   1972 " re-entered immediately after <C-L>
   1973 func Test_edit_insertmode_ex_edit()
   1974  CheckRunVimInTerminal
   1975 
   1976  let lines =<< trim END
   1977    set insertmode noruler
   1978    inoremap <C-B> <Cmd>edit Xfoo<CR>
   1979  END
   1980  call writefile(lines, 'Xtest_edit_insertmode_ex_edit', 'D')
   1981 
   1982  let buf = RunVimInTerminal('-S Xtest_edit_insertmode_ex_edit', #{rows: 6, wait_for_ruler: 0})
   1983  " Somehow when using valgrind "INSERT" does not show up unless we send
   1984  " something to the terminal.
   1985  for i in range(30)
   1986    if term_getline(buf, 6) =~ 'INSERT'
   1987      break
   1988    endif
   1989    call term_sendkeys(buf, "-")
   1990    sleep 100m
   1991  endfor
   1992  call WaitForAssert({-> assert_match('^-- INSERT --\s*$', term_getline(buf, 6))})
   1993  call term_sendkeys(buf, "\<C-B>\<C-L>")
   1994  call WaitForAssert({-> assert_notmatch('^-- INSERT --\s*$', term_getline(buf, 6))})
   1995 
   1996  " clean up
   1997  call StopVimInTerminal(buf)
   1998 endfunc
   1999 
   2000 " Pressing escape in 'insertmode' should beep
   2001 " FIXME: Execute this later, when using valgrind it makes the next test
   2002 " Test_edit_insertmode_ex_edit() fail.
   2003 func Test_z_edit_insertmode_esc_beeps()
   2004  new
   2005  " set insertmode
   2006  " call assert_beeps("call feedkeys(\"one\<Esc>\", 'xt')")
   2007  set insertmode&
   2008  " unsupported "CTRL-G l" command should beep in insert mode.
   2009  call assert_beeps("normal i\<C-G>l")
   2010  bwipe!
   2011 endfunc
   2012 
   2013 " Test for 'hkmap' and 'hkmapp'
   2014 func Test_edit_hkmap()
   2015  throw "Skipped: Nvim does not support 'hkmap'"
   2016  CheckFeature rightleft
   2017  if has('win32') && !has('gui')
   2018    " Test fails on the MS-Windows terminal version
   2019    return
   2020  endif
   2021  new
   2022 
   2023  set revins hkmap
   2024  let str = 'abcdefghijklmnopqrstuvwxyz'
   2025  let str ..= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
   2026  let str ..= '`/'',.;'
   2027  call feedkeys('i' .. str, 'xt')
   2028  let expected = "óõú,.;"
   2029  let expected ..= "ZYXWVUTSRQPONMLKJIHGFEDCBA"
   2030  let expected ..= "æèñ'äåàãø/ôíîöêìçïéòë÷âáðù"
   2031  call assert_equal(expected, getline(1))
   2032 
   2033  %d
   2034  set revins hkmap hkmapp
   2035  let str = 'abcdefghijklmnopqrstuvwxyz'
   2036  let str ..= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
   2037  call feedkeys('i' .. str, 'xt')
   2038  let expected = "õYXWVUTSRQóOïíLKJIHGFEDêBA"
   2039  let expected ..= "öòXùåèúæø'ôñðîì÷çéäâóǟãëáà"
   2040  call assert_equal(expected, getline(1))
   2041 
   2042  set revins& hkmap& hkmapp&
   2043  bw!
   2044 endfunc
   2045 
   2046 " Test for 'allowrevins' and using CTRL-_ in insert mode
   2047 func Test_edit_allowrevins()
   2048  CheckFeature rightleft
   2049  new
   2050  set allowrevins
   2051  call feedkeys("iABC\<C-_>DEF\<C-_>GHI", 'xt')
   2052  call assert_equal('ABCFEDGHI', getline(1))
   2053  set allowrevins&
   2054  bw!
   2055 endfunc
   2056 
   2057 " Test for inserting a register in insert mode using CTRL-R
   2058 func Test_edit_insert_reg()
   2059  throw 'Skipped: use test/functional/legacy/edit_spec.lua'
   2060  new
   2061  let g:Line = ''
   2062  func SaveFirstLine()
   2063    let g:Line = Screenline(1)
   2064    return 'r'
   2065  endfunc
   2066  inoremap <expr> <buffer> <F2> SaveFirstLine()
   2067  call test_override('redraw_flag', 1)
   2068  call test_override('char_avail', 1)
   2069  let @r = 'sample'
   2070  call feedkeys("a\<C-R>=SaveFirstLine()\<CR>", "xt")
   2071  call assert_equal('"', g:Line)
   2072 
   2073  " Test for inserting an null and an empty list
   2074  call feedkeys("a\<C-R>=test_null_list()\<CR>", "xt")
   2075  call feedkeys("a\<C-R>=[]\<CR>", "xt")
   2076  call assert_equal(['r'], getbufline('', 1, '$'))
   2077  call test_override('ALL', 0)
   2078  bw!
   2079 endfunc
   2080 
   2081 " Test for positioning cursor after CTRL-R expression failed
   2082 func Test_edit_ctrl_r_failed()
   2083  CheckScreendump
   2084  CheckRunVimInTerminal
   2085 
   2086  let buf = RunVimInTerminal('', #{rows: 6, cols: 60})
   2087 
   2088  " trying to insert a blob produces an error
   2089  call term_sendkeys(buf, "i\<C-R>=0z\<CR>")
   2090 
   2091  " ending Insert mode should put the cursor back on the ':'
   2092  call term_sendkeys(buf, ":\<Esc>")
   2093  call VerifyScreenDump(buf, 'Test_edit_ctlr_r_failed_1', {})
   2094 
   2095  call StopVimInTerminal(buf)
   2096 endfunc
   2097 
   2098 " When a character is inserted at the last position of the last line in a
   2099 " window, the window contents should be scrolled one line up. If the top line
   2100 " is part of a fold, then the entire fold should be scrolled up.
   2101 func Test_edit_lastline_scroll()
   2102  if has('linux')
   2103    " TODO: For unknown reasons, this test fails on CI when run in Gui mode
   2104    CheckNotGui
   2105  endif
   2106  new
   2107  let h = winheight(0)
   2108  let lines = ['one', 'two', 'three']
   2109  let lines += repeat(['vim'], h - 4)
   2110  call setline(1, lines)
   2111  call setline(h, repeat('x', winwidth(0) - 1))
   2112  call feedkeys("GAx", 'xt')
   2113  redraw!
   2114  call assert_equal(h - 1, winline())
   2115  call assert_equal(2, line('w0'))
   2116 
   2117  " scroll with a fold
   2118  1,2fold
   2119  normal gg
   2120  call setline(h + 1, repeat('x', winwidth(0) - 1))
   2121  call feedkeys("GAx", 'xt')
   2122  redraw!
   2123  call assert_equal(h - 1, winline())
   2124  call assert_equal(3, line('w0'))
   2125 
   2126  bw!
   2127 endfunc
   2128 
   2129 func Test_edit_browse()
   2130  " in the GUI this opens a file picker, we only test the terminal behavior
   2131  CheckNotGui
   2132 
   2133  " ":browse xxx" checks for the FileExplorer augroup and assumes editing "."
   2134  " works then.
   2135  augroup FileExplorer
   2136    au!
   2137  augroup END
   2138 
   2139  " When the CASE_INSENSITIVE_FILENAME is defined this used to cause a crash.
   2140  browse enew
   2141  bwipe!
   2142 
   2143  browse split
   2144  bwipe!
   2145 endfunc
   2146 
   2147 func Test_read_invalid()
   2148  " set encoding=latin1
   2149  " This was not properly checking for going past the end.
   2150  call assert_fails('r`=', 'E484:')
   2151  set encoding=utf-8
   2152 endfunc
   2153 
   2154 " Test for the 'revins' option
   2155 func Test_edit_revins()
   2156  CheckFeature rightleft
   2157  new
   2158  set revins
   2159  exe "normal! ione\ttwo three"
   2160  call assert_equal("eerht owt\teno", getline(1))
   2161  call setline(1, "one\ttwo three")
   2162  normal! gg$bi a
   2163  call assert_equal("one\ttwo a three", getline(1))
   2164  exe "normal! $bi\<BS>\<BS>"
   2165  call assert_equal("one\ttwo a ree", getline(1))
   2166  exe "normal! 0wi\<C-W>"
   2167  call assert_equal("one\t a ree", getline(1))
   2168  exe "normal! 0wi\<C-U>"
   2169  call assert_equal("one\t ", getline(1))
   2170  " newline in insert mode starts at the end of the line
   2171  call setline(1, 'one two three')
   2172  exe "normal! wi\nfour"
   2173  call assert_equal(['one two three', 'ruof'], getline(1, '$'))
   2174  set backspace=indent,eol,start
   2175  exe "normal! ggA\<BS>:"
   2176  call assert_equal(['one two three:ruof'], getline(1, '$'))
   2177  set revins& backspace&
   2178  bw!
   2179 endfunc
   2180 
   2181 " Test for getting the character of the line below after "p"
   2182 func Test_edit_put_CTRL_E()
   2183  " set encoding=latin1
   2184  new
   2185  let @" = ''
   2186  sil! norm orggRx
   2187  sil! norm pr
   2188  call assert_equal(['r', 'r'], getline(1, 2))
   2189  bwipe!
   2190  set encoding=utf-8
   2191 endfunc
   2192 
   2193 " Test toggling of input method. See :help i_CTRL-^
   2194 func Test_edit_CTRL_hat()
   2195  CheckFeature xim
   2196 
   2197  " FIXME: test fails with Motif GUI.
   2198  "        test also fails when running in the GUI.
   2199  CheckFeature gui_gtk
   2200  CheckNotGui
   2201 
   2202  new
   2203 
   2204  call assert_equal(0, &iminsert)
   2205  call feedkeys("i\<C-^>", 'xt')
   2206  call assert_equal(2, &iminsert)
   2207  call feedkeys("i\<C-^>", 'xt')
   2208  call assert_equal(0, &iminsert)
   2209 
   2210  bwipe!
   2211 endfunc
   2212 
   2213 " Weird long file name was going over the end of NameBuff
   2214 func Test_edit_overlong_file_name()
   2215  CheckUnix
   2216 
   2217  file 0000000000000000000000000000
   2218  file %%%%%%%%%%%%%%%%%%%%%%%%%%
   2219  file %%%%%%
   2220  set readonly
   2221  set ls=2
   2222 
   2223  redraw!
   2224  set noreadonly ls&
   2225  bwipe!
   2226 endfunc
   2227 
   2228 func Test_edit_shift_bs()
   2229  CheckMSWindows
   2230 
   2231  " FIXME: this works interactively, but the test fails
   2232  throw 'Skipped: Shift-Backspace Test not working correctly :('
   2233 
   2234  " Need to run this in Win32 Terminal, do not use CheckRunVimInTerminal
   2235  if !has("terminal")
   2236    return
   2237  endif
   2238 
   2239  " Shift Backspace should work like Backspace in insert mode
   2240  let lines =<< trim END
   2241    call setline(1, ['abc'])
   2242  END
   2243  call writefile(lines, 'Xtest_edit_shift_bs', 'D')
   2244 
   2245  let buf = RunVimInTerminal('-S Xtest_edit_shift_bs', #{rows: 3})
   2246  call term_sendkeys(buf, "A\<S-BS>-\<esc>")
   2247  call TermWait(buf, 50)
   2248  call assert_equal('ab-', term_getline(buf, 1))
   2249 
   2250  " clean up
   2251  call StopVimInTerminal(buf)
   2252 endfunc
   2253 
   2254 func Test_edit_Ctrl_RSB()
   2255  new
   2256  let g:triggered = []
   2257  autocmd InsertCharPre <buffer> let g:triggered += [v:char]
   2258 
   2259  " i_CTRL-] should not trigger InsertCharPre
   2260  exe "normal! A\<C-]>"
   2261  call assert_equal([], g:triggered)
   2262 
   2263  " i_CTRL-] should expand abbreviations but not trigger InsertCharPre
   2264  inoreabbr <buffer> f foo
   2265  exe "normal! Af\<C-]>a"
   2266  call assert_equal(['f', 'f', 'o', 'o', 'a'], g:triggered)
   2267  call assert_equal('fooa', getline(1))
   2268 
   2269  " CTRL-] followed by i_CTRL-V should not expand abbreviations
   2270  " i_CTRL-V doesn't trigger InsertCharPre
   2271  call setline(1, '')
   2272  exe "normal! Af\<C-V>\<C-]>"
   2273  call assert_equal("f\<C-]>", getline(1))
   2274 
   2275  let g:triggered = []
   2276  call setline(1, '')
   2277 
   2278  " Also test assigning to v:char
   2279  autocmd InsertCharPre <buffer> let v:char = 'f'
   2280  exe "normal! Ag\<C-]>h"
   2281  call assert_equal(['g', 'f', 'o', 'o', 'h'], g:triggered)
   2282  call assert_equal('ffff', getline(1))
   2283 
   2284  autocmd! InsertCharPre
   2285  unlet g:triggered
   2286  bwipe!
   2287 endfunc
   2288 
   2289 func s:check_backspace(expected)
   2290  let g:actual = []
   2291  inoremap <buffer> <F2> <Cmd>let g:actual += [getline('.')]<CR>
   2292  set backspace=indent,eol,start
   2293 
   2294  exe "normal i" .. repeat("\<BS>\<F2>", len(a:expected))
   2295  call assert_equal(a:expected, g:actual)
   2296 
   2297  set backspace&
   2298  iunmap <buffer> <F2>
   2299  unlet g:actual
   2300 endfunc
   2301 
   2302 " Test that backspace works with 'smarttab' and mixed Tabs and spaces.
   2303 func Test_edit_backspace_smarttab_mixed()
   2304  set smarttab
   2305  call NewWindow(1, 30)
   2306  setlocal tabstop=4 shiftwidth=4
   2307 
   2308  call setline(1, "\t    \t         \t a")
   2309  normal! $
   2310  call s:check_backspace([
   2311        \ "\t    \t         \ta",
   2312        \ "\t    \t        a",
   2313        \ "\t    \t    a",
   2314        \ "\t    \ta",
   2315        \ "\t    a",
   2316        \ "\ta",
   2317        \ "a",
   2318        \ ])
   2319 
   2320  call CloseWindow()
   2321  set smarttab&
   2322 endfunc
   2323 
   2324 " Test that backspace works with 'smarttab' and 'varsofttabstop'.
   2325 func Test_edit_backspace_smarttab_varsofttabstop()
   2326  CheckFeature vartabs
   2327 
   2328  set smarttab
   2329  call NewWindow(1, 30)
   2330  setlocal tabstop=8 varsofttabstop=6,2,5,3
   2331 
   2332  call setline(1, "a\t    \t a")
   2333  normal! $
   2334  call s:check_backspace([
   2335        \ "a\t    \ta",
   2336        \ "a\t     a",
   2337        \ "a\ta",
   2338        \ "a     a",
   2339        \ "aa",
   2340        \ "a",
   2341        \ ])
   2342 
   2343  call CloseWindow()
   2344  set smarttab&
   2345 endfunc
   2346 
   2347 " Test that backspace works with 'smarttab' when a Tab is shown as "^I".
   2348 func Test_edit_backspace_smarttab_list()
   2349  set smarttab
   2350  call NewWindow(1, 30)
   2351  setlocal tabstop=4 shiftwidth=4 list listchars=
   2352 
   2353  call setline(1, "\t    \t         \t a")
   2354  normal! $
   2355  call s:check_backspace([
   2356        \ "\t    \t        a",
   2357        \ "\t    \t    a",
   2358        \ "\t    \ta",
   2359        \ "\t  a",
   2360        \ "a",
   2361        \ ])
   2362 
   2363  call CloseWindow()
   2364  set smarttab&
   2365 endfunc
   2366 
   2367 " Test that backspace works with 'smarttab' and 'breakindent'.
   2368 func Test_edit_backspace_smarttab_breakindent()
   2369  CheckFeature linebreak
   2370 
   2371  set smarttab
   2372  call NewWindow(3, 17)
   2373  setlocal tabstop=4 shiftwidth=4 breakindent breakindentopt=min:5
   2374 
   2375  call setline(1, "\t    \t         \t a")
   2376  normal! $
   2377  call s:check_backspace([
   2378        \ "\t    \t         \ta",
   2379        \ "\t    \t        a",
   2380        \ "\t    \t    a",
   2381        \ "\t    \ta",
   2382        \ "\t    a",
   2383        \ "\ta",
   2384        \ "a",
   2385        \ ])
   2386 
   2387  call CloseWindow()
   2388  set smarttab&
   2389 endfunc
   2390 
   2391 " Test that backspace works with 'smarttab' and virtual text.
   2392 func Test_edit_backspace_smarttab_virtual_text()
   2393  CheckFeature textprop
   2394 
   2395  set smarttab
   2396  call NewWindow(1, 50)
   2397  setlocal tabstop=4 shiftwidth=4
   2398 
   2399  call setline(1, "\t    \t         \t a")
   2400  call prop_type_add('theprop', {})
   2401  call prop_add(1, 3, {'type': 'theprop', 'text': 'text'})
   2402  normal! $
   2403  call s:check_backspace([
   2404        \ "\t    \t         \ta",
   2405        \ "\t    \t        a",
   2406        \ "\t    \t    a",
   2407        \ "\t    \ta",
   2408        \ "\t    a",
   2409        \ "\ta",
   2410        \ "a",
   2411        \ ])
   2412 
   2413  call CloseWindow()
   2414  call prop_type_delete('theprop')
   2415  set smarttab&
   2416 endfunc
   2417 
   2418 func Test_edit_CAR_with_completion()
   2419  new
   2420 
   2421  " With "noselect", behavior is the same with and without "noinsert":
   2422  " Enter inserts a new line when no selection is done or after selecting with
   2423  " Ctrl-N/P, but does not insert a new line when selecting with cursor keys.
   2424  for cot in ['menu,menuone,noselect', 'menu,menuone,noselect,noinsert']
   2425    let &cot = cot
   2426    %delete
   2427    call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>e\<CR>", 'tx')
   2428    call assert_equal(['hello hero', 'he', ''], getline(1, '$'))
   2429    %delete
   2430    call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<CR>", 'tx')
   2431    call assert_equal(['hello hero', 'h', ''], getline(1, '$'))
   2432    %delete
   2433    call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<C-N>\<CR>", 'tx')
   2434    call assert_equal(['hello hero', 'hello', ''], getline(1, '$'))
   2435    %delete
   2436    call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<C-N>\<C-N>\<CR>", 'tx')
   2437    call assert_equal(['hello hero', 'hero', ''], getline(1, '$'))
   2438    %delete
   2439    call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<C-N>\<C-P>\<CR>", 'tx')
   2440    call assert_equal(['hello hero', 'h', ''], getline(1, '$'))
   2441    %delete
   2442    call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<Down>\<CR>", 'tx')
   2443    call assert_equal(['hello hero', 'hello'], getline(1, '$'))
   2444    %delete
   2445    call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<Down>\<Down>\<CR>", 'tx')
   2446    call assert_equal(['hello hero', 'hero'], getline(1, '$'))
   2447    %delete
   2448    call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<Down>\<Up>\<CR>", 'tx')
   2449    call assert_equal(['hello hero', 'h'], getline(1, '$'))
   2450  endfor
   2451 
   2452  " With "noinsert" but not "noselect": like pressing <Down> after "noselect".
   2453  set cot=menu,menuone,noinsert
   2454  %delete
   2455  call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>e\<CR>", 'tx')
   2456  call assert_equal(['hello hero', 'hello'], getline(1, '$'))
   2457  %delete
   2458  call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<CR>", 'tx')
   2459  call assert_equal(['hello hero', 'hello'], getline(1, '$'))
   2460  %delete
   2461  call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<Down>\<CR>", 'tx')
   2462  call assert_equal(['hello hero', 'hero'], getline(1, '$'))
   2463  %delete
   2464  call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<Up>\<CR>", 'tx')
   2465  call assert_equal(['hello hero', 'h'], getline(1, '$'))
   2466  %delete
   2467  call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<C-N>\<CR>", 'tx')
   2468  call assert_equal(['hello hero', 'hero', ''], getline(1, '$'))
   2469  %delete
   2470  call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>\<C-P>\<CR>", 'tx')
   2471  call assert_equal(['hello hero', 'h', ''], getline(1, '$'))
   2472 
   2473  set cot&
   2474  bw!
   2475 endfunc
   2476 
   2477 " vim: shiftwidth=2 sts=2 expandtab