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