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