xref: /vim-8.2.3635/src/testdir/test_edit.vim (revision 4eeedc09)
1" Test for edit functions
2
3if exists("+t_kD")
4  let &t_kD="[3;*~"
5endif
6
7source check.vim
8
9" Needed for testing basic rightleft: Test_edit_rightleft
10source view_util.vim
11
12" Needs to come first until the bug in getchar() is
13" fixed: https://groups.google.com/d/msg/vim_dev/fXL9yme4H4c/bOR-U6_bAQAJ
14func Test_edit_00b()
15  new
16  call setline(1, ['abc '])
17  inoreabbr <buffer> h here some more
18  call cursor(1, 4)
19  " <c-l> expands the abbreviation and ends insertmode
20  call feedkeys(":set im\<cr> h\<c-l>:set noim\<cr>", 'tix')
21  call assert_equal(['abc here some more '], getline(1,'$'))
22  iunabbr <buffer> h
23  bw!
24endfunc
25
26func 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!
62endfunc
63
64func 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!
102endfunc
103
104func 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!
121endfunc
122
123func 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!
133endfunc
134
135func 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!
155endfunc
156
157func Test_edit_06()
158  " Test in diff mode
159  CheckFeature diff
160  CheckExecutable diff
161  new
162  call setline(1, ['abc', 'xxx', 'yyy'])
163  vnew
164  call setline(1, ['abc', 'zzz', 'xxx', 'yyy'])
165  wincmd p
166  diffthis
167  wincmd p
168  diffthis
169  wincmd p
170  call cursor(2, 1)
171  norm! zt
172  call feedkeys("Ozzz\<esc>", 'tnix')
173  call assert_equal(['abc', 'zzz', 'xxx', 'yyy'], getline(1,'$'))
174  bw!
175  bw!
176endfunc
177
178func Test_edit_07()
179  " 1) Test with completion <c-l> when popupmenu is visible
180  new
181  call setline(1, 'J')
182
183  func! ListMonths()
184    call complete(col('.')-1, ['January', 'February', 'March',
185    \ 'April', 'May', 'June', 'July', 'August', 'September',
186    \ 'October', 'November', 'December'])
187    return ''
188  endfunc
189  inoremap <buffer> <F5> <C-R>=ListMonths()<CR>
190
191  call feedkeys("A\<f5>\<c-p>". repeat("\<down>", 6)."\<c-l>\<down>\<c-l>\<cr>", 'tx')
192  call assert_equal(['July'], getline(1,'$'))
193  " 1) Test completion when InsertCharPre kicks in
194  %d
195  call setline(1, 'J')
196  fu! DoIt()
197    if v:char=='u'
198      let v:char='an'
199    endif
200  endfu
201  au InsertCharPre <buffer> :call DoIt()
202  call feedkeys("A\<f5>\<c-p>u\<cr>\<c-l>\<cr>", 'tx')
203  call assert_equal(["Jan\<c-l>",''], 1->getline('$'))
204  %d
205  call setline(1, 'J')
206  call feedkeys("A\<f5>\<c-p>u\<down>\<c-l>\<cr>", 'tx')
207  call assert_equal(["January"], 1->getline('$'))
208
209  delfu ListMonths
210  delfu DoIt
211  iunmap <buffer> <f5>
212  bw!
213endfunc
214
215func Test_edit_08()
216  " reset insertmode from i_ctrl-r_=
217  let g:bufnr = bufnr('%')
218  new
219  call setline(1, ['abc'])
220  call cursor(1, 4)
221  call feedkeys(":set im\<cr>ZZZ\<c-r>=setbufvar(g:bufnr,'&im', 0)\<cr>",'tnix')
222  call assert_equal(['abZZZc'], getline(1,'$'))
223  call assert_equal([0, 1, 1, 0], getpos('.'))
224  call assert_false(0, '&im')
225  bw!
226  unlet g:bufnr
227endfunc
228
229func Test_edit_09()
230  " test i_CTRL-\ combinations
231  new
232  call setline(1, ['abc', 'def', 'ghi'])
233  call cursor(1, 1)
234  " 1) CTRL-\ CTLR-N
235  call feedkeys(":set im\<cr>\<c-\>\<c-n>ccABC\<c-l>", 'txin')
236  call assert_equal(['ABC', 'def', 'ghi'], getline(1,'$'))
237  call setline(1, ['ABC', 'def', 'ghi'])
238  " 2) CTRL-\ CTLR-G
239  call feedkeys("j0\<c-\>\<c-g>ZZZ\<cr>\<c-l>", 'txin')
240  call assert_equal(['ABC', 'ZZZ', 'def', 'ghi'], getline(1,'$'))
241  call feedkeys("I\<c-\>\<c-g>YYY\<c-l>", 'txin')
242  call assert_equal(['ABC', 'ZZZ', 'YYYdef', 'ghi'], getline(1,'$'))
243  set noinsertmode
244  " 3) CTRL-\ CTRL-O
245  call setline(1, ['ABC', 'ZZZ', 'def', 'ghi'])
246  call cursor(1, 1)
247  call feedkeys("A\<c-o>ix", 'txin')
248  call assert_equal(['ABxC', 'ZZZ', 'def', 'ghi'], getline(1,'$'))
249  call feedkeys("A\<c-\>\<c-o>ix", 'txin')
250  call assert_equal(['ABxCx', 'ZZZ', 'def', 'ghi'], getline(1,'$'))
251  " 4) CTRL-\ a (should be inserted literally, not special after <c-\>
252  call setline(1, ['ABC', 'ZZZ', 'def', 'ghi'])
253  call cursor(1, 1)
254  call feedkeys("A\<c-\>a", 'txin')
255  call assert_equal(["ABC\<c-\>a", 'ZZZ', 'def', 'ghi'], getline(1, '$'))
256  bw!
257endfunc
258
259func Test_edit_11()
260  " Test that indenting kicks in
261  new
262  set cindent
263  call setline(1, ['{', '', ''])
264  call cursor(2, 1)
265  call feedkeys("i\<c-f>int c;\<esc>", 'tnix')
266  call cursor(3, 1)
267  call feedkeys("\<Insert>/* comment */", 'tnix')
268  call assert_equal(['{', "\<tab>int c;", "/* comment */"], getline(1, '$'))
269  " added changed cindentkeys slightly
270  set cindent cinkeys+=*/
271  call setline(1, ['{', '', ''])
272  call cursor(2, 1)
273  call feedkeys("i\<c-f>int c;\<esc>", 'tnix')
274  call cursor(3, 1)
275  call feedkeys("i/* comment */", 'tnix')
276  call assert_equal(['{', "\<tab>int c;", "\<tab>/* comment */"], getline(1, '$'))
277  set cindent cinkeys+==end
278  call feedkeys("oend\<cr>\<esc>", 'tnix')
279  call assert_equal(['{', "\<tab>int c;", "\<tab>/* comment */", "\tend", ''], getline(1, '$'))
280  set cinkeys-==end
281  %d
282  " Use indentexpr instead of cindenting
283  func! Do_Indent()
284    if v:lnum == 3
285      return 3*shiftwidth()
286    else
287      return 2*shiftwidth()
288    endif
289  endfunc
290  setl indentexpr=Do_Indent() indentkeys+=*/
291  call setline(1, ['{', '', ''])
292  call cursor(2, 1)
293  call feedkeys("i\<c-f>int c;\<esc>", 'tnix')
294  call cursor(3, 1)
295  call feedkeys("i/* comment */", 'tnix')
296  call assert_equal(['{', "\<tab>\<tab>int c;", "\<tab>\<tab>\<tab>/* comment */"], getline(1, '$'))
297  set cinkeys&vim indentkeys&vim
298  set nocindent indentexpr=
299  delfu Do_Indent
300  bw!
301endfunc
302
303func Test_edit_11_indentexpr()
304  " Test that indenting kicks in
305  new
306  " Use indentexpr instead of cindenting
307  func! Do_Indent()
308    let pline=prevnonblank(v:lnum)
309    if empty(getline(v:lnum))
310      if getline(pline) =~ 'if\|then'
311        return shiftwidth()
312      else
313        return 0
314      endif
315    else
316        return 0
317    endif
318  endfunc
319  setl indentexpr=Do_Indent() indentkeys+=0=then,0=fi
320  call setline(1, ['if [ $this ]'])
321  call cursor(1, 1)
322  call feedkeys("othen\<cr>that\<cr>fi", 'tnix')
323  call assert_equal(['if [ $this ]', "then", "\<tab>that", "fi"], getline(1, '$'))
324  set cinkeys&vim indentkeys&vim
325  set nocindent indentexpr=
326  delfu Do_Indent
327  bw!
328endfunc
329
330" Test changing indent in replace mode
331func Test_edit_12()
332  new
333  call setline(1, ["\tabc", "\tdef"])
334  call cursor(2, 4)
335  call feedkeys("R^\<c-d>", 'tnix')
336  call assert_equal(["\tabc", "def"], getline(1, '$'))
337  call assert_equal([0, 2, 2, 0], '.'->getpos())
338  %d
339  call setline(1, ["\tabc", "\t\tdef"])
340  call cursor(2, 2)
341  call feedkeys("R^\<c-d>", 'tnix')
342  call assert_equal(["\tabc", "def"], getline(1, '$'))
343  call assert_equal([0, 2, 1, 0], getpos('.'))
344  %d
345  call setline(1, ["\tabc", "\t\tdef"])
346  call cursor(2, 2)
347  call feedkeys("R\<c-t>", 'tnix')
348  call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$'))
349  call assert_equal([0, 2, 2, 0], getpos('.'))
350  bw!
351  10vnew
352  call setline(1, ["\tabc", "\t\tdef"])
353  call cursor(2, 2)
354  call feedkeys("R\<c-t>", 'tnix')
355  call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$'))
356  call assert_equal([0, 2, 2, 0], getpos('.'))
357  %d
358  set sw=4
359  call setline(1, ["\tabc", "\t\tdef"])
360  call cursor(2, 2)
361  call feedkeys("R\<c-t>\<c-t>", 'tnix')
362  call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$'))
363  call assert_equal([0, 2, 2, 0], getpos('.'))
364  %d
365  call setline(1, ["\tabc", "\t\tdef"])
366  call cursor(2, 2)
367  call feedkeys("R\<c-t>\<c-t>", 'tnix')
368  call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$'))
369  call assert_equal([0, 2, 2, 0], getpos('.'))
370  set sw&
371
372  " In replace mode, after hitting enter in a line with tab characters,
373  " pressing backspace should restore the tab characters.
374  %d
375  setlocal autoindent backspace=2
376  call setline(1, "\tone\t\ttwo")
377  exe "normal ggRred\<CR>six" .. repeat("\<BS>", 8)
378  call assert_equal(["\tone\t\ttwo"], getline(1, '$'))
379  bw!
380endfunc
381
382func Test_edit_13()
383  " Test smartindenting
384  if exists("+smartindent")
385    new
386    set smartindent autoindent
387    call setline(1, ["\tabc"])
388    call feedkeys("A {\<cr>more\<cr>}\<esc>", 'tnix')
389    call assert_equal(["\tabc {", "\t\tmore", "\t}"], getline(1, '$'))
390    set smartindent& autoindent&
391    bwipe!
392  endif
393
394  " Test autoindent removing indent of blank line.
395  new
396  call setline(1, '    foo bar baz')
397  set autoindent
398  exe "normal 0eea\<CR>\<CR>\<Esc>"
399  call assert_equal("    foo bar", getline(1))
400  call assert_equal("", getline(2))
401  call assert_equal("    baz", getline(3))
402  set autoindent&
403
404  " pressing <C-U> to erase line should keep the indent with 'autoindent'
405  set backspace=2 autoindent
406  %d
407  exe "normal i\tone\<CR>three\<C-U>two"
408  call assert_equal(["\tone", "\ttwo"], getline(1, '$'))
409  set backspace& autoindent&
410
411  bwipe!
412endfunc
413
414" Test for autoindent removing indent when insert mode is stopped.  Some parts
415" of the code is exercised only when interactive mode is used. So use Vim in a
416" terminal.
417func Test_autoindent_remove_indent()
418  CheckRunVimInTerminal
419  let buf = RunVimInTerminal('-N Xfile', {'rows': 6, 'cols' : 20})
420  call TermWait(buf)
421  call term_sendkeys(buf, ":set autoindent\n")
422  " leaving insert mode in a new line with indent added by autoindent, should
423  " remove the indent.
424  call term_sendkeys(buf, "i\<Tab>foo\<CR>\<Esc>")
425  " Need to delay for sometime, otherwise the code in getchar.c will not be
426  " exercised.
427  call TermWait(buf, 50)
428  " when a line is wrapped and the cursor is at the start of the second line,
429  " leaving insert mode, should move the cursor back to the first line.
430  call term_sendkeys(buf, "o" .. repeat('x', 20) .. "\<Esc>")
431  " Need to delay for sometime, otherwise the code in getchar.c will not be
432  " exercised.
433  call TermWait(buf, 50)
434  call term_sendkeys(buf, ":w\n")
435  call TermWait(buf)
436  call StopVimInTerminal(buf)
437  call assert_equal(["\tfoo", '', repeat('x', 20)], readfile('Xfile'))
438  call delete('Xfile')
439endfunc
440
441func Test_edit_CR()
442  " Test for <CR> in insert mode
443  " basically only in quickfix mode ist tested, the rest
444  " has been taken care of by other tests
445  CheckFeature quickfix
446  botright new
447  call writefile(range(1, 10), 'Xqflist.txt')
448  call setqflist([{'filename': 'Xqflist.txt', 'lnum': 2}])
449  copen
450  set modifiable
451  call feedkeys("A\<cr>", 'tnix')
452  call assert_equal('Xqflist.txt', bufname(''))
453  call assert_equal(2, line('.'))
454  cclose
455  botright new
456  call setloclist(0, [{'filename': 'Xqflist.txt', 'lnum': 10}])
457  lopen
458  set modifiable
459  call feedkeys("A\<cr>", 'tnix')
460  call assert_equal('Xqflist.txt', bufname(''))
461  call assert_equal(10, line('.'))
462  call feedkeys("A\<Enter>", 'tnix')
463  call feedkeys("A\<kEnter>", 'tnix')
464  call feedkeys("A\n", 'tnix')
465  call feedkeys("A\r", 'tnix')
466  call assert_equal(map(range(1, 10), 'string(v:val)') + ['', '', '', ''], getline(1, '$'))
467  bw!
468  lclose
469  call delete('Xqflist.txt')
470endfunc
471
472func Test_edit_CTRL_()
473  CheckFeature rightleft
474  " disabled for Windows builds, why?
475  CheckNotMSWindows
476  let _encoding=&encoding
477  set encoding=utf-8
478  " Test for CTRL-_
479  new
480  call setline(1, ['abc'])
481  call cursor(1, 1)
482  call feedkeys("i\<c-_>xyz\<esc>", 'tnix')
483  call assert_equal(["\<C-_>xyzabc"], getline(1, '$'))
484  call assert_false(&revins)
485  set ari
486  call setline(1, ['abc'])
487  call cursor(1, 1)
488  call feedkeys("i\<c-_>xyz\<esc>", 'tnix')
489  call assert_equal(["æèñabc"], getline(1, '$'))
490  call assert_true(&revins)
491  call setline(1, ['abc'])
492  call cursor(1, 1)
493  call feedkeys("i\<c-_>xyz\<esc>", 'tnix')
494  call assert_equal(["xyzabc"], getline(1, '$'))
495  call assert_false(&revins)
496  set noari
497  let &encoding=_encoding
498  bw!
499endfunc
500
501" needs to come first, to have the @. register empty
502func Test_edit_00a_CTRL_A()
503  " Test pressing CTRL-A
504  new
505  call setline(1, repeat([''], 5))
506  call cursor(1, 1)
507  try
508    call feedkeys("A\<NUL>", 'tnix')
509  catch /^Vim\%((\a\+)\)\=:E29/
510    call assert_true(1, 'E29 error caught')
511  endtry
512  call cursor(1, 1)
513  call feedkeys("Afoobar \<esc>", 'tnix')
514  call cursor(2, 1)
515  call feedkeys("A\<c-a>more\<esc>", 'tnix')
516  call cursor(3, 1)
517  call feedkeys("A\<NUL>and more\<esc>", 'tnix')
518  call assert_equal(['foobar ', 'foobar more', 'foobar morend more', '', ''], getline(1, '$'))
519  bw!
520endfunc
521
522func Test_edit_CTRL_EY()
523  " Ctrl-E/ Ctrl-Y in insert mode completion to scroll
524  10new
525  call setline(1, range(1, 100))
526  call cursor(30, 1)
527  norm! z.
528  call feedkeys("A\<c-x>\<c-e>\<c-e>\<c-e>\<c-e>\<c-e>", 'tnix')
529  call assert_equal(30, winsaveview()['topline'])
530  call assert_equal([0, 30, 2, 0], getpos('.'))
531  call feedkeys("A\<c-x>\<c-e>\<c-e>\<c-e>\<c-e>\<c-e>", 'tnix')
532  call feedkeys("A\<c-x>".repeat("\<c-y>", 10), 'tnix')
533  call assert_equal(21, winsaveview()['topline'])
534  call assert_equal([0, 30, 2, 0], getpos('.'))
535  bw!
536endfunc
537
538func Test_edit_CTRL_G()
539  new
540  call setline(1, ['foobar', 'foobar', 'foobar'])
541  call cursor(2, 4)
542  call feedkeys("ioooooooo\<c-g>k\<c-r>.\<esc>", 'tnix')
543  call assert_equal(['foooooooooobar', 'foooooooooobar', 'foobar'], getline(1, '$'))
544  call assert_equal([0, 1, 11, 0], getpos('.'))
545  call feedkeys("i\<c-g>k\<esc>", 'tnix')
546  call assert_equal([0, 1, 10, 0], getpos('.'))
547  call cursor(2, 4)
548  call feedkeys("i\<c-g>jzzzz\<esc>", 'tnix')
549  call assert_equal(['foooooooooobar', 'foooooooooobar', 'foozzzzbar'], getline(1, '$'))
550  call assert_equal([0, 3, 7, 0], getpos('.'))
551  call feedkeys("i\<c-g>j\<esc>", 'tnix')
552  call assert_equal([0, 3, 6, 0], getpos('.'))
553  bw!
554endfunc
555
556func Test_edit_CTRL_I()
557  " Tab in completion mode
558  let path=expand("%:p:h")
559  new
560  call setline(1, [path. "/", ''])
561  call feedkeys("Arunt\<c-x>\<c-f>\<tab>\<cr>\<esc>", 'tnix')
562  call assert_match('runtest\.vim', getline(1))
563  %d
564  call writefile(['one', 'two', 'three'], 'Xinclude.txt')
565  let include='#include Xinclude.txt'
566  call setline(1, [include, ''])
567  call cursor(2, 1)
568  call feedkeys("A\<c-x>\<tab>\<cr>\<esc>", 'tnix')
569  call assert_equal([include, 'one', ''], getline(1, '$'))
570  call feedkeys("2ggC\<c-x>\<tab>\<down>\<cr>\<esc>", 'tnix')
571  call assert_equal([include, 'two', ''], getline(1, '$'))
572  call feedkeys("2ggC\<c-x>\<tab>\<down>\<down>\<cr>\<esc>", 'tnix')
573  call assert_equal([include, 'three', ''], getline(1, '$'))
574  call feedkeys("2ggC\<c-x>\<tab>\<down>\<down>\<down>\<cr>\<esc>", 'tnix')
575  call assert_equal([include, '', ''], getline(1, '$'))
576  call delete("Xinclude.txt")
577  bw!
578endfunc
579
580func Test_edit_CTRL_K()
581  " Test pressing CTRL-K (basically only dictionary completion and digraphs
582  " the rest is already covered
583  call writefile(['A', 'AA', 'AAA', 'AAAA'], 'Xdictionary.txt')
584  set dictionary=Xdictionary.txt
585  new
586  call setline(1, 'A')
587  call cursor(1, 1)
588  call feedkeys("A\<c-x>\<c-k>\<cr>\<esc>", 'tnix')
589  call assert_equal(['AA', ''], getline(1, '$'))
590  %d
591  call setline(1, 'A')
592  call cursor(1, 1)
593  call feedkeys("A\<c-x>\<c-k>\<down>\<cr>\<esc>", 'tnix')
594  call assert_equal(['AAA'], getline(1, '$'))
595  %d
596  call setline(1, 'A')
597  call cursor(1, 1)
598  call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<cr>\<esc>", 'tnix')
599  call assert_equal(['AAAA'], getline(1, '$'))
600  %d
601  call setline(1, 'A')
602  call cursor(1, 1)
603  call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<down>\<cr>\<esc>", 'tnix')
604  call assert_equal(['A'], getline(1, '$'))
605  %d
606  call setline(1, 'A')
607  call cursor(1, 1)
608  call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<down>\<down>\<cr>\<esc>", 'tnix')
609  call assert_equal(['AA'], getline(1, '$'))
610
611  " press an unexpected key after dictionary completion
612  %d
613  call setline(1, 'A')
614  call cursor(1, 1)
615  call feedkeys("A\<c-x>\<c-k>\<c-]>\<cr>\<esc>", 'tnix')
616  call assert_equal(['AA', ''], getline(1, '$'))
617  %d
618  call setline(1, 'A')
619  call cursor(1, 1)
620  call feedkeys("A\<c-x>\<c-k>\<c-s>\<cr>\<esc>", 'tnix')
621  call assert_equal(["AA\<c-s>", ''], getline(1, '$'))
622  %d
623  call setline(1, 'A')
624  call cursor(1, 1)
625  call feedkeys("A\<c-x>\<c-k>\<c-f>\<cr>\<esc>", 'tnix')
626  call assert_equal(["AA\<c-f>", ''], getline(1, '$'))
627
628  set dictionary=
629  %d
630  call setline(1, 'A')
631  call cursor(1, 1)
632  let v:testing = 1
633  try
634    call feedkeys("A\<c-x>\<c-k>\<esc>", 'tnix')
635  catch
636    " error sleeps 2 seconds, when v:testing is not set
637    let v:testing = 0
638  endtry
639  call delete('Xdictionary.txt')
640
641  call test_override("char_avail", 1)
642  set showcmd
643  %d
644  call feedkeys("A\<c-k>a:\<esc>", 'tnix')
645  call assert_equal(['ä'], getline(1, '$'))
646  call test_override("char_avail", 0)
647  set noshowcmd
648
649  bw!
650endfunc
651
652func Test_edit_CTRL_L()
653  " Test Ctrl-X Ctrl-L (line completion)
654  new
655  set complete=.
656  call setline(1, ['one', 'two', 'three', '', '', '', ''])
657  call cursor(4, 1)
658  call feedkeys("A\<c-x>\<c-l>\<esc>", 'tnix')
659  call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$'))
660  call feedkeys("cct\<c-x>\<c-l>\<c-n>\<esc>", 'tnix')
661  call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$'))
662  call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<esc>", 'tnix')
663  call assert_equal(['one', 'two', 'three', 'two', '', '', ''], getline(1, '$'))
664  call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<c-n>\<esc>", 'tnix')
665  call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$'))
666  call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<c-n>\<c-n>\<esc>", 'tnix')
667  call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$'))
668  call feedkeys("cct\<c-x>\<c-l>\<c-p>\<esc>", 'tnix')
669  call assert_equal(['one', 'two', 'three', 'two', '', '', ''], getline(1, '$'))
670  call feedkeys("cct\<c-x>\<c-l>\<c-p>\<c-p>\<esc>", 'tnix')
671  call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$'))
672  call feedkeys("cct\<c-x>\<c-l>\<c-p>\<c-p>\<c-p>\<esc>", 'tnix')
673  call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$'))
674  set complete=
675  call cursor(5, 1)
676  call feedkeys("A\<c-x>\<c-l>\<c-p>\<c-n>\<esc>", 'tnix')
677  call assert_equal(['one', 'two', 'three', 'three', "\<c-l>\<c-p>\<c-n>", '', ''], getline(1, '$'))
678  set complete&
679  %d
680  if has("conceal") && has("syntax")
681    call setline(1, ['foo', 'bar', 'foobar'])
682    call test_override("char_avail", 1)
683    set conceallevel=2 concealcursor=n
684    syn on
685    syn match ErrorMsg "^bar"
686    call matchadd("Conceal", 'oo', 10, -1, {'conceal': 'X'})
687    func! DoIt()
688      let g:change=1
689    endfunc
690    au! TextChangedI <buffer> :call DoIt()
691
692    call cursor(2, 1)
693    call assert_false(exists("g:change"))
694    call feedkeys("A \<esc>", 'tnix')
695    call assert_equal(['foo', 'bar ', 'foobar'], getline(1, '$'))
696    call assert_equal(1, g:change)
697
698    call test_override("char_avail", 0)
699    call clearmatches()
700    syn off
701    au! TextChangedI
702    delfu DoIt
703    unlet! g:change
704  endif
705  bw!
706endfunc
707
708func Test_edit_CTRL_N()
709  " Check keyword completion
710  for e in ['latin1', 'utf-8']
711    exe 'set encoding=' .. e
712    new
713    set complete=.
714    call setline(1, ['INFER', 'loWER', '', '', ])
715    call cursor(3, 1)
716    call feedkeys("Ai\<c-n>\<cr>\<esc>", "tnix")
717    call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix')
718    call assert_equal(['INFER', 'loWER', 'i', 'LO', '', ''], getline(1, '$'), e)
719    %d
720    call setline(1, ['INFER', 'loWER', '', '', ])
721    call cursor(3, 1)
722    set ignorecase infercase
723    call feedkeys("Ii\<c-n>\<cr>\<esc>", "tnix")
724    call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix')
725    call assert_equal(['INFER', 'loWER', 'infer', 'LOWER', '', ''], getline(1, '$'), e)
726
727    set noignorecase noinfercase complete&
728    bw!
729  endfor
730endfunc
731
732func Test_edit_CTRL_O()
733  " Check for CTRL-O in insert mode
734  new
735  inoreabbr <buffer> h here some more
736  call setline(1, ['abc', 'def'])
737  call cursor(1, 1)
738  " Ctrl-O after an abbreviation
739  exe "norm A h\<c-o>:set nu\<cr> text"
740  call assert_equal(['abc here some more text', 'def'], getline(1, '$'))
741  call assert_true(&nu)
742  set nonu
743  iunabbr <buffer> h
744  " Ctrl-O at end of line with 've'=onemore
745  call cursor(1, 1)
746  call feedkeys("A\<c-o>:let g:a=getpos('.')\<cr>\<esc>", 'tnix')
747  call assert_equal([0, 1, 23, 0], g:a)
748  call cursor(1, 1)
749  set ve=onemore
750  call feedkeys("A\<c-o>:let g:a=getpos('.')\<cr>\<esc>", 'tnix')
751  call assert_equal([0, 1, 24, 0], g:a)
752  set ve=
753  unlet! g:a
754  bw!
755endfunc
756
757func Test_edit_CTRL_R()
758  " Insert Register
759  new
760  call test_override("ALL", 1)
761  set showcmd
762  call feedkeys("AFOOBAR eins zwei\<esc>", 'tnix')
763  call feedkeys("O\<c-r>.", 'tnix')
764  call feedkeys("O\<c-r>=10*500\<cr>\<esc>", 'tnix')
765  call feedkeys("O\<c-r>=getreg('=', 1)\<cr>\<esc>", 'tnix')
766  call assert_equal(["getreg('=', 1)", '5000', "FOOBAR eins zwei", "FOOBAR eins zwei"], getline(1, '$'))
767  call test_override("ALL", 0)
768  set noshowcmd
769  bw!
770endfunc
771
772func Test_edit_CTRL_S()
773  " Test pressing CTRL-S (basically only spellfile completion)
774  " the rest is already covered
775  new
776  if !has("spell")
777    call setline(1, 'vim')
778    call feedkeys("A\<c-x>ss\<cr>\<esc>", 'tnix')
779    call assert_equal(['vims', ''], getline(1, '$'))
780    bw!
781    return
782  endif
783  call setline(1, 'vim')
784  " spell option not yet set
785  try
786    call feedkeys("A\<c-x>\<c-s>\<cr>\<esc>", 'tnix')
787  catch /^Vim\%((\a\+)\)\=:E756/
788    call assert_true(1, 'error caught')
789  endtry
790  call assert_equal(['vim', ''], getline(1, '$'))
791  %d
792  setl spell spelllang=en
793  call setline(1, 'vim')
794  call cursor(1, 1)
795  call feedkeys("A\<c-x>\<c-s>\<cr>\<esc>", 'tnix')
796  call assert_equal(['Vim', ''], getline(1, '$'))
797  %d
798  call setline(1, 'vim')
799  call cursor(1, 1)
800  call feedkeys("A\<c-x>\<c-s>\<down>\<cr>\<esc>", 'tnix')
801  call assert_equal(['Aim'], getline(1, '$'))
802  %d
803  call setline(1, 'vim')
804  call cursor(1, 1)
805  call feedkeys("A\<c-x>\<c-s>\<c-p>\<cr>\<esc>", 'tnix')
806  call assert_equal(['vim', ''], getline(1, '$'))
807  %d
808  " empty buffer
809  call cursor(1, 1)
810  call feedkeys("A\<c-x>\<c-s>\<c-p>\<cr>\<esc>", 'tnix')
811  call assert_equal(['', ''], getline(1, '$'))
812  setl nospell
813  bw!
814endfunc
815
816func Test_edit_CTRL_T()
817  " Check for CTRL-T and CTRL-X CTRL-T in insert mode
818  " 1) increase indent
819  new
820  call setline(1, "abc")
821  call cursor(1, 1)
822  call feedkeys("A\<c-t>xyz", 'tnix')
823  call assert_equal(["\<tab>abcxyz"], getline(1, '$'))
824  " 2) also when paste option is set
825  set paste
826  call setline(1, "abc")
827  call cursor(1, 1)
828  call feedkeys("A\<c-t>xyz", 'tnix')
829  call assert_equal(["\<tab>abcxyz"], getline(1, '$'))
830  set nopaste
831  " CTRL-X CTRL-T (thesaurus complete)
832  call writefile(['angry furious mad enraged'], 'Xthesaurus')
833  set thesaurus=Xthesaurus
834  call setline(1, 'mad')
835  call cursor(1, 1)
836  call feedkeys("A\<c-x>\<c-t>\<cr>\<esc>", 'tnix')
837  call assert_equal(['mad', ''], getline(1, '$'))
838  %d
839  call setline(1, 'mad')
840  call cursor(1, 1)
841  call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix')
842  call assert_equal(['angry', ''], getline(1, '$'))
843  %d
844  call setline(1, 'mad')
845  call cursor(1, 1)
846  call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<cr>\<esc>", 'tnix')
847  call assert_equal(['furious', ''], getline(1, '$'))
848  %d
849  call setline(1, 'mad')
850  call cursor(1, 1)
851  call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix')
852  call assert_equal(['enraged', ''], getline(1, '$'))
853  %d
854  call setline(1, 'mad')
855  call cursor(1, 1)
856  call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix')
857  call assert_equal(['mad', ''], getline(1, '$'))
858  %d
859  call setline(1, 'mad')
860  call cursor(1, 1)
861  call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix')
862  call assert_equal(['mad', ''], getline(1, '$'))
863  " Using <c-p> <c-n> when 'complete' is empty
864  set complete=
865  %d
866  call setline(1, 'mad')
867  call cursor(1, 1)
868  call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix')
869  call assert_equal(['angry', ''], getline(1, '$'))
870  %d
871  call setline(1, 'mad')
872  call cursor(1, 1)
873  call feedkeys("A\<c-x>\<c-t>\<c-p>\<cr>\<esc>", 'tnix')
874  call assert_equal(['mad', ''], getline(1, '$'))
875  set complete&
876
877  set thesaurus=
878  %d
879  call setline(1, 'mad')
880  call cursor(1, 1)
881  let v:testing = 1
882  try
883    call feedkeys("A\<c-x>\<c-t>\<esc>", 'tnix')
884  catch
885    " error sleeps 2 seconds, when v:testing is not set
886    let v:testing = 0
887  endtry
888  call assert_equal(['mad'], getline(1, '$'))
889  call delete('Xthesaurus')
890  bw!
891endfunc
892
893" Test 'thesaurusfunc'
894func MyThesaurus(findstart, base)
895  let mythesaurus = [
896        \ #{word: "happy",
897        \   synonyms: "cheerful,blissful,flying high,looking good,peppy"},
898        \ #{word: "kind",
899        \   synonyms: "amiable,bleeding-heart,heart in right place"}]
900  if a:findstart
901    " locate the start of the word
902    let line = getline('.')
903    let start = col('.') - 1
904    while start > 0 && line[start - 1] =~ '\a'
905      let start -= 1
906    endwhile
907    return start
908  else
909    " find strings matching with "a:base"
910    let res = []
911    for w in mythesaurus
912      if w.word =~ '^' . a:base
913        call add(res, w.word)
914        call extend(res, split(w.synonyms, ","))
915      endif
916    endfor
917    return res
918  endif
919endfunc
920
921func Test_thesaurus_func()
922  new
923  set thesaurus=
924  set thesaurusfunc=MyThesaurus
925  call setline(1, "an ki")
926  call cursor(1, 1)
927  call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix')
928  call assert_equal(['an amiable', ''], getline(1, '$'))
929  set thesaurusfunc=NonExistingFunc
930  call assert_fails("normal $a\<C-X>\<C-T>", 'E117:')
931  set thesaurusfunc&
932  %bw!
933endfunc
934
935func Test_edit_CTRL_U()
936  " Test 'completefunc'
937  new
938  " -1, -2 and -3 are special return values
939  let g:special=0
940  fun! CompleteMonths(findstart, base)
941    if a:findstart
942      " locate the start of the word
943      return g:special
944    else
945      " find months matching with "a:base"
946      let res = []
947      for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")
948        if m =~ '^\c'.a:base
949          call add(res, {'word': m, 'abbr': m.' Month', 'icase': 0})
950        endif
951      endfor
952      return {'words': res, 'refresh': 'always'}
953    endif
954  endfun
955  set completefunc=CompleteMonths
956  call setline(1, ['', ''])
957  call cursor(1, 1)
958  call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix')
959  call assert_equal(['X', '', ''], getline(1, '$'))
960  %d
961  let g:special=-1
962  call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix')
963  call assert_equal(['XJan', ''], getline(1, '$'))
964  %d
965  let g:special=-2
966  call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix')
967  call assert_equal(['X', ''], getline(1, '$'))
968  %d
969  let g:special=-3
970  call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix')
971  call assert_equal(['X', ''], getline(1, '$'))
972  %d
973  let g:special=0
974  call feedkeys("AM\<c-x>\<c-u>\<cr>\<esc>", 'tnix')
975  call assert_equal(['Mar', ''], getline(1, '$'))
976  %d
977  call feedkeys("AM\<c-x>\<c-u>\<c-n>\<cr>\<esc>", 'tnix')
978  call assert_equal(['May', ''], getline(1, '$'))
979  %d
980  call feedkeys("AM\<c-x>\<c-u>\<c-n>\<c-n>\<cr>\<esc>", 'tnix')
981  call assert_equal(['M', ''], getline(1, '$'))
982  delfu CompleteMonths
983  %d
984  try
985    call feedkeys("A\<c-x>\<c-u>", 'tnix')
986    call assert_fails(1, 'unknown completion function')
987  catch /^Vim\%((\a\+)\)\=:E117/
988    call assert_true(1, 'E117 error caught')
989  endtry
990  set completefunc=
991  bw!
992endfunc
993
994func Test_edit_completefunc_delete()
995  func CompleteFunc(findstart, base)
996    if a:findstart == 1
997      return col('.') - 1
998    endif
999    normal dd
1000    return ['a', 'b']
1001  endfunc
1002  new
1003  set completefunc=CompleteFunc
1004  call setline(1, ['', 'abcd', ''])
1005  2d
1006  call assert_fails("normal 2G$a\<C-X>\<C-U>", 'E578:')
1007  bwipe!
1008endfunc
1009
1010
1011func Test_edit_CTRL_Z()
1012  " Ctrl-Z when insertmode is not set inserts it literally
1013  new
1014  call setline(1, 'abc')
1015  call feedkeys("A\<c-z>\<esc>", 'tnix')
1016  call assert_equal(["abc\<c-z>"], getline(1,'$'))
1017  bw!
1018  " TODO: How to Test Ctrl-Z in insert mode, e.g. suspend?
1019endfunc
1020
1021func Test_edit_DROP()
1022  CheckFeature dnd
1023  new
1024  call setline(1, ['abc def ghi'])
1025  call cursor(1, 1)
1026  try
1027    call feedkeys("i\<Drop>\<Esc>", 'tnix')
1028    call assert_fails(1, 'Invalid register name')
1029  catch /^Vim\%((\a\+)\)\=:E353/
1030    call assert_true(1, 'error caught')
1031  endtry
1032  bw!
1033endfunc
1034
1035func Test_edit_CTRL_V()
1036  CheckFeature ebcdic
1037  new
1038  call setline(1, ['abc'])
1039  call cursor(2, 1)
1040  " force some redraws
1041  set showmode showcmd
1042  "call test_override_char_avail(1)
1043  call test_override('ALL', 1)
1044  call feedkeys("A\<c-v>\<c-n>\<c-v>\<c-l>\<c-v>\<c-b>\<esc>", 'tnix')
1045  call assert_equal(["abc\x0e\x0c\x02"], getline(1, '$'))
1046
1047  if has("rightleft") && exists("+rl")
1048    set rl
1049    call setline(1, ['abc'])
1050    call cursor(2, 1)
1051    call feedkeys("A\<c-v>\<c-n>\<c-v>\<c-l>\<c-v>\<c-b>\<esc>", 'tnix')
1052    call assert_equal(["abc\x0e\x0c\x02"], getline(1, '$'))
1053    set norl
1054  endif
1055
1056  call test_override('ALL', 0)
1057  set noshowmode showcmd
1058  bw!
1059endfunc
1060
1061func Test_edit_F1()
1062  CheckFeature quickfix
1063
1064  " Pressing <f1>
1065  new
1066  call feedkeys(":set im\<cr>\<f1>\<c-l>", 'tnix')
1067  set noinsertmode
1068  call assert_equal('help', &buftype)
1069  bw
1070  bw
1071endfunc
1072
1073func Test_edit_F21()
1074  " Pressing <f21>
1075  " sends a netbeans command
1076  CheckFeature netbeans_intg
1077  new
1078  " I have no idea what this is supposed to do :)
1079  call feedkeys("A\<F21>\<F1>\<esc>", 'tnix')
1080  bw
1081endfunc
1082
1083func Test_edit_HOME_END()
1084  " Test Home/End Keys
1085  new
1086  set foldopen+=hor
1087  call setline(1, ['abc', 'def'])
1088  call cursor(1, 1)
1089  call feedkeys("AX\<Home>Y\<esc>", 'tnix')
1090  call cursor(2, 1)
1091  call feedkeys("iZ\<End>Y\<esc>", 'tnix')
1092  call assert_equal(['YabcX', 'ZdefY'], getline(1, '$'))
1093
1094  set foldopen-=hor
1095  bw!
1096endfunc
1097
1098func Test_edit_INS()
1099  " Test for Pressing <Insert>
1100  new
1101  call setline(1, ['abc', 'def'])
1102  call cursor(1, 1)
1103  call feedkeys("i\<Insert>ZYX>", 'tnix')
1104  call assert_equal(['ZYX>', 'def'], getline(1, '$'))
1105  call setline(1, ['abc', 'def'])
1106  call cursor(1, 1)
1107  call feedkeys("i\<Insert>Z\<Insert>YX>", 'tnix')
1108  call assert_equal(['ZYX>bc', 'def'], getline(1, '$'))
1109  bw!
1110endfunc
1111
1112func Test_edit_LEFT_RIGHT()
1113  " Left, Shift-Left, Right, Shift-Right
1114  new
1115  call setline(1, ['abc def ghi', 'ABC DEF GHI', 'ZZZ YYY XXX'])
1116  let _ww=&ww
1117  set ww=
1118  call cursor(2, 1)
1119  call feedkeys("i\<left>\<esc>", 'tnix')
1120  call assert_equal([0, 2, 1, 0], getpos('.'))
1121  " Is this a bug, <s-left> does not respect whichwrap option
1122  call feedkeys("i\<s-left>\<esc>", 'tnix')
1123  call assert_equal([0, 1, 8, 0], getpos('.'))
1124  call feedkeys("i". repeat("\<s-left>", 3). "\<esc>", 'tnix')
1125  call assert_equal([0, 1, 1, 0], getpos('.'))
1126  call feedkeys("i\<right>\<esc>", 'tnix')
1127  call assert_equal([0, 1, 1, 0], getpos('.'))
1128  call feedkeys("i\<right>\<right>\<esc>", 'tnix')
1129  call assert_equal([0, 1, 2, 0], getpos('.'))
1130  call feedkeys("A\<right>\<esc>", 'tnix')
1131  call assert_equal([0, 1, 11, 0], getpos('.'))
1132  call feedkeys("A\<s-right>\<esc>", 'tnix')
1133  call assert_equal([0, 2, 1, 0], getpos('.'))
1134  call feedkeys("i\<s-right>\<esc>", 'tnix')
1135  call assert_equal([0, 2, 4, 0], getpos('.'))
1136  call cursor(3, 11)
1137  call feedkeys("A\<right>\<esc>", 'tnix')
1138  call feedkeys("A\<s-right>\<esc>", 'tnix')
1139  call assert_equal([0, 3, 11, 0], getpos('.'))
1140  call cursor(2, 11)
1141  " <S-Right> does not respect 'whichwrap' option
1142  call feedkeys("A\<s-right>\<esc>", 'tnix')
1143  call assert_equal([0, 3, 1, 0], getpos('.'))
1144  " Check motion when 'whichwrap' contains cursor keys for insert mode
1145  set ww+=[,]
1146  call cursor(2, 1)
1147  call feedkeys("i\<left>\<esc>", 'tnix')
1148  call assert_equal([0, 1, 11, 0], getpos('.'))
1149  call cursor(2, 11)
1150  call feedkeys("A\<right>\<esc>", 'tnix')
1151  call assert_equal([0, 3, 1, 0], getpos('.'))
1152  call cursor(2, 11)
1153  call feedkeys("A\<s-right>\<esc>", 'tnix')
1154  call assert_equal([0, 3, 1, 0], getpos('.'))
1155  let &ww = _ww
1156  bw!
1157endfunc
1158
1159func Test_edit_MOUSE()
1160  " This is a simple test, since we not really using the mouse here
1161  CheckFeature mouse
1162  10new
1163  call setline(1, range(1, 100))
1164  call cursor(1, 1)
1165  set mouse=a
1166  call feedkeys("A\<ScrollWheelDown>\<esc>", 'tnix')
1167  call assert_equal([0, 4, 1, 0], getpos('.'))
1168  " This should move by one pageDown, but only moves
1169  " by one line when the test is run...
1170  call feedkeys("A\<S-ScrollWheelDown>\<esc>", 'tnix')
1171  call assert_equal([0, 5, 1, 0], getpos('.'))
1172  set nostartofline
1173  call feedkeys("A\<C-ScrollWheelDown>\<esc>", 'tnix')
1174  call assert_equal([0, 6, 1, 0], getpos('.'))
1175  call feedkeys("A\<LeftMouse>\<esc>", 'tnix')
1176  call assert_equal([0, 6, 1, 0], getpos('.'))
1177  call feedkeys("A\<RightMouse>\<esc>", 'tnix')
1178  call assert_equal([0, 6, 1, 0], getpos('.'))
1179  call cursor(1, 100)
1180  norm! zt
1181  " this should move by a screen up, but when the test
1182  " is run, it moves up to the top of the buffer...
1183  call feedkeys("A\<ScrollWheelUp>\<esc>", 'tnix')
1184  call assert_equal([0, 1, 1, 0], getpos('.'))
1185  call cursor(1, 30)
1186  norm! zt
1187  call feedkeys("A\<S-ScrollWheelUp>\<esc>", 'tnix')
1188  call assert_equal([0, 1, 1, 0], getpos('.'))
1189  call cursor(1, 30)
1190  norm! zt
1191  call feedkeys("A\<C-ScrollWheelUp>\<esc>", 'tnix')
1192  call assert_equal([0, 1, 1, 0], getpos('.'))
1193  %d
1194  call setline(1, repeat(["12345678901234567890"], 100))
1195  call cursor(2, 1)
1196  call feedkeys("A\<ScrollWheelRight>\<esc>", 'tnix')
1197  call assert_equal([0, 2, 20, 0], getpos('.'))
1198  call feedkeys("A\<ScrollWheelLeft>\<esc>", 'tnix')
1199  call assert_equal([0, 2, 20, 0], getpos('.'))
1200  call feedkeys("A\<S-ScrollWheelRight>\<esc>", 'tnix')
1201  call assert_equal([0, 2, 20, 0], getpos('.'))
1202  call feedkeys("A\<S-ScrollWheelLeft>\<esc>", 'tnix')
1203  call assert_equal([0, 2, 20, 0], getpos('.'))
1204  call feedkeys("A\<C-ScrollWheelRight>\<esc>", 'tnix')
1205  call assert_equal([0, 2, 20, 0], getpos('.'))
1206  call feedkeys("A\<C-ScrollWheelLeft>\<esc>", 'tnix')
1207  call assert_equal([0, 2, 20, 0], getpos('.'))
1208  set mouse& startofline
1209  bw!
1210endfunc
1211
1212func Test_edit_PAGEUP_PAGEDOWN()
1213  10new
1214  call setline(1, repeat(['abc def ghi'], 30))
1215  call cursor(1, 1)
1216  call feedkeys("i\<PageDown>\<esc>", 'tnix')
1217  call assert_equal([0, 9, 1, 0], getpos('.'))
1218  call feedkeys("i\<PageDown>\<esc>", 'tnix')
1219  call assert_equal([0, 17, 1, 0], getpos('.'))
1220  call feedkeys("i\<PageDown>\<esc>", 'tnix')
1221  call assert_equal([0, 25, 1, 0], getpos('.'))
1222  call feedkeys("i\<PageDown>\<esc>", 'tnix')
1223  call assert_equal([0, 30, 1, 0], getpos('.'))
1224  call feedkeys("i\<PageDown>\<esc>", 'tnix')
1225  call assert_equal([0, 30, 1, 0], getpos('.'))
1226  call feedkeys("A\<PageUp>\<esc>", 'tnix')
1227  call assert_equal([0, 29, 1, 0], getpos('.'))
1228  call feedkeys("A\<PageUp>\<esc>", 'tnix')
1229  call assert_equal([0, 21, 1, 0], getpos('.'))
1230  call feedkeys("A\<PageUp>\<esc>", 'tnix')
1231  call assert_equal([0, 13, 1, 0], getpos('.'))
1232  call feedkeys("A\<PageUp>\<esc>", 'tnix')
1233  call assert_equal([0, 5, 1, 0], getpos('.'))
1234  call feedkeys("A\<PageUp>\<esc>", 'tnix')
1235  call assert_equal([0, 5, 11, 0], getpos('.'))
1236  " <S-Up> is the same as <PageUp>
1237  " <S-Down> is the same as <PageDown>
1238  call cursor(1, 1)
1239  call feedkeys("i\<S-Down>\<esc>", 'tnix')
1240  call assert_equal([0, 9, 1, 0], getpos('.'))
1241  call feedkeys("i\<S-Down>\<esc>", 'tnix')
1242  call assert_equal([0, 17, 1, 0], getpos('.'))
1243  call feedkeys("i\<S-Down>\<esc>", 'tnix')
1244  call assert_equal([0, 25, 1, 0], getpos('.'))
1245  call feedkeys("i\<S-Down>\<esc>", 'tnix')
1246  call assert_equal([0, 30, 1, 0], getpos('.'))
1247  call feedkeys("i\<S-Down>\<esc>", 'tnix')
1248  call assert_equal([0, 30, 1, 0], getpos('.'))
1249  call feedkeys("A\<S-Up>\<esc>", 'tnix')
1250  call assert_equal([0, 29, 1, 0], getpos('.'))
1251  call feedkeys("A\<S-Up>\<esc>", 'tnix')
1252  call assert_equal([0, 21, 1, 0], getpos('.'))
1253  call feedkeys("A\<S-Up>\<esc>", 'tnix')
1254  call assert_equal([0, 13, 1, 0], getpos('.'))
1255  call feedkeys("A\<S-Up>\<esc>", 'tnix')
1256  call assert_equal([0, 5, 1, 0], getpos('.'))
1257  call feedkeys("A\<S-Up>\<esc>", 'tnix')
1258  call assert_equal([0, 5, 11, 0], getpos('.'))
1259  set nostartofline
1260  call cursor(30, 11)
1261  norm! zt
1262  call feedkeys("A\<PageUp>\<esc>", 'tnix')
1263  call assert_equal([0, 29, 11, 0], getpos('.'))
1264  call feedkeys("A\<PageUp>\<esc>", 'tnix')
1265  call assert_equal([0, 21, 11, 0], getpos('.'))
1266  call feedkeys("A\<PageUp>\<esc>", 'tnix')
1267  call assert_equal([0, 13, 11, 0], getpos('.'))
1268  call feedkeys("A\<PageUp>\<esc>", 'tnix')
1269  call assert_equal([0, 5, 11, 0], getpos('.'))
1270  call feedkeys("A\<PageUp>\<esc>", 'tnix')
1271  call assert_equal([0, 5, 11, 0], getpos('.'))
1272  call cursor(1, 1)
1273  call feedkeys("A\<PageDown>\<esc>", 'tnix')
1274  call assert_equal([0, 9, 11, 0], getpos('.'))
1275  call feedkeys("A\<PageDown>\<esc>", 'tnix')
1276  call assert_equal([0, 17, 11, 0], getpos('.'))
1277  call feedkeys("A\<PageDown>\<esc>", 'tnix')
1278  call assert_equal([0, 25, 11, 0], getpos('.'))
1279  call feedkeys("A\<PageDown>\<esc>", 'tnix')
1280  call assert_equal([0, 30, 11, 0], getpos('.'))
1281  call feedkeys("A\<PageDown>\<esc>", 'tnix')
1282  call assert_equal([0, 30, 11, 0], getpos('.'))
1283  " <S-Up> is the same as <PageUp>
1284  " <S-Down> is the same as <PageDown>
1285  call cursor(30, 11)
1286  norm! zt
1287  call feedkeys("A\<S-Up>\<esc>", 'tnix')
1288  call assert_equal([0, 29, 11, 0], getpos('.'))
1289  call feedkeys("A\<S-Up>\<esc>", 'tnix')
1290  call assert_equal([0, 21, 11, 0], getpos('.'))
1291  call feedkeys("A\<S-Up>\<esc>", 'tnix')
1292  call assert_equal([0, 13, 11, 0], getpos('.'))
1293  call feedkeys("A\<S-Up>\<esc>", 'tnix')
1294  call assert_equal([0, 5, 11, 0], getpos('.'))
1295  call feedkeys("A\<S-Up>\<esc>", 'tnix')
1296  call assert_equal([0, 5, 11, 0], getpos('.'))
1297  call cursor(1, 1)
1298  call feedkeys("A\<S-Down>\<esc>", 'tnix')
1299  call assert_equal([0, 9, 11, 0], getpos('.'))
1300  call feedkeys("A\<S-Down>\<esc>", 'tnix')
1301  call assert_equal([0, 17, 11, 0], getpos('.'))
1302  call feedkeys("A\<S-Down>\<esc>", 'tnix')
1303  call assert_equal([0, 25, 11, 0], getpos('.'))
1304  call feedkeys("A\<S-Down>\<esc>", 'tnix')
1305  call assert_equal([0, 30, 11, 0], getpos('.'))
1306  call feedkeys("A\<S-Down>\<esc>", 'tnix')
1307  call assert_equal([0, 30, 11, 0], getpos('.'))
1308  bw!
1309endfunc
1310
1311func Test_edit_forbidden()
1312  new
1313  " 1) edit in the sandbox is not allowed
1314  call setline(1, 'a')
1315  com! Sandbox :sandbox call feedkeys("i\<del>\<esc>", 'tnix')
1316  call assert_fails(':Sandbox', 'E48:')
1317  com! Sandbox :sandbox exe "norm! i\<del>"
1318  call assert_fails(':Sandbox', 'E48:')
1319  delcom Sandbox
1320  call assert_equal(['a'], getline(1,'$'))
1321  " 2) edit with textlock set
1322  fu! DoIt()
1323    call feedkeys("i\<del>\<esc>", 'tnix')
1324  endfu
1325  au InsertCharPre <buffer> :call DoIt()
1326  try
1327    call feedkeys("ix\<esc>", 'tnix')
1328    call assert_fails(1, 'textlock')
1329  catch /^Vim\%((\a\+)\)\=:E565/ " catch E565: not allowed here
1330  endtry
1331  " TODO: Might be a bug: should x really be inserted here
1332  call assert_equal(['xa'], getline(1, '$'))
1333  delfu DoIt
1334  try
1335    call feedkeys("ix\<esc>", 'tnix')
1336    call assert_fails(1, 'unknown function')
1337  catch /^Vim\%((\a\+)\)\=:E117/ " catch E117: unknown function
1338  endtry
1339  au! InsertCharPre
1340  " 3) edit when completion is shown
1341  fun! Complete(findstart, base)
1342    if a:findstart
1343      return col('.')
1344    else
1345      call feedkeys("i\<del>\<esc>", 'tnix')
1346      return []
1347    endif
1348  endfun
1349  set completefunc=Complete
1350  try
1351    call feedkeys("i\<c-x>\<c-u>\<esc>", 'tnix')
1352    call assert_fails(1, 'change in complete function')
1353  catch /^Vim\%((\a\+)\)\=:E565/ " catch E565
1354  endtry
1355  delfu Complete
1356  set completefunc=
1357  if has("rightleft") && exists("+fkmap")
1358    " 4) 'R' when 'fkmap' and 'revins' is set.
1359    set revins fkmap
1360    try
1361      normal Ri
1362      call assert_fails(1, "R with 'fkmap' and 'ri' set")
1363    catch
1364    finally
1365      set norevins nofkmap
1366    endtry
1367  endif
1368  bw!
1369endfunc
1370
1371func Test_edit_rightleft()
1372  " Cursor in rightleft mode moves differently
1373  CheckFeature rightleft
1374  call NewWindow(10, 20)
1375  call setline(1, ['abc', 'def', 'ghi'])
1376  call cursor(1, 2)
1377  set rightleft
1378  " Screen looks as expected
1379  let lines = ScreenLines([1, 4], winwidth(0))
1380  let expect = [
1381        \"                 cba",
1382        \"                 fed",
1383        \"                 ihg",
1384        \"                   ~"]
1385  call assert_equal(join(expect, "\n"), join(lines, "\n"))
1386  " 2) right moves to the left
1387  call feedkeys("i\<right>\<esc>x", 'txin')
1388  call assert_equal(['bc', 'def', 'ghi'], getline(1,'$'))
1389  call cursor(1, 2)
1390  call feedkeys("i\<s-right>\<esc>", 'txin')
1391  call cursor(1, 2)
1392  call feedkeys("i\<c-right>\<esc>", 'txin')
1393  " Screen looks as expected
1394  let lines = ScreenLines([1, 4], winwidth(0))
1395  let expect = [
1396        \"                  cb",
1397        \"                 fed",
1398        \"                 ihg",
1399        \"                   ~"]
1400  call assert_equal(join(expect, "\n"), join(lines, "\n"))
1401  " 2) left moves to the right
1402  call setline(1, ['abc', 'def', 'ghi'])
1403  call cursor(1, 2)
1404  call feedkeys("i\<left>\<esc>x", 'txin')
1405  call assert_equal(['ac', 'def', 'ghi'], getline(1,'$'))
1406  call cursor(1, 2)
1407  call feedkeys("i\<s-left>\<esc>", 'txin')
1408  call cursor(1, 2)
1409  call feedkeys("i\<c-left>\<esc>", 'txin')
1410  " Screen looks as expected
1411  let lines = ScreenLines([1, 4], winwidth(0))
1412  let expect = [
1413        \"                  ca",
1414        \"                 fed",
1415        \"                 ihg",
1416        \"                   ~"]
1417  call assert_equal(join(expect, "\n"), join(lines, "\n"))
1418  %d _
1419  call test_override('redraw_flag', 1)
1420  call test_override('char_avail', 1)
1421  call feedkeys("a\<C-V>x41", "xt")
1422  redraw!
1423  call assert_equal(repeat(' ', 19) .. 'A', Screenline(1))
1424  call test_override('ALL', 0)
1425  set norightleft
1426  bw!
1427endfunc
1428
1429func Test_edit_complete_very_long_name()
1430  " Long directory names only work on Unix.
1431  CheckUnix
1432
1433  let dirname = getcwd() . "/Xdir"
1434  let longdirname = dirname . repeat('/' . repeat('d', 255), 4)
1435  try
1436    call mkdir(longdirname, 'p')
1437  catch /E739:/
1438    " Long directory name probably not supported.
1439    call delete(dirname, 'rf')
1440    return
1441  endtry
1442
1443  " Try to get the Vim window position before setting 'columns', so that we can
1444  " move the window back to where it was.
1445  let winposx = getwinposx()
1446  let winposy = getwinposy()
1447
1448  if winposx >= 0 && winposy >= 0 && !has('gui_running')
1449    " We did get the window position, but xterm may report the wrong numbers.
1450    " Move the window to the reported position and compute any offset.
1451    exe 'winpos ' . winposx . ' ' . winposy
1452    sleep 100m
1453    let x = getwinposx()
1454    if x >= 0
1455      let winposx += winposx - x
1456    endif
1457    let y = getwinposy()
1458    if y >= 0
1459      let winposy += winposy - y
1460    endif
1461  endif
1462
1463  let save_columns = &columns
1464  " Need at least about 1100 columns to reproduce the problem.
1465  set columns=2000
1466  set noswapfile
1467
1468  let longfilename = longdirname . '/' . repeat('a', 255)
1469  call writefile(['Totum', 'Table'], longfilename)
1470  new
1471  exe "next Xfile " . longfilename
1472  exe "normal iT\<C-N>"
1473
1474  bwipe!
1475  exe 'bwipe! ' . longfilename
1476  call delete(dirname, 'rf')
1477  let &columns = save_columns
1478  if winposx >= 0 && winposy >= 0
1479    exe 'winpos ' . winposx . ' ' . winposy
1480  endif
1481  set swapfile&
1482endfunc
1483
1484func Test_edit_backtick()
1485  next a\`b c
1486  call assert_equal('a`b', expand('%'))
1487  next
1488  call assert_equal('c', expand('%'))
1489  call assert_equal('a\`b c', expand('##'))
1490endfunc
1491
1492func Test_edit_quit()
1493  edit foo.txt
1494  split
1495  new
1496  call setline(1, 'hello')
1497  3wincmd w
1498  redraw!
1499  call assert_fails('1q', 'E37:')
1500  bwipe! foo.txt
1501  only
1502endfunc
1503
1504func Test_edit_alt()
1505  " Keeping the cursor line didn't happen when the first line has indent.
1506  new
1507  call setline(1, ['  one', 'two', 'three'])
1508  w XAltFile
1509  $
1510  call assert_equal(3, line('.'))
1511  e Xother
1512  e #
1513  call assert_equal(3, line('.'))
1514
1515  bwipe XAltFile
1516  call delete('XAltFile')
1517endfunc
1518
1519func Test_edit_InsertLeave()
1520  new
1521  au InsertLeavePre * let g:did_au_pre = 1
1522  au InsertLeave * let g:did_au = 1
1523  let g:did_au_pre = 0
1524  let g:did_au = 0
1525  call feedkeys("afoo\<Esc>", 'tx')
1526  call assert_equal(1, g:did_au_pre)
1527  call assert_equal(1, g:did_au)
1528  call assert_equal('foo', getline(1))
1529
1530  let g:did_au_pre = 0
1531  let g:did_au = 0
1532  call feedkeys("Sbar\<C-C>", 'tx')
1533  call assert_equal(1, g:did_au_pre)
1534  call assert_equal(0, g:did_au)
1535  call assert_equal('bar', getline(1))
1536
1537  inoremap x xx<Esc>
1538  let g:did_au_pre = 0
1539  let g:did_au = 0
1540  call feedkeys("Saax", 'tx')
1541  call assert_equal(1, g:did_au_pre)
1542  call assert_equal(1, g:did_au)
1543  call assert_equal('aaxx', getline(1))
1544
1545  inoremap x xx<C-C>
1546  let g:did_au_pre = 0
1547  let g:did_au = 0
1548  call feedkeys("Sbbx", 'tx')
1549  call assert_equal(1, g:did_au_pre)
1550  call assert_equal(0, g:did_au)
1551  call assert_equal('bbxx', getline(1))
1552
1553  bwipe!
1554  au! InsertLeave InsertLeavePre
1555  iunmap x
1556endfunc
1557
1558func Test_edit_InsertLeave_undo()
1559  new XtestUndo
1560  set undofile
1561  au InsertLeave * wall
1562  exe "normal ofoo\<Esc>"
1563  call assert_equal(2, line('$'))
1564  normal u
1565  call assert_equal(1, line('$'))
1566
1567  bwipe!
1568  au! InsertLeave
1569  call delete('XtestUndo')
1570  call delete(undofile('XtestUndo'))
1571  set undofile&
1572endfunc
1573
1574" Test for inserting characters using CTRL-V followed by a number.
1575func Test_edit_special_chars()
1576  new
1577
1578  if has("ebcdic")
1579    let t = "o\<C-V>193\<C-V>xc2\<C-V>o303 \<C-V>90a\<C-V>xfg\<C-V>o578\<Esc>"
1580  else
1581    let t = "o\<C-V>65\<C-V>x42\<C-V>o103 \<C-V>33a\<C-V>xfg\<C-V>o78\<Esc>"
1582  endif
1583
1584  exe "normal " . t
1585  call assert_equal("ABC !a\<C-O>g\<C-G>8", getline(2))
1586
1587  close!
1588endfunc
1589
1590func Test_edit_startinsert()
1591  new
1592  set backspace+=start
1593  call setline(1, 'foobar')
1594  call feedkeys("A\<C-U>\<Esc>", 'xt')
1595  call assert_equal('', getline(1))
1596
1597  call setline(1, 'foobar')
1598  call feedkeys(":startinsert!\<CR>\<C-U>\<Esc>", 'xt')
1599  call assert_equal('', getline(1))
1600
1601  set backspace&
1602  bwipe!
1603endfunc
1604
1605" Test for :startreplace and :startgreplace
1606func Test_edit_startreplace()
1607  new
1608  call setline(1, 'abc')
1609  call feedkeys("l:startreplace\<CR>xyz\e", 'xt')
1610  call assert_equal('axyz', getline(1))
1611  call feedkeys("0:startreplace!\<CR>abc\e", 'xt')
1612  call assert_equal('axyzabc', getline(1))
1613  call setline(1, "a\tb")
1614  call feedkeys("0l:startgreplace\<CR>xyz\e", 'xt')
1615  call assert_equal("axyz\tb", getline(1))
1616  call feedkeys("0i\<C-R>=execute('startreplace')\<CR>12\e", 'xt')
1617  call assert_equal("12axyz\tb", getline(1))
1618  close!
1619endfunc
1620
1621func Test_edit_noesckeys()
1622  CheckNotGui
1623  new
1624
1625  " <Left> moves cursor when 'esckeys' is set
1626  exe "set t_kl=\<Esc>OD"
1627  set esckeys
1628  call feedkeys("axyz\<Esc>ODX", "xt")
1629  call assert_equal("xyXz", getline(1))
1630
1631  " <Left> exits Insert mode when 'esckeys' is off
1632  set noesckeys
1633  call setline(1, '')
1634  call feedkeys("axyz\<Esc>ODX", "xt")
1635  call assert_equal(["DX", "xyz"], getline(1, 2))
1636
1637  bwipe!
1638  set esckeys
1639endfunc
1640
1641" Test for running an invalid ex command in insert mode using CTRL-O
1642func Test_edit_ctrl_o_invalid_cmd()
1643  new
1644  set showmode showcmd
1645  " Avoid a sleep of 3 seconds. Zero might have side effects.
1646  call test_override('ui_delay', 50)
1647  let caught_e492 = 0
1648  try
1649    call feedkeys("i\<C-O>:invalid\<CR>abc\<Esc>", "xt")
1650  catch /E492:/
1651    let caught_e492 = 1
1652  endtry
1653  call assert_equal(1, caught_e492)
1654  call assert_equal('abc', getline(1))
1655  set showmode& showcmd&
1656  call test_override('ui_delay', 0)
1657  close!
1658endfunc
1659
1660" Test for editing a file with a very long name
1661func Test_edit_illegal_filename()
1662  CheckEnglish
1663  new
1664  redir => msg
1665  exe 'edit ' . repeat('f', 5000)
1666  redir END
1667  call assert_match("Illegal file name$", split(msg, "\n")[0])
1668  close!
1669endfunc
1670
1671" Test for editing a directory
1672func Test_edit_is_a_directory()
1673  CheckEnglish
1674  let dirname = getcwd() . "/Xdir"
1675  call mkdir(dirname, 'p')
1676
1677  new
1678  redir => msg
1679  exe 'edit' dirname
1680  redir END
1681  call assert_match("is a directory$", split(msg, "\n")[0])
1682  bwipe!
1683
1684  let dirname .= '/'
1685
1686  new
1687  redir => msg
1688  exe 'edit' dirname
1689  redir END
1690  call assert_match("is a directory$", split(msg, "\n")[0])
1691  bwipe!
1692
1693  call delete(dirname, 'rf')
1694endfunc
1695
1696" Test for editing a file using invalid file encoding
1697func Test_edit_invalid_encoding()
1698  CheckEnglish
1699  call writefile([], 'Xfile')
1700  redir => msg
1701  new ++enc=axbyc Xfile
1702  redir END
1703  call assert_match('\[NOT converted\]', msg)
1704  call delete('Xfile')
1705  close!
1706endfunc
1707
1708" Test for the "charconvert" option
1709func Test_edit_charconvert()
1710  CheckEnglish
1711  call writefile(['one', 'two'], 'Xfile')
1712
1713  " set 'charconvert' to a non-existing function
1714  set charconvert=NonExitingFunc()
1715  new
1716  let caught_e117 = v:false
1717  try
1718    redir => msg
1719    edit ++enc=axbyc Xfile
1720  catch /E117:/
1721    let caught_e117 = v:true
1722  finally
1723    redir END
1724  endtry
1725  call assert_true(caught_e117)
1726  call assert_equal(['one', 'two'], getline(1, '$'))
1727  call assert_match("Conversion with 'charconvert' failed", msg)
1728  close!
1729  set charconvert&
1730
1731  " 'charconvert' function doesn't create a output file
1732  func Cconv1()
1733  endfunc
1734  set charconvert=Cconv1()
1735  new
1736  redir => msg
1737  edit ++enc=axbyc Xfile
1738  redir END
1739  call assert_equal(['one', 'two'], getline(1, '$'))
1740  call assert_match("can't read output of 'charconvert'", msg)
1741  close!
1742  delfunc Cconv1
1743  set charconvert&
1744
1745  " 'charconvert' function to convert to upper case
1746  func Cconv2()
1747    let data = readfile(v:fname_in)
1748    call map(data, 'toupper(v:val)')
1749    call writefile(data, v:fname_out)
1750  endfunc
1751  set charconvert=Cconv2()
1752  new Xfile
1753  write ++enc=ucase Xfile1
1754  call assert_equal(['ONE', 'TWO'], readfile('Xfile1'))
1755  call delete('Xfile1')
1756  close!
1757  delfunc Cconv2
1758  set charconvert&
1759
1760  " 'charconvert' function removes the input file
1761  func Cconv3()
1762    call delete(v:fname_in)
1763  endfunc
1764  set charconvert=Cconv3()
1765  new
1766  call assert_fails('edit ++enc=lcase Xfile', 'E202:')
1767  call assert_equal([''], getline(1, '$'))
1768  close!
1769  delfunc Cconv3
1770  set charconvert&
1771
1772  call delete('Xfile')
1773endfunc
1774
1775" Test for editing a file without read permission
1776func Test_edit_file_no_read_perm()
1777  CheckUnix
1778  CheckNotRoot
1779
1780  call writefile(['one', 'two'], 'Xfile')
1781  call setfperm('Xfile', '-w-------')
1782  new
1783  redir => msg
1784  edit Xfile
1785  redir END
1786  call assert_equal(1, &readonly)
1787  call assert_equal([''], getline(1, '$'))
1788  call assert_match('\[Permission Denied\]', msg)
1789  close!
1790  call delete('Xfile')
1791endfunc
1792
1793" Pressing escape in 'insertmode' should beep
1794func Test_edit_insertmode_esc_beeps()
1795  new
1796  set insertmode
1797  call assert_beeps("call feedkeys(\"one\<Esc>\", 'xt')")
1798  set insertmode&
1799  " unsupported CTRL-G command should beep in insert mode.
1800  call assert_beeps("normal i\<C-G>l")
1801  close!
1802endfunc
1803
1804" Test for 'hkmap' and 'hkmapp'
1805func Test_edit_hkmap()
1806  CheckFeature rightleft
1807  if has('win32') && !has('gui')
1808    throw 'Skipped: fails on the MS-Windows terminal version'
1809  endif
1810  new
1811
1812  set revins hkmap
1813  let str = 'abcdefghijklmnopqrstuvwxyz'
1814  let str ..= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
1815  let str ..= '`/'',.;'
1816  call feedkeys('i' .. str, 'xt')
1817  let expected = "óõú,.;"
1818  let expected ..= "ZYXWVUTSRQPONMLKJIHGFEDCBA"
1819  let expected ..= "æèñ'äåàãø/ôíîöêìçïéòë÷âáðù"
1820  call assert_equal(expected, getline(1))
1821
1822  %d
1823  set revins hkmap hkmapp
1824  let str = 'abcdefghijklmnopqrstuvwxyz'
1825  let str ..= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
1826  call feedkeys('i' .. str, 'xt')
1827  let expected = "õYXWVUTSRQóOïíLKJIHGFEDêBA"
1828  let expected ..= "öòXùåèúæø'ôñðîì÷çéäâóǟãëáà"
1829  call assert_equal(expected, getline(1))
1830
1831  set revins& hkmap& hkmapp&
1832  close!
1833endfunc
1834
1835" Test for 'allowrevins' and using CTRL-_ in insert mode
1836func Test_edit_allowrevins()
1837  CheckFeature rightleft
1838  new
1839  set allowrevins
1840  call feedkeys("iABC\<C-_>DEF\<C-_>GHI", 'xt')
1841  call assert_equal('ABCFEDGHI', getline(1))
1842  set allowrevins&
1843  close!
1844endfunc
1845
1846" Test for inserting a register in insert mode using CTRL-R
1847func Test_edit_insert_reg()
1848  new
1849  let g:Line = ''
1850  func SaveFirstLine()
1851    let g:Line = Screenline(1)
1852    return 'r'
1853  endfunc
1854  inoremap <expr> <buffer> <F2> SaveFirstLine()
1855  call test_override('redraw_flag', 1)
1856  call test_override('char_avail', 1)
1857  let @r = 'sample'
1858  call feedkeys("a\<C-R>=SaveFirstLine()\<CR>", "xt")
1859  call assert_equal('"', g:Line)
1860  call test_override('ALL', 0)
1861  close!
1862endfunc
1863
1864" When a character is inserted at the last position of the last line in a
1865" window, the window contents should be scrolled one line up. If the top line
1866" is part of a fold, then the entire fold should be scrolled up.
1867func Test_edit_lastline_scroll()
1868  new
1869  let h = winheight(0)
1870  let lines = ['one', 'two', 'three']
1871  let lines += repeat(['vim'], h - 4)
1872  call setline(1, lines)
1873  call setline(h, repeat('x', winwidth(0) - 1))
1874  call feedkeys("GAx", 'xt')
1875  redraw!
1876  call assert_equal(h - 1, winline())
1877  call assert_equal(2, line('w0'))
1878
1879  " scroll with a fold
1880  1,2fold
1881  normal gg
1882  call setline(h + 1, repeat('x', winwidth(0) - 1))
1883  call feedkeys("GAx", 'xt')
1884  redraw!
1885  call assert_equal(h - 1, winline())
1886  call assert_equal(3, line('w0'))
1887
1888  close!
1889endfunc
1890
1891func Test_edit_browse()
1892  " in the GUI this opens a file picker, we only test the terminal behavior
1893  CheckNotGui
1894
1895  " ":browse xxx" checks for the FileExplorer augroup and assumes editing "."
1896  " works then.
1897  augroup FileExplorer
1898    au!
1899  augroup END
1900
1901  " When the USE_FNAME_CASE is defined this used to cause a crash.
1902  browse enew
1903  bwipe!
1904
1905  browse split
1906  bwipe!
1907endfunc
1908
1909func Test_read_invalid()
1910  set encoding=latin1
1911  " This was not properly checking for going past the end.
1912  call assert_fails('r`=', 'E484')
1913  set encoding=utf-8
1914endfunc
1915
1916" Test for the 'revins' option
1917func Test_edit_revins()
1918  CheckFeature rightleft
1919  new
1920  set revins
1921  exe "normal! ione\ttwo three"
1922  call assert_equal("eerht owt\teno", getline(1))
1923  call setline(1, "one\ttwo three")
1924  normal! gg$bi a
1925  call assert_equal("one\ttwo a three", getline(1))
1926  exe "normal! $bi\<BS>\<BS>"
1927  call assert_equal("one\ttwo a ree", getline(1))
1928  exe "normal! 0wi\<C-W>"
1929  call assert_equal("one\t a ree", getline(1))
1930  exe "normal! 0wi\<C-U>"
1931  call assert_equal("one\t ", getline(1))
1932  " newline in insert mode starts at the end of the line
1933  call setline(1, 'one two three')
1934  exe "normal! wi\nfour"
1935  call assert_equal(['one two three', 'ruof'], getline(1, '$'))
1936  set revins&
1937  bw!
1938endfunc
1939
1940" Test for getting the character of the line below after "p"
1941func Test_edit_put_CTRL_E()
1942  set encoding=latin1
1943  new
1944  let @" = ''
1945  sil! norm orggRx
1946  sil! norm pr
1947  call assert_equal(['r', 'r'], getline(1, 2))
1948  bwipe!
1949  set encoding=utf-8
1950endfunc
1951
1952" Test for ModeChanged pattern
1953func Test_mode_changes()
1954  let g:count = 0
1955  func! DoIt()
1956    let g:count += 1
1957  endfunc
1958  let g:index = 0
1959  let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'n', 'V', 'v', 'n']
1960  func! TestMode()
1961    call assert_equal(g:mode_seq[g:index], get(v:event, "old_mode"))
1962    call assert_equal(g:mode_seq[g:index + 1], get(v:event, "new_mode"))
1963    call assert_equal(mode(1), get(v:event, "new_mode"))
1964    let g:index += 1
1965  endfunc
1966
1967  au ModeChanged * :call TestMode()
1968  au ModeChanged n:* :call DoIt()
1969  call feedkeys("i\<esc>vV\<esc>", 'tnix')
1970  call assert_equal(2, g:count)
1971
1972  au ModeChanged V:v :call DoIt()
1973  call feedkeys("Vv\<esc>", 'tnix')
1974  call assert_equal(4, g:count)
1975  call assert_equal(len(g:mode_seq) - 1, g:index)
1976
1977  let g:n_to_i = 0
1978  au ModeChanged n:i let g:n_to_i += 1
1979  let g:n_to_niI = 0
1980  au ModeChanged i:niI let g:n_to_niI += 1
1981  let g:niI_to_i = 0
1982  au ModeChanged niI:i let g:niI_to_i += 1
1983  let g:nany_to_i = 0
1984  au ModeChanged n*:i let g:nany_to_i += 1
1985  let g:i_to_n = 0
1986  au ModeChanged i:n let g:i_to_n += 1
1987  let g:nori_to_any = 0
1988  au ModeChanged [ni]:* let g:nori_to_any += 1
1989  let g:i_to_any = 0
1990  au ModeChanged i:* let g:i_to_any += 1
1991  let g:index = 0
1992  let g:mode_seq = ['n', 'i', 'niI', 'i', 'n']
1993  call feedkeys("a\<C-O>l\<esc>", 'tnix')
1994  call assert_equal(len(g:mode_seq) - 1, g:index)
1995  call assert_equal(1, g:n_to_i)
1996  call assert_equal(1, g:n_to_niI)
1997  call assert_equal(1, g:niI_to_i)
1998  call assert_equal(2, g:nany_to_i)
1999  call assert_equal(1, g:i_to_n)
2000  call assert_equal(2, g:i_to_any)
2001  call assert_equal(3, g:nori_to_any)
2002
2003  au! ModeChanged
2004  delfunc TestMode
2005  unlet! g:mode_seq
2006  unlet! g:index
2007  delfunc DoIt
2008  unlet! g:count
2009endfunc
2010
2011" vim: shiftwidth=2 sts=2 expandtab
2012