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