blob: dbd0a7e320c9bd5b893d41ef416d09b356439a7d [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!
975endfunc
976
977" text object enters visual mode
978func TextObj()
979 if mode() !=# "v"
980 normal! v
981 end
982 call cursor(1, 3)
983 normal! o
984 call cursor(2, 4)
985endfunc
986
987func s:cmdmap(lhs, rhs)
988 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
989 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
990endfunc
991
992func s:cmdunmap(lhs)
993 exe 'unmap ' .. a:lhs
994 exe 'unmap! ' .. a:lhs
995endfunc
996
997" Map various <Fx> keys used by the <Cmd> key tests
998func s:setupMaps()
999 call s:cmdmap('<F3>', 'let m = mode(1)')
1000 call s:cmdmap('<F4>', 'normal! ww')
1001 call s:cmdmap('<F5>', 'normal! "ay')
1002 call s:cmdmap('<F6>', 'throw "very error"')
1003 call s:cmdmap('<F7>', 'call TextObj()')
1004 call s:cmdmap('<F8>', 'startinsert')
1005 call s:cmdmap('<F9>', 'stopinsert')
1006endfunc
1007
1008" Remove the mappings setup by setupMaps()
1009func s:cleanupMaps()
1010 call s:cmdunmap('<F3>')
1011 call s:cmdunmap('<F4>')
1012 call s:cmdunmap('<F5>')
1013 call s:cmdunmap('<F6>')
1014 call s:cmdunmap('<F7>')
1015 call s:cmdunmap('<F8>')
1016 call s:cmdunmap('<F9>')
1017endfunc
1018
1019" Test for <Cmd> mapping in normal mode
1020func Test_map_cmdkey_normal_mode()
1021 new
1022 call s:setupMaps()
1023
1024 " check v:count and v:register works
1025 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1026 call feedkeys("\<F2>", 'xt')
1027 call assert_equal(['n', 0, '"'], s)
1028 call feedkeys("7\<F2>", 'xt')
1029 call assert_equal(['n', 7, '"'], s)
1030 call feedkeys("\"e\<F2>", 'xt')
1031 call assert_equal(['n', 0, 'e'], s)
1032 call feedkeys("5\"k\<F2>", 'xt')
1033 call assert_equal(['n', 5, 'k'], s)
1034 call s:cmdunmap('<F2>')
1035
1036 call setline(1, ['some short lines', 'of test text'])
1037 call feedkeys("\<F7>y", 'xt')
1038 call assert_equal("me short lines\nof t", @")
1039 call assert_equal('v', getregtype('"'))
1040 call assert_equal([0, 1, 3, 0], getpos("'<"))
1041 call assert_equal([0, 2, 4, 0], getpos("'>"))
1042
1043 " startinsert
1044 %d
1045 call feedkeys("\<F8>abc", 'xt')
1046 call assert_equal('abc', getline(1))
1047
1048 " feedkeys are not executed immediately
1049 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1050 %d
1051 call setline(1, ['some short lines', 'of test text'])
1052 call cursor(2, 3)
1053 call feedkeys(",a\<F3>", 'xt')
1054 call assert_equal('of test text', g:a)
1055 call assert_equal('n', m)
1056 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1057 nunmap ,a
1058
1059 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1060 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1061 call feedkeys(",b\<F3>", 'xt')
1062 call assert_equal('n', m)
1063 call assert_equal('of alphabetatest text', g:b)
1064 nunmap ,b
1065
1066 call s:cleanupMaps()
1067 %bw!
1068endfunc
1069
1070" Test for <Cmd> mapping with the :normal command
1071func Test_map_cmdkey_normal_cmd()
1072 new
1073 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1074 noremap ,f <Cmd>nosuchcommand<CR>
1075 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1076 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1077 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1078
1079 call setline(1, ['some short lines', 'of test text'])
1080 exe "norm ,x\r"
1081 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1082
1083 call assert_fails('norm ,f', 'E492:')
1084 call assert_fails('norm ,e', 'very error')
1085 call assert_fails('norm ,m', 'The message.')
1086 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1087
1088 %d
1089 let caught_err = 0
1090 try
1091 exe "normal ,w"
1092 catch /Vim(echoerr):Err/
1093 let caught_err = 1
1094 endtry
1095 call assert_equal(1, caught_err)
1096 call assert_equal(['', '0'], getline(1, '$'))
1097
1098 %d
1099 call assert_fails('normal ,w', 'Err')
1100 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1101 call assert_equal(1, line('.'))
1102
1103 nunmap ,x
1104 nunmap ,f
1105 nunmap ,e
1106 nunmap ,m
1107 nunmap ,w
1108 %bw!
1109endfunc
1110
1111" Test for <Cmd> mapping in visual mode
1112func Test_map_cmdkey_visual_mode()
1113 new
1114 set showmode
1115 call s:setupMaps()
1116
1117 call setline(1, ['some short lines', 'of test text'])
1118 call feedkeys("v\<F4>", 'xt!')
1119 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1120
1121 " can invoke an opeartor, ending the visual mode
1122 let @a = ''
1123 call feedkeys("\<F5>", 'xt!')
1124 call assert_equal('n', mode(1))
1125 call assert_equal('some short l', @a)
1126
1127 " error doesn't interrupt visual mode
1128 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1129 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1130 call feedkeys("\<F7>", 'xt!')
1131 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1132
1133 " startinsert gives "-- (insert) VISUAL --" mode
1134 call feedkeys("\<F8>", 'xt!')
1135 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1136 redraw!
1137 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1138 call feedkeys("\<Esc>new ", 'x')
1139 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1140
1141 call s:cleanupMaps()
1142 set showmode&
1143 %bw!
1144endfunc
1145
1146" Test for <Cmd> mapping in select mode
1147func Test_map_cmdkey_select_mode()
1148 new
1149 set showmode
1150 call s:setupMaps()
1151
1152 snoremap <F1> <cmd>throw "very error"<CR>
1153 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1154 call setline(1, ['some short lines', 'of test text'])
1155
1156 call feedkeys("gh\<F4>", "xt!")
1157 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1158 redraw!
1159 call assert_match('^-- SELECT --', Screenline(&lines))
1160
1161 " visual mapping in select mode restarts select mode after operator
1162 let @a = ''
1163 call feedkeys("\<F5>", 'xt!')
1164 call assert_equal('s', mode(1))
1165 call assert_equal('some short l', @a)
1166
1167 " select mode mapping works, and does not restart select mode
1168 let @b = ''
1169 call feedkeys("\<F2>", 'xt!')
1170 call assert_equal('n', mode(1))
1171 call assert_equal('some short l', @b)
1172
1173 " error doesn't interrupt temporary visual mode
1174 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1175 redraw!
1176 call assert_match('^-- VISUAL --', Screenline(&lines))
1177 " quirk: restoration of select mode is not performed
1178 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1179
1180 " error doesn't interrupt select mode
1181 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1182 redraw!
1183 call assert_match('^-- SELECT --', Screenline(&lines))
1184 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1185
1186 call feedkeys("\<F7>", 'xt!')
1187 redraw!
1188 call assert_match('^-- SELECT --', Screenline(&lines))
1189 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1190
1191 " startinsert gives "-- SELECT (insert) --" mode
1192 call feedkeys("\<F8>", 'xt!')
1193 redraw!
1194 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1195 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1196 call feedkeys("\<Esc>new ", 'x')
1197 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1198
1199 sunmap <F1>
1200 sunmap <F2>
1201 call s:cleanupMaps()
1202 set showmode&
1203 %bw!
1204endfunc
1205
1206" Test for <Cmd> mapping in operator-pending mode
1207func Test_map_cmdkey_op_pending_mode()
1208 new
1209 call s:setupMaps()
1210
1211 call setline(1, ['some short lines', 'of test text'])
1212 call feedkeys("d\<F4>", 'xt')
1213 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1214 call assert_equal(['some short '], getreg('"', 1, 1))
1215 " create a new undo point
1216 let &undolevels = &undolevels
1217
1218 call feedkeys(".", 'xt')
1219 call assert_equal(['test text'], getline(1, '$'))
1220 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1221 " create a new undo point
1222 let &undolevels = &undolevels
1223
1224 call feedkeys("uu", 'xt')
1225 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1226
1227 " error aborts operator-pending, operator not performed
1228 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1229 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1230
1231 call feedkeys("\"bd\<F7>", 'xt')
1232 call assert_equal(['soest text'], getline(1, '$'))
1233 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1234
1235 " startinsert aborts operator
1236 call feedkeys("d\<F8>cc", 'xt')
1237 call assert_equal(['soccest text'], getline(1, '$'))
1238
1239 call s:cleanupMaps()
1240 %bw!
1241endfunc
1242
1243" Test for <Cmd> mapping in insert mode
1244func Test_map_cmdkey_insert_mode()
1245 new
1246 call s:setupMaps()
1247
1248 call setline(1, ['some short lines', 'of test text'])
1249 " works the same as <C-O>w<C-O>w
1250 call feedkeys("iindeed \<F4>little ", 'xt')
1251 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1252 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1253 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1254
1255 " Note when entering visual mode from InsertEnter autocmd, an async event,
1256 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1257 call feedkeys("i\<F7>stuff ", 'xt')
1258 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1259 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1260
1261 call feedkeys("\<F5>", 'xt')
1262 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1263
1264 " also works as part of abbreviation
1265 abbr foo <Cmd>let g:y = 17<CR>bar
1266 exe "normal i\<space>foo "
1267 call assert_equal(17, g:y)
1268 call assert_equal('in bar deed some short little 2 lines', getline(1))
1269 unabbr foo
1270
1271 " :startinsert does nothing
1272 call setline(1, 'foo bar')
1273 call feedkeys("ggi\<F8>vim", 'xt')
1274 call assert_equal('vimfoo bar', getline(1))
1275
1276 " :stopinsert works
1277 call feedkeys("ggi\<F9>Abc", 'xt')
1278 call assert_equal('vimfoo barbc', getline(1))
1279
1280 call s:cleanupMaps()
1281 %bw!
1282endfunc
1283
1284" Test for <Cmd> mapping in insert-completion mode
1285func Test_map_cmdkey_insert_complete_mode()
1286 new
1287 call s:setupMaps()
1288
1289 call setline(1, 'some short lines')
1290 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1291 call assert_equal('ic', m)
1292 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1293
1294 call s:cleanupMaps()
1295 %bw!
1296endfunc
1297
1298" Test for <Cmd> mapping in cmdline mode
1299func Test_map_cmdkey_cmdline_mode()
1300 new
1301 call s:setupMaps()
1302
1303 call setline(1, ['some short lines', 'of test text'])
1304 let x = 0
1305 call feedkeys(":let x\<F3>= 10\r", 'xt')
1306 call assert_equal('c', m)
1307 call assert_equal(10, x)
1308
1309 " exception doesn't leave cmdline mode
1310 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1311 call assert_equal(20, x)
1312
1313 " move cursor in the buffer from cmdline mode
1314 call feedkeys(":let x\<F4>= 30\r", 'xt')
1315 call assert_equal(30, x)
1316 call assert_equal(12, col('.'))
1317
1318 " :startinsert takes effect after leaving cmdline mode
1319 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1320 call assert_equal(40, x)
1321 call assert_equal('some short new lines', getline(1))
1322
1323 call s:cleanupMaps()
1324 %bw!
1325endfunc
1326
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001327" vim: shiftwidth=2 sts=2 expandtab