xref: /vim-8.2.3635/src/testdir/test_mapping.vim (revision 3fb377fa)
1" Tests for mappings and abbreviations
2
3source shared.vim
4source check.vim
5source screendump.vim
6
7func Test_abbreviation()
8  " abbreviation with 0x80 should work
9  inoreab чкпр   vim
10  call feedkeys("Goчкпр \<Esc>", "xt")
11  call assert_equal('vim ', getline('$'))
12  iunab чкпр
13  set nomodified
14endfunc
15
16func Test_abclear()
17   abbrev foo foobar
18   iabbrev fooi foobari
19   cabbrev fooc foobarc
20   call assert_equal("\n\n"
21         \        .. "c  fooc          foobarc\n"
22         \        .. "i  fooi          foobari\n"
23         \        .. "!  foo           foobar", execute('abbrev'))
24
25   iabclear
26   call assert_equal("\n\n"
27         \        .. "c  fooc          foobarc\n"
28         \        .. "c  foo           foobar", execute('abbrev'))
29   abbrev foo foobar
30   iabbrev fooi foobari
31
32   cabclear
33   call assert_equal("\n\n"
34         \        .. "i  fooi          foobari\n"
35         \        .. "i  foo           foobar", execute('abbrev'))
36   abbrev foo foobar
37   cabbrev fooc foobarc
38
39   abclear
40   call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
41endfunc
42
43func Test_abclear_buffer()
44  abbrev foo foobar
45  new X1
46  abbrev <buffer> foo1 foobar1
47  new X2
48  abbrev <buffer> foo2 foobar2
49
50  call assert_equal("\n\n"
51        \        .. "!  foo2         @foobar2\n"
52        \        .. "!  foo           foobar", execute('abbrev'))
53
54  abclear <buffer>
55  call assert_equal("\n\n"
56        \        .. "!  foo           foobar", execute('abbrev'))
57
58  b X1
59  call assert_equal("\n\n"
60        \        .. "!  foo1         @foobar1\n"
61        \        .. "!  foo           foobar", execute('abbrev'))
62  abclear <buffer>
63  call assert_equal("\n\n"
64        \        .. "!  foo           foobar", execute('abbrev'))
65
66  abclear
67   call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
68
69  %bwipe
70endfunc
71
72func Test_map_ctrl_c_insert()
73  " mapping of ctrl-c in Insert mode
74  set cpo-=< cpo-=k
75  inoremap <c-c> <ctrl-c>
76  cnoremap <c-c> dummy
77  cunmap <c-c>
78  call feedkeys("GoTEST2: CTRL-C |\<C-C>A|\<Esc>", "xt")
79  call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
80  unmap! <c-c>
81  set nomodified
82endfunc
83
84func Test_map_ctrl_c_visual()
85  " mapping of ctrl-c in Visual mode
86  vnoremap <c-c> :<C-u>$put ='vmap works'
87  call feedkeys("GV\<C-C>\<CR>", "xt")
88  call assert_equal('vmap works', getline('$'))
89  vunmap <c-c>
90  set nomodified
91endfunc
92
93func Test_map_langmap()
94  if !has('langmap')
95    return
96  endif
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  if !has('timers')
262    return
263  endif
264  nnoremap aaaa :let got_aaaa = 1<CR>
265  nnoremap bb :let got_bb = 1<CR>
266  nmap b aaa
267  new
268  func ExitInsert(timer)
269    let g:line = getline(1)
270    call feedkeys("\<Esc>", "t")
271  endfunc
272  set timeout timeoutlen=200
273  let timer = timer_start(300, 'ExitInsert')
274  " After the 'b' Vim waits for another character to see if it matches 'bb'.
275  " When it times out it is expanded to "aaa", but there is no wait for
276  " "aaaa".  Can't check that reliably though.
277  call feedkeys("b", "xt!")
278  call assert_equal("aa", g:line)
279  call assert_false(exists('got_aaa'))
280  call assert_false(exists('got_bb'))
281
282  bwipe!
283  nunmap aaaa
284  nunmap bb
285  nunmap b
286  set timeoutlen&
287  delfunc ExitInsert
288  call timer_stop(timer)
289endfunc
290
291func Test_map_timeout_with_timer_interrupt()
292  if !has('job') || !has('timers')
293    return
294  endif
295
296  " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
297  " sequence.
298  new
299  let g:val = 0
300  nnoremap \12 :let g:val = 1<CR>
301  nnoremap \123 :let g:val = 2<CR>
302  set timeout timeoutlen=200
303
304  func ExitCb(job, status)
305    let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
306  endfunc
307
308  call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
309  call feedkeys('\12', 'xt!')
310  call assert_equal(2, g:val)
311
312  bwipe!
313  nunmap \12
314  nunmap \123
315  set timeoutlen&
316  call WaitFor({-> exists('g:timer')})
317  call timer_stop(g:timer)
318  unlet g:timer
319  unlet g:val
320  delfunc ExitCb
321endfunc
322
323func Test_abbreviation_CR()
324  new
325  func Eatchar(pat)
326    let c = nr2char(getchar(0))
327    return (c =~ a:pat) ? '' : c
328  endfunc
329  iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
330  call feedkeys("GA~~7 \<esc>", 'xt')
331  call assert_equal('~~~~~~~', getline('$'))
332  %d
333  call feedkeys("GA~~7\<cr>\<esc>", 'xt')
334  call assert_equal(['~~~~~~~', ''], getline(1,'$'))
335  delfunc Eatchar
336  bw!
337endfunc
338
339func Test_cabbr_visual_mode()
340  cabbr s su
341  call feedkeys(":s \<c-B>\"\<CR>", 'itx')
342  call assert_equal('"su ', getreg(':'))
343  call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
344  let expected = '"'. "'<,'>su "
345  call assert_equal(expected, getreg(':'))
346  call feedkeys(":  '<,'>s \<c-B>\"\<CR>", 'itx')
347  let expected = '"  '. "'<,'>su "
348  call assert_equal(expected, getreg(':'))
349  call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
350  let expected = '"'. "'a,'bsu "
351  call assert_equal(expected, getreg(':'))
352  cunabbr s
353endfunc
354
355func Test_motionforce_omap()
356  func GetCommand()
357    let g:m=mode(1)
358    let [g:lnum1, g:col1] = searchpos('-', 'Wb')
359    if g:lnum1 == 0
360        return "\<Esc>"
361    endif
362    let [g:lnum2, g:col2] = searchpos('-', 'W')
363    if g:lnum2 == 0
364        return "\<Esc>"
365    endif
366    return ":call Select()\<CR>"
367  endfunc
368  func Select()
369    call cursor([g:lnum1, g:col1])
370    exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
371    call cursor([g:lnum2, g:col2])
372    execute "normal! \<BS>"
373  endfunc
374  new
375  onoremap <buffer><expr> i- GetCommand()
376  " 1) default omap mapping
377  %d_
378  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
379  call cursor(2, 1)
380  norm di-
381  call assert_equal('no', g:m)
382  call assert_equal(['aaa -- eee'], getline(1, '$'))
383  " 2) forced characterwise operation
384  %d_
385  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
386  call cursor(2, 1)
387  norm dvi-
388  call assert_equal('nov', g:m)
389  call assert_equal(['aaa -- eee'], getline(1, '$'))
390  " 3) forced linewise operation
391  %d_
392  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
393  call cursor(2, 1)
394  norm dVi-
395  call assert_equal('noV', g:m)
396  call assert_equal([''], getline(1, '$'))
397  " 4) forced blockwise operation
398  %d_
399  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
400  call cursor(2, 1)
401  exe "norm d\<C-V>i-"
402  call assert_equal("no\<C-V>", g:m)
403  call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
404  bwipe!
405  delfunc Select
406  delfunc GetCommand
407endfunc
408
409func Test_error_in_map_expr()
410  " Unlike CheckRunVimInTerminal this does work in a win32 console
411  CheckFeature terminal
412  if has('win32') && has('gui_running')
413    throw 'Skipped: cannot run Vim in a terminal window'
414  endif
415
416  let lines =<< trim [CODE]
417  func Func()
418    " fail to create list
419    let x = [
420  endfunc
421  nmap <expr> ! Func()
422  set updatetime=50
423  [CODE]
424  call writefile(lines, 'Xtest.vim')
425
426  let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
427  let job = term_getjob(buf)
428  call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
429
430  " GC must not run during map-expr processing, which can make Vim crash.
431  call term_sendkeys(buf, '!')
432  call term_wait(buf, 100)
433  call term_sendkeys(buf, "\<CR>")
434  call term_wait(buf, 100)
435  call assert_equal('run', job_status(job))
436
437  call term_sendkeys(buf, ":qall!\<CR>")
438  call WaitFor({-> job_status(job) ==# 'dead'})
439  if has('unix')
440    call assert_equal('', job_info(job).termsig)
441  endif
442
443  call delete('Xtest.vim')
444  exe buf .. 'bwipe!'
445endfunc
446
447func Test_list_mappings()
448  " Remove default mappings
449  imapclear
450
451  inoremap <C-M> CtrlM
452  inoremap <A-S> AltS
453  inoremap <S-/> ShiftSlash
454  call assert_equal([
455	\ 'i  <S-/>       * ShiftSlash',
456	\ 'i  <M-S>       * AltS',
457	\ 'i  <C-M>       * CtrlM',
458	\], execute('imap')->trim()->split("\n"))
459  iunmap <C-M>
460  iunmap <A-S>
461  call assert_equal(['i  <S-/>       * ShiftSlash'], execute('imap')->trim()->split("\n"))
462  iunmap <S-/>
463  call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
464
465  " List global, buffer local and script local mappings
466  nmap ,f /^\k\+ (<CR>
467  nmap <buffer> ,f /^\k\+ (<CR>
468  nmap <script> ,fs /^\k\+ (<CR>
469  call assert_equal(['n  ,f           @/^\k\+ (<CR>',
470        \ 'n  ,fs         & /^\k\+ (<CR>',
471        \ 'n  ,f            /^\k\+ (<CR>'],
472        \ execute('nmap ,f')->trim()->split("\n"))
473
474  " List <Nop> mapping
475  nmap ,n <Nop>
476  call assert_equal(['n  ,n            <Nop>'],
477        \ execute('nmap ,n')->trim()->split("\n"))
478
479  " verbose map
480  call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
481        \ execute('verbose map ,n')->trim()->split("\n")[1])
482
483  " map to CTRL-V
484  exe "nmap ,k \<C-V>"
485  call assert_equal(['n  ,k            <Nop>'],
486        \ execute('nmap ,k')->trim()->split("\n"))
487
488  nmapclear
489endfunc
490
491func Test_expr_map_restore_cursor()
492  CheckScreendump
493
494  let lines =<< trim END
495      call setline(1, ['one', 'two', 'three'])
496      2
497      set ls=2
498      hi! link StatusLine ErrorMsg
499      noremap <expr> <C-B> Func()
500      func Func()
501	  let g:on = !get(g:, 'on', 0)
502	  redraws
503	  return ''
504      endfunc
505      func Status()
506	  return get(g:, 'on', 0) ? '[on]' : ''
507      endfunc
508      set stl=%{Status()}
509  END
510  call writefile(lines, 'XtestExprMap')
511  let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
512  call term_wait(buf)
513  call term_sendkeys(buf, "\<C-B>")
514  call VerifyScreenDump(buf, 'Test_map_expr_1', {})
515
516  " clean up
517  call StopVimInTerminal(buf)
518  call delete('XtestExprMap')
519endfunc
520
521" Test for mapping errors
522func Test_map_error()
523  call assert_fails('unmap', 'E474:')
524  call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
525  call assert_fails('unmap abc', 'E31:')
526  call assert_fails('unabbr abc', 'E24:')
527  call assert_equal('', maparg(''))
528  call assert_fails('echo maparg("abc", [])', 'E730:')
529
530  " unique map
531  map ,w /[#&!]<CR>
532  call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
533  " unique buffer-local map
534  call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
535  unmap ,w
536
537  " unique abbreviation
538  abbr SP special
539  call assert_fails("abbr <unique> SP special", 'E226:')
540  " unique buffer-local map
541  call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
542  unabbr SP
543
544  call assert_fails('mapclear abc', 'E474:')
545  call assert_fails('abclear abc', 'E474:')
546  call assert_fails('abbr $xyz abc', 'E474:')
547
548  " space character in an abbreviation
549  call assert_fails('abbr ab<space> ABC', 'E474:')
550
551  " invalid <expr> map
552  map <expr> ,f abc
553  call assert_fails('normal ,f', 'E121:')
554  unmap <expr> ,f
555
556  " Recursive use of :normal in a map
557  set maxmapdepth=100
558  map gq :normal gq<CR>
559  call assert_fails('normal gq', 'E192:')
560  unmap gq
561  set maxmapdepth&
562endfunc
563
564" Test for <special> key mapping
565func Test_map_special()
566  new
567  let old_cpo = &cpo
568  set cpo+=<
569  imap <F12> Blue
570  call feedkeys("i\<F12>", "x")
571  call assert_equal("<F12>", getline(1))
572  call feedkeys("ddi<F12>", "x")
573  call assert_equal("Blue", getline(1))
574  iunmap <F12>
575  imap <special> <F12> Green
576  call feedkeys("ddi\<F12>", "x")
577  call assert_equal("Green", getline(1))
578  call feedkeys("ddi<F12>", "x")
579  call assert_equal("<F12>", getline(1))
580  iunmap <special> <F12>
581  let &cpo = old_cpo
582  %bwipe!
583endfunc
584
585" Test for hasmapto()
586func Test_hasmapto()
587  call assert_equal(0, hasmapto('/^\k\+ ('))
588  map ,f /^\k\+ (<CR>
589  call assert_equal(1, hasmapto('/^\k\+ ('))
590  unmap ,f
591
592  " Insert mode mapping
593  call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
594  imap ,f /^\k\+ (<CR>
595  call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
596  iunmap ,f
597
598  " Normal mode mapping
599  call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
600  nmap ,f /^\k\+ (<CR>
601  call assert_equal(1, hasmapto('/^\k\+ ('))
602  call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
603  nunmap ,f
604
605  " Visual and Select mode mapping
606  call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
607  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
608  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
609  vmap ,f /^\k\+ (<CR>
610  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
611  call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
612  call assert_equal(1, hasmapto('/^\k\+ (', 's'))
613  vunmap ,f
614
615  " Visual mode mapping
616  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
617  xmap ,f /^\k\+ (<CR>
618  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
619  call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
620  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
621  xunmap ,f
622
623  " Select mode mapping
624  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
625  smap ,f /^\k\+ (<CR>
626  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
627  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
628  call assert_equal(1, hasmapto('/^\k\+ (', 's'))
629  sunmap ,f
630
631  " Operator-pending mode mapping
632  call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
633  omap ,f /^\k\+ (<CR>
634  call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
635  ounmap ,f
636
637  " Language mapping
638  call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
639  lmap ,f /^\k\+ (<CR>
640  call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
641  lunmap ,f
642
643  " Cmdline mode mapping
644  call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
645  cmap ,f /^\k\+ (<CR>
646  call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
647  cunmap ,f
648
649  call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
650endfunc
651
652" Test for command-line completion of maps
653func Test_mapcomplete()
654  call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
655	      \ '<silent>', '<special>', '<unique>'],
656	      \ getcompletion('', 'mapping'))
657  call assert_equal([], getcompletion(',d', 'mapping'))
658
659  call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
660  call assert_equal('"unmap <buffer>', @:)
661
662  call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
663  call assert_equal('"unabbr <buffer>', @:)
664
665  call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
666  call assert_equal("\"abbr! \x01", @:)
667
668  " Multiple matches for a map
669  nmap ,f /H<CR>
670  omap ,f /H<CR>
671  call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
672  call assert_equal('"map ,f', @:)
673  mapclear
674endfunc
675
676" Test for <expr> in abbreviation
677func Test_expr_abbr()
678  new
679  iabbr <expr> teh "the"
680  call feedkeys("iteh ", "tx")
681  call assert_equal('the ', getline(1))
682  iabclear
683  call setline(1, '')
684
685  " invalid <expr> abbreviation
686  abbr <expr> hte GetAbbr()
687  call assert_fails('normal ihte ', 'E117:')
688  call assert_equal(' ', getline(1))
689  unabbr <expr> hte
690
691  close!
692endfunc
693
694" Test for storing mappings in different modes in a vimrc file
695func Test_mkvimrc_mapmodes()
696  map a1 /a1
697  nmap a2 /a2
698  vmap a3 /a3
699  smap a4 /a4
700  xmap a5 /a5
701  omap a6 /a6
702  map! a7 /a7
703  imap a8 /a8
704  lmap a9 /a9
705  cmap a10 /a10
706  tmap a11 /a11
707  " Normal + Visual map
708  map a12 /a12
709  sunmap a12
710  ounmap a12
711  " Normal + Selectmode map
712  map a13 /a13
713  xunmap a13
714  ounmap a13
715  " Normal + OpPending map
716  map a14 /a14
717  vunmap a14
718  " Visual + Selectmode map
719  map a15 /a15
720  nunmap a15
721  ounmap a15
722  " Visual + OpPending map
723  map a16 /a16
724  nunmap a16
725  sunmap a16
726  " Selectmode + OpPending map
727  map a17 /a17
728  nunmap a17
729  xunmap a17
730  " Normal + Visual + Selectmode map
731  map a18 /a18
732  ounmap a18
733  " Normal + Visual + OpPending map
734  map a19 /a19
735  sunmap a19
736  " Normal + Selectmode + OpPending map
737  map a20 /a20
738  xunmap a20
739  " Visual + Selectmode + OpPending map
740  map a21 /a21
741  nunmap a21
742  " Mapping to Nop
743  map a22 <Nop>
744  " Script local mapping
745  map <script> a23 /a23
746
747  " Newline in {lhs} and {rhs} of a map
748  exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
749
750  " Abbreviation
751  abbr a25 A25
752  cabbr a26 A26
753  iabbr a27 A27
754
755  mkvimrc! Xvimrc
756  let l = readfile('Xvimrc')
757  call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
758  call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
759  call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
760  call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
761  call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
762  call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
763  call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
764  call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
765  call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
766  call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
767  call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
768  call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
769        \ filter(copy(l), 'v:val =~ " a12 "'))
770  call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
771        \ filter(copy(l), 'v:val =~ " a13 "'))
772  call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
773        \ filter(copy(l), 'v:val =~ " a14 "'))
774  call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
775  call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
776        \ filter(copy(l), 'v:val =~ " a16 "'))
777  call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
778        \ filter(copy(l), 'v:val =~ " a17 "'))
779  call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
780        \ filter(copy(l), 'v:val =~ " a18 "'))
781  call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
782        \ filter(copy(l), 'v:val =~ " a19 "'))
783  call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
784        \ filter(copy(l), 'v:val =~ " a20 "'))
785  call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
786        \ filter(copy(l), 'v:val =~ " a21 "'))
787  call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
788  call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
789  call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
790        \ filter(copy(l), 'v:val =~ " a24"'))
791
792  call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
793  call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
794  call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
795  call delete('Xvimrc')
796
797  mapclear
798  nmapclear
799  vmapclear
800  xmapclear
801  smapclear
802  omapclear
803  imapclear
804  lmapclear
805  cmapclear
806  tmapclear
807endfunc
808
809" Test for recursive mapping ('maxmapdepth')
810func Test_map_recursive()
811  map x y
812  map y x
813  call assert_fails('normal x', 'E223:')
814  unmap x
815  unmap y
816endfunc
817
818" Test for removing an abbreviation using {rhs} and with space after {lhs}
819func Test_abbr_remove()
820  abbr foo bar
821  let d = maparg('foo', 'i', 1, 1)
822  call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
823  unabbr bar
824  call assert_equal({}, maparg('foo', 'i', 1, 1))
825
826  abbr foo bar
827  unabbr foo<space><tab>
828  call assert_equal({}, maparg('foo', 'i', 1, 1))
829endfunc
830
831" Trigger an abbreviation using a special key
832func Test_abbr_trigger_special()
833  new
834  iabbr teh the
835  call feedkeys("iteh\<F2>\<Esc>", 'xt')
836  call assert_equal('the<F2>', getline(1))
837  iunab teh
838  close!
839endfunc
840
841" Test for '<' in 'cpoptions'
842func Test_map_cpo_special_keycode()
843  set cpo-=<
844  imap x<Bslash>k Test
845  let d = maparg('x<Bslash>k', 'i', 0, 1)
846  call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
847  call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
848  call assert_equal('"imap x\k', @:)
849  iunmap x<Bslash>k
850  set cpo+=<
851  imap x<Bslash>k Test
852  let d = maparg('x<Bslash>k', 'i', 0, 1)
853  call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
854  call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
855  call assert_equal('"imap x<Bslash>k', @:)
856  iunmap x<Bslash>k
857  set cpo-=<
858  " Modifying 'cpo' above adds some default mappings, remove them
859  mapclear
860  mapclear!
861endfunc
862
863" vim: shiftwidth=2 sts=2 expandtab
864