blob: 1750f39d5342c2bf6f0da9fcad2185b841bd44dd [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 Moolenaar957cf672020-11-12 14:21:06 +01006source term_util.vim
Bram Moolenaar26d98212019-01-27 22:32:55 +01007
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02008func 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
Bram Moolenaar8485be42019-04-23 16:36:05 +020017func 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'))
Bram Moolenaarf0cee192020-02-16 13:33:56 +010042 call assert_fails('%abclear', 'E481:')
Bram Moolenaar8485be42019-04-23 16:36:05 +020043endfunc
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
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020074func 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>
Bram Moolenaarfccd93f2020-05-31 22:06:51 +020080 call feedkeys("GoTEST2: CTRL-C |\<*C-C>A|\<Esc>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020081 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'
Bram Moolenaarfccd93f2020-05-31 22:06:51 +020089 call feedkeys("GV\<*C-C>\<CR>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020090 call assert_equal('vmap works', getline('$'))
91 vunmap <c-c>
92 set nomodified
93endfunc
94
95func Test_map_langmap()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +020096 CheckFeature langmap
Bram Moolenaar920694c2016-08-21 17:45:02 +020097
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
Bram Moolenaarfccd93f2020-05-31 22:06:51 +0200237 call feedkeys("Go-\<*M-\">-\<Esc>", "xt")
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200238 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 Moolenaar6d91bcb2020-08-12 18:50:36 +0200261 CheckFeature timers
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200262 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
Bram Moolenaar26d98212019-01-27 22:32:55 +0100271 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200272 " 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
Bram Moolenaar26d98212019-01-27 22:32:55 +0100286 call timer_stop(timer)
287endfunc
288
289func Test_map_timeout_with_timer_interrupt()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200290 CheckFeature job
291 CheckFeature timers
Bram Moolenaar26d98212019-01-27 22:32:55 +0100292
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>
Bram Moolenaarea94c852019-08-16 21:47:27 +0200299 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100300
301 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100302 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100303 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
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200318endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200319
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
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200335
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
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100351
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
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200405
406func Test_error_in_map_expr()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200407 " Unlike CheckRunVimInTerminal this does work in a win32 console
408 CheckFeature terminal
409 if has('win32') && has('gui_running')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200410 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
Bram Moolenaar0d702022019-07-04 14:20:41 +0200423 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200424 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, '!')
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200429 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200430 call term_sendkeys(buf, "\<CR>")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200431 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200432 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
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200443
444func Test_list_mappings()
Bram Moolenaar2559a472019-10-16 23:33:12 +0200445 " Remove default mappings
446 imapclear
Bram Moolenaar4f2f61a2019-10-16 22:27:49 +0200447
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200448 inoremap <C-M> CtrlM
449 inoremap <A-S> AltS
450 inoremap <S-/> ShiftSlash
451 call assert_equal([
452 \ 'i <S-/> * ShiftSlash',
453 \ 'i <M-S> * AltS',
454 \ 'i <C-M> * CtrlM',
455 \], execute('imap')->trim()->split("\n"))
456 iunmap <C-M>
457 iunmap <A-S>
458 call assert_equal(['i <S-/> * ShiftSlash'], execute('imap')->trim()->split("\n"))
459 iunmap <S-/>
460 call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100461
462 " List global, buffer local and script local mappings
463 nmap ,f /^\k\+ (<CR>
464 nmap <buffer> ,f /^\k\+ (<CR>
465 nmap <script> ,fs /^\k\+ (<CR>
466 call assert_equal(['n ,f @/^\k\+ (<CR>',
467 \ 'n ,fs & /^\k\+ (<CR>',
468 \ 'n ,f /^\k\+ (<CR>'],
469 \ execute('nmap ,f')->trim()->split("\n"))
470
471 " List <Nop> mapping
472 nmap ,n <Nop>
473 call assert_equal(['n ,n <Nop>'],
474 \ execute('nmap ,n')->trim()->split("\n"))
475
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100476 " verbose map
477 call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
478 \ execute('verbose map ,n')->trim()->split("\n")[1])
479
480 " map to CTRL-V
481 exe "nmap ,k \<C-V>"
482 call assert_equal(['n ,k <Nop>'],
483 \ execute('nmap ,k')->trim()->split("\n"))
484
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100485 nmapclear
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200486endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100487
488func Test_expr_map_restore_cursor()
489 CheckScreendump
490
491 let lines =<< trim END
492 call setline(1, ['one', 'two', 'three'])
493 2
494 set ls=2
495 hi! link StatusLine ErrorMsg
496 noremap <expr> <C-B> Func()
497 func Func()
498 let g:on = !get(g:, 'on', 0)
499 redraws
500 return ''
501 endfunc
502 func Status()
503 return get(g:, 'on', 0) ? '[on]' : ''
504 endfunc
505 set stl=%{Status()}
506 END
507 call writefile(lines, 'XtestExprMap')
508 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200509 call TermWait(buf)
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100510 call term_sendkeys(buf, "\<C-B>")
511 call VerifyScreenDump(buf, 'Test_map_expr_1', {})
512
513 " clean up
514 call StopVimInTerminal(buf)
515 call delete('XtestExprMap')
516endfunc
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100517
518" Test for mapping errors
519func Test_map_error()
520 call assert_fails('unmap', 'E474:')
521 call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
522 call assert_fails('unmap abc', 'E31:')
523 call assert_fails('unabbr abc', 'E24:')
524 call assert_equal('', maparg(''))
525 call assert_fails('echo maparg("abc", [])', 'E730:')
526
527 " unique map
528 map ,w /[#&!]<CR>
529 call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
530 " unique buffer-local map
531 call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
532 unmap ,w
533
534 " unique abbreviation
535 abbr SP special
536 call assert_fails("abbr <unique> SP special", 'E226:')
537 " unique buffer-local map
538 call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
539 unabbr SP
540
541 call assert_fails('mapclear abc', 'E474:')
542 call assert_fails('abclear abc', 'E474:')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100543 call assert_fails('abbr $xyz abc', 'E474:')
544
545 " space character in an abbreviation
546 call assert_fails('abbr ab<space> ABC', 'E474:')
547
548 " invalid <expr> map
549 map <expr> ,f abc
550 call assert_fails('normal ,f', 'E121:')
551 unmap <expr> ,f
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100552
553 " Recursive use of :normal in a map
554 set maxmapdepth=100
555 map gq :normal gq<CR>
556 call assert_fails('normal gq', 'E192:')
557 unmap gq
558 set maxmapdepth&
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100559endfunc
560
561" Test for <special> key mapping
562func Test_map_special()
563 new
564 let old_cpo = &cpo
565 set cpo+=<
566 imap <F12> Blue
567 call feedkeys("i\<F12>", "x")
568 call assert_equal("<F12>", getline(1))
569 call feedkeys("ddi<F12>", "x")
570 call assert_equal("Blue", getline(1))
571 iunmap <F12>
572 imap <special> <F12> Green
573 call feedkeys("ddi\<F12>", "x")
574 call assert_equal("Green", getline(1))
575 call feedkeys("ddi<F12>", "x")
576 call assert_equal("<F12>", getline(1))
577 iunmap <special> <F12>
578 let &cpo = old_cpo
579 %bwipe!
580endfunc
581
582" Test for hasmapto()
583func Test_hasmapto()
584 call assert_equal(0, hasmapto('/^\k\+ ('))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100585 map ,f /^\k\+ (<CR>
586 call assert_equal(1, hasmapto('/^\k\+ ('))
587 unmap ,f
588
589 " Insert mode mapping
590 call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
591 imap ,f /^\k\+ (<CR>
592 call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
593 iunmap ,f
594
595 " Normal mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100596 call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
597 nmap ,f /^\k\+ (<CR>
598 call assert_equal(1, hasmapto('/^\k\+ ('))
599 call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100600 nunmap ,f
601
602 " Visual and Select mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100603 call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100604 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
605 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
606 vmap ,f /^\k\+ (<CR>
607 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
608 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
609 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
610 vunmap ,f
611
612 " Visual mode mapping
613 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
614 xmap ,f /^\k\+ (<CR>
615 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
616 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
617 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
618 xunmap ,f
619
620 " Select mode mapping
621 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
622 smap ,f /^\k\+ (<CR>
623 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
624 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
625 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
626 sunmap ,f
627
628 " Operator-pending mode mapping
629 call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
630 omap ,f /^\k\+ (<CR>
631 call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
632 ounmap ,f
633
634 " Language mapping
635 call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
636 lmap ,f /^\k\+ (<CR>
637 call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
638 lunmap ,f
639
640 " Cmdline mode mapping
641 call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
642 cmap ,f /^\k\+ (<CR>
643 call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
644 cunmap ,f
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100645
646 call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
647endfunc
648
649" Test for command-line completion of maps
650func Test_mapcomplete()
651 call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
652 \ '<silent>', '<special>', '<unique>'],
653 \ getcompletion('', 'mapping'))
654 call assert_equal([], getcompletion(',d', 'mapping'))
655
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100656 call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
657 call assert_equal('"unmap <buffer>', @:)
658
659 call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
660 call assert_equal('"unabbr <buffer>', @:)
661
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100662 call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100663 call assert_equal("\"abbr! \x01", @:)
664
665 " Multiple matches for a map
666 nmap ,f /H<CR>
667 omap ,f /H<CR>
668 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
669 call assert_equal('"map ,f', @:)
670 mapclear
671endfunc
672
673" Test for <expr> in abbreviation
674func Test_expr_abbr()
675 new
676 iabbr <expr> teh "the"
677 call feedkeys("iteh ", "tx")
678 call assert_equal('the ', getline(1))
679 iabclear
680 call setline(1, '')
681
682 " invalid <expr> abbreviation
683 abbr <expr> hte GetAbbr()
684 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100685 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100686 unabbr <expr> hte
687
688 close!
689endfunc
690
691" Test for storing mappings in different modes in a vimrc file
692func Test_mkvimrc_mapmodes()
693 map a1 /a1
694 nmap a2 /a2
695 vmap a3 /a3
696 smap a4 /a4
697 xmap a5 /a5
698 omap a6 /a6
699 map! a7 /a7
700 imap a8 /a8
701 lmap a9 /a9
702 cmap a10 /a10
703 tmap a11 /a11
704 " Normal + Visual map
705 map a12 /a12
706 sunmap a12
707 ounmap a12
708 " Normal + Selectmode map
709 map a13 /a13
710 xunmap a13
711 ounmap a13
712 " Normal + OpPending map
713 map a14 /a14
714 vunmap a14
715 " Visual + Selectmode map
716 map a15 /a15
717 nunmap a15
718 ounmap a15
719 " Visual + OpPending map
720 map a16 /a16
721 nunmap a16
722 sunmap a16
723 " Selectmode + OpPending map
724 map a17 /a17
725 nunmap a17
726 xunmap a17
727 " Normal + Visual + Selectmode map
728 map a18 /a18
729 ounmap a18
730 " Normal + Visual + OpPending map
731 map a19 /a19
732 sunmap a19
733 " Normal + Selectmode + OpPending map
734 map a20 /a20
735 xunmap a20
736 " Visual + Selectmode + OpPending map
737 map a21 /a21
738 nunmap a21
739 " Mapping to Nop
740 map a22 <Nop>
741 " Script local mapping
742 map <script> a23 /a23
743
744 " Newline in {lhs} and {rhs} of a map
745 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
746
747 " Abbreviation
748 abbr a25 A25
749 cabbr a26 A26
750 iabbr a27 A27
751
752 mkvimrc! Xvimrc
753 let l = readfile('Xvimrc')
754 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
755 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
756 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
757 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
758 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
759 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
760 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
761 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
762 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
763 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
764 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
765 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
766 \ filter(copy(l), 'v:val =~ " a12 "'))
767 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
768 \ filter(copy(l), 'v:val =~ " a13 "'))
769 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
770 \ filter(copy(l), 'v:val =~ " a14 "'))
771 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
772 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
773 \ filter(copy(l), 'v:val =~ " a16 "'))
774 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
775 \ filter(copy(l), 'v:val =~ " a17 "'))
776 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
777 \ filter(copy(l), 'v:val =~ " a18 "'))
778 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
779 \ filter(copy(l), 'v:val =~ " a19 "'))
780 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
781 \ filter(copy(l), 'v:val =~ " a20 "'))
782 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
783 \ filter(copy(l), 'v:val =~ " a21 "'))
784 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
785 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
786 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
787 \ filter(copy(l), 'v:val =~ " a24"'))
788
789 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
790 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
791 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
792 call delete('Xvimrc')
793
794 mapclear
795 nmapclear
796 vmapclear
797 xmapclear
798 smapclear
799 omapclear
800 imapclear
801 lmapclear
802 cmapclear
803 tmapclear
804endfunc
805
806" Test for recursive mapping ('maxmapdepth')
807func Test_map_recursive()
808 map x y
809 map y x
810 call assert_fails('normal x', 'E223:')
811 unmap x
812 unmap y
813endfunc
814
815" Test for removing an abbreviation using {rhs} and with space after {lhs}
816func Test_abbr_remove()
817 abbr foo bar
818 let d = maparg('foo', 'i', 1, 1)
819 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
820 unabbr bar
821 call assert_equal({}, maparg('foo', 'i', 1, 1))
822
823 abbr foo bar
824 unabbr foo<space><tab>
825 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100826endfunc
827
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100828" Trigger an abbreviation using a special key
829func Test_abbr_trigger_special()
830 new
831 iabbr teh the
832 call feedkeys("iteh\<F2>\<Esc>", 'xt')
833 call assert_equal('the<F2>', getline(1))
834 iunab teh
835 close!
836endfunc
837
838" Test for '<' in 'cpoptions'
839func Test_map_cpo_special_keycode()
840 set cpo-=<
841 imap x<Bslash>k Test
842 let d = maparg('x<Bslash>k', 'i', 0, 1)
843 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
844 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
845 call assert_equal('"imap x\k', @:)
846 iunmap x<Bslash>k
847 set cpo+=<
848 imap x<Bslash>k Test
849 let d = maparg('x<Bslash>k', 'i', 0, 1)
850 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
851 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
852 call assert_equal('"imap x<Bslash>k', @:)
853 iunmap x<Bslash>k
854 set cpo-=<
855 " Modifying 'cpo' above adds some default mappings, remove them
856 mapclear
857 mapclear!
858endfunc
859
Bram Moolenaar957cf672020-11-12 14:21:06 +0100860" Test for <Cmd> key in maps to execute commands
861func Test_map_cmdkey()
862 new
863
864 " Error cases
865 let x = 0
866 noremap <F3> <Cmd><Cmd>let x = 1<CR>
867 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
868 call assert_equal(0, x)
869
870 noremap <F3> <Cmd><F3>let x = 2<CR>
871 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1137:')
872 call assert_equal(0, x)
873
874 noremap <F3> <Cmd>let x = 3
875 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1135:')
876 call assert_equal(0, x)
877
878 " works in various modes and sees the correct mode()
879 noremap <F3> <Cmd>let m = mode(1)<CR>
880 noremap! <F3> <Cmd>let m = mode(1)<CR>
881
882 " normal mode
883 call feedkeys("\<F3>", 'xt')
884 call assert_equal('n', m)
885
886 " visual mode
887 call feedkeys("v\<F3>", 'xt!')
888 call assert_equal('v', m)
889 " shouldn't leave the visual mode
890 call assert_equal('v', mode(1))
891 call feedkeys("\<Esc>", 'xt')
892 call assert_equal('n', mode(1))
893
894 " visual mapping in select mode
895 call feedkeys("gh\<F3>", 'xt!')
896 call assert_equal('v', m)
897 " shouldn't leave select mode
898 call assert_equal('s', mode(1))
899 call feedkeys("\<Esc>", 'xt')
900 call assert_equal('n', mode(1))
901
902 " select mode mapping
903 snoremap <F3> <Cmd>let m = mode(1)<cr>
904 call feedkeys("gh\<F3>", 'xt!')
905 call assert_equal('s', m)
906 " shouldn't leave select mode
907 call assert_equal('s', mode(1))
908 call feedkeys("\<Esc>", 'xt')
909 call assert_equal('n', mode(1))
910
911 " operator-pending mode
912 call feedkeys("d\<F3>", 'xt!')
913 call assert_equal('no', m)
914 " leaves the operator-pending mode
915 call assert_equal('n', mode(1))
916
917 " insert mode
918 call feedkeys("i\<F3>abc", 'xt')
919 call assert_equal('i', m)
920 call assert_equal('abc', getline('.'))
921
922 " replace mode
923 call feedkeys("0R\<F3>two", 'xt')
924 call assert_equal('R', m)
925 call assert_equal('two', getline('.'))
926
927 " virtual replace mode
928 call setline('.', "one\ttwo")
929 call feedkeys("4|gR\<F3>xxx", 'xt')
930 call assert_equal('Rv', m)
931 call assert_equal("onexxx\ttwo", getline('.'))
932
933 " cmdline mode
934 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
935 call assert_equal('c', m)
936 call assert_equal('"xxx', @:)
937
938 " terminal mode
939 if CanRunVimInTerminal()
940 tnoremap <F3> <Cmd>let m = mode(1)<CR>
941 let buf = Run_shell_in_terminal({})
942 call feedkeys("\<F3>", 'xt')
943 call assert_equal('t', m)
944 call assert_equal('t', mode(1))
945 call StopShellInTerminal(buf)
946 call TermWait(buf)
947 close!
948 tunmap <F3>
949 endif
950
951 " invoke cmdline mode recursively
952 noremap! <F2> <Cmd>norm! :foo<CR>
953 %d
954 call setline(1, ['some short lines', 'of test text'])
955 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
956 call assert_equal('"barx', @:)
957 unmap! <F2>
958
959 " test for calling a <SID> function
960 let lines =<< trim END
961 map <F2> <Cmd>call <SID>do_it()<CR>
962 func s:do_it()
963 let g:x = 32
964 endfunc
965 END
966 call writefile(lines, 'Xscript')
967 source Xscript
968 call feedkeys("\<F2>", 'xt')
969 call assert_equal(32, g:x)
970 call delete('Xscript')
971
972 unmap <F3>
973 unmap! <F3>
974 %bw!
Bram Moolenaar4a441202020-11-28 14:43:26 +0100975
976 " command line ending in "0" is handled without errors
977 onoremap ix <cmd>eval 0<cr>
978 call feedkeys('dix.', 'xt')
979 ounmap ix
Bram Moolenaar957cf672020-11-12 14:21:06 +0100980endfunc
981
982" text object enters visual mode
983func TextObj()
984 if mode() !=# "v"
985 normal! v
986 end
987 call cursor(1, 3)
988 normal! o
989 call cursor(2, 4)
990endfunc
991
992func s:cmdmap(lhs, rhs)
993 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
994 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
995endfunc
996
997func s:cmdunmap(lhs)
998 exe 'unmap ' .. a:lhs
999 exe 'unmap! ' .. a:lhs
1000endfunc
1001
1002" Map various <Fx> keys used by the <Cmd> key tests
1003func s:setupMaps()
1004 call s:cmdmap('<F3>', 'let m = mode(1)')
1005 call s:cmdmap('<F4>', 'normal! ww')
1006 call s:cmdmap('<F5>', 'normal! "ay')
1007 call s:cmdmap('<F6>', 'throw "very error"')
1008 call s:cmdmap('<F7>', 'call TextObj()')
1009 call s:cmdmap('<F8>', 'startinsert')
1010 call s:cmdmap('<F9>', 'stopinsert')
1011endfunc
1012
1013" Remove the mappings setup by setupMaps()
1014func s:cleanupMaps()
1015 call s:cmdunmap('<F3>')
1016 call s:cmdunmap('<F4>')
1017 call s:cmdunmap('<F5>')
1018 call s:cmdunmap('<F6>')
1019 call s:cmdunmap('<F7>')
1020 call s:cmdunmap('<F8>')
1021 call s:cmdunmap('<F9>')
1022endfunc
1023
1024" Test for <Cmd> mapping in normal mode
1025func Test_map_cmdkey_normal_mode()
1026 new
1027 call s:setupMaps()
1028
1029 " check v:count and v:register works
1030 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1031 call feedkeys("\<F2>", 'xt')
1032 call assert_equal(['n', 0, '"'], s)
1033 call feedkeys("7\<F2>", 'xt')
1034 call assert_equal(['n', 7, '"'], s)
1035 call feedkeys("\"e\<F2>", 'xt')
1036 call assert_equal(['n', 0, 'e'], s)
1037 call feedkeys("5\"k\<F2>", 'xt')
1038 call assert_equal(['n', 5, 'k'], s)
1039 call s:cmdunmap('<F2>')
1040
1041 call setline(1, ['some short lines', 'of test text'])
1042 call feedkeys("\<F7>y", 'xt')
1043 call assert_equal("me short lines\nof t", @")
1044 call assert_equal('v', getregtype('"'))
1045 call assert_equal([0, 1, 3, 0], getpos("'<"))
1046 call assert_equal([0, 2, 4, 0], getpos("'>"))
1047
1048 " startinsert
1049 %d
1050 call feedkeys("\<F8>abc", 'xt')
1051 call assert_equal('abc', getline(1))
1052
1053 " feedkeys are not executed immediately
1054 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1055 %d
1056 call setline(1, ['some short lines', 'of test text'])
1057 call cursor(2, 3)
1058 call feedkeys(",a\<F3>", 'xt')
1059 call assert_equal('of test text', g:a)
1060 call assert_equal('n', m)
1061 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1062 nunmap ,a
1063
1064 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1065 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1066 call feedkeys(",b\<F3>", 'xt')
1067 call assert_equal('n', m)
1068 call assert_equal('of alphabetatest text', g:b)
1069 nunmap ,b
1070
1071 call s:cleanupMaps()
1072 %bw!
1073endfunc
1074
1075" Test for <Cmd> mapping with the :normal command
1076func Test_map_cmdkey_normal_cmd()
1077 new
1078 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1079 noremap ,f <Cmd>nosuchcommand<CR>
1080 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1081 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1082 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1083
1084 call setline(1, ['some short lines', 'of test text'])
1085 exe "norm ,x\r"
1086 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1087
1088 call assert_fails('norm ,f', 'E492:')
1089 call assert_fails('norm ,e', 'very error')
1090 call assert_fails('norm ,m', 'The message.')
1091 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1092
1093 %d
1094 let caught_err = 0
1095 try
1096 exe "normal ,w"
1097 catch /Vim(echoerr):Err/
1098 let caught_err = 1
1099 endtry
1100 call assert_equal(1, caught_err)
1101 call assert_equal(['', '0'], getline(1, '$'))
1102
1103 %d
1104 call assert_fails('normal ,w', 'Err')
1105 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1106 call assert_equal(1, line('.'))
1107
1108 nunmap ,x
1109 nunmap ,f
1110 nunmap ,e
1111 nunmap ,m
1112 nunmap ,w
1113 %bw!
1114endfunc
1115
1116" Test for <Cmd> mapping in visual mode
1117func Test_map_cmdkey_visual_mode()
1118 new
1119 set showmode
1120 call s:setupMaps()
1121
1122 call setline(1, ['some short lines', 'of test text'])
1123 call feedkeys("v\<F4>", 'xt!')
1124 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1125
1126 " can invoke an opeartor, ending the visual mode
1127 let @a = ''
1128 call feedkeys("\<F5>", 'xt!')
1129 call assert_equal('n', mode(1))
1130 call assert_equal('some short l', @a)
1131
1132 " error doesn't interrupt visual mode
1133 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1134 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1135 call feedkeys("\<F7>", 'xt!')
1136 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1137
1138 " startinsert gives "-- (insert) VISUAL --" mode
1139 call feedkeys("\<F8>", 'xt!')
1140 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1141 redraw!
1142 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1143 call feedkeys("\<Esc>new ", 'x')
1144 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1145
1146 call s:cleanupMaps()
1147 set showmode&
1148 %bw!
1149endfunc
1150
1151" Test for <Cmd> mapping in select mode
1152func Test_map_cmdkey_select_mode()
1153 new
1154 set showmode
1155 call s:setupMaps()
1156
1157 snoremap <F1> <cmd>throw "very error"<CR>
1158 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1159 call setline(1, ['some short lines', 'of test text'])
1160
1161 call feedkeys("gh\<F4>", "xt!")
1162 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1163 redraw!
1164 call assert_match('^-- SELECT --', Screenline(&lines))
1165
1166 " visual mapping in select mode restarts select mode after operator
1167 let @a = ''
1168 call feedkeys("\<F5>", 'xt!')
1169 call assert_equal('s', mode(1))
1170 call assert_equal('some short l', @a)
1171
1172 " select mode mapping works, and does not restart select mode
1173 let @b = ''
1174 call feedkeys("\<F2>", 'xt!')
1175 call assert_equal('n', mode(1))
1176 call assert_equal('some short l', @b)
1177
1178 " error doesn't interrupt temporary visual mode
1179 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1180 redraw!
1181 call assert_match('^-- VISUAL --', Screenline(&lines))
1182 " quirk: restoration of select mode is not performed
1183 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1184
1185 " error doesn't interrupt select mode
1186 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1187 redraw!
1188 call assert_match('^-- SELECT --', Screenline(&lines))
1189 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1190
1191 call feedkeys("\<F7>", 'xt!')
1192 redraw!
1193 call assert_match('^-- SELECT --', Screenline(&lines))
1194 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1195
1196 " startinsert gives "-- SELECT (insert) --" mode
1197 call feedkeys("\<F8>", 'xt!')
1198 redraw!
1199 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1200 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1201 call feedkeys("\<Esc>new ", 'x')
1202 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1203
1204 sunmap <F1>
1205 sunmap <F2>
1206 call s:cleanupMaps()
1207 set showmode&
1208 %bw!
1209endfunc
1210
1211" Test for <Cmd> mapping in operator-pending mode
1212func Test_map_cmdkey_op_pending_mode()
1213 new
1214 call s:setupMaps()
1215
1216 call setline(1, ['some short lines', 'of test text'])
1217 call feedkeys("d\<F4>", 'xt')
1218 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1219 call assert_equal(['some short '], getreg('"', 1, 1))
1220 " create a new undo point
1221 let &undolevels = &undolevels
1222
1223 call feedkeys(".", 'xt')
1224 call assert_equal(['test text'], getline(1, '$'))
1225 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1226 " create a new undo point
1227 let &undolevels = &undolevels
1228
1229 call feedkeys("uu", 'xt')
1230 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1231
1232 " error aborts operator-pending, operator not performed
1233 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1234 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1235
1236 call feedkeys("\"bd\<F7>", 'xt')
1237 call assert_equal(['soest text'], getline(1, '$'))
1238 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1239
1240 " startinsert aborts operator
1241 call feedkeys("d\<F8>cc", 'xt')
1242 call assert_equal(['soccest text'], getline(1, '$'))
1243
1244 call s:cleanupMaps()
1245 %bw!
1246endfunc
1247
1248" Test for <Cmd> mapping in insert mode
1249func Test_map_cmdkey_insert_mode()
1250 new
1251 call s:setupMaps()
1252
1253 call setline(1, ['some short lines', 'of test text'])
1254 " works the same as <C-O>w<C-O>w
1255 call feedkeys("iindeed \<F4>little ", 'xt')
1256 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1257 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1258 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1259
1260 " Note when entering visual mode from InsertEnter autocmd, an async event,
1261 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1262 call feedkeys("i\<F7>stuff ", 'xt')
1263 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1264 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1265
1266 call feedkeys("\<F5>", 'xt')
1267 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1268
1269 " also works as part of abbreviation
1270 abbr foo <Cmd>let g:y = 17<CR>bar
1271 exe "normal i\<space>foo "
1272 call assert_equal(17, g:y)
1273 call assert_equal('in bar deed some short little 2 lines', getline(1))
1274 unabbr foo
1275
1276 " :startinsert does nothing
1277 call setline(1, 'foo bar')
1278 call feedkeys("ggi\<F8>vim", 'xt')
1279 call assert_equal('vimfoo bar', getline(1))
1280
1281 " :stopinsert works
1282 call feedkeys("ggi\<F9>Abc", 'xt')
1283 call assert_equal('vimfoo barbc', getline(1))
1284
1285 call s:cleanupMaps()
1286 %bw!
1287endfunc
1288
1289" Test for <Cmd> mapping in insert-completion mode
1290func Test_map_cmdkey_insert_complete_mode()
1291 new
1292 call s:setupMaps()
1293
1294 call setline(1, 'some short lines')
1295 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1296 call assert_equal('ic', m)
1297 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1298
1299 call s:cleanupMaps()
1300 %bw!
1301endfunc
1302
1303" Test for <Cmd> mapping in cmdline mode
1304func Test_map_cmdkey_cmdline_mode()
1305 new
1306 call s:setupMaps()
1307
1308 call setline(1, ['some short lines', 'of test text'])
1309 let x = 0
1310 call feedkeys(":let x\<F3>= 10\r", 'xt')
1311 call assert_equal('c', m)
1312 call assert_equal(10, x)
1313
1314 " exception doesn't leave cmdline mode
1315 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1316 call assert_equal(20, x)
1317
1318 " move cursor in the buffer from cmdline mode
1319 call feedkeys(":let x\<F4>= 30\r", 'xt')
1320 call assert_equal(30, x)
1321 call assert_equal(12, col('.'))
1322
1323 " :startinsert takes effect after leaving cmdline mode
1324 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1325 call assert_equal(40, x)
1326 call assert_equal('some short new lines', getline(1))
1327
1328 call s:cleanupMaps()
1329 %bw!
1330endfunc
1331
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001332func Test_map_cmdkey_redo()
1333 func SelectDash()
1334 call search('^---\n\zs', 'bcW')
1335 norm! V
1336 call search('\n\ze---$', 'W')
1337 endfunc
1338
1339 let text =<< trim END
1340 ---
1341 aaa
1342 ---
1343 bbb
1344 bbb
1345 ---
1346 ccc
1347 ccc
1348 ccc
1349 ---
1350 END
1351 new Xcmdtext
1352 call setline(1, text)
1353
1354 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1355 call feedkeys('2Gdi-', 'xt')
1356 call assert_equal(['---', '---'], getline(1, 2))
1357 call feedkeys('j.', 'xt')
1358 call assert_equal(['---', '---', '---'], getline(1, 3))
1359 call feedkeys('j.', 'xt')
1360 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1361
1362 bwipe!
1363 call delete('Xcmdtext')
1364 delfunc SelectDash
1365 ounmap i-
1366endfunc
1367
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001368" vim: shiftwidth=2 sts=2 expandtab