xref: /vim-8.2.3635/src/testdir/test_mapping.vim (revision a7c4e747)
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'))
41   call assert_fails('%abclear', 'E481:')
42endfunc
43
44func Test_abclear_buffer()
45  abbrev foo foobar
46  new X1
47  abbrev <buffer> foo1 foobar1
48  new X2
49  abbrev <buffer> foo2 foobar2
50
51  call assert_equal("\n\n"
52        \        .. "!  foo2         @foobar2\n"
53        \        .. "!  foo           foobar", execute('abbrev'))
54
55  abclear <buffer>
56  call assert_equal("\n\n"
57        \        .. "!  foo           foobar", execute('abbrev'))
58
59  b X1
60  call assert_equal("\n\n"
61        \        .. "!  foo1         @foobar1\n"
62        \        .. "!  foo           foobar", execute('abbrev'))
63  abclear <buffer>
64  call assert_equal("\n\n"
65        \        .. "!  foo           foobar", execute('abbrev'))
66
67  abclear
68   call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
69
70  %bwipe
71endfunc
72
73func Test_map_ctrl_c_insert()
74  " mapping of ctrl-c in Insert mode
75  set cpo-=< cpo-=k
76  inoremap <c-c> <ctrl-c>
77  cnoremap <c-c> dummy
78  cunmap <c-c>
79  call feedkeys("GoTEST2: CTRL-C |\<*C-C>A|\<Esc>", "xt")
80  call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
81  unmap! <c-c>
82  set nomodified
83endfunc
84
85func Test_map_ctrl_c_visual()
86  " mapping of ctrl-c in Visual mode
87  vnoremap <c-c> :<C-u>$put ='vmap works'
88  call feedkeys("GV\<*C-C>\<CR>", "xt")
89  call assert_equal('vmap works', getline('$'))
90  vunmap <c-c>
91  set nomodified
92endfunc
93
94func Test_map_langmap()
95  CheckFeature langmap
96
97  " check langmap applies in normal mode
98  set langmap=+- nolangremap
99  new
100  call setline(1, ['a', 'b', 'c'])
101  2
102  call assert_equal('b', getline('.'))
103  call feedkeys("+", "xt")
104  call assert_equal('a', getline('.'))
105
106  " check no remapping
107  map x +
108  2
109  call feedkeys("x", "xt")
110  call assert_equal('c', getline('.'))
111
112  " check with remapping
113  set langremap
114  2
115  call feedkeys("x", "xt")
116  call assert_equal('a', getline('.'))
117
118  unmap x
119  bwipe!
120
121  " 'langnoremap' follows 'langremap' and vise versa
122  set langremap
123  set langnoremap
124  call assert_equal(0, &langremap)
125  set langremap
126  call assert_equal(0, &langnoremap)
127  set nolangremap
128  call assert_equal(1, &langnoremap)
129
130  " check default values
131  set langnoremap&
132  call assert_equal(0, &langnoremap)
133  call assert_equal(1, &langremap)
134  set langremap&
135  call assert_equal(0, &langnoremap)
136  call assert_equal(1, &langremap)
137
138  " langmap should not apply in insert mode, 'langremap' doesn't matter
139  set langmap=+{ nolangremap
140  call feedkeys("Go+\<Esc>", "xt")
141  call assert_equal('+', getline('$'))
142  set langmap=+{ langremap
143  call feedkeys("Go+\<Esc>", "xt")
144  call assert_equal('+', getline('$'))
145
146  " langmap used for register name in insert mode.
147  call setreg('a', 'aaaa')
148  call setreg('b', 'bbbb')
149  call setreg('c', 'cccc')
150  set langmap=ab langremap
151  call feedkeys("Go\<C-R>a\<Esc>", "xt")
152  call assert_equal('bbbb', getline('$'))
153  call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt")
154  call assert_equal('bbbb', getline('$'))
155  " mapping does not apply
156  imap c a
157  call feedkeys("Go\<C-R>c\<Esc>", "xt")
158  call assert_equal('cccc', getline('$'))
159  imap a c
160  call feedkeys("Go\<C-R>a\<Esc>", "xt")
161  call assert_equal('bbbb', getline('$'))
162
163  " langmap should not apply in Command-line mode
164  set langmap=+{ nolangremap
165  call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
166  call assert_equal('+', getline('$'))
167
168  iunmap a
169  iunmap c
170  set nomodified
171endfunc
172
173func Test_map_feedkeys()
174  " issue #212 (feedkeys insert mapping at current position)
175  nnoremap . :call feedkeys(".", "in")<cr>
176  call setline('$', ['a b c d', 'a b c d'])
177  $-1
178  call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt")
179  call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$')))
180  nunmap .
181  set nomodified
182endfunc
183
184func Test_map_cursor()
185  " <c-g>U<cursor> works only within a single line
186  imapclear
187  imap ( ()<c-g>U<left>
188  call feedkeys("G2o\<Esc>ki\<CR>Test1: text with a (here some more text\<Esc>k.", "xt")
189  call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 2))
190  call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 1))
191
192  " test undo
193  call feedkeys("G2o\<Esc>ki\<CR>Test2: text wit a (here some more text [und undo]\<C-G>u\<Esc>k.u", "xt")
194  call assert_equal('', getline(line('$') - 2))
195  call assert_equal('Test2: text wit a (here some more text [und undo])', getline(line('$') - 1))
196  set nomodified
197  imapclear
198endfunc
199
200func Test_map_cursor_ctrl_gU()
201  " <c-g>U<cursor> works only within a single line
202  nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left>
203  call setline(1, ['foo', 'foobar', '', 'foo'])
204  call cursor(1,2)
205  call feedkeys("c<*PREFIX\<esc>.", 'xt')
206  call assert_equal(['PREFIXfoo', 'foobar', '', 'PREFIXfoo'], getline(1,'$'))
207  " break undo manually
208  set ul=1000
209  exe ":norm! uu"
210  call assert_equal(['foo', 'foobar', '', 'foo'], getline(1,'$'))
211
212  " Test that it does not work if the cursor moves to the previous line
213  " 2 times <S-Left> move to the previous line
214  nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left><C-G>U<S-Left>
215  call setline(1, ['', ' foo', 'foobar', '', 'foo'])
216  call cursor(2,3)
217  call feedkeys("c<*PREFIX\<esc>.", 'xt')
218  call assert_equal(['PREFIXPREFIX', ' foo', 'foobar', '', 'foo'], getline(1,'$'))
219  nmapclear
220endfunc
221
222
223" This isn't actually testing a mapping, but similar use of CTRL-G U as above.
224func Test_break_undo()
225  set whichwrap=<,>,[,]
226  call feedkeys("G4o2k", "xt")
227  exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."
228  call assert_equal('new line here', getline(line('$') - 3))
229  call assert_equal('Test3: text with a (parenthesis here', getline(line('$') - 2))
230  call assert_equal('new line here', getline(line('$') - 1))
231  set nomodified
232endfunc
233
234func Test_map_meta_quotes()
235  imap <M-"> foo
236  call feedkeys("Go-\<*M-\">-\<Esc>", "xt")
237  call assert_equal("-foo-", getline('$'))
238  set nomodified
239  iunmap <M-">
240endfunc
241
242func Test_map_meta_multibyte()
243  imap <M-á> foo
244  call assert_match('i  <M-á>\s*foo', execute('imap'))
245  iunmap <M-á>
246endfunc
247
248func Test_abbr_after_line_join()
249  new
250  abbr foo bar
251  set backspace=indent,eol,start
252  exe "normal o\<BS>foo "
253  call assert_equal("bar ", getline(1))
254  bwipe!
255  unabbr foo
256  set backspace&
257endfunc
258
259func Test_map_timeout()
260  CheckFeature timers
261  nnoremap aaaa :let got_aaaa = 1<CR>
262  nnoremap bb :let got_bb = 1<CR>
263  nmap b aaa
264  new
265  func ExitInsert(timer)
266    let g:line = getline(1)
267    call feedkeys("\<Esc>", "t")
268  endfunc
269  set timeout timeoutlen=200
270  let timer = timer_start(300, 'ExitInsert')
271  " After the 'b' Vim waits for another character to see if it matches 'bb'.
272  " When it times out it is expanded to "aaa", but there is no wait for
273  " "aaaa".  Can't check that reliably though.
274  call feedkeys("b", "xt!")
275  call assert_equal("aa", g:line)
276  call assert_false(exists('got_aaa'))
277  call assert_false(exists('got_bb'))
278
279  bwipe!
280  nunmap aaaa
281  nunmap bb
282  nunmap b
283  set timeoutlen&
284  delfunc ExitInsert
285  call timer_stop(timer)
286endfunc
287
288func Test_map_timeout_with_timer_interrupt()
289  CheckFeature job
290  CheckFeature timers
291
292  " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
293  " sequence.
294  new
295  let g:val = 0
296  nnoremap \12 :let g:val = 1<CR>
297  nnoremap \123 :let g:val = 2<CR>
298  set timeout timeoutlen=200
299
300  func ExitCb(job, status)
301    let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
302  endfunc
303
304  call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
305  call feedkeys('\12', 'xt!')
306  call assert_equal(2, g:val)
307
308  bwipe!
309  nunmap \12
310  nunmap \123
311  set timeoutlen&
312  call WaitFor({-> exists('g:timer')})
313  call timer_stop(g:timer)
314  unlet g:timer
315  unlet g:val
316  delfunc ExitCb
317endfunc
318
319func Test_abbreviation_CR()
320  new
321  func Eatchar(pat)
322    let c = nr2char(getchar(0))
323    return (c =~ a:pat) ? '' : c
324  endfunc
325  iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
326  call feedkeys("GA~~7 \<esc>", 'xt')
327  call assert_equal('~~~~~~~', getline('$'))
328  %d
329  call feedkeys("GA~~7\<cr>\<esc>", 'xt')
330  call assert_equal(['~~~~~~~', ''], getline(1,'$'))
331  delfunc Eatchar
332  bw!
333endfunc
334
335func Test_cabbr_visual_mode()
336  cabbr s su
337  call feedkeys(":s \<c-B>\"\<CR>", 'itx')
338  call assert_equal('"su ', getreg(':'))
339  call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
340  let expected = '"'. "'<,'>su "
341  call assert_equal(expected, getreg(':'))
342  call feedkeys(":  '<,'>s \<c-B>\"\<CR>", 'itx')
343  let expected = '"  '. "'<,'>su "
344  call assert_equal(expected, getreg(':'))
345  call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
346  let expected = '"'. "'a,'bsu "
347  call assert_equal(expected, getreg(':'))
348  cunabbr s
349endfunc
350
351func Test_motionforce_omap()
352  func GetCommand()
353    let g:m=mode(1)
354    let [g:lnum1, g:col1] = searchpos('-', 'Wb')
355    if g:lnum1 == 0
356        return "\<Esc>"
357    endif
358    let [g:lnum2, g:col2] = searchpos('-', 'W')
359    if g:lnum2 == 0
360        return "\<Esc>"
361    endif
362    return ":call Select()\<CR>"
363  endfunc
364  func Select()
365    call cursor([g:lnum1, g:col1])
366    exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
367    call cursor([g:lnum2, g:col2])
368    execute "normal! \<BS>"
369  endfunc
370  new
371  onoremap <buffer><expr> i- GetCommand()
372  " 1) default omap mapping
373  %d_
374  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
375  call cursor(2, 1)
376  norm di-
377  call assert_equal('no', g:m)
378  call assert_equal(['aaa -- eee'], getline(1, '$'))
379  " 2) forced characterwise operation
380  %d_
381  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
382  call cursor(2, 1)
383  norm dvi-
384  call assert_equal('nov', g:m)
385  call assert_equal(['aaa -- eee'], getline(1, '$'))
386  " 3) forced linewise operation
387  %d_
388  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
389  call cursor(2, 1)
390  norm dVi-
391  call assert_equal('noV', g:m)
392  call assert_equal([''], getline(1, '$'))
393  " 4) forced blockwise operation
394  %d_
395  call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
396  call cursor(2, 1)
397  exe "norm d\<C-V>i-"
398  call assert_equal("no\<C-V>", g:m)
399  call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
400  bwipe!
401  delfunc Select
402  delfunc GetCommand
403endfunc
404
405func Test_error_in_map_expr()
406  " Unlike CheckRunVimInTerminal this does work in a win32 console
407  CheckFeature terminal
408  if has('win32') && has('gui_running')
409    throw 'Skipped: cannot run Vim in a terminal window'
410  endif
411
412  let lines =<< trim [CODE]
413  func Func()
414    " fail to create list
415    let x = [
416  endfunc
417  nmap <expr> ! Func()
418  set updatetime=50
419  [CODE]
420  call writefile(lines, 'Xtest.vim')
421
422  let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
423  let job = term_getjob(buf)
424  call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
425
426  " GC must not run during map-expr processing, which can make Vim crash.
427  call term_sendkeys(buf, '!')
428  call TermWait(buf, 50)
429  call term_sendkeys(buf, "\<CR>")
430  call TermWait(buf, 50)
431  call assert_equal('run', job_status(job))
432
433  call term_sendkeys(buf, ":qall!\<CR>")
434  call WaitFor({-> job_status(job) ==# 'dead'})
435  if has('unix')
436    call assert_equal('', job_info(job).termsig)
437  endif
438
439  call delete('Xtest.vim')
440  exe buf .. 'bwipe!'
441endfunc
442
443func Test_list_mappings()
444  " Remove default mappings
445  imapclear
446
447  inoremap <C-M> CtrlM
448  inoremap <A-S> AltS
449  inoremap <S-/> ShiftSlash
450  call assert_equal([
451	\ 'i  <S-/>       * ShiftSlash',
452	\ 'i  <M-S>       * AltS',
453	\ 'i  <C-M>       * CtrlM',
454	\], execute('imap')->trim()->split("\n"))
455  iunmap <C-M>
456  iunmap <A-S>
457  call assert_equal(['i  <S-/>       * ShiftSlash'], execute('imap')->trim()->split("\n"))
458  iunmap <S-/>
459  call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
460
461  " List global, buffer local and script local mappings
462  nmap ,f /^\k\+ (<CR>
463  nmap <buffer> ,f /^\k\+ (<CR>
464  nmap <script> ,fs /^\k\+ (<CR>
465  call assert_equal(['n  ,f           @/^\k\+ (<CR>',
466        \ 'n  ,fs         & /^\k\+ (<CR>',
467        \ 'n  ,f            /^\k\+ (<CR>'],
468        \ execute('nmap ,f')->trim()->split("\n"))
469
470  " List <Nop> mapping
471  nmap ,n <Nop>
472  call assert_equal(['n  ,n            <Nop>'],
473        \ execute('nmap ,n')->trim()->split("\n"))
474
475  " verbose map
476  call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
477        \ execute('verbose map ,n')->trim()->split("\n")[1])
478
479  " map to CTRL-V
480  exe "nmap ,k \<C-V>"
481  call assert_equal(['n  ,k            <Nop>'],
482        \ execute('nmap ,k')->trim()->split("\n"))
483
484  nmapclear
485endfunc
486
487func Test_expr_map_restore_cursor()
488  CheckScreendump
489
490  let lines =<< trim END
491      call setline(1, ['one', 'two', 'three'])
492      2
493      set ls=2
494      hi! link StatusLine ErrorMsg
495      noremap <expr> <C-B> Func()
496      func Func()
497	  let g:on = !get(g:, 'on', 0)
498	  redraws
499	  return ''
500      endfunc
501      func Status()
502	  return get(g:, 'on', 0) ? '[on]' : ''
503      endfunc
504      set stl=%{Status()}
505  END
506  call writefile(lines, 'XtestExprMap')
507  let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
508  call TermWait(buf)
509  call term_sendkeys(buf, "\<C-B>")
510  call VerifyScreenDump(buf, 'Test_map_expr_1', {})
511
512  " clean up
513  call StopVimInTerminal(buf)
514  call delete('XtestExprMap')
515endfunc
516
517" Test for mapping errors
518func Test_map_error()
519  call assert_fails('unmap', 'E474:')
520  call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
521  call assert_fails('unmap abc', 'E31:')
522  call assert_fails('unabbr abc', 'E24:')
523  call assert_equal('', maparg(''))
524  call assert_fails('echo maparg("abc", [])', 'E730:')
525
526  " unique map
527  map ,w /[#&!]<CR>
528  call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
529  " unique buffer-local map
530  call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
531  unmap ,w
532
533  " unique abbreviation
534  abbr SP special
535  call assert_fails("abbr <unique> SP special", 'E226:')
536  " unique buffer-local map
537  call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
538  unabbr SP
539
540  call assert_fails('mapclear abc', 'E474:')
541  call assert_fails('abclear abc', 'E474:')
542  call assert_fails('abbr $xyz abc', 'E474:')
543
544  " space character in an abbreviation
545  call assert_fails('abbr ab<space> ABC', 'E474:')
546
547  " invalid <expr> map
548  map <expr> ,f abc
549  call assert_fails('normal ,f', 'E121:')
550  unmap <expr> ,f
551
552  " Recursive use of :normal in a map
553  set maxmapdepth=100
554  map gq :normal gq<CR>
555  call assert_fails('normal gq', 'E192:')
556  unmap gq
557  set maxmapdepth&
558endfunc
559
560" Test for <special> key mapping
561func Test_map_special()
562  new
563  let old_cpo = &cpo
564  set cpo+=<
565  imap <F12> Blue
566  call feedkeys("i\<F12>", "x")
567  call assert_equal("<F12>", getline(1))
568  call feedkeys("ddi<F12>", "x")
569  call assert_equal("Blue", getline(1))
570  iunmap <F12>
571  imap <special> <F12> Green
572  call feedkeys("ddi\<F12>", "x")
573  call assert_equal("Green", getline(1))
574  call feedkeys("ddi<F12>", "x")
575  call assert_equal("<F12>", getline(1))
576  iunmap <special> <F12>
577  let &cpo = old_cpo
578  %bwipe!
579endfunc
580
581" Test for hasmapto()
582func Test_hasmapto()
583  call assert_equal(0, hasmapto('/^\k\+ ('))
584  map ,f /^\k\+ (<CR>
585  call assert_equal(1, hasmapto('/^\k\+ ('))
586  unmap ,f
587
588  " Insert mode mapping
589  call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
590  imap ,f /^\k\+ (<CR>
591  call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
592  iunmap ,f
593
594  " Normal mode mapping
595  call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
596  nmap ,f /^\k\+ (<CR>
597  call assert_equal(1, hasmapto('/^\k\+ ('))
598  call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
599  nunmap ,f
600
601  " Visual and Select mode mapping
602  call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
603  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
604  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
605  vmap ,f /^\k\+ (<CR>
606  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
607  call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
608  call assert_equal(1, hasmapto('/^\k\+ (', 's'))
609  vunmap ,f
610
611  " Visual mode mapping
612  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
613  xmap ,f /^\k\+ (<CR>
614  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
615  call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
616  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
617  xunmap ,f
618
619  " Select mode mapping
620  call assert_equal(0, hasmapto('/^\k\+ (', 's'))
621  smap ,f /^\k\+ (<CR>
622  call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
623  call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
624  call assert_equal(1, hasmapto('/^\k\+ (', 's'))
625  sunmap ,f
626
627  " Operator-pending mode mapping
628  call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
629  omap ,f /^\k\+ (<CR>
630  call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
631  ounmap ,f
632
633  " Language mapping
634  call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
635  lmap ,f /^\k\+ (<CR>
636  call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
637  lunmap ,f
638
639  " Cmdline mode mapping
640  call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
641  cmap ,f /^\k\+ (<CR>
642  call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
643  cunmap ,f
644
645  call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
646endfunc
647
648" Test for command-line completion of maps
649func Test_mapcomplete()
650  call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
651	      \ '<silent>', '<special>', '<unique>'],
652	      \ getcompletion('', 'mapping'))
653  call assert_equal([], getcompletion(',d', 'mapping'))
654
655  call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
656  call assert_equal('"unmap <buffer>', @:)
657
658  call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
659  call assert_equal('"unabbr <buffer>', @:)
660
661  call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
662  call assert_equal("\"abbr! \x01", @:)
663
664  " Multiple matches for a map
665  nmap ,f /H<CR>
666  omap ,f /H<CR>
667  call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
668  call assert_equal('"map ,f', @:)
669  mapclear
670endfunc
671
672" Test for <expr> in abbreviation
673func Test_expr_abbr()
674  new
675  iabbr <expr> teh "the"
676  call feedkeys("iteh ", "tx")
677  call assert_equal('the ', getline(1))
678  iabclear
679  call setline(1, '')
680
681  " invalid <expr> abbreviation
682  abbr <expr> hte GetAbbr()
683  call assert_fails('normal ihte ', 'E117:')
684  call assert_equal(' ', getline(1))
685  unabbr <expr> hte
686
687  close!
688endfunc
689
690" Test for storing mappings in different modes in a vimrc file
691func Test_mkvimrc_mapmodes()
692  map a1 /a1
693  nmap a2 /a2
694  vmap a3 /a3
695  smap a4 /a4
696  xmap a5 /a5
697  omap a6 /a6
698  map! a7 /a7
699  imap a8 /a8
700  lmap a9 /a9
701  cmap a10 /a10
702  tmap a11 /a11
703  " Normal + Visual map
704  map a12 /a12
705  sunmap a12
706  ounmap a12
707  " Normal + Selectmode map
708  map a13 /a13
709  xunmap a13
710  ounmap a13
711  " Normal + OpPending map
712  map a14 /a14
713  vunmap a14
714  " Visual + Selectmode map
715  map a15 /a15
716  nunmap a15
717  ounmap a15
718  " Visual + OpPending map
719  map a16 /a16
720  nunmap a16
721  sunmap a16
722  " Selectmode + OpPending map
723  map a17 /a17
724  nunmap a17
725  xunmap a17
726  " Normal + Visual + Selectmode map
727  map a18 /a18
728  ounmap a18
729  " Normal + Visual + OpPending map
730  map a19 /a19
731  sunmap a19
732  " Normal + Selectmode + OpPending map
733  map a20 /a20
734  xunmap a20
735  " Visual + Selectmode + OpPending map
736  map a21 /a21
737  nunmap a21
738  " Mapping to Nop
739  map a22 <Nop>
740  " Script local mapping
741  map <script> a23 /a23
742
743  " Newline in {lhs} and {rhs} of a map
744  exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
745
746  " Abbreviation
747  abbr a25 A25
748  cabbr a26 A26
749  iabbr a27 A27
750
751  mkvimrc! Xvimrc
752  let l = readfile('Xvimrc')
753  call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
754  call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
755  call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
756  call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
757  call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
758  call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
759  call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
760  call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
761  call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
762  call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
763  call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
764  call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
765        \ filter(copy(l), 'v:val =~ " a12 "'))
766  call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
767        \ filter(copy(l), 'v:val =~ " a13 "'))
768  call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
769        \ filter(copy(l), 'v:val =~ " a14 "'))
770  call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
771  call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
772        \ filter(copy(l), 'v:val =~ " a16 "'))
773  call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
774        \ filter(copy(l), 'v:val =~ " a17 "'))
775  call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
776        \ filter(copy(l), 'v:val =~ " a18 "'))
777  call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
778        \ filter(copy(l), 'v:val =~ " a19 "'))
779  call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
780        \ filter(copy(l), 'v:val =~ " a20 "'))
781  call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
782        \ filter(copy(l), 'v:val =~ " a21 "'))
783  call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
784  call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
785  call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
786        \ filter(copy(l), 'v:val =~ " a24"'))
787
788  call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
789  call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
790  call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
791  call delete('Xvimrc')
792
793  mapclear
794  nmapclear
795  vmapclear
796  xmapclear
797  smapclear
798  omapclear
799  imapclear
800  lmapclear
801  cmapclear
802  tmapclear
803endfunc
804
805" Test for recursive mapping ('maxmapdepth')
806func Test_map_recursive()
807  map x y
808  map y x
809  call assert_fails('normal x', 'E223:')
810  unmap x
811  unmap y
812endfunc
813
814" Test for removing an abbreviation using {rhs} and with space after {lhs}
815func Test_abbr_remove()
816  abbr foo bar
817  let d = maparg('foo', 'i', 1, 1)
818  call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
819  unabbr bar
820  call assert_equal({}, maparg('foo', 'i', 1, 1))
821
822  abbr foo bar
823  unabbr foo<space><tab>
824  call assert_equal({}, maparg('foo', 'i', 1, 1))
825endfunc
826
827" Trigger an abbreviation using a special key
828func Test_abbr_trigger_special()
829  new
830  iabbr teh the
831  call feedkeys("iteh\<F2>\<Esc>", 'xt')
832  call assert_equal('the<F2>', getline(1))
833  iunab teh
834  close!
835endfunc
836
837" Test for '<' in 'cpoptions'
838func Test_map_cpo_special_keycode()
839  set cpo-=<
840  imap x<Bslash>k Test
841  let d = maparg('x<Bslash>k', 'i', 0, 1)
842  call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
843  call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
844  call assert_equal('"imap x\k', @:)
845  iunmap x<Bslash>k
846  set cpo+=<
847  imap x<Bslash>k Test
848  let d = maparg('x<Bslash>k', 'i', 0, 1)
849  call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
850  call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
851  call assert_equal('"imap x<Bslash>k', @:)
852  iunmap x<Bslash>k
853  set cpo-=<
854  " Modifying 'cpo' above adds some default mappings, remove them
855  mapclear
856  mapclear!
857endfunc
858
859" vim: shiftwidth=2 sts=2 expandtab
860