xref: /vim-8.2.3635/src/testdir/test_mapping.vim (revision 5ee0981f)
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!
975endfunc
976
977" text object enters visual mode
978func TextObj()
979  if mode() !=# "v"
980    normal! v
981  end
982  call cursor(1, 3)
983  normal! o
984  call cursor(2, 4)
985endfunc
986
987func s:cmdmap(lhs, rhs)
988  exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
989  exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
990endfunc
991
992func s:cmdunmap(lhs)
993  exe 'unmap ' .. a:lhs
994  exe 'unmap! ' .. a:lhs
995endfunc
996
997" Map various <Fx> keys used by the <Cmd> key tests
998func s:setupMaps()
999  call s:cmdmap('<F3>', 'let m = mode(1)')
1000  call s:cmdmap('<F4>', 'normal! ww')
1001  call s:cmdmap('<F5>', 'normal! "ay')
1002  call s:cmdmap('<F6>', 'throw "very error"')
1003  call s:cmdmap('<F7>', 'call TextObj()')
1004  call s:cmdmap('<F8>', 'startinsert')
1005  call s:cmdmap('<F9>', 'stopinsert')
1006endfunc
1007
1008" Remove the mappings setup by setupMaps()
1009func s:cleanupMaps()
1010  call s:cmdunmap('<F3>')
1011  call s:cmdunmap('<F4>')
1012  call s:cmdunmap('<F5>')
1013  call s:cmdunmap('<F6>')
1014  call s:cmdunmap('<F7>')
1015  call s:cmdunmap('<F8>')
1016  call s:cmdunmap('<F9>')
1017endfunc
1018
1019" Test for <Cmd> mapping in normal mode
1020func Test_map_cmdkey_normal_mode()
1021  new
1022  call s:setupMaps()
1023
1024  " check v:count and v:register works
1025  call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1026  call feedkeys("\<F2>", 'xt')
1027  call assert_equal(['n', 0, '"'], s)
1028  call feedkeys("7\<F2>", 'xt')
1029  call assert_equal(['n', 7, '"'], s)
1030  call feedkeys("\"e\<F2>", 'xt')
1031  call assert_equal(['n', 0, 'e'], s)
1032  call feedkeys("5\"k\<F2>", 'xt')
1033  call assert_equal(['n', 5, 'k'], s)
1034  call s:cmdunmap('<F2>')
1035
1036  call setline(1, ['some short lines', 'of test text'])
1037  call feedkeys("\<F7>y", 'xt')
1038  call assert_equal("me short lines\nof t", @")
1039  call assert_equal('v', getregtype('"'))
1040  call assert_equal([0, 1, 3, 0], getpos("'<"))
1041  call assert_equal([0, 2, 4, 0], getpos("'>"))
1042
1043  " startinsert
1044  %d
1045  call feedkeys("\<F8>abc", 'xt')
1046  call assert_equal('abc', getline(1))
1047
1048  " feedkeys are not executed immediately
1049  noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1050  %d
1051  call setline(1, ['some short lines', 'of test text'])
1052  call cursor(2, 3)
1053  call feedkeys(",a\<F3>", 'xt')
1054  call assert_equal('of test text', g:a)
1055  call assert_equal('n', m)
1056  call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1057  nunmap ,a
1058
1059  " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1060  noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1061  call feedkeys(",b\<F3>", 'xt')
1062  call assert_equal('n', m)
1063  call assert_equal('of alphabetatest text', g:b)
1064  nunmap ,b
1065
1066  call s:cleanupMaps()
1067  %bw!
1068endfunc
1069
1070" Test for <Cmd> mapping with the :normal command
1071func Test_map_cmdkey_normal_cmd()
1072  new
1073  noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1074  noremap ,f <Cmd>nosuchcommand<CR>
1075  noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1076  noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1077  noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1078
1079  call setline(1, ['some short lines', 'of test text'])
1080  exe "norm ,x\r"
1081  call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1082
1083  call assert_fails('norm ,f', 'E492:')
1084  call assert_fails('norm ,e', 'very error')
1085  call assert_fails('norm ,m', 'The message.')
1086  call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1087
1088  %d
1089  let caught_err = 0
1090  try
1091    exe "normal ,w"
1092  catch /Vim(echoerr):Err/
1093    let caught_err = 1
1094  endtry
1095  call assert_equal(1, caught_err)
1096  call assert_equal(['', '0'], getline(1, '$'))
1097
1098  %d
1099  call assert_fails('normal ,w', 'Err')
1100  call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1101  call assert_equal(1, line('.'))
1102
1103  nunmap ,x
1104  nunmap ,f
1105  nunmap ,e
1106  nunmap ,m
1107  nunmap ,w
1108  %bw!
1109endfunc
1110
1111" Test for <Cmd> mapping in visual mode
1112func Test_map_cmdkey_visual_mode()
1113  new
1114  set showmode
1115  call s:setupMaps()
1116
1117  call setline(1, ['some short lines', 'of test text'])
1118  call feedkeys("v\<F4>", 'xt!')
1119  call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1120
1121  " can invoke an opeartor, ending the visual mode
1122  let @a = ''
1123  call feedkeys("\<F5>", 'xt!')
1124  call assert_equal('n', mode(1))
1125  call assert_equal('some short l', @a)
1126
1127  " error doesn't interrupt visual mode
1128  call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1129  call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1130  call feedkeys("\<F7>", 'xt!')
1131  call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1132
1133  " startinsert gives "-- (insert) VISUAL --" mode
1134  call feedkeys("\<F8>", 'xt!')
1135  call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1136  redraw!
1137  call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1138  call feedkeys("\<Esc>new ", 'x')
1139  call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1140
1141  call s:cleanupMaps()
1142  set showmode&
1143  %bw!
1144endfunc
1145
1146" Test for <Cmd> mapping in select mode
1147func Test_map_cmdkey_select_mode()
1148  new
1149  set showmode
1150  call s:setupMaps()
1151
1152  snoremap <F1> <cmd>throw "very error"<CR>
1153  snoremap <F2> <cmd>normal! <c-g>"by<CR>
1154  call setline(1, ['some short lines', 'of test text'])
1155
1156  call feedkeys("gh\<F4>", "xt!")
1157  call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1158  redraw!
1159  call assert_match('^-- SELECT --', Screenline(&lines))
1160
1161  " visual mapping in select mode restarts select mode after operator
1162  let @a = ''
1163  call feedkeys("\<F5>", 'xt!')
1164  call assert_equal('s', mode(1))
1165  call assert_equal('some short l', @a)
1166
1167  " select mode mapping works, and does not restart select mode
1168  let @b = ''
1169  call feedkeys("\<F2>", 'xt!')
1170  call assert_equal('n', mode(1))
1171  call assert_equal('some short l', @b)
1172
1173  " error doesn't interrupt temporary visual mode
1174  call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1175  redraw!
1176  call assert_match('^-- VISUAL --', Screenline(&lines))
1177  " quirk: restoration of select mode is not performed
1178  call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1179
1180  " error doesn't interrupt select mode
1181  call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1182  redraw!
1183  call assert_match('^-- SELECT --', Screenline(&lines))
1184  call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1185
1186  call feedkeys("\<F7>", 'xt!')
1187  redraw!
1188  call assert_match('^-- SELECT --', Screenline(&lines))
1189  call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1190
1191  " startinsert gives "-- SELECT (insert) --" mode
1192  call feedkeys("\<F8>", 'xt!')
1193  redraw!
1194  call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1195  call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1196  call feedkeys("\<Esc>new ", 'x')
1197  call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1198
1199  sunmap <F1>
1200  sunmap <F2>
1201  call s:cleanupMaps()
1202  set showmode&
1203  %bw!
1204endfunc
1205
1206" Test for <Cmd> mapping in operator-pending mode
1207func Test_map_cmdkey_op_pending_mode()
1208  new
1209  call s:setupMaps()
1210
1211  call setline(1, ['some short lines', 'of test text'])
1212  call feedkeys("d\<F4>", 'xt')
1213  call assert_equal(['lines', 'of test text'], getline(1, '$'))
1214  call assert_equal(['some short '], getreg('"', 1, 1))
1215  " create a new undo point
1216  let &undolevels = &undolevels
1217
1218  call feedkeys(".", 'xt')
1219  call assert_equal(['test text'], getline(1, '$'))
1220  call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1221  " create a new undo point
1222  let &undolevels = &undolevels
1223
1224  call feedkeys("uu", 'xt')
1225  call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1226
1227  " error aborts operator-pending, operator not performed
1228  call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1229  call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1230
1231  call feedkeys("\"bd\<F7>", 'xt')
1232  call assert_equal(['soest text'], getline(1, '$'))
1233  call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1234
1235  " startinsert aborts operator
1236  call feedkeys("d\<F8>cc", 'xt')
1237  call assert_equal(['soccest text'], getline(1, '$'))
1238
1239  call s:cleanupMaps()
1240  %bw!
1241endfunc
1242
1243" Test for <Cmd> mapping in insert mode
1244func Test_map_cmdkey_insert_mode()
1245  new
1246  call s:setupMaps()
1247
1248  call setline(1, ['some short lines', 'of test text'])
1249  " works the same as <C-O>w<C-O>w
1250  call feedkeys("iindeed \<F4>little ", 'xt')
1251  call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1252  call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1253  call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1254
1255  " Note when entering visual mode from InsertEnter autocmd, an async event,
1256  " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1257  call feedkeys("i\<F7>stuff ", 'xt')
1258  call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1259  call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1260
1261  call feedkeys("\<F5>", 'xt')
1262  call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1263
1264  " also works as part of abbreviation
1265  abbr foo <Cmd>let g:y = 17<CR>bar
1266  exe "normal i\<space>foo "
1267  call assert_equal(17, g:y)
1268  call assert_equal('in bar deed some short little 2 lines', getline(1))
1269  unabbr foo
1270
1271  " :startinsert does nothing
1272  call setline(1, 'foo bar')
1273  call feedkeys("ggi\<F8>vim", 'xt')
1274  call assert_equal('vimfoo bar', getline(1))
1275
1276  " :stopinsert works
1277  call feedkeys("ggi\<F9>Abc", 'xt')
1278  call assert_equal('vimfoo barbc', getline(1))
1279
1280  call s:cleanupMaps()
1281  %bw!
1282endfunc
1283
1284" Test for <Cmd> mapping in insert-completion mode
1285func Test_map_cmdkey_insert_complete_mode()
1286  new
1287  call s:setupMaps()
1288
1289  call setline(1, 'some short lines')
1290  call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1291  call assert_equal('ic', m)
1292  call assert_equal(['some short lines', 'short '], getline(1, '$'))
1293
1294  call s:cleanupMaps()
1295  %bw!
1296endfunc
1297
1298" Test for <Cmd> mapping in cmdline mode
1299func Test_map_cmdkey_cmdline_mode()
1300  new
1301  call s:setupMaps()
1302
1303  call setline(1, ['some short lines', 'of test text'])
1304  let x = 0
1305  call feedkeys(":let x\<F3>= 10\r", 'xt')
1306  call assert_equal('c', m)
1307  call assert_equal(10, x)
1308
1309  " exception doesn't leave cmdline mode
1310  call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1311  call assert_equal(20, x)
1312
1313  " move cursor in the buffer from cmdline mode
1314  call feedkeys(":let x\<F4>= 30\r", 'xt')
1315  call assert_equal(30, x)
1316  call assert_equal(12, col('.'))
1317
1318  " :startinsert takes effect after leaving cmdline mode
1319  call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1320  call assert_equal(40, x)
1321  call assert_equal('some short new lines', getline(1))
1322
1323  call s:cleanupMaps()
1324  %bw!
1325endfunc
1326
1327func Test_map_cmdkey_redo()
1328  func SelectDash()
1329    call search('^---\n\zs', 'bcW')
1330    norm! V
1331    call search('\n\ze---$', 'W')
1332  endfunc
1333
1334  let text =<< trim END
1335      ---
1336      aaa
1337      ---
1338      bbb
1339      bbb
1340      ---
1341      ccc
1342      ccc
1343      ccc
1344      ---
1345  END
1346  new Xcmdtext
1347  call setline(1, text)
1348
1349  onoremap <silent> i- <Cmd>call SelectDash()<CR>
1350  call feedkeys('2Gdi-', 'xt')
1351  call assert_equal(['---', '---'], getline(1, 2))
1352  call feedkeys('j.', 'xt')
1353  call assert_equal(['---', '---', '---'], getline(1, 3))
1354  call feedkeys('j.', 'xt')
1355  call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1356
1357  bwipe!
1358  call delete('Xcmdtext')
1359  delfunc SelectDash
1360  ounmap i-
1361endfunc
1362
1363" vim: shiftwidth=2 sts=2 expandtab
1364