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