xref: /vim-8.2.3635/src/testdir/test_mapping.vim (revision 8ea05de6)
1" Tests for mappings and abbreviations
2
3source shared.vim
4source check.vim
5source screendump.vim
6source term_util.vim
7
8func Test_abbreviation()
9  " abbreviation with 0x80 should work
10  inoreab чкпр   vim
11  call feedkeys("Goчкпр \<Esc>", "xt")
12  call assert_equal('vim ', getline('$'))
13  iunab чкпр
14  set nomodified
15endfunc
16
17func Test_abclear()
18   abbrev foo foobar
19   iabbrev fooi foobari
20   cabbrev fooc foobarc
21   call assert_equal("\n\n"
22         \        .. "c  fooc          foobarc\n"
23         \        .. "i  fooi          foobari\n"
24         \        .. "!  foo           foobar", execute('abbrev'))
25
26   iabclear
27   call assert_equal("\n\n"
28         \        .. "c  fooc          foobarc\n"
29         \        .. "c  foo           foobar", execute('abbrev'))
30   abbrev foo foobar
31   iabbrev fooi foobari
32
33   cabclear
34   call assert_equal("\n\n"
35         \        .. "i  fooi          foobari\n"
36         \        .. "i  foo           foobar", execute('abbrev'))
37   abbrev foo foobar
38   cabbrev fooc foobarc
39
40   abclear
41   call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
42   call assert_fails('%abclear', 'E481:')
43endfunc
44
45func Test_abclear_buffer()
46  abbrev foo foobar
47  new X1
48  abbrev <buffer> foo1 foobar1
49  new X2
50  abbrev <buffer> foo2 foobar2
51
52  call assert_equal("\n\n"
53        \        .. "!  foo2         @foobar2\n"
54        \        .. "!  foo           foobar", execute('abbrev'))
55
56  abclear <buffer>
57  call assert_equal("\n\n"
58        \        .. "!  foo           foobar", execute('abbrev'))
59
60  b X1
61  call assert_equal("\n\n"
62        \        .. "!  foo1         @foobar1\n"
63        \        .. "!  foo           foobar", execute('abbrev'))
64  abclear <buffer>
65  call assert_equal("\n\n"
66        \        .. "!  foo           foobar", execute('abbrev'))
67
68  abclear
69   call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
70
71  %bwipe
72endfunc
73
74func Test_map_ctrl_c_insert()
75  " mapping of ctrl-c in Insert mode
76  set cpo-=< cpo-=k
77  inoremap <c-c> <ctrl-c>
78  cnoremap <c-c> dummy
79  cunmap <c-c>
80  call feedkeys("GoTEST2: CTRL-C |\<*C-C>A|\<Esc>", "xt")
81  call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
82  unmap! <c-c>
83  set nomodified
84endfunc
85
86func Test_map_ctrl_c_visual()
87  " mapping of ctrl-c in Visual mode
88  vnoremap <c-c> :<C-u>$put ='vmap works'
89  call feedkeys("GV\<*C-C>\<CR>", "xt")
90  call assert_equal('vmap works', getline('$'))
91  vunmap <c-c>
92  set nomodified
93endfunc
94
95func Test_map_langmap()
96  CheckFeature langmap
97
98  " check langmap applies in normal mode
99  set langmap=+- nolangremap
100  new
101  call setline(1, ['a', 'b', 'c'])
102  2
103  call assert_equal('b', getline('.'))
104  call feedkeys("+", "xt")
105  call assert_equal('a', getline('.'))
106
107  " check no remapping
108  map x +
109  2
110  call feedkeys("x", "xt")
111  call assert_equal('c', getline('.'))
112
113  " check with remapping
114  set langremap
115  2
116  call feedkeys("x", "xt")
117  call assert_equal('a', getline('.'))
118
119  unmap x
120  bwipe!
121
122  " 'langnoremap' follows 'langremap' and vise versa
123  set langremap
124  set langnoremap
125  call assert_equal(0, &langremap)
126  set langremap
127  call assert_equal(0, &langnoremap)
128  set nolangremap
129  call assert_equal(1, &langnoremap)
130
131  " check default values
132  set langnoremap&
133  call assert_equal(0, &langnoremap)
134  call assert_equal(1, &langremap)
135  set langremap&
136  call assert_equal(0, &langnoremap)
137  call assert_equal(1, &langremap)
138
139  " langmap should not apply in insert mode, 'langremap' doesn't matter
140  set langmap=+{ nolangremap
141  call feedkeys("Go+\<Esc>", "xt")
142  call assert_equal('+', getline('$'))
143  set langmap=+{ langremap
144  call feedkeys("Go+\<Esc>", "xt")
145  call assert_equal('+', getline('$'))
146
147  " langmap used for register name in insert mode.
148  call setreg('a', 'aaaa')
149  call setreg('b', 'bbbb')
150  call setreg('c', 'cccc')
151  set langmap=ab langremap
152  call feedkeys("Go\<C-R>a\<Esc>", "xt")
153  call assert_equal('bbbb', getline('$'))
154  call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt")
155  call assert_equal('bbbb', getline('$'))
156  " mapping does not apply
157  imap c a
158  call feedkeys("Go\<C-R>c\<Esc>", "xt")
159  call assert_equal('cccc', getline('$'))
160  imap a c
161  call feedkeys("Go\<C-R>a\<Esc>", "xt")
162  call assert_equal('bbbb', getline('$'))
163
164  " langmap should not apply in Command-line mode
165  set langmap=+{ nolangremap
166  call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
167  call assert_equal('+', getline('$'))
168
169  iunmap a
170  iunmap c
171  set nomodified
172endfunc
173
174func Test_map_feedkeys()
175  " issue #212 (feedkeys insert mapping at current position)
176  nnoremap . :call feedkeys(".", "in")<cr>
177  call setline('$', ['a b c d', 'a b c d'])
178  $-1
179  call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt")
180  call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$')))
181  nunmap .
182  set nomodified
183endfunc
184
185func Test_map_cursor()
186  " <c-g>U<cursor> works only within a single line
187  imapclear
188  imap ( ()<c-g>U<left>
189  call feedkeys("G2o\<Esc>ki\<CR>Test1: text with a (here some more text\<Esc>k.", "xt")
190  call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 2))
191  call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 1))
192
193  " test undo
194  call feedkeys("G2o\<Esc>ki\<CR>Test2: text wit a (here some more text [und undo]\<C-G>u\<Esc>k.u", "xt")
195  call assert_equal('', getline(line('$') - 2))
196  call assert_equal('Test2: text wit a (here some more text [und undo])', getline(line('$') - 1))
197  set nomodified
198  imapclear
199endfunc
200
201func Test_map_cursor_ctrl_gU()
202  " <c-g>U<cursor> works only within a single line
203  nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left>
204  call setline(1, ['foo', 'foobar', '', 'foo'])
205  call cursor(1,2)
206  call feedkeys("c<*PREFIX\<esc>.", 'xt')
207  call assert_equal(['PREFIXfoo', 'foobar', '', 'PREFIXfoo'], getline(1,'$'))
208  " break undo manually
209  set ul=1000
210  exe ":norm! uu"
211  call assert_equal(['foo', 'foobar', '', 'foo'], getline(1,'$'))
212
213  " Test that it does not work if the cursor moves to the previous line
214  " 2 times <S-Left> move to the previous line
215  nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left><C-G>U<S-Left>
216  call setline(1, ['', ' foo', 'foobar', '', 'foo'])
217  call cursor(2,3)
218  call feedkeys("c<*PREFIX\<esc>.", 'xt')
219  call assert_equal(['PREFIXPREFIX', ' foo', 'foobar', '', 'foo'], getline(1,'$'))
220  nmapclear
221endfunc
222
223
224" This isn't actually testing a mapping, but similar use of CTRL-G U as above.
225func Test_break_undo()
226  set whichwrap=<,>,[,]
227  call feedkeys("G4o2k", "xt")
228  exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."
229  call assert_equal('new line here', getline(line('$') - 3))
230  call assert_equal('Test3: text with a (parenthesis here', getline(line('$') - 2))
231  call assert_equal('new line here', getline(line('$') - 1))
232  set nomodified
233endfunc
234
235func Test_map_meta_quotes()
236  imap <M-"> foo
237  call feedkeys("Go-\<*M-\">-\<Esc>", "xt")
238  call assert_equal("-foo-", getline('$'))
239  set nomodified
240  iunmap <M-">
241endfunc
242
243func Test_map_meta_multibyte()
244  imap <M-á> foo
245  call assert_match('i  <M-á>\s*foo', execute('imap'))
246  iunmap <M-á>
247endfunc
248
249func Test_abbr_after_line_join()
250  new
251  abbr foo bar
252  set backspace=indent,eol,start
253  exe "normal o\<BS>foo "
254  call assert_equal("bar ", getline(1))
255  bwipe!
256  unabbr foo
257  set backspace&
258endfunc
259
260func Test_map_timeout()
261  CheckFeature timers
262  nnoremap aaaa :let got_aaaa = 1<CR>
263  nnoremap bb :let got_bb = 1<CR>
264  nmap b aaa
265  new
266  func ExitInsert(timer)
267    let g:line = getline(1)
268    call feedkeys("\<Esc>", "t")
269  endfunc
270  set timeout timeoutlen=200
271  let timer = timer_start(300, 'ExitInsert')
272  " After the 'b' Vim waits for another character to see if it matches 'bb'.
273  " When it times out it is expanded to "aaa", but there is no wait for
274  " "aaaa".  Can't check that reliably though.
275  call feedkeys("b", "xt!")
276  call assert_equal("aa", g:line)
277  call assert_false(exists('got_aaa'))
278  call assert_false(exists('got_bb'))
279
280  bwipe!
281  nunmap aaaa
282  nunmap bb
283  nunmap b
284  set timeoutlen&
285  delfunc ExitInsert
286  call timer_stop(timer)
287endfunc
288
289func Test_map_timeout_with_timer_interrupt()
290  CheckFeature job
291  CheckFeature timers
292
293  " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
294  " sequence.
295  new
296  let g:val = 0
297  nnoremap \12 :let g:val = 1<CR>
298  nnoremap \123 :let g:val = 2<CR>
299  set timeout timeoutlen=200
300
301  func ExitCb(job, status)
302    let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
303  endfunc
304
305  call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
306  call feedkeys('\12', 'xt!')
307  call assert_equal(2, g:val)
308
309  bwipe!
310  nunmap \12
311  nunmap \123
312  set timeoutlen&
313  call WaitFor({-> exists('g:timer')})
314  call timer_stop(g:timer)
315  unlet g:timer
316  unlet g:val
317  delfunc ExitCb
318endfunc
319
320func Test_abbreviation_CR()
321  new
322  func Eatchar(pat)
323    let c = nr2char(getchar(0))
324    return (c =~ a:pat) ? '' : c
325  endfunc
326  iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
327  call feedkeys("GA~~7 \<esc>", 'xt')
328  call assert_equal('~~~~~~~', getline('$'))
329  %d
330  call feedkeys("GA~~7\<cr>\<esc>", 'xt')
331  call assert_equal(['~~~~~~~', ''], getline(1,'$'))
332  delfunc Eatchar
333  bw!
334endfunc
335
336func Test_cabbr_visual_mode()
337  cabbr s su
338  call feedkeys(":s \<c-B>\"\<CR>", 'itx')
339  call assert_equal('"su ', getreg(':'))
340  call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
341  let expected = '"'. "'<,'>su "
342  call assert_equal(expected, getreg(':'))
343  call feedkeys(":  '<,'>s \<c-B>\"\<CR>", 'itx')
344  let expected = '"  '. "'<,'>su "
345  call assert_equal(expected, getreg(':'))
346  call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
347  let expected = '"'. "'a,'bsu "
348  call assert_equal(expected, getreg(':'))
349  cunabbr s
350endfunc
351
352func Test_motionforce_omap()
353  func GetCommand()
354    let g:m=mode(1)
355    let [g:lnum1, g:col1] = searchpos('-', 'Wb')
356    if g:lnum1 == 0
357        return "\<Esc>"
358    endif
359    let [g:lnum2, g:col2] = searchpos('-', 'W')
360    if g:lnum2 == 0
361        return "\<Esc>"
362    endif
363    return ":call Select()\<CR>"
364  endfunc
365  func Select()
366    call cursor([g:lnum1, g:col1])
367    exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
368    call cursor([g:lnum2, g:col2])
369    execute "normal! \<BS>"
370  endfunc
371  new
372  onoremap <buffer><expr> i- GetCommand()
373  " 1) default omap mapping
374  %d_
375  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
376  call cursor(2, 1)
377  norm di-
378  call assert_equal('no', g:m)
379  call assert_equal(['aaa -- eee'], getline(1, '$'))
380  " 2) forced characterwise operation
381  %d_
382  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
383  call cursor(2, 1)
384  norm dvi-
385  call assert_equal('nov', g:m)
386  call assert_equal(['aaa -- eee'], getline(1, '$'))
387  " 3) forced linewise operation
388  %d_
389  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
390  call cursor(2, 1)
391  norm dVi-
392  call assert_equal('noV', g:m)
393  call assert_equal([''], getline(1, '$'))
394  " 4) forced blockwise operation
395  %d_
396  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
397  call cursor(2, 1)
398  exe "norm d\<C-V>i-"
399  call assert_equal("no\<C-V>", g:m)
400  call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
401  bwipe!
402  delfunc Select
403  delfunc GetCommand
404endfunc
405
406func Test_error_in_map_expr()
407  " Unlike CheckRunVimInTerminal this does work in a win32 console
408  CheckFeature terminal
409  if has('win32') && has('gui_running')
410    throw 'Skipped: cannot run Vim in a terminal window'
411  endif
412
413  let lines =<< trim [CODE]
414  func Func()
415    " fail to create list
416    let x = [
417  endfunc
418  nmap <expr> ! Func()
419  set updatetime=50
420  [CODE]
421  call writefile(lines, 'Xtest.vim')
422
423  let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
424  let job = term_getjob(buf)
425  call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
426
427  " GC must not run during map-expr processing, which can make Vim crash.
428  call term_sendkeys(buf, '!')
429  call TermWait(buf, 50)
430  call term_sendkeys(buf, "\<CR>")
431  call TermWait(buf, 50)
432  call assert_equal('run', job_status(job))
433
434  call term_sendkeys(buf, ":qall!\<CR>")
435  call WaitFor({-> job_status(job) ==# 'dead'})
436  if has('unix')
437    call assert_equal('', job_info(job).termsig)
438  endif
439
440  call delete('Xtest.vim')
441  exe buf .. 'bwipe!'
442endfunc
443
444func Test_list_mappings()
445  " Remove default mappings
446  imapclear
447
448  inoremap <C-M> CtrlM
449  inoremap <A-S> AltS
450  inoremap <S-/> ShiftSlash
451  call assert_equal([
452	\ 'i  <S-/>       * ShiftSlash',
453	\ 'i  <M-S>       * AltS',
454	\ 'i  <C-M>       * CtrlM',
455	\], execute('imap')->trim()->split("\n"))
456  iunmap <C-M>
457  iunmap <A-S>
458  call assert_equal(['i  <S-/>       * ShiftSlash'], execute('imap')->trim()->split("\n"))
459  iunmap <S-/>
460  call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
461
462  " List global, buffer local and script local mappings
463  nmap ,f /^\k\+ (<CR>
464  nmap <buffer> ,f /^\k\+ (<CR>
465  nmap <script> ,fs /^\k\+ (<CR>
466  call assert_equal(['n  ,f           @/^\k\+ (<CR>',
467        \ 'n  ,fs         & /^\k\+ (<CR>',
468        \ 'n  ,f            /^\k\+ (<CR>'],
469        \ execute('nmap ,f')->trim()->split("\n"))
470
471  " List <Nop> mapping
472  nmap ,n <Nop>
473  call assert_equal(['n  ,n            <Nop>'],
474        \ execute('nmap ,n')->trim()->split("\n"))
475
476  " verbose map
477  call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
478        \ execute('verbose map ,n')->trim()->split("\n")[1])
479
480  " map to CTRL-V
481  exe "nmap ,k \<C-V>"
482  call assert_equal(['n  ,k            <Nop>'],
483        \ execute('nmap ,k')->trim()->split("\n"))
484
485  nmapclear
486endfunc
487
488func Test_expr_map_restore_cursor()
489  CheckScreendump
490
491  let lines =<< trim END
492      call setline(1, ['one', 'two', 'three'])
493      2
494      set ls=2
495      hi! link StatusLine ErrorMsg
496      noremap <expr> <C-B> Func()
497      func Func()
498	  let g:on = !get(g:, 'on', 0)
499	  redraws
500	  return ''
501      endfunc
502      func Status()
503	  return get(g:, 'on', 0) ? '[on]' : ''
504      endfunc
505      set stl=%{Status()}
506  END
507  call writefile(lines, 'XtestExprMap')
508  let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
509  call TermWait(buf)
510  call term_sendkeys(buf, "\<C-B>")
511  call VerifyScreenDump(buf, 'Test_map_expr_1', {})
512
513  " clean up
514  call StopVimInTerminal(buf)
515  call delete('XtestExprMap')
516endfunc
517
518" Test for mapping errors
519func Test_map_error()
520  call assert_fails('unmap', 'E474:')
521  call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
522  call assert_fails('unmap abc', 'E31:')
523  call assert_fails('unabbr abc', 'E24:')
524  call assert_equal('', maparg(''))
525  call assert_fails('echo maparg("abc", [])', 'E730:')
526
527  " unique map
528  map ,w /[#&!]<CR>
529  call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
530  " unique buffer-local map
531  call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
532  unmap ,w
533
534  " unique abbreviation
535  abbr SP special
536  call assert_fails("abbr <unique> SP special", 'E226:')
537  " unique buffer-local map
538  call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
539  unabbr SP
540
541  call assert_fails('mapclear abc', 'E474:')
542  call assert_fails('abclear abc', 'E474:')
543  call assert_fails('abbr $xyz abc', 'E474:')
544
545  " space character in an abbreviation
546  call assert_fails('abbr ab<space> ABC', 'E474:')
547
548  " invalid <expr> map
549  map <expr> ,f abc
550  call assert_fails('normal ,f', 'E121:')
551  unmap <expr> ,f
552
553  " Recursive use of :normal in a map
554  set maxmapdepth=100
555  map gq :normal gq<CR>
556  call assert_fails('normal gq', 'E192:')
557  unmap gq
558  set maxmapdepth&
559endfunc
560
561" Test for <special> key mapping
562func Test_map_special()
563  new
564  let old_cpo = &cpo
565  set cpo+=<
566  imap <F12> Blue
567  call feedkeys("i\<F12>", "x")
568  call assert_equal("<F12>", getline(1))
569  call feedkeys("ddi<F12>", "x")
570  call assert_equal("Blue", getline(1))
571  iunmap <F12>
572  imap <special> <F12> Green
573  call feedkeys("ddi\<F12>", "x")
574  call assert_equal("Green", getline(1))
575  call feedkeys("ddi<F12>", "x")
576  call assert_equal("<F12>", getline(1))
577  iunmap <special> <F12>
578  let &cpo = old_cpo
579  %bwipe!
580endfunc
581
582" Test for hasmapto()
583func Test_hasmapto()
584  call assert_equal(0, hasmapto('/^\k\+ ('))
585  map ,f /^\k\+ (<CR>
586  call assert_equal(1, hasmapto('/^\k\+ ('))
587  unmap ,f
588
589  " Insert mode mapping
590  call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
591  imap ,f /^\k\+ (<CR>
592  call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
593  iunmap ,f
594
595  " Normal mode mapping
596  call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
597  nmap ,f /^\k\+ (<CR>
598  call assert_equal(1, hasmapto('/^\k\+ ('))
599  call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
600  nunmap ,f
601
602  " Visual and Select mode mapping
603  call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
604  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
605  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
606  vmap ,f /^\k\+ (<CR>
607  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
608  call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
609  call assert_equal(1, hasmapto('/^\k\+ (', 's'))
610  vunmap ,f
611
612  " Visual mode mapping
613  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
614  xmap ,f /^\k\+ (<CR>
615  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
616  call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
617  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
618  xunmap ,f
619
620  " Select mode mapping
621  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
622  smap ,f /^\k\+ (<CR>
623  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
624  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
625  call assert_equal(1, hasmapto('/^\k\+ (', 's'))
626  sunmap ,f
627
628  " Operator-pending mode mapping
629  call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
630  omap ,f /^\k\+ (<CR>
631  call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
632  ounmap ,f
633
634  " Language mapping
635  call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
636  lmap ,f /^\k\+ (<CR>
637  call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
638  lunmap ,f
639
640  " Cmdline mode mapping
641  call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
642  cmap ,f /^\k\+ (<CR>
643  call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
644  cunmap ,f
645
646  call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
647endfunc
648
649" Test for command-line completion of maps
650func Test_mapcomplete()
651  call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
652	      \ '<silent>', '<special>', '<unique>'],
653	      \ getcompletion('', 'mapping'))
654  call assert_equal([], getcompletion(',d', 'mapping'))
655
656  call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
657  call assert_equal('"unmap <buffer>', @:)
658
659  call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
660  call assert_equal('"unabbr <buffer>', @:)
661
662  call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
663  call assert_equal("\"abbr! \x01", @:)
664
665  " Multiple matches for a map
666  nmap ,f /H<CR>
667  omap ,f /H<CR>
668  call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
669  call assert_equal('"map ,f', @:)
670  mapclear
671endfunc
672
673" Test for <expr> in abbreviation
674func Test_expr_abbr()
675  new
676  iabbr <expr> teh "the"
677  call feedkeys("iteh ", "tx")
678  call assert_equal('the ', getline(1))
679  iabclear
680  call setline(1, '')
681
682  " invalid <expr> abbreviation
683  abbr <expr> hte GetAbbr()
684  call assert_fails('normal ihte ', 'E117:')
685  call assert_equal('', getline(1))
686  unabbr <expr> hte
687
688  close!
689endfunc
690
691" Test for storing mappings in different modes in a vimrc file
692func Test_mkvimrc_mapmodes()
693  map a1 /a1
694  nmap a2 /a2
695  vmap a3 /a3
696  smap a4 /a4
697  xmap a5 /a5
698  omap a6 /a6
699  map! a7 /a7
700  imap a8 /a8
701  lmap a9 /a9
702  cmap a10 /a10
703  tmap a11 /a11
704  " Normal + Visual map
705  map a12 /a12
706  sunmap a12
707  ounmap a12
708  " Normal + Selectmode map
709  map a13 /a13
710  xunmap a13
711  ounmap a13
712  " Normal + OpPending map
713  map a14 /a14
714  vunmap a14
715  " Visual + Selectmode map
716  map a15 /a15
717  nunmap a15
718  ounmap a15
719  " Visual + OpPending map
720  map a16 /a16
721  nunmap a16
722  sunmap a16
723  " Selectmode + OpPending map
724  map a17 /a17
725  nunmap a17
726  xunmap a17
727  " Normal + Visual + Selectmode map
728  map a18 /a18
729  ounmap a18
730  " Normal + Visual + OpPending map
731  map a19 /a19
732  sunmap a19
733  " Normal + Selectmode + OpPending map
734  map a20 /a20
735  xunmap a20
736  " Visual + Selectmode + OpPending map
737  map a21 /a21
738  nunmap a21
739  " Mapping to Nop
740  map a22 <Nop>
741  " Script local mapping
742  map <script> a23 /a23
743
744  " Newline in {lhs} and {rhs} of a map
745  exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
746
747  " Abbreviation
748  abbr a25 A25
749  cabbr a26 A26
750  iabbr a27 A27
751
752  mkvimrc! Xvimrc
753  let l = readfile('Xvimrc')
754  call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
755  call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
756  call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
757  call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
758  call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
759  call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
760  call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
761  call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
762  call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
763  call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
764  call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
765  call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
766        \ filter(copy(l), 'v:val =~ " a12 "'))
767  call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
768        \ filter(copy(l), 'v:val =~ " a13 "'))
769  call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
770        \ filter(copy(l), 'v:val =~ " a14 "'))
771  call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
772  call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
773        \ filter(copy(l), 'v:val =~ " a16 "'))
774  call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
775        \ filter(copy(l), 'v:val =~ " a17 "'))
776  call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
777        \ filter(copy(l), 'v:val =~ " a18 "'))
778  call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
779        \ filter(copy(l), 'v:val =~ " a19 "'))
780  call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
781        \ filter(copy(l), 'v:val =~ " a20 "'))
782  call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
783        \ filter(copy(l), 'v:val =~ " a21 "'))
784  call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
785  call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
786  call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
787        \ filter(copy(l), 'v:val =~ " a24"'))
788
789  call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
790  call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
791  call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
792  call delete('Xvimrc')
793
794  mapclear
795  nmapclear
796  vmapclear
797  xmapclear
798  smapclear
799  omapclear
800  imapclear
801  lmapclear
802  cmapclear
803  tmapclear
804endfunc
805
806" Test for recursive mapping ('maxmapdepth')
807func Test_map_recursive()
808  map x y
809  map y x
810  call assert_fails('normal x', 'E223:')
811  unmap x
812  unmap y
813endfunc
814
815" Test for removing an abbreviation using {rhs} and with space after {lhs}
816func Test_abbr_remove()
817  abbr foo bar
818  let d = maparg('foo', 'i', 1, 1)
819  call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
820  unabbr bar
821  call assert_equal({}, maparg('foo', 'i', 1, 1))
822
823  abbr foo bar
824  unabbr foo<space><tab>
825  call assert_equal({}, maparg('foo', 'i', 1, 1))
826endfunc
827
828" Trigger an abbreviation using a special key
829func Test_abbr_trigger_special()
830  new
831  iabbr teh the
832  call feedkeys("iteh\<F2>\<Esc>", 'xt')
833  call assert_equal('the<F2>', getline(1))
834  iunab teh
835  close!
836endfunc
837
838" Test for '<' in 'cpoptions'
839func Test_map_cpo_special_keycode()
840  set cpo-=<
841  imap x<Bslash>k Test
842  let d = maparg('x<Bslash>k', 'i', 0, 1)
843  call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
844  call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
845  call assert_equal('"imap x\k', @:)
846  iunmap x<Bslash>k
847  set cpo+=<
848  imap x<Bslash>k Test
849  let d = maparg('x<Bslash>k', 'i', 0, 1)
850  call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
851  call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
852  call assert_equal('"imap x<Bslash>k', @:)
853  iunmap x<Bslash>k
854  set cpo-=<
855  " Modifying 'cpo' above adds some default mappings, remove them
856  mapclear
857  mapclear!
858endfunc
859
860" Test for <Cmd> key in maps to execute commands
861func Test_map_cmdkey()
862  new
863
864  " Error cases
865  let x = 0
866  noremap <F3> <Cmd><Cmd>let x = 1<CR>
867  call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
868  call assert_equal(0, x)
869
870  noremap <F3> <Cmd><F3>let x = 2<CR>
871  call assert_fails('call feedkeys("\<F3>", "xt")', 'E1137:')
872  call assert_equal(0, x)
873
874  noremap <F3> <Cmd>let x = 3
875  call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1135:')
876  call assert_equal(0, x)
877
878  " works in various modes and sees the correct mode()
879  noremap <F3> <Cmd>let m = mode(1)<CR>
880  noremap! <F3> <Cmd>let m = mode(1)<CR>
881
882  " normal mode
883  call feedkeys("\<F3>", 'xt')
884  call assert_equal('n', m)
885
886  " visual mode
887  call feedkeys("v\<F3>", 'xt!')
888  call assert_equal('v', m)
889  " shouldn't leave the visual mode
890  call assert_equal('v', mode(1))
891  call feedkeys("\<Esc>", 'xt')
892  call assert_equal('n', mode(1))
893
894  " visual mapping in select mode
895  call feedkeys("gh\<F3>", 'xt!')
896  call assert_equal('v', m)
897  " shouldn't leave select mode
898  call assert_equal('s', mode(1))
899  call feedkeys("\<Esc>", 'xt')
900  call assert_equal('n', mode(1))
901
902  " select mode mapping
903  snoremap <F3> <Cmd>let m = mode(1)<cr>
904  call feedkeys("gh\<F3>", 'xt!')
905  call assert_equal('s', m)
906  " shouldn't leave select mode
907  call assert_equal('s', mode(1))
908  call feedkeys("\<Esc>", 'xt')
909  call assert_equal('n', mode(1))
910
911  " operator-pending mode
912  call feedkeys("d\<F3>", 'xt!')
913  call assert_equal('no', m)
914  " leaves the operator-pending mode
915  call assert_equal('n', mode(1))
916
917  " insert mode
918  call feedkeys("i\<F3>abc", 'xt')
919  call assert_equal('i', m)
920  call assert_equal('abc', getline('.'))
921
922  " replace mode
923  call feedkeys("0R\<F3>two", 'xt')
924  call assert_equal('R', m)
925  call assert_equal('two', getline('.'))
926
927  " virtual replace mode
928  call setline('.', "one\ttwo")
929  call feedkeys("4|gR\<F3>xxx", 'xt')
930  call assert_equal('Rv', m)
931  call assert_equal("onexxx\ttwo", getline('.'))
932
933  " cmdline mode
934  call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
935  call assert_equal('c', m)
936  call assert_equal('"xxx', @:)
937
938  " terminal mode
939  if CanRunVimInTerminal()
940    tnoremap <F3> <Cmd>let m = mode(1)<CR>
941    let buf = Run_shell_in_terminal({})
942    call feedkeys("\<F3>", 'xt')
943    call assert_equal('t', m)
944    call assert_equal('t', mode(1))
945    call StopShellInTerminal(buf)
946    call TermWait(buf)
947    close!
948    tunmap <F3>
949  endif
950
951  " invoke cmdline mode recursively
952  noremap! <F2> <Cmd>norm! :foo<CR>
953  %d
954  call setline(1, ['some short lines', 'of test text'])
955  call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
956  call assert_equal('"barx', @:)
957  unmap! <F2>
958
959  " test for calling a <SID> function
960  let lines =<< trim END
961    map <F2> <Cmd>call <SID>do_it()<CR>
962    func s:do_it()
963      let g:x = 32
964    endfunc
965  END
966  call writefile(lines, 'Xscript')
967  source Xscript
968  call feedkeys("\<F2>", 'xt')
969  call assert_equal(32, g:x)
970  call delete('Xscript')
971
972  unmap <F3>
973  unmap! <F3>
974  %bw!
975
976  " command line ending in "0" is handled without errors
977  onoremap ix <cmd>eval 0<cr>
978  call feedkeys('dix.', 'xt')
979  ounmap ix
980endfunc
981
982" text object enters visual mode
983func TextObj()
984  if mode() !=# "v"
985    normal! v
986  end
987  call cursor(1, 3)
988  normal! o
989  call cursor(2, 4)
990endfunc
991
992func s:cmdmap(lhs, rhs)
993  exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
994  exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
995endfunc
996
997func s:cmdunmap(lhs)
998  exe 'unmap ' .. a:lhs
999  exe 'unmap! ' .. a:lhs
1000endfunc
1001
1002" Map various <Fx> keys used by the <Cmd> key tests
1003func s:setupMaps()
1004  call s:cmdmap('<F3>', 'let m = mode(1)')
1005  call s:cmdmap('<F4>', 'normal! ww')
1006  call s:cmdmap('<F5>', 'normal! "ay')
1007  call s:cmdmap('<F6>', 'throw "very error"')
1008  call s:cmdmap('<F7>', 'call TextObj()')
1009  call s:cmdmap('<F8>', 'startinsert')
1010  call s:cmdmap('<F9>', 'stopinsert')
1011endfunc
1012
1013" Remove the mappings setup by setupMaps()
1014func s:cleanupMaps()
1015  call s:cmdunmap('<F3>')
1016  call s:cmdunmap('<F4>')
1017  call s:cmdunmap('<F5>')
1018  call s:cmdunmap('<F6>')
1019  call s:cmdunmap('<F7>')
1020  call s:cmdunmap('<F8>')
1021  call s:cmdunmap('<F9>')
1022endfunc
1023
1024" Test for <Cmd> mapping in normal mode
1025func Test_map_cmdkey_normal_mode()
1026  new
1027  call s:setupMaps()
1028
1029  " check v:count and v:register works
1030  call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1031  call feedkeys("\<F2>", 'xt')
1032  call assert_equal(['n', 0, '"'], s)
1033  call feedkeys("7\<F2>", 'xt')
1034  call assert_equal(['n', 7, '"'], s)
1035  call feedkeys("\"e\<F2>", 'xt')
1036  call assert_equal(['n', 0, 'e'], s)
1037  call feedkeys("5\"k\<F2>", 'xt')
1038  call assert_equal(['n', 5, 'k'], s)
1039  call s:cmdunmap('<F2>')
1040
1041  call setline(1, ['some short lines', 'of test text'])
1042  call feedkeys("\<F7>y", 'xt')
1043  call assert_equal("me short lines\nof t", @")
1044  call assert_equal('v', getregtype('"'))
1045  call assert_equal([0, 1, 3, 0], getpos("'<"))
1046  call assert_equal([0, 2, 4, 0], getpos("'>"))
1047
1048  " startinsert
1049  %d
1050  call feedkeys("\<F8>abc", 'xt')
1051  call assert_equal('abc', getline(1))
1052
1053  " feedkeys are not executed immediately
1054  noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1055  %d
1056  call setline(1, ['some short lines', 'of test text'])
1057  call cursor(2, 3)
1058  call feedkeys(",a\<F3>", 'xt')
1059  call assert_equal('of test text', g:a)
1060  call assert_equal('n', m)
1061  call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1062  nunmap ,a
1063
1064  " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1065  noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1066  call feedkeys(",b\<F3>", 'xt')
1067  call assert_equal('n', m)
1068  call assert_equal('of alphabetatest text', g:b)
1069  nunmap ,b
1070
1071  call s:cleanupMaps()
1072  %bw!
1073endfunc
1074
1075" Test for <Cmd> mapping with the :normal command
1076func Test_map_cmdkey_normal_cmd()
1077  new
1078  noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1079  noremap ,f <Cmd>nosuchcommand<CR>
1080  noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1081  noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1082  noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1083
1084  call setline(1, ['some short lines', 'of test text'])
1085  exe "norm ,x\r"
1086  call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1087
1088  call assert_fails('norm ,f', 'E492:')
1089  call assert_fails('norm ,e', 'very error')
1090  call assert_fails('norm ,m', 'The message.')
1091  call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1092
1093  %d
1094  let caught_err = 0
1095  try
1096    exe "normal ,w"
1097  catch /Vim(echoerr):Err/
1098    let caught_err = 1
1099  endtry
1100  call assert_equal(1, caught_err)
1101  call assert_equal(['', '0'], getline(1, '$'))
1102
1103  %d
1104  call assert_fails('normal ,w', 'Err')
1105  call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1106  call assert_equal(1, line('.'))
1107
1108  nunmap ,x
1109  nunmap ,f
1110  nunmap ,e
1111  nunmap ,m
1112  nunmap ,w
1113  %bw!
1114endfunc
1115
1116" Test for <Cmd> mapping in visual mode
1117func Test_map_cmdkey_visual_mode()
1118  new
1119  set showmode
1120  call s:setupMaps()
1121
1122  call setline(1, ['some short lines', 'of test text'])
1123  call feedkeys("v\<F4>", 'xt!')
1124  call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1125
1126  " can invoke an opeartor, ending the visual mode
1127  let @a = ''
1128  call feedkeys("\<F5>", 'xt!')
1129  call assert_equal('n', mode(1))
1130  call assert_equal('some short l', @a)
1131
1132  " error doesn't interrupt visual mode
1133  call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1134  call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1135  call feedkeys("\<F7>", 'xt!')
1136  call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1137
1138  " startinsert gives "-- (insert) VISUAL --" mode
1139  call feedkeys("\<F8>", 'xt!')
1140  call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1141  redraw!
1142  call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1143  call feedkeys("\<Esc>new ", 'x')
1144  call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1145
1146  call s:cleanupMaps()
1147  set showmode&
1148  %bw!
1149endfunc
1150
1151" Test for <Cmd> mapping in select mode
1152func Test_map_cmdkey_select_mode()
1153  new
1154  set showmode
1155  call s:setupMaps()
1156
1157  snoremap <F1> <cmd>throw "very error"<CR>
1158  snoremap <F2> <cmd>normal! <c-g>"by<CR>
1159  call setline(1, ['some short lines', 'of test text'])
1160
1161  call feedkeys("gh\<F4>", "xt!")
1162  call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1163  redraw!
1164  call assert_match('^-- SELECT --', Screenline(&lines))
1165
1166  " visual mapping in select mode restarts select mode after operator
1167  let @a = ''
1168  call feedkeys("\<F5>", 'xt!')
1169  call assert_equal('s', mode(1))
1170  call assert_equal('some short l', @a)
1171
1172  " select mode mapping works, and does not restart select mode
1173  let @b = ''
1174  call feedkeys("\<F2>", 'xt!')
1175  call assert_equal('n', mode(1))
1176  call assert_equal('some short l', @b)
1177
1178  " error doesn't interrupt temporary visual mode
1179  call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1180  redraw!
1181  call assert_match('^-- VISUAL --', Screenline(&lines))
1182  " quirk: restoration of select mode is not performed
1183  call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1184
1185  " error doesn't interrupt select mode
1186  call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1187  redraw!
1188  call assert_match('^-- SELECT --', Screenline(&lines))
1189  call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1190
1191  call feedkeys("\<F7>", 'xt!')
1192  redraw!
1193  call assert_match('^-- SELECT --', Screenline(&lines))
1194  call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1195
1196  " startinsert gives "-- SELECT (insert) --" mode
1197  call feedkeys("\<F8>", 'xt!')
1198  redraw!
1199  call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1200  call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1201  call feedkeys("\<Esc>new ", 'x')
1202  call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1203
1204  sunmap <F1>
1205  sunmap <F2>
1206  call s:cleanupMaps()
1207  set showmode&
1208  %bw!
1209endfunc
1210
1211" Test for <Cmd> mapping in operator-pending mode
1212func Test_map_cmdkey_op_pending_mode()
1213  new
1214  call s:setupMaps()
1215
1216  call setline(1, ['some short lines', 'of test text'])
1217  call feedkeys("d\<F4>", 'xt')
1218  call assert_equal(['lines', 'of test text'], getline(1, '$'))
1219  call assert_equal(['some short '], getreg('"', 1, 1))
1220  " create a new undo point
1221  let &undolevels = &undolevels
1222
1223  call feedkeys(".", 'xt')
1224  call assert_equal(['test text'], getline(1, '$'))
1225  call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1226  " create a new undo point
1227  let &undolevels = &undolevels
1228
1229  call feedkeys("uu", 'xt')
1230  call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1231
1232  " error aborts operator-pending, operator not performed
1233  call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1234  call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1235
1236  call feedkeys("\"bd\<F7>", 'xt')
1237  call assert_equal(['soest text'], getline(1, '$'))
1238  call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1239
1240  " startinsert aborts operator
1241  call feedkeys("d\<F8>cc", 'xt')
1242  call assert_equal(['soccest text'], getline(1, '$'))
1243
1244  call s:cleanupMaps()
1245  %bw!
1246endfunc
1247
1248" Test for <Cmd> mapping in insert mode
1249func Test_map_cmdkey_insert_mode()
1250  new
1251  call s:setupMaps()
1252
1253  call setline(1, ['some short lines', 'of test text'])
1254  " works the same as <C-O>w<C-O>w
1255  call feedkeys("iindeed \<F4>little ", 'xt')
1256  call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1257  call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1258  call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1259
1260  " Note when entering visual mode from InsertEnter autocmd, an async event,
1261  " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1262  call feedkeys("i\<F7>stuff ", 'xt')
1263  call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1264  call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1265
1266  call feedkeys("\<F5>", 'xt')
1267  call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1268
1269  " also works as part of abbreviation
1270  abbr foo <Cmd>let g:y = 17<CR>bar
1271  exe "normal i\<space>foo "
1272  call assert_equal(17, g:y)
1273  call assert_equal('in bar deed some short little 2 lines', getline(1))
1274  unabbr foo
1275
1276  " :startinsert does nothing
1277  call setline(1, 'foo bar')
1278  call feedkeys("ggi\<F8>vim", 'xt')
1279  call assert_equal('vimfoo bar', getline(1))
1280
1281  " :stopinsert works
1282  call feedkeys("ggi\<F9>Abc", 'xt')
1283  call assert_equal('vimfoo barbc', getline(1))
1284
1285  call s:cleanupMaps()
1286  %bw!
1287endfunc
1288
1289" Test for <Cmd> mapping in insert-completion mode
1290func Test_map_cmdkey_insert_complete_mode()
1291  new
1292  call s:setupMaps()
1293
1294  call setline(1, 'some short lines')
1295  call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1296  call assert_equal('ic', m)
1297  call assert_equal(['some short lines', 'short '], getline(1, '$'))
1298
1299  call s:cleanupMaps()
1300  %bw!
1301endfunc
1302
1303" Test for <Cmd> mapping in cmdline mode
1304func Test_map_cmdkey_cmdline_mode()
1305  new
1306  call s:setupMaps()
1307
1308  call setline(1, ['some short lines', 'of test text'])
1309  let x = 0
1310  call feedkeys(":let x\<F3>= 10\r", 'xt')
1311  call assert_equal('c', m)
1312  call assert_equal(10, x)
1313
1314  " exception doesn't leave cmdline mode
1315  call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1316  call assert_equal(20, x)
1317
1318  " move cursor in the buffer from cmdline mode
1319  call feedkeys(":let x\<F4>= 30\r", 'xt')
1320  call assert_equal(30, x)
1321  call assert_equal(12, col('.'))
1322
1323  " :startinsert takes effect after leaving cmdline mode
1324  call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1325  call assert_equal(40, x)
1326  call assert_equal('some short new lines', getline(1))
1327
1328  call s:cleanupMaps()
1329  %bw!
1330endfunc
1331
1332func Test_map_cmdkey_redo()
1333  func SelectDash()
1334    call search('^---\n\zs', 'bcW')
1335    norm! V
1336    call search('\n\ze---$', 'W')
1337  endfunc
1338
1339  let text =<< trim END
1340      ---
1341      aaa
1342      ---
1343      bbb
1344      bbb
1345      ---
1346      ccc
1347      ccc
1348      ccc
1349      ---
1350  END
1351  new Xcmdtext
1352  call setline(1, text)
1353
1354  onoremap <silent> i- <Cmd>call SelectDash()<CR>
1355  call feedkeys('2Gdi-', 'xt')
1356  call assert_equal(['---', '---'], getline(1, 2))
1357  call feedkeys('j.', 'xt')
1358  call assert_equal(['---', '---', '---'], getline(1, 3))
1359  call feedkeys('j.', 'xt')
1360  call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1361
1362  bwipe!
1363  call delete('Xcmdtext')
1364  delfunc SelectDash
1365  ounmap i-
1366endfunc
1367
1368" vim: shiftwidth=2 sts=2 expandtab
1369