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