xref: /vim-8.2.3635/src/testdir/test_mapping.vim (revision 56994d21)
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  " reset 'isident' to check it isn't used
449  set isident=
450  inoremap <C-m> CtrlM
451  inoremap <A-S> AltS
452  inoremap <S-/> ShiftSlash
453  set isident&
454  call assert_equal([
455	\ 'i  <S-/>       * ShiftSlash',
456	\ 'i  <M-S>       * AltS',
457	\ 'i  <C-M>       * CtrlM',
458	\], execute('imap')->trim()->split("\n"))
459  iunmap <C-M>
460  iunmap <A-S>
461  call assert_equal(['i  <S-/>       * ShiftSlash'], execute('imap')->trim()->split("\n"))
462  iunmap <S-/>
463  call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
464
465  " List global, buffer local and script local mappings
466  nmap ,f /^\k\+ (<CR>
467  nmap <buffer> ,f /^\k\+ (<CR>
468  nmap <script> ,fs /^\k\+ (<CR>
469  call assert_equal(['n  ,f           @/^\k\+ (<CR>',
470        \ 'n  ,fs         & /^\k\+ (<CR>',
471        \ 'n  ,f            /^\k\+ (<CR>'],
472        \ execute('nmap ,f')->trim()->split("\n"))
473
474  " List <Nop> mapping
475  nmap ,n <Nop>
476  call assert_equal(['n  ,n            <Nop>'],
477        \ execute('nmap ,n')->trim()->split("\n"))
478
479  " verbose map
480  call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
481        \ execute('verbose map ,n')->trim()->split("\n")[1])
482
483  " map to CTRL-V
484  exe "nmap ,k \<C-V>"
485  call assert_equal(['n  ,k            <Nop>'],
486        \ execute('nmap ,k')->trim()->split("\n"))
487
488  nmapclear
489endfunc
490
491func Test_expr_map_gets_cursor()
492  new
493  call setline(1, ['one', 'some w!rd'])
494  func StoreColumn()
495    let g:exprLine = line('.')
496    let g:exprCol = col('.')
497    return 'x'
498  endfunc
499  nnoremap <expr> x StoreColumn()
500  2
501  nmap ! f!<Ignore>x
502  call feedkeys("!", 'xt')
503  call assert_equal('some wrd', getline(2))
504  call assert_equal(2, g:exprLine)
505  call assert_equal(7, g:exprCol)
506
507  bwipe!
508  unlet g:exprLine
509  unlet g:exprCol
510  delfunc StoreColumn
511  nunmap x
512  nunmap !
513endfunc
514
515func Test_expr_map_restore_cursor()
516  CheckScreendump
517
518  let lines =<< trim END
519      call setline(1, ['one', 'two', 'three'])
520      2
521      set ls=2
522      hi! link StatusLine ErrorMsg
523      noremap <expr> <C-B> Func()
524      func Func()
525	  let g:on = !get(g:, 'on', 0)
526	  redraws
527	  return ''
528      endfunc
529      func Status()
530	  return get(g:, 'on', 0) ? '[on]' : ''
531      endfunc
532      set stl=%{Status()}
533  END
534  call writefile(lines, 'XtestExprMap')
535  let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
536  call TermWait(buf)
537  call term_sendkeys(buf, "\<C-B>")
538  call VerifyScreenDump(buf, 'Test_map_expr_1', {})
539
540  " clean up
541  call StopVimInTerminal(buf)
542  call delete('XtestExprMap')
543endfunc
544
545" Test for mapping errors
546func Test_map_error()
547  call assert_fails('unmap', 'E474:')
548  call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
549  call assert_fails('unmap abc', 'E31:')
550  call assert_fails('unabbr abc', 'E24:')
551  call assert_equal('', maparg(''))
552  call assert_fails('echo maparg("abc", [])', 'E730:')
553
554  " unique map
555  map ,w /[#&!]<CR>
556  call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
557  " unique buffer-local map
558  call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
559  unmap ,w
560
561  " unique abbreviation
562  abbr SP special
563  call assert_fails("abbr <unique> SP special", 'E226:')
564  " unique buffer-local map
565  call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
566  unabbr SP
567
568  call assert_fails('mapclear abc', 'E474:')
569  call assert_fails('abclear abc', 'E474:')
570  call assert_fails('abbr $xyz abc', 'E474:')
571
572  " space character in an abbreviation
573  call assert_fails('abbr ab<space> ABC', 'E474:')
574
575  " invalid <expr> map
576  map <expr> ,f abc
577  call assert_fails('normal ,f', 'E121:')
578  unmap <expr> ,f
579
580  " Recursive use of :normal in a map
581  set maxmapdepth=100
582  map gq :normal gq<CR>
583  call assert_fails('normal gq', 'E192:')
584  unmap gq
585  set maxmapdepth&
586endfunc
587
588" Test for <special> key mapping
589func Test_map_special()
590  new
591  let old_cpo = &cpo
592  set cpo+=<
593  imap <F12> Blue
594  call feedkeys("i\<F12>", "x")
595  call assert_equal("<F12>", getline(1))
596  call feedkeys("ddi<F12>", "x")
597  call assert_equal("Blue", getline(1))
598  iunmap <F12>
599  imap <special> <F12> Green
600  call feedkeys("ddi\<F12>", "x")
601  call assert_equal("Green", getline(1))
602  call feedkeys("ddi<F12>", "x")
603  call assert_equal("<F12>", getline(1))
604  iunmap <special> <F12>
605  let &cpo = old_cpo
606  %bwipe!
607endfunc
608
609" Test for hasmapto()
610func Test_hasmapto()
611  call assert_equal(0, hasmapto('/^\k\+ ('))
612  map ,f /^\k\+ (<CR>
613  call assert_equal(1, hasmapto('/^\k\+ ('))
614  unmap ,f
615
616  " Insert mode mapping
617  call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
618  imap ,f /^\k\+ (<CR>
619  call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
620  iunmap ,f
621
622  " Normal mode mapping
623  call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
624  nmap ,f /^\k\+ (<CR>
625  call assert_equal(1, hasmapto('/^\k\+ ('))
626  call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
627  nunmap ,f
628
629  " Visual and Select mode mapping
630  call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
631  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
632  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
633  vmap ,f /^\k\+ (<CR>
634  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
635  call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
636  call assert_equal(1, hasmapto('/^\k\+ (', 's'))
637  vunmap ,f
638
639  " Visual mode mapping
640  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
641  xmap ,f /^\k\+ (<CR>
642  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
643  call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
644  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
645  xunmap ,f
646
647  " Select mode mapping
648  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
649  smap ,f /^\k\+ (<CR>
650  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
651  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
652  call assert_equal(1, hasmapto('/^\k\+ (', 's'))
653  sunmap ,f
654
655  " Operator-pending mode mapping
656  call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
657  omap ,f /^\k\+ (<CR>
658  call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
659  ounmap ,f
660
661  " Language mapping
662  call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
663  lmap ,f /^\k\+ (<CR>
664  call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
665  lunmap ,f
666
667  " Cmdline mode mapping
668  call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
669  cmap ,f /^\k\+ (<CR>
670  call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
671  cunmap ,f
672
673  call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
674endfunc
675
676" Test for command-line completion of maps
677func Test_mapcomplete()
678  call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
679	      \ '<silent>', '<special>', '<unique>'],
680	      \ getcompletion('', 'mapping'))
681  call assert_equal([], getcompletion(',d', 'mapping'))
682
683  call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
684  call assert_equal('"unmap <buffer>', @:)
685
686  call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
687  call assert_equal('"unabbr <buffer>', @:)
688
689  call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
690  call assert_equal("\"abbr! \x01", @:)
691
692  " Multiple matches for a map
693  nmap ,f /H<CR>
694  omap ,f /H<CR>
695  call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
696  call assert_equal('"map ,f', @:)
697  mapclear
698endfunc
699
700" Test for <expr> in abbreviation
701func Test_expr_abbr()
702  new
703  iabbr <expr> teh "the"
704  call feedkeys("iteh ", "tx")
705  call assert_equal('the ', getline(1))
706  iabclear
707  call setline(1, '')
708
709  " invalid <expr> abbreviation
710  abbr <expr> hte GetAbbr()
711  call assert_fails('normal ihte ', 'E117:')
712  call assert_equal('', getline(1))
713  unabbr <expr> hte
714
715  close!
716endfunc
717
718" Test for storing mappings in different modes in a vimrc file
719func Test_mkvimrc_mapmodes()
720  map a1 /a1
721  nmap a2 /a2
722  vmap a3 /a3
723  smap a4 /a4
724  xmap a5 /a5
725  omap a6 /a6
726  map! a7 /a7
727  imap a8 /a8
728  lmap a9 /a9
729  cmap a10 /a10
730  tmap a11 /a11
731  " Normal + Visual map
732  map a12 /a12
733  sunmap a12
734  ounmap a12
735  " Normal + Selectmode map
736  map a13 /a13
737  xunmap a13
738  ounmap a13
739  " Normal + OpPending map
740  map a14 /a14
741  vunmap a14
742  " Visual + Selectmode map
743  map a15 /a15
744  nunmap a15
745  ounmap a15
746  " Visual + OpPending map
747  map a16 /a16
748  nunmap a16
749  sunmap a16
750  " Selectmode + OpPending map
751  map a17 /a17
752  nunmap a17
753  xunmap a17
754  " Normal + Visual + Selectmode map
755  map a18 /a18
756  ounmap a18
757  " Normal + Visual + OpPending map
758  map a19 /a19
759  sunmap a19
760  " Normal + Selectmode + OpPending map
761  map a20 /a20
762  xunmap a20
763  " Visual + Selectmode + OpPending map
764  map a21 /a21
765  nunmap a21
766  " Mapping to Nop
767  map a22 <Nop>
768  " Script local mapping
769  map <script> a23 /a23
770
771  " Newline in {lhs} and {rhs} of a map
772  exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
773
774  " Abbreviation
775  abbr a25 A25
776  cabbr a26 A26
777  iabbr a27 A27
778
779  mkvimrc! Xvimrc
780  let l = readfile('Xvimrc')
781  call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
782  call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
783  call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
784  call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
785  call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
786  call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
787  call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
788  call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
789  call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
790  call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
791  call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
792  call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
793        \ filter(copy(l), 'v:val =~ " a12 "'))
794  call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
795        \ filter(copy(l), 'v:val =~ " a13 "'))
796  call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
797        \ filter(copy(l), 'v:val =~ " a14 "'))
798  call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
799  call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
800        \ filter(copy(l), 'v:val =~ " a16 "'))
801  call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
802        \ filter(copy(l), 'v:val =~ " a17 "'))
803  call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
804        \ filter(copy(l), 'v:val =~ " a18 "'))
805  call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
806        \ filter(copy(l), 'v:val =~ " a19 "'))
807  call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
808        \ filter(copy(l), 'v:val =~ " a20 "'))
809  call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
810        \ filter(copy(l), 'v:val =~ " a21 "'))
811  call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
812  call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
813  call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
814        \ filter(copy(l), 'v:val =~ " a24"'))
815
816  call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
817  call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
818  call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
819  call delete('Xvimrc')
820
821  mapclear
822  nmapclear
823  vmapclear
824  xmapclear
825  smapclear
826  omapclear
827  imapclear
828  lmapclear
829  cmapclear
830  tmapclear
831endfunc
832
833" Test for recursive mapping ('maxmapdepth')
834func Test_map_recursive()
835  map x y
836  map y x
837  call assert_fails('normal x', 'E223:')
838  unmap x
839  unmap y
840endfunc
841
842" Test for removing an abbreviation using {rhs} and with space after {lhs}
843func Test_abbr_remove()
844  abbr foo bar
845  let d = maparg('foo', 'i', 1, 1)
846  call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
847  unabbr bar
848  call assert_equal({}, maparg('foo', 'i', 1, 1))
849
850  abbr foo bar
851  unabbr foo<space><tab>
852  call assert_equal({}, maparg('foo', 'i', 1, 1))
853endfunc
854
855" Trigger an abbreviation using a special key
856func Test_abbr_trigger_special()
857  new
858  iabbr teh the
859  call feedkeys("iteh\<F2>\<Esc>", 'xt')
860  call assert_equal('the<F2>', getline(1))
861  iunab teh
862  close!
863endfunc
864
865" Test for '<' in 'cpoptions'
866func Test_map_cpo_special_keycode()
867  set cpo-=<
868  imap x<Bslash>k Test
869  let d = maparg('x<Bslash>k', 'i', 0, 1)
870  call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
871  call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
872  call assert_equal('"imap x\k', @:)
873  iunmap x<Bslash>k
874  set cpo+=<
875  imap x<Bslash>k Test
876  let d = maparg('x<Bslash>k', 'i', 0, 1)
877  call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
878  call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
879  call assert_equal('"imap x<Bslash>k', @:)
880  iunmap x<Bslash>k
881  set cpo-=<
882  " Modifying 'cpo' above adds some default mappings, remove them
883  mapclear
884  mapclear!
885endfunc
886
887" Test for <Cmd> key in maps to execute commands
888func Test_map_cmdkey()
889  new
890
891  " Error cases
892  let x = 0
893  noremap <F3> <Cmd><Cmd>let x = 1<CR>
894  call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
895  call assert_equal(0, x)
896
897  noremap <F3> <Cmd><F3>let x = 2<CR>
898  call assert_fails('call feedkeys("\<F3>", "xt")', 'E1137:')
899  call assert_equal(0, x)
900
901  noremap <F3> <Cmd>let x = 3
902  call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1135:')
903  call assert_equal(0, x)
904
905  " works in various modes and sees the correct mode()
906  noremap <F3> <Cmd>let m = mode(1)<CR>
907  noremap! <F3> <Cmd>let m = mode(1)<CR>
908
909  " normal mode
910  call feedkeys("\<F3>", 'xt')
911  call assert_equal('n', m)
912
913  " visual mode
914  call feedkeys("v\<F3>", 'xt!')
915  call assert_equal('v', m)
916  " shouldn't leave the visual mode
917  call assert_equal('v', mode(1))
918  call feedkeys("\<Esc>", 'xt')
919  call assert_equal('n', mode(1))
920
921  " visual mapping in select mode
922  call feedkeys("gh\<F3>", 'xt!')
923  call assert_equal('v', m)
924  " shouldn't leave select mode
925  call assert_equal('s', mode(1))
926  call feedkeys("\<Esc>", 'xt')
927  call assert_equal('n', mode(1))
928
929  " select mode mapping
930  snoremap <F3> <Cmd>let m = mode(1)<cr>
931  call feedkeys("gh\<F3>", 'xt!')
932  call assert_equal('s', m)
933  " shouldn't leave select mode
934  call assert_equal('s', mode(1))
935  call feedkeys("\<Esc>", 'xt')
936  call assert_equal('n', mode(1))
937
938  " operator-pending mode
939  call feedkeys("d\<F3>", 'xt!')
940  call assert_equal('no', m)
941  " leaves the operator-pending mode
942  call assert_equal('n', mode(1))
943
944  " insert mode
945  call feedkeys("i\<F3>abc", 'xt')
946  call assert_equal('i', m)
947  call assert_equal('abc', getline('.'))
948
949  " replace mode
950  call feedkeys("0R\<F3>two", 'xt')
951  call assert_equal('R', m)
952  call assert_equal('two', getline('.'))
953
954  " virtual replace mode
955  call setline('.', "one\ttwo")
956  call feedkeys("4|gR\<F3>xxx", 'xt')
957  call assert_equal('Rv', m)
958  call assert_equal("onexxx\ttwo", getline('.'))
959
960  " cmdline mode
961  call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
962  call assert_equal('c', m)
963  call assert_equal('"xxx', @:)
964
965  " terminal mode
966  if CanRunVimInTerminal()
967    tnoremap <F3> <Cmd>let m = mode(1)<CR>
968    let buf = Run_shell_in_terminal({})
969    call feedkeys("\<F3>", 'xt')
970    call assert_equal('t', m)
971    call assert_equal('t', mode(1))
972    call StopShellInTerminal(buf)
973    call TermWait(buf)
974    close!
975    tunmap <F3>
976  endif
977
978  " invoke cmdline mode recursively
979  noremap! <F2> <Cmd>norm! :foo<CR>
980  %d
981  call setline(1, ['some short lines', 'of test text'])
982  call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
983  call assert_equal('"barx', @:)
984  unmap! <F2>
985
986  " test for calling a <SID> function
987  let lines =<< trim END
988    map <F2> <Cmd>call <SID>do_it()<CR>
989    func s:do_it()
990      let g:x = 32
991    endfunc
992  END
993  call writefile(lines, 'Xscript')
994  source Xscript
995  call feedkeys("\<F2>", 'xt')
996  call assert_equal(32, g:x)
997  call delete('Xscript')
998
999  unmap <F3>
1000  unmap! <F3>
1001  %bw!
1002
1003  " command line ending in "0" is handled without errors
1004  onoremap ix <cmd>eval 0<cr>
1005  call feedkeys('dix.', 'xt')
1006  ounmap ix
1007endfunc
1008
1009" text object enters visual mode
1010func TextObj()
1011  if mode() !=# "v"
1012    normal! v
1013  end
1014  call cursor(1, 3)
1015  normal! o
1016  call cursor(2, 4)
1017endfunc
1018
1019func s:cmdmap(lhs, rhs)
1020  exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1021  exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1022endfunc
1023
1024func s:cmdunmap(lhs)
1025  exe 'unmap ' .. a:lhs
1026  exe 'unmap! ' .. a:lhs
1027endfunc
1028
1029" Map various <Fx> keys used by the <Cmd> key tests
1030func s:setupMaps()
1031  call s:cmdmap('<F3>', 'let m = mode(1)')
1032  call s:cmdmap('<F4>', 'normal! ww')
1033  call s:cmdmap('<F5>', 'normal! "ay')
1034  call s:cmdmap('<F6>', 'throw "very error"')
1035  call s:cmdmap('<F7>', 'call TextObj()')
1036  call s:cmdmap('<F8>', 'startinsert')
1037  call s:cmdmap('<F9>', 'stopinsert')
1038endfunc
1039
1040" Remove the mappings setup by setupMaps()
1041func s:cleanupMaps()
1042  call s:cmdunmap('<F3>')
1043  call s:cmdunmap('<F4>')
1044  call s:cmdunmap('<F5>')
1045  call s:cmdunmap('<F6>')
1046  call s:cmdunmap('<F7>')
1047  call s:cmdunmap('<F8>')
1048  call s:cmdunmap('<F9>')
1049endfunc
1050
1051" Test for <Cmd> mapping in normal mode
1052func Test_map_cmdkey_normal_mode()
1053  new
1054  call s:setupMaps()
1055
1056  " check v:count and v:register works
1057  call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1058  call feedkeys("\<F2>", 'xt')
1059  call assert_equal(['n', 0, '"'], s)
1060  call feedkeys("7\<F2>", 'xt')
1061  call assert_equal(['n', 7, '"'], s)
1062  call feedkeys("\"e\<F2>", 'xt')
1063  call assert_equal(['n', 0, 'e'], s)
1064  call feedkeys("5\"k\<F2>", 'xt')
1065  call assert_equal(['n', 5, 'k'], s)
1066  call s:cmdunmap('<F2>')
1067
1068  call setline(1, ['some short lines', 'of test text'])
1069  call feedkeys("\<F7>y", 'xt')
1070  call assert_equal("me short lines\nof t", @")
1071  call assert_equal('v', getregtype('"'))
1072  call assert_equal([0, 1, 3, 0], getpos("'<"))
1073  call assert_equal([0, 2, 4, 0], getpos("'>"))
1074
1075  " startinsert
1076  %d
1077  call feedkeys("\<F8>abc", 'xt')
1078  call assert_equal('abc', getline(1))
1079
1080  " feedkeys are not executed immediately
1081  noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1082  %d
1083  call setline(1, ['some short lines', 'of test text'])
1084  call cursor(2, 3)
1085  call feedkeys(",a\<F3>", 'xt')
1086  call assert_equal('of test text', g:a)
1087  call assert_equal('n', m)
1088  call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1089  nunmap ,a
1090
1091  " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1092  noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1093  call feedkeys(",b\<F3>", 'xt')
1094  call assert_equal('n', m)
1095  call assert_equal('of alphabetatest text', g:b)
1096  nunmap ,b
1097
1098  call s:cleanupMaps()
1099  %bw!
1100endfunc
1101
1102" Test for <Cmd> mapping with the :normal command
1103func Test_map_cmdkey_normal_cmd()
1104  new
1105  noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1106  noremap ,f <Cmd>nosuchcommand<CR>
1107  noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1108  noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1109  noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1110
1111  call setline(1, ['some short lines', 'of test text'])
1112  exe "norm ,x\r"
1113  call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1114
1115  call assert_fails('norm ,f', 'E492:')
1116  call assert_fails('norm ,e', 'very error')
1117  call assert_fails('norm ,m', 'The message.')
1118  call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1119
1120  %d
1121  let caught_err = 0
1122  try
1123    exe "normal ,w"
1124  catch /Vim(echoerr):Err/
1125    let caught_err = 1
1126  endtry
1127  call assert_equal(1, caught_err)
1128  call assert_equal(['', '0'], getline(1, '$'))
1129
1130  %d
1131  call assert_fails('normal ,w', 'Err')
1132  call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1133  call assert_equal(1, line('.'))
1134
1135  nunmap ,x
1136  nunmap ,f
1137  nunmap ,e
1138  nunmap ,m
1139  nunmap ,w
1140  %bw!
1141endfunc
1142
1143" Test for <Cmd> mapping in visual mode
1144func Test_map_cmdkey_visual_mode()
1145  new
1146  set showmode
1147  call s:setupMaps()
1148
1149  call setline(1, ['some short lines', 'of test text'])
1150  call feedkeys("v\<F4>", 'xt!')
1151  call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1152
1153  " can invoke an opeartor, ending the visual mode
1154  let @a = ''
1155  call feedkeys("\<F5>", 'xt!')
1156  call assert_equal('n', mode(1))
1157  call assert_equal('some short l', @a)
1158
1159  " error doesn't interrupt visual mode
1160  call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1161  call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1162  call feedkeys("\<F7>", 'xt!')
1163  call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1164
1165  " startinsert gives "-- (insert) VISUAL --" mode
1166  call feedkeys("\<F8>", 'xt!')
1167  call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1168  redraw!
1169  call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1170  call feedkeys("\<Esc>new ", 'x')
1171  call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1172
1173  call s:cleanupMaps()
1174  set showmode&
1175  %bw!
1176endfunc
1177
1178" Test for <Cmd> mapping in select mode
1179func Test_map_cmdkey_select_mode()
1180  new
1181  set showmode
1182  call s:setupMaps()
1183
1184  snoremap <F1> <cmd>throw "very error"<CR>
1185  snoremap <F2> <cmd>normal! <c-g>"by<CR>
1186  call setline(1, ['some short lines', 'of test text'])
1187
1188  call feedkeys("gh\<F4>", "xt!")
1189  call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1190  redraw!
1191  call assert_match('^-- SELECT --', Screenline(&lines))
1192
1193  " visual mapping in select mode restarts select mode after operator
1194  let @a = ''
1195  call feedkeys("\<F5>", 'xt!')
1196  call assert_equal('s', mode(1))
1197  call assert_equal('some short l', @a)
1198
1199  " select mode mapping works, and does not restart select mode
1200  let @b = ''
1201  call feedkeys("\<F2>", 'xt!')
1202  call assert_equal('n', mode(1))
1203  call assert_equal('some short l', @b)
1204
1205  " error doesn't interrupt temporary visual mode
1206  call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1207  redraw!
1208  call assert_match('^-- VISUAL --', Screenline(&lines))
1209  " quirk: restoration of select mode is not performed
1210  call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1211
1212  " error doesn't interrupt select mode
1213  call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1214  redraw!
1215  call assert_match('^-- SELECT --', Screenline(&lines))
1216  call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1217
1218  call feedkeys("\<F7>", 'xt!')
1219  redraw!
1220  call assert_match('^-- SELECT --', Screenline(&lines))
1221  call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1222
1223  " startinsert gives "-- SELECT (insert) --" mode
1224  call feedkeys("\<F8>", 'xt!')
1225  redraw!
1226  call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1227  call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1228  call feedkeys("\<Esc>new ", 'x')
1229  call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1230
1231  sunmap <F1>
1232  sunmap <F2>
1233  call s:cleanupMaps()
1234  set showmode&
1235  %bw!
1236endfunc
1237
1238" Test for <Cmd> mapping in operator-pending mode
1239func Test_map_cmdkey_op_pending_mode()
1240  new
1241  call s:setupMaps()
1242
1243  call setline(1, ['some short lines', 'of test text'])
1244  call feedkeys("d\<F4>", 'xt')
1245  call assert_equal(['lines', 'of test text'], getline(1, '$'))
1246  call assert_equal(['some short '], getreg('"', 1, 1))
1247  " create a new undo point
1248  let &undolevels = &undolevels
1249
1250  call feedkeys(".", 'xt')
1251  call assert_equal(['test text'], getline(1, '$'))
1252  call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1253  " create a new undo point
1254  let &undolevels = &undolevels
1255
1256  call feedkeys("uu", 'xt')
1257  call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1258
1259  " error aborts operator-pending, operator not performed
1260  call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1261  call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1262
1263  call feedkeys("\"bd\<F7>", 'xt')
1264  call assert_equal(['soest text'], getline(1, '$'))
1265  call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1266
1267  " startinsert aborts operator
1268  call feedkeys("d\<F8>cc", 'xt')
1269  call assert_equal(['soccest text'], getline(1, '$'))
1270
1271  call s:cleanupMaps()
1272  %bw!
1273endfunc
1274
1275" Test for <Cmd> mapping in insert mode
1276func Test_map_cmdkey_insert_mode()
1277  new
1278  call s:setupMaps()
1279
1280  call setline(1, ['some short lines', 'of test text'])
1281  " works the same as <C-O>w<C-O>w
1282  call feedkeys("iindeed \<F4>little ", 'xt')
1283  call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1284  call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1285  call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1286
1287  " Note when entering visual mode from InsertEnter autocmd, an async event,
1288  " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1289  call feedkeys("i\<F7>stuff ", 'xt')
1290  call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1291  call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1292
1293  call feedkeys("\<F5>", 'xt')
1294  call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1295
1296  " also works as part of abbreviation
1297  abbr foo <Cmd>let g:y = 17<CR>bar
1298  exe "normal i\<space>foo "
1299  call assert_equal(17, g:y)
1300  call assert_equal('in bar deed some short little 2 lines', getline(1))
1301  unabbr foo
1302
1303  " :startinsert does nothing
1304  call setline(1, 'foo bar')
1305  call feedkeys("ggi\<F8>vim", 'xt')
1306  call assert_equal('vimfoo bar', getline(1))
1307
1308  " :stopinsert works
1309  call feedkeys("ggi\<F9>Abc", 'xt')
1310  call assert_equal('vimfoo barbc', getline(1))
1311
1312  call s:cleanupMaps()
1313  %bw!
1314endfunc
1315
1316" Test for <Cmd> mapping in insert-completion mode
1317func Test_map_cmdkey_insert_complete_mode()
1318  new
1319  call s:setupMaps()
1320
1321  call setline(1, 'some short lines')
1322  call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1323  call assert_equal('ic', m)
1324  call assert_equal(['some short lines', 'short '], getline(1, '$'))
1325
1326  call s:cleanupMaps()
1327  %bw!
1328endfunc
1329
1330" Test for <Cmd> mapping in cmdline mode
1331func Test_map_cmdkey_cmdline_mode()
1332  new
1333  call s:setupMaps()
1334
1335  call setline(1, ['some short lines', 'of test text'])
1336  let x = 0
1337  call feedkeys(":let x\<F3>= 10\r", 'xt')
1338  call assert_equal('c', m)
1339  call assert_equal(10, x)
1340
1341  " exception doesn't leave cmdline mode
1342  call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1343  call assert_equal(20, x)
1344
1345  " move cursor in the buffer from cmdline mode
1346  call feedkeys(":let x\<F4>= 30\r", 'xt')
1347  call assert_equal(30, x)
1348  call assert_equal(12, col('.'))
1349
1350  " :startinsert takes effect after leaving cmdline mode
1351  call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1352  call assert_equal(40, x)
1353  call assert_equal('some short new lines', getline(1))
1354
1355  call s:cleanupMaps()
1356  %bw!
1357endfunc
1358
1359func Test_map_cmdkey_redo()
1360  func SelectDash()
1361    call search('^---\n\zs', 'bcW')
1362    norm! V
1363    call search('\n\ze---$', 'W')
1364  endfunc
1365
1366  let text =<< trim END
1367      ---
1368      aaa
1369      ---
1370      bbb
1371      bbb
1372      ---
1373      ccc
1374      ccc
1375      ccc
1376      ---
1377  END
1378  new Xcmdtext
1379  call setline(1, text)
1380
1381  onoremap <silent> i- <Cmd>call SelectDash()<CR>
1382  call feedkeys('2Gdi-', 'xt')
1383  call assert_equal(['---', '---'], getline(1, 2))
1384  call feedkeys('j.', 'xt')
1385  call assert_equal(['---', '---', '---'], getline(1, 3))
1386  call feedkeys('j.', 'xt')
1387  call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1388
1389  bwipe!
1390  call delete('Xcmdtext')
1391  delfunc SelectDash
1392  ounmap i-
1393endfunc
1394
1395" Test for using <script> with a map to remap characters in rhs
1396func Test_script_local_remap()
1397  new
1398  inoremap <buffer> <SID>xyz mno
1399  inoremap <buffer> <script> abc st<SID>xyzre
1400  normal iabc
1401  call assert_equal('stmnore', getline(1))
1402  bwipe!
1403endfunc
1404
1405" vim: shiftwidth=2 sts=2 expandtab
1406