blob: 7aeb23c14d3d9314ffa526b694d0ff5a52dd5182 [file] [log] [blame]
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02001" Tests for mappings and abbreviations
2
Bram Moolenaar26d98212019-01-27 22:32:55 +01003source shared.vim
Bram Moolenaar8c5a2782019-08-07 23:07:07 +02004source check.vim
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +01005source screendump.vim
Bram Moolenaar26d98212019-01-27 22:32:55 +01006
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02007func 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
Bram Moolenaar8485be42019-04-23 16:36:05 +020016func 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
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020072func 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()
Bram Moolenaar920694c2016-08-21 17:45:02 +020094 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
Bram Moolenaarda9ce2c2016-09-02 19:34:10 +0200131 " 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
Bram Moolenaar920694c2016-08-21 17:45:02 +0200139 " 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
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200144 call feedkeys("Go+\<Esc>", "xt")
145 call assert_equal('+', getline('$'))
146
Bram Moolenaar920694c2016-08-21 17:45:02 +0200147 " 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
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200166 call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
167 call assert_equal('+', getline('$'))
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200168
Bram Moolenaare90858d2017-02-01 17:24:34 +0100169 iunmap a
170 iunmap c
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200171 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('$')))
Bram Moolenaare90858d2017-02-01 17:24:34 +0100181 nunmap .
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200182 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
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100201func 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
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200224" This isn't actually testing a mapping, but similar use of CTRL-G U as above.
225func Test_break_undo()
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100226 set whichwrap=<,>,[,]
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200227 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
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200234
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
Bram Moolenaar878c2632017-04-01 15:15:52 +0200242
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200243func Test_map_meta_multibyte()
244 imap <M-á> foo
Bram Moolenaar2f710af2019-08-16 20:56:03 +0200245 call assert_match('i <M-á>\s*foo', execute('imap'))
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200246 iunmap <M-á>
247endfunc
248
Bram Moolenaar878c2632017-04-01 15:15:52 +0200249func 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
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200259
260func Test_map_timeout()
Bram Moolenaar26d98212019-01-27 22:32:55 +0100261 if !has('timers')
262 return
263 endif
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200264 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
Bram Moolenaar26d98212019-01-27 22:32:55 +0100273 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200274 " 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
Bram Moolenaar26d98212019-01-27 22:32:55 +0100288 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>
Bram Moolenaarea94c852019-08-16 21:47:27 +0200302 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100303
304 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100305 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100306 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
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200321endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200322
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
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200338
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
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100354
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
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200408
409func Test_error_in_map_expr()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200410 " Unlike CheckRunVimInTerminal this does work in a win32 console
411 CheckFeature terminal
412 if has('win32') && has('gui_running')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200413 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
Bram Moolenaar0d702022019-07-04 14:20:41 +0200426 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200427 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
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200446
447func Test_list_mappings()
Bram Moolenaar2559a472019-10-16 23:33:12 +0200448 " Remove default mappings
449 imapclear
Bram Moolenaar4f2f61a2019-10-16 22:27:49 +0200450
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200451 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"))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100464
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
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100479 " 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
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100488 nmapclear
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200489endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100490
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
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100520
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:')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100546 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
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100555endfunc
556
557" Test for <special> key mapping
558func Test_map_special()
559 new
560 let old_cpo = &cpo
561 set cpo+=<
562 imap <F12> Blue
563 call feedkeys("i\<F12>", "x")
564 call assert_equal("<F12>", getline(1))
565 call feedkeys("ddi<F12>", "x")
566 call assert_equal("Blue", getline(1))
567 iunmap <F12>
568 imap <special> <F12> Green
569 call feedkeys("ddi\<F12>", "x")
570 call assert_equal("Green", getline(1))
571 call feedkeys("ddi<F12>", "x")
572 call assert_equal("<F12>", getline(1))
573 iunmap <special> <F12>
574 let &cpo = old_cpo
575 %bwipe!
576endfunc
577
578" Test for hasmapto()
579func Test_hasmapto()
580 call assert_equal(0, hasmapto('/^\k\+ ('))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100581 map ,f /^\k\+ (<CR>
582 call assert_equal(1, hasmapto('/^\k\+ ('))
583 unmap ,f
584
585 " Insert mode mapping
586 call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
587 imap ,f /^\k\+ (<CR>
588 call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
589 iunmap ,f
590
591 " Normal mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100592 call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
593 nmap ,f /^\k\+ (<CR>
594 call assert_equal(1, hasmapto('/^\k\+ ('))
595 call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100596 nunmap ,f
597
598 " Visual and Select mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100599 call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100600 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
601 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
602 vmap ,f /^\k\+ (<CR>
603 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
604 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
605 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
606 vunmap ,f
607
608 " Visual mode mapping
609 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
610 xmap ,f /^\k\+ (<CR>
611 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
612 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
613 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
614 xunmap ,f
615
616 " Select mode mapping
617 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
618 smap ,f /^\k\+ (<CR>
619 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
620 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
621 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
622 sunmap ,f
623
624 " Operator-pending mode mapping
625 call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
626 omap ,f /^\k\+ (<CR>
627 call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
628 ounmap ,f
629
630 " Language mapping
631 call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
632 lmap ,f /^\k\+ (<CR>
633 call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
634 lunmap ,f
635
636 " Cmdline mode mapping
637 call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
638 cmap ,f /^\k\+ (<CR>
639 call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
640 cunmap ,f
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100641
642 call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
643endfunc
644
645" Test for command-line completion of maps
646func Test_mapcomplete()
647 call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
648 \ '<silent>', '<special>', '<unique>'],
649 \ getcompletion('', 'mapping'))
650 call assert_equal([], getcompletion(',d', 'mapping'))
651
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100652 call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
653 call assert_equal('"unmap <buffer>', @:)
654
655 call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
656 call assert_equal('"unabbr <buffer>', @:)
657
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100658 call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100659 call assert_equal("\"abbr! \x01", @:)
660
661 " Multiple matches for a map
662 nmap ,f /H<CR>
663 omap ,f /H<CR>
664 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
665 call assert_equal('"map ,f', @:)
666 mapclear
667endfunc
668
669" Test for <expr> in abbreviation
670func Test_expr_abbr()
671 new
672 iabbr <expr> teh "the"
673 call feedkeys("iteh ", "tx")
674 call assert_equal('the ', getline(1))
675 iabclear
676 call setline(1, '')
677
678 " invalid <expr> abbreviation
679 abbr <expr> hte GetAbbr()
680 call assert_fails('normal ihte ', 'E117:')
681 call assert_equal(' ', getline(1))
682 unabbr <expr> hte
683
684 close!
685endfunc
686
687" Test for storing mappings in different modes in a vimrc file
688func Test_mkvimrc_mapmodes()
689 map a1 /a1
690 nmap a2 /a2
691 vmap a3 /a3
692 smap a4 /a4
693 xmap a5 /a5
694 omap a6 /a6
695 map! a7 /a7
696 imap a8 /a8
697 lmap a9 /a9
698 cmap a10 /a10
699 tmap a11 /a11
700 " Normal + Visual map
701 map a12 /a12
702 sunmap a12
703 ounmap a12
704 " Normal + Selectmode map
705 map a13 /a13
706 xunmap a13
707 ounmap a13
708 " Normal + OpPending map
709 map a14 /a14
710 vunmap a14
711 " Visual + Selectmode map
712 map a15 /a15
713 nunmap a15
714 ounmap a15
715 " Visual + OpPending map
716 map a16 /a16
717 nunmap a16
718 sunmap a16
719 " Selectmode + OpPending map
720 map a17 /a17
721 nunmap a17
722 xunmap a17
723 " Normal + Visual + Selectmode map
724 map a18 /a18
725 ounmap a18
726 " Normal + Visual + OpPending map
727 map a19 /a19
728 sunmap a19
729 " Normal + Selectmode + OpPending map
730 map a20 /a20
731 xunmap a20
732 " Visual + Selectmode + OpPending map
733 map a21 /a21
734 nunmap a21
735 " Mapping to Nop
736 map a22 <Nop>
737 " Script local mapping
738 map <script> a23 /a23
739
740 " Newline in {lhs} and {rhs} of a map
741 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
742
743 " Abbreviation
744 abbr a25 A25
745 cabbr a26 A26
746 iabbr a27 A27
747
748 mkvimrc! Xvimrc
749 let l = readfile('Xvimrc')
750 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
751 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
752 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
753 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
754 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
755 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
756 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
757 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
758 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
759 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
760 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
761 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
762 \ filter(copy(l), 'v:val =~ " a12 "'))
763 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
764 \ filter(copy(l), 'v:val =~ " a13 "'))
765 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
766 \ filter(copy(l), 'v:val =~ " a14 "'))
767 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
768 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
769 \ filter(copy(l), 'v:val =~ " a16 "'))
770 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
771 \ filter(copy(l), 'v:val =~ " a17 "'))
772 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
773 \ filter(copy(l), 'v:val =~ " a18 "'))
774 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
775 \ filter(copy(l), 'v:val =~ " a19 "'))
776 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
777 \ filter(copy(l), 'v:val =~ " a20 "'))
778 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
779 \ filter(copy(l), 'v:val =~ " a21 "'))
780 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
781 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
782 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
783 \ filter(copy(l), 'v:val =~ " a24"'))
784
785 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
786 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
787 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
788 call delete('Xvimrc')
789
790 mapclear
791 nmapclear
792 vmapclear
793 xmapclear
794 smapclear
795 omapclear
796 imapclear
797 lmapclear
798 cmapclear
799 tmapclear
800endfunc
801
802" Test for recursive mapping ('maxmapdepth')
803func Test_map_recursive()
804 map x y
805 map y x
806 call assert_fails('normal x', 'E223:')
807 unmap x
808 unmap y
809endfunc
810
811" Test for removing an abbreviation using {rhs} and with space after {lhs}
812func Test_abbr_remove()
813 abbr foo bar
814 let d = maparg('foo', 'i', 1, 1)
815 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
816 unabbr bar
817 call assert_equal({}, maparg('foo', 'i', 1, 1))
818
819 abbr foo bar
820 unabbr foo<space><tab>
821 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100822endfunc
823
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100824" Trigger an abbreviation using a special key
825func Test_abbr_trigger_special()
826 new
827 iabbr teh the
828 call feedkeys("iteh\<F2>\<Esc>", 'xt')
829 call assert_equal('the<F2>', getline(1))
830 iunab teh
831 close!
832endfunc
833
834" Test for '<' in 'cpoptions'
835func Test_map_cpo_special_keycode()
836 set cpo-=<
837 imap x<Bslash>k Test
838 let d = maparg('x<Bslash>k', 'i', 0, 1)
839 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
840 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
841 call assert_equal('"imap x\k', @:)
842 iunmap x<Bslash>k
843 set cpo+=<
844 imap x<Bslash>k Test
845 let d = maparg('x<Bslash>k', 'i', 0, 1)
846 call assert_equal(['x<Bslash>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<Bslash>k', @:)
849 iunmap x<Bslash>k
850 set cpo-=<
851 " Modifying 'cpo' above adds some default mappings, remove them
852 mapclear
853 mapclear!
854endfunc
855
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100856" vim: shiftwidth=2 sts=2 expandtab