blob: b170b580dc981dcf470dd52011c36393f7d2ca05 [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 Moolenaara9725222022-01-16 13:30:33 +00007source vim9.vim
Bram Moolenaar26d98212019-01-27 22:32:55 +01008
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02009func Test_abbreviation()
10 " abbreviation with 0x80 should work
11 inoreab чкпр vim
12 call feedkeys("Goчкпр \<Esc>", "xt")
13 call assert_equal('vim ', getline('$'))
14 iunab чкпр
15 set nomodified
16endfunc
17
Bram Moolenaar8485be42019-04-23 16:36:05 +020018func Test_abclear()
19 abbrev foo foobar
20 iabbrev fooi foobari
21 cabbrev fooc foobarc
22 call assert_equal("\n\n"
23 \ .. "c fooc foobarc\n"
24 \ .. "i fooi foobari\n"
25 \ .. "! foo foobar", execute('abbrev'))
26
27 iabclear
28 call assert_equal("\n\n"
29 \ .. "c fooc foobarc\n"
30 \ .. "c foo foobar", execute('abbrev'))
31 abbrev foo foobar
32 iabbrev fooi foobari
33
34 cabclear
35 call assert_equal("\n\n"
36 \ .. "i fooi foobari\n"
37 \ .. "i foo foobar", execute('abbrev'))
38 abbrev foo foobar
39 cabbrev fooc foobarc
40
41 abclear
42 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
Bram Moolenaarf0cee192020-02-16 13:33:56 +010043 call assert_fails('%abclear', 'E481:')
Bram Moolenaar8485be42019-04-23 16:36:05 +020044endfunc
45
46func Test_abclear_buffer()
47 abbrev foo foobar
48 new X1
49 abbrev <buffer> foo1 foobar1
50 new X2
51 abbrev <buffer> foo2 foobar2
52
53 call assert_equal("\n\n"
54 \ .. "! foo2 @foobar2\n"
55 \ .. "! foo foobar", execute('abbrev'))
56
57 abclear <buffer>
58 call assert_equal("\n\n"
59 \ .. "! foo foobar", execute('abbrev'))
60
61 b X1
62 call assert_equal("\n\n"
63 \ .. "! foo1 @foobar1\n"
64 \ .. "! foo foobar", execute('abbrev'))
65 abclear <buffer>
66 call assert_equal("\n\n"
67 \ .. "! foo foobar", execute('abbrev'))
68
69 abclear
70 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
71
72 %bwipe
73endfunc
74
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020075func Test_map_ctrl_c_insert()
76 " mapping of ctrl-c in Insert mode
77 set cpo-=< cpo-=k
78 inoremap <c-c> <ctrl-c>
79 cnoremap <c-c> dummy
80 cunmap <c-c>
Bram Moolenaarfccd93f2020-05-31 22:06:51 +020081 call feedkeys("GoTEST2: CTRL-C |\<*C-C>A|\<Esc>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020082 call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
83 unmap! <c-c>
84 set nomodified
85endfunc
86
87func Test_map_ctrl_c_visual()
88 " mapping of ctrl-c in Visual mode
89 vnoremap <c-c> :<C-u>$put ='vmap works'
Bram Moolenaarfccd93f2020-05-31 22:06:51 +020090 call feedkeys("GV\<*C-C>\<CR>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020091 call assert_equal('vmap works', getline('$'))
92 vunmap <c-c>
93 set nomodified
94endfunc
95
96func Test_map_langmap()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +020097 CheckFeature langmap
Bram Moolenaar920694c2016-08-21 17:45:02 +020098
99 " check langmap applies in normal mode
100 set langmap=+- nolangremap
101 new
102 call setline(1, ['a', 'b', 'c'])
103 2
104 call assert_equal('b', getline('.'))
105 call feedkeys("+", "xt")
106 call assert_equal('a', getline('.'))
107
108 " check no remapping
109 map x +
110 2
111 call feedkeys("x", "xt")
112 call assert_equal('c', getline('.'))
113
114 " check with remapping
115 set langremap
116 2
117 call feedkeys("x", "xt")
118 call assert_equal('a', getline('.'))
119
120 unmap x
121 bwipe!
122
123 " 'langnoremap' follows 'langremap' and vise versa
124 set langremap
125 set langnoremap
126 call assert_equal(0, &langremap)
127 set langremap
128 call assert_equal(0, &langnoremap)
129 set nolangremap
130 call assert_equal(1, &langnoremap)
131
Bram Moolenaarda9ce2c2016-09-02 19:34:10 +0200132 " check default values
133 set langnoremap&
134 call assert_equal(0, &langnoremap)
135 call assert_equal(1, &langremap)
136 set langremap&
137 call assert_equal(0, &langnoremap)
138 call assert_equal(1, &langremap)
139
Bram Moolenaar920694c2016-08-21 17:45:02 +0200140 " langmap should not apply in insert mode, 'langremap' doesn't matter
141 set langmap=+{ nolangremap
142 call feedkeys("Go+\<Esc>", "xt")
143 call assert_equal('+', getline('$'))
144 set langmap=+{ langremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200145 call feedkeys("Go+\<Esc>", "xt")
146 call assert_equal('+', getline('$'))
147
Bram Moolenaar920694c2016-08-21 17:45:02 +0200148 " langmap used for register name in insert mode.
149 call setreg('a', 'aaaa')
150 call setreg('b', 'bbbb')
151 call setreg('c', 'cccc')
152 set langmap=ab langremap
153 call feedkeys("Go\<C-R>a\<Esc>", "xt")
154 call assert_equal('bbbb', getline('$'))
155 call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt")
156 call assert_equal('bbbb', getline('$'))
157 " mapping does not apply
158 imap c a
159 call feedkeys("Go\<C-R>c\<Esc>", "xt")
160 call assert_equal('cccc', getline('$'))
161 imap a c
162 call feedkeys("Go\<C-R>a\<Esc>", "xt")
163 call assert_equal('bbbb', getline('$'))
164
165 " langmap should not apply in Command-line mode
166 set langmap=+{ nolangremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200167 call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
168 call assert_equal('+', getline('$'))
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200169
Bram Moolenaare90858d2017-02-01 17:24:34 +0100170 iunmap a
171 iunmap c
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200172 set nomodified
173endfunc
174
175func Test_map_feedkeys()
176 " issue #212 (feedkeys insert mapping at current position)
177 nnoremap . :call feedkeys(".", "in")<cr>
178 call setline('$', ['a b c d', 'a b c d'])
179 $-1
180 call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt")
181 call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$')))
Bram Moolenaare90858d2017-02-01 17:24:34 +0100182 nunmap .
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200183 set nomodified
184endfunc
185
186func Test_map_cursor()
187 " <c-g>U<cursor> works only within a single line
188 imapclear
189 imap ( ()<c-g>U<left>
190 call feedkeys("G2o\<Esc>ki\<CR>Test1: text with a (here some more text\<Esc>k.", "xt")
191 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 2))
192 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 1))
193
194 " test undo
195 call feedkeys("G2o\<Esc>ki\<CR>Test2: text wit a (here some more text [und undo]\<C-G>u\<Esc>k.u", "xt")
196 call assert_equal('', getline(line('$') - 2))
197 call assert_equal('Test2: text wit a (here some more text [und undo])', getline(line('$') - 1))
198 set nomodified
199 imapclear
200endfunc
201
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100202func Test_map_cursor_ctrl_gU()
203 " <c-g>U<cursor> works only within a single line
204 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left>
205 call setline(1, ['foo', 'foobar', '', 'foo'])
206 call cursor(1,2)
207 call feedkeys("c<*PREFIX\<esc>.", 'xt')
208 call assert_equal(['PREFIXfoo', 'foobar', '', 'PREFIXfoo'], getline(1,'$'))
209 " break undo manually
210 set ul=1000
211 exe ":norm! uu"
212 call assert_equal(['foo', 'foobar', '', 'foo'], getline(1,'$'))
213
214 " Test that it does not work if the cursor moves to the previous line
215 " 2 times <S-Left> move to the previous line
216 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left><C-G>U<S-Left>
217 call setline(1, ['', ' foo', 'foobar', '', 'foo'])
218 call cursor(2,3)
219 call feedkeys("c<*PREFIX\<esc>.", 'xt')
220 call assert_equal(['PREFIXPREFIX', ' foo', 'foobar', '', 'foo'], getline(1,'$'))
221 nmapclear
222endfunc
223
224
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200225" This isn't actually testing a mapping, but similar use of CTRL-G U as above.
226func Test_break_undo()
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100227 set whichwrap=<,>,[,]
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200228 call feedkeys("G4o2k", "xt")
229 exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."
230 call assert_equal('new line here', getline(line('$') - 3))
231 call assert_equal('Test3: text with a (parenthesis here', getline(line('$') - 2))
232 call assert_equal('new line here', getline(line('$') - 1))
233 set nomodified
234endfunc
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200235
236func Test_map_meta_quotes()
237 imap <M-"> foo
Bram Moolenaarfccd93f2020-05-31 22:06:51 +0200238 call feedkeys("Go-\<*M-\">-\<Esc>", "xt")
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200239 call assert_equal("-foo-", getline('$'))
240 set nomodified
241 iunmap <M-">
242endfunc
Bram Moolenaar878c2632017-04-01 15:15:52 +0200243
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200244func Test_map_meta_multibyte()
245 imap <M-á> foo
Bram Moolenaar2f710af2019-08-16 20:56:03 +0200246 call assert_match('i <M-á>\s*foo', execute('imap'))
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200247 iunmap <M-á>
248endfunc
249
Bram Moolenaar878c2632017-04-01 15:15:52 +0200250func Test_abbr_after_line_join()
251 new
252 abbr foo bar
253 set backspace=indent,eol,start
254 exe "normal o\<BS>foo "
255 call assert_equal("bar ", getline(1))
256 bwipe!
257 unabbr foo
258 set backspace&
259endfunc
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200260
261func Test_map_timeout()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200262 CheckFeature timers
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200263 nnoremap aaaa :let got_aaaa = 1<CR>
264 nnoremap bb :let got_bb = 1<CR>
265 nmap b aaa
266 new
267 func ExitInsert(timer)
268 let g:line = getline(1)
269 call feedkeys("\<Esc>", "t")
270 endfunc
271 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100272 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200273 " After the 'b' Vim waits for another character to see if it matches 'bb'.
274 " When it times out it is expanded to "aaa", but there is no wait for
275 " "aaaa". Can't check that reliably though.
276 call feedkeys("b", "xt!")
277 call assert_equal("aa", g:line)
278 call assert_false(exists('got_aaa'))
279 call assert_false(exists('got_bb'))
280
281 bwipe!
282 nunmap aaaa
283 nunmap bb
284 nunmap b
285 set timeoutlen&
286 delfunc ExitInsert
Bram Moolenaar26d98212019-01-27 22:32:55 +0100287 call timer_stop(timer)
288endfunc
289
290func Test_map_timeout_with_timer_interrupt()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200291 CheckFeature job
292 CheckFeature timers
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100293 let g:test_is_flaky = 1
Bram Moolenaar26d98212019-01-27 22:32:55 +0100294
295 " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
296 " sequence.
297 new
298 let g:val = 0
299 nnoremap \12 :let g:val = 1<CR>
300 nnoremap \123 :let g:val = 2<CR>
Bram Moolenaarea94c852019-08-16 21:47:27 +0200301 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100302
303 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100304 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100305 endfunc
306
307 call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
308 call feedkeys('\12', 'xt!')
309 call assert_equal(2, g:val)
310
311 bwipe!
312 nunmap \12
313 nunmap \123
314 set timeoutlen&
315 call WaitFor({-> exists('g:timer')})
316 call timer_stop(g:timer)
317 unlet g:timer
318 unlet g:val
319 delfunc ExitCb
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200320endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200321
322func Test_abbreviation_CR()
323 new
324 func Eatchar(pat)
325 let c = nr2char(getchar(0))
326 return (c =~ a:pat) ? '' : c
327 endfunc
328 iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
329 call feedkeys("GA~~7 \<esc>", 'xt')
330 call assert_equal('~~~~~~~', getline('$'))
331 %d
332 call feedkeys("GA~~7\<cr>\<esc>", 'xt')
333 call assert_equal(['~~~~~~~', ''], getline(1,'$'))
334 delfunc Eatchar
335 bw!
336endfunc
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200337
338func Test_cabbr_visual_mode()
339 cabbr s su
340 call feedkeys(":s \<c-B>\"\<CR>", 'itx')
341 call assert_equal('"su ', getreg(':'))
342 call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
343 let expected = '"'. "'<,'>su "
344 call assert_equal(expected, getreg(':'))
345 call feedkeys(": '<,'>s \<c-B>\"\<CR>", 'itx')
346 let expected = '" '. "'<,'>su "
347 call assert_equal(expected, getreg(':'))
348 call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
349 let expected = '"'. "'a,'bsu "
350 call assert_equal(expected, getreg(':'))
351 cunabbr s
352endfunc
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100353
354func Test_motionforce_omap()
355 func GetCommand()
356 let g:m=mode(1)
357 let [g:lnum1, g:col1] = searchpos('-', 'Wb')
358 if g:lnum1 == 0
359 return "\<Esc>"
360 endif
361 let [g:lnum2, g:col2] = searchpos('-', 'W')
362 if g:lnum2 == 0
363 return "\<Esc>"
364 endif
365 return ":call Select()\<CR>"
366 endfunc
367 func Select()
368 call cursor([g:lnum1, g:col1])
369 exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
370 call cursor([g:lnum2, g:col2])
371 execute "normal! \<BS>"
372 endfunc
373 new
374 onoremap <buffer><expr> i- GetCommand()
375 " 1) default omap mapping
376 %d_
377 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
378 call cursor(2, 1)
379 norm di-
380 call assert_equal('no', g:m)
381 call assert_equal(['aaa -- eee'], getline(1, '$'))
382 " 2) forced characterwise operation
383 %d_
384 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
385 call cursor(2, 1)
386 norm dvi-
387 call assert_equal('nov', g:m)
388 call assert_equal(['aaa -- eee'], getline(1, '$'))
389 " 3) forced linewise operation
390 %d_
391 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
392 call cursor(2, 1)
393 norm dVi-
394 call assert_equal('noV', g:m)
395 call assert_equal([''], getline(1, '$'))
396 " 4) forced blockwise operation
397 %d_
398 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
399 call cursor(2, 1)
400 exe "norm d\<C-V>i-"
401 call assert_equal("no\<C-V>", g:m)
402 call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
403 bwipe!
404 delfunc Select
405 delfunc GetCommand
406endfunc
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200407
408func Test_error_in_map_expr()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200409 " Unlike CheckRunVimInTerminal this does work in a win32 console
410 CheckFeature terminal
411 if has('win32') && has('gui_running')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200412 throw 'Skipped: cannot run Vim in a terminal window'
413 endif
414
415 let lines =<< trim [CODE]
416 func Func()
417 " fail to create list
418 let x = [
419 endfunc
420 nmap <expr> ! Func()
421 set updatetime=50
422 [CODE]
423 call writefile(lines, 'Xtest.vim')
424
Bram Moolenaar0d702022019-07-04 14:20:41 +0200425 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200426 let job = term_getjob(buf)
427 call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
428
429 " GC must not run during map-expr processing, which can make Vim crash.
430 call term_sendkeys(buf, '!')
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200431 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200432 call term_sendkeys(buf, "\<CR>")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200433 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200434 call assert_equal('run', job_status(job))
435
436 call term_sendkeys(buf, ":qall!\<CR>")
437 call WaitFor({-> job_status(job) ==# 'dead'})
438 if has('unix')
439 call assert_equal('', job_info(job).termsig)
440 endif
441
442 call delete('Xtest.vim')
443 exe buf .. 'bwipe!'
444endfunc
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200445
446func Test_list_mappings()
Bram Moolenaar2559a472019-10-16 23:33:12 +0200447 " Remove default mappings
448 imapclear
Bram Moolenaar4f2f61a2019-10-16 22:27:49 +0200449
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200450 " reset 'isident' to check it isn't used
451 set isident=
452 inoremap <C-m> CtrlM
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200453 inoremap <A-S> AltS
454 inoremap <S-/> ShiftSlash
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200455 set isident&
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200456 call assert_equal([
457 \ 'i <S-/> * ShiftSlash',
458 \ 'i <M-S> * AltS',
459 \ 'i <C-M> * CtrlM',
460 \], execute('imap')->trim()->split("\n"))
461 iunmap <C-M>
462 iunmap <A-S>
463 call assert_equal(['i <S-/> * ShiftSlash'], execute('imap')->trim()->split("\n"))
464 iunmap <S-/>
465 call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100466
467 " List global, buffer local and script local mappings
468 nmap ,f /^\k\+ (<CR>
469 nmap <buffer> ,f /^\k\+ (<CR>
470 nmap <script> ,fs /^\k\+ (<CR>
471 call assert_equal(['n ,f @/^\k\+ (<CR>',
472 \ 'n ,fs & /^\k\+ (<CR>',
473 \ 'n ,f /^\k\+ (<CR>'],
474 \ execute('nmap ,f')->trim()->split("\n"))
475
476 " List <Nop> mapping
477 nmap ,n <Nop>
478 call assert_equal(['n ,n <Nop>'],
479 \ execute('nmap ,n')->trim()->split("\n"))
480
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100481 " verbose map
482 call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
483 \ execute('verbose map ,n')->trim()->split("\n")[1])
484
485 " map to CTRL-V
486 exe "nmap ,k \<C-V>"
487 call assert_equal(['n ,k <Nop>'],
488 \ execute('nmap ,k')->trim()->split("\n"))
489
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +0200490 " map with space at the beginning
491 exe "nmap \<C-V> w <Nop>"
492 call assert_equal(['n <Space>w <Nop>'],
493 \ execute("nmap \<C-V> w")->trim()->split("\n"))
494
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100495 nmapclear
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200496endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100497
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100498func Test_expr_map_gets_cursor()
499 new
500 call setline(1, ['one', 'some w!rd'])
501 func StoreColumn()
502 let g:exprLine = line('.')
503 let g:exprCol = col('.')
504 return 'x'
505 endfunc
506 nnoremap <expr> x StoreColumn()
507 2
508 nmap ! f!<Ignore>x
509 call feedkeys("!", 'xt')
510 call assert_equal('some wrd', getline(2))
511 call assert_equal(2, g:exprLine)
512 call assert_equal(7, g:exprCol)
513
514 bwipe!
515 unlet g:exprLine
516 unlet g:exprCol
Bram Moolenaar6ccfd992021-03-17 13:39:33 +0100517 delfunc StoreColumn
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100518 nunmap x
519 nunmap !
520endfunc
521
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100522func Test_expr_map_restore_cursor()
523 CheckScreendump
524
525 let lines =<< trim END
526 call setline(1, ['one', 'two', 'three'])
527 2
528 set ls=2
529 hi! link StatusLine ErrorMsg
530 noremap <expr> <C-B> Func()
531 func Func()
532 let g:on = !get(g:, 'on', 0)
533 redraws
534 return ''
535 endfunc
536 func Status()
537 return get(g:, 'on', 0) ? '[on]' : ''
538 endfunc
539 set stl=%{Status()}
540 END
541 call writefile(lines, 'XtestExprMap')
542 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200543 call TermWait(buf)
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100544 call term_sendkeys(buf, "\<C-B>")
545 call VerifyScreenDump(buf, 'Test_map_expr_1', {})
546
547 " clean up
548 call StopVimInTerminal(buf)
549 call delete('XtestExprMap')
550endfunc
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100551
552" Test for mapping errors
553func Test_map_error()
554 call assert_fails('unmap', 'E474:')
555 call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
556 call assert_fails('unmap abc', 'E31:')
557 call assert_fails('unabbr abc', 'E24:')
558 call assert_equal('', maparg(''))
559 call assert_fails('echo maparg("abc", [])', 'E730:')
560
561 " unique map
562 map ,w /[#&!]<CR>
563 call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
564 " unique buffer-local map
565 call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
566 unmap ,w
567
568 " unique abbreviation
569 abbr SP special
570 call assert_fails("abbr <unique> SP special", 'E226:')
571 " unique buffer-local map
572 call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
573 unabbr SP
574
575 call assert_fails('mapclear abc', 'E474:')
576 call assert_fails('abclear abc', 'E474:')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100577 call assert_fails('abbr $xyz abc', 'E474:')
578
579 " space character in an abbreviation
580 call assert_fails('abbr ab<space> ABC', 'E474:')
581
582 " invalid <expr> map
583 map <expr> ,f abc
584 call assert_fails('normal ,f', 'E121:')
585 unmap <expr> ,f
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100586
587 " Recursive use of :normal in a map
588 set maxmapdepth=100
589 map gq :normal gq<CR>
590 call assert_fails('normal gq', 'E192:')
591 unmap gq
592 set maxmapdepth&
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100593endfunc
594
595" Test for <special> key mapping
596func Test_map_special()
597 new
598 let old_cpo = &cpo
599 set cpo+=<
600 imap <F12> Blue
601 call feedkeys("i\<F12>", "x")
602 call assert_equal("<F12>", getline(1))
603 call feedkeys("ddi<F12>", "x")
604 call assert_equal("Blue", getline(1))
605 iunmap <F12>
606 imap <special> <F12> Green
607 call feedkeys("ddi\<F12>", "x")
608 call assert_equal("Green", getline(1))
609 call feedkeys("ddi<F12>", "x")
610 call assert_equal("<F12>", getline(1))
611 iunmap <special> <F12>
612 let &cpo = old_cpo
613 %bwipe!
614endfunc
615
616" Test for hasmapto()
617func Test_hasmapto()
618 call assert_equal(0, hasmapto('/^\k\+ ('))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100619 map ,f /^\k\+ (<CR>
620 call assert_equal(1, hasmapto('/^\k\+ ('))
621 unmap ,f
622
623 " Insert mode mapping
624 call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
625 imap ,f /^\k\+ (<CR>
626 call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
627 iunmap ,f
628
629 " Normal mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100630 call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
631 nmap ,f /^\k\+ (<CR>
632 call assert_equal(1, hasmapto('/^\k\+ ('))
633 call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100634 nunmap ,f
635
636 " Visual and Select mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100637 call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100638 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
639 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
640 vmap ,f /^\k\+ (<CR>
641 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
642 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
643 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
644 vunmap ,f
645
646 " Visual mode mapping
647 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
648 xmap ,f /^\k\+ (<CR>
649 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
650 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
651 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
652 xunmap ,f
653
654 " Select mode mapping
655 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
656 smap ,f /^\k\+ (<CR>
657 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
658 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
659 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
660 sunmap ,f
661
662 " Operator-pending mode mapping
663 call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
664 omap ,f /^\k\+ (<CR>
665 call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
666 ounmap ,f
667
668 " Language mapping
669 call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
670 lmap ,f /^\k\+ (<CR>
671 call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
672 lunmap ,f
673
674 " Cmdline mode mapping
675 call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
676 cmap ,f /^\k\+ (<CR>
677 call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
678 cunmap ,f
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100679
680 call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
681endfunc
682
683" Test for command-line completion of maps
684func Test_mapcomplete()
685 call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
686 \ '<silent>', '<special>', '<unique>'],
687 \ getcompletion('', 'mapping'))
688 call assert_equal([], getcompletion(',d', 'mapping'))
689
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100690 call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
691 call assert_equal('"unmap <buffer>', @:)
692
693 call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
694 call assert_equal('"unabbr <buffer>', @:)
695
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100696 call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100697 call assert_equal("\"abbr! \x01", @:)
698
699 " Multiple matches for a map
700 nmap ,f /H<CR>
701 omap ,f /H<CR>
702 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
703 call assert_equal('"map ,f', @:)
704 mapclear
705endfunc
706
707" Test for <expr> in abbreviation
708func Test_expr_abbr()
709 new
710 iabbr <expr> teh "the"
711 call feedkeys("iteh ", "tx")
712 call assert_equal('the ', getline(1))
713 iabclear
714 call setline(1, '')
715
716 " invalid <expr> abbreviation
717 abbr <expr> hte GetAbbr()
718 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100719 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100720 unabbr <expr> hte
721
722 close!
723endfunc
724
725" Test for storing mappings in different modes in a vimrc file
726func Test_mkvimrc_mapmodes()
727 map a1 /a1
728 nmap a2 /a2
729 vmap a3 /a3
730 smap a4 /a4
731 xmap a5 /a5
732 omap a6 /a6
733 map! a7 /a7
734 imap a8 /a8
735 lmap a9 /a9
736 cmap a10 /a10
737 tmap a11 /a11
738 " Normal + Visual map
739 map a12 /a12
740 sunmap a12
741 ounmap a12
742 " Normal + Selectmode map
743 map a13 /a13
744 xunmap a13
745 ounmap a13
746 " Normal + OpPending map
747 map a14 /a14
748 vunmap a14
749 " Visual + Selectmode map
750 map a15 /a15
751 nunmap a15
752 ounmap a15
753 " Visual + OpPending map
754 map a16 /a16
755 nunmap a16
756 sunmap a16
757 " Selectmode + OpPending map
758 map a17 /a17
759 nunmap a17
760 xunmap a17
761 " Normal + Visual + Selectmode map
762 map a18 /a18
763 ounmap a18
764 " Normal + Visual + OpPending map
765 map a19 /a19
766 sunmap a19
767 " Normal + Selectmode + OpPending map
768 map a20 /a20
769 xunmap a20
770 " Visual + Selectmode + OpPending map
771 map a21 /a21
772 nunmap a21
773 " Mapping to Nop
774 map a22 <Nop>
775 " Script local mapping
776 map <script> a23 /a23
777
778 " Newline in {lhs} and {rhs} of a map
779 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
780
781 " Abbreviation
782 abbr a25 A25
783 cabbr a26 A26
784 iabbr a27 A27
785
786 mkvimrc! Xvimrc
787 let l = readfile('Xvimrc')
788 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
789 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
790 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
791 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
792 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
793 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
794 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
795 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
796 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
797 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
798 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
799 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
800 \ filter(copy(l), 'v:val =~ " a12 "'))
801 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
802 \ filter(copy(l), 'v:val =~ " a13 "'))
803 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
804 \ filter(copy(l), 'v:val =~ " a14 "'))
805 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
806 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
807 \ filter(copy(l), 'v:val =~ " a16 "'))
808 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
809 \ filter(copy(l), 'v:val =~ " a17 "'))
810 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
811 \ filter(copy(l), 'v:val =~ " a18 "'))
812 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
813 \ filter(copy(l), 'v:val =~ " a19 "'))
814 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
815 \ filter(copy(l), 'v:val =~ " a20 "'))
816 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
817 \ filter(copy(l), 'v:val =~ " a21 "'))
818 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
819 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
820 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
821 \ filter(copy(l), 'v:val =~ " a24"'))
822
823 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
824 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
825 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
826 call delete('Xvimrc')
827
828 mapclear
829 nmapclear
830 vmapclear
831 xmapclear
832 smapclear
833 omapclear
834 imapclear
835 lmapclear
836 cmapclear
837 tmapclear
838endfunc
839
840" Test for recursive mapping ('maxmapdepth')
841func Test_map_recursive()
842 map x y
843 map y x
844 call assert_fails('normal x', 'E223:')
845 unmap x
846 unmap y
847endfunc
848
849" Test for removing an abbreviation using {rhs} and with space after {lhs}
850func Test_abbr_remove()
851 abbr foo bar
852 let d = maparg('foo', 'i', 1, 1)
853 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
854 unabbr bar
855 call assert_equal({}, maparg('foo', 'i', 1, 1))
856
857 abbr foo bar
858 unabbr foo<space><tab>
859 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100860endfunc
861
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100862" Trigger an abbreviation using a special key
863func Test_abbr_trigger_special()
864 new
865 iabbr teh the
866 call feedkeys("iteh\<F2>\<Esc>", 'xt')
867 call assert_equal('the<F2>', getline(1))
868 iunab teh
869 close!
870endfunc
871
872" Test for '<' in 'cpoptions'
873func Test_map_cpo_special_keycode()
874 set cpo-=<
875 imap x<Bslash>k Test
876 let d = maparg('x<Bslash>k', 'i', 0, 1)
877 call assert_equal(['x\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\k', @:)
880 iunmap x<Bslash>k
881 set cpo+=<
882 imap x<Bslash>k Test
883 let d = maparg('x<Bslash>k', 'i', 0, 1)
884 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
885 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
886 call assert_equal('"imap x<Bslash>k', @:)
887 iunmap x<Bslash>k
888 set cpo-=<
889 " Modifying 'cpo' above adds some default mappings, remove them
890 mapclear
891 mapclear!
892endfunc
893
Bram Moolenaar957cf672020-11-12 14:21:06 +0100894" Test for <Cmd> key in maps to execute commands
895func Test_map_cmdkey()
896 new
897
898 " Error cases
899 let x = 0
900 noremap <F3> <Cmd><Cmd>let x = 1<CR>
901 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
902 call assert_equal(0, x)
903
904 noremap <F3> <Cmd><F3>let x = 2<CR>
905 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1137:')
906 call assert_equal(0, x)
907
908 noremap <F3> <Cmd>let x = 3
Bram Moolenaar806da512021-12-24 19:54:52 +0000909 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
Bram Moolenaar957cf672020-11-12 14:21:06 +0100910 call assert_equal(0, x)
911
912 " works in various modes and sees the correct mode()
913 noremap <F3> <Cmd>let m = mode(1)<CR>
914 noremap! <F3> <Cmd>let m = mode(1)<CR>
915
916 " normal mode
917 call feedkeys("\<F3>", 'xt')
918 call assert_equal('n', m)
919
920 " visual mode
921 call feedkeys("v\<F3>", 'xt!')
922 call assert_equal('v', m)
923 " shouldn't leave the visual mode
924 call assert_equal('v', mode(1))
925 call feedkeys("\<Esc>", 'xt')
926 call assert_equal('n', mode(1))
927
928 " visual mapping in select mode
929 call feedkeys("gh\<F3>", 'xt!')
930 call assert_equal('v', m)
931 " shouldn't leave select mode
932 call assert_equal('s', mode(1))
933 call feedkeys("\<Esc>", 'xt')
934 call assert_equal('n', mode(1))
935
936 " select mode mapping
937 snoremap <F3> <Cmd>let m = mode(1)<cr>
938 call feedkeys("gh\<F3>", 'xt!')
939 call assert_equal('s', m)
940 " shouldn't leave select mode
941 call assert_equal('s', mode(1))
942 call feedkeys("\<Esc>", 'xt')
943 call assert_equal('n', mode(1))
944
945 " operator-pending mode
946 call feedkeys("d\<F3>", 'xt!')
947 call assert_equal('no', m)
948 " leaves the operator-pending mode
949 call assert_equal('n', mode(1))
950
951 " insert mode
952 call feedkeys("i\<F3>abc", 'xt')
953 call assert_equal('i', m)
954 call assert_equal('abc', getline('.'))
955
956 " replace mode
957 call feedkeys("0R\<F3>two", 'xt')
958 call assert_equal('R', m)
959 call assert_equal('two', getline('.'))
960
961 " virtual replace mode
962 call setline('.', "one\ttwo")
963 call feedkeys("4|gR\<F3>xxx", 'xt')
964 call assert_equal('Rv', m)
965 call assert_equal("onexxx\ttwo", getline('.'))
966
967 " cmdline mode
968 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
969 call assert_equal('c', m)
970 call assert_equal('"xxx', @:)
971
972 " terminal mode
973 if CanRunVimInTerminal()
974 tnoremap <F3> <Cmd>let m = mode(1)<CR>
975 let buf = Run_shell_in_terminal({})
976 call feedkeys("\<F3>", 'xt')
977 call assert_equal('t', m)
978 call assert_equal('t', mode(1))
979 call StopShellInTerminal(buf)
Bram Moolenaar957cf672020-11-12 14:21:06 +0100980 close!
981 tunmap <F3>
982 endif
983
984 " invoke cmdline mode recursively
985 noremap! <F2> <Cmd>norm! :foo<CR>
986 %d
987 call setline(1, ['some short lines', 'of test text'])
988 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
989 call assert_equal('"barx', @:)
990 unmap! <F2>
991
992 " test for calling a <SID> function
993 let lines =<< trim END
994 map <F2> <Cmd>call <SID>do_it()<CR>
995 func s:do_it()
996 let g:x = 32
997 endfunc
998 END
999 call writefile(lines, 'Xscript')
1000 source Xscript
1001 call feedkeys("\<F2>", 'xt')
1002 call assert_equal(32, g:x)
1003 call delete('Xscript')
1004
1005 unmap <F3>
1006 unmap! <F3>
1007 %bw!
Bram Moolenaar4a441202020-11-28 14:43:26 +01001008
1009 " command line ending in "0" is handled without errors
1010 onoremap ix <cmd>eval 0<cr>
1011 call feedkeys('dix.', 'xt')
1012 ounmap ix
Bram Moolenaar957cf672020-11-12 14:21:06 +01001013endfunc
1014
1015" text object enters visual mode
1016func TextObj()
1017 if mode() !=# "v"
1018 normal! v
1019 end
1020 call cursor(1, 3)
1021 normal! o
1022 call cursor(2, 4)
1023endfunc
1024
1025func s:cmdmap(lhs, rhs)
1026 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1027 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1028endfunc
1029
1030func s:cmdunmap(lhs)
1031 exe 'unmap ' .. a:lhs
1032 exe 'unmap! ' .. a:lhs
1033endfunc
1034
1035" Map various <Fx> keys used by the <Cmd> key tests
1036func s:setupMaps()
1037 call s:cmdmap('<F3>', 'let m = mode(1)')
1038 call s:cmdmap('<F4>', 'normal! ww')
1039 call s:cmdmap('<F5>', 'normal! "ay')
1040 call s:cmdmap('<F6>', 'throw "very error"')
1041 call s:cmdmap('<F7>', 'call TextObj()')
1042 call s:cmdmap('<F8>', 'startinsert')
1043 call s:cmdmap('<F9>', 'stopinsert')
1044endfunc
1045
1046" Remove the mappings setup by setupMaps()
1047func s:cleanupMaps()
1048 call s:cmdunmap('<F3>')
1049 call s:cmdunmap('<F4>')
1050 call s:cmdunmap('<F5>')
1051 call s:cmdunmap('<F6>')
1052 call s:cmdunmap('<F7>')
1053 call s:cmdunmap('<F8>')
1054 call s:cmdunmap('<F9>')
1055endfunc
1056
1057" Test for <Cmd> mapping in normal mode
1058func Test_map_cmdkey_normal_mode()
1059 new
1060 call s:setupMaps()
1061
1062 " check v:count and v:register works
1063 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1064 call feedkeys("\<F2>", 'xt')
1065 call assert_equal(['n', 0, '"'], s)
1066 call feedkeys("7\<F2>", 'xt')
1067 call assert_equal(['n', 7, '"'], s)
1068 call feedkeys("\"e\<F2>", 'xt')
1069 call assert_equal(['n', 0, 'e'], s)
1070 call feedkeys("5\"k\<F2>", 'xt')
1071 call assert_equal(['n', 5, 'k'], s)
1072 call s:cmdunmap('<F2>')
1073
1074 call setline(1, ['some short lines', 'of test text'])
1075 call feedkeys("\<F7>y", 'xt')
1076 call assert_equal("me short lines\nof t", @")
1077 call assert_equal('v', getregtype('"'))
1078 call assert_equal([0, 1, 3, 0], getpos("'<"))
1079 call assert_equal([0, 2, 4, 0], getpos("'>"))
1080
1081 " startinsert
1082 %d
1083 call feedkeys("\<F8>abc", 'xt')
1084 call assert_equal('abc', getline(1))
1085
1086 " feedkeys are not executed immediately
1087 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1088 %d
1089 call setline(1, ['some short lines', 'of test text'])
1090 call cursor(2, 3)
1091 call feedkeys(",a\<F3>", 'xt')
1092 call assert_equal('of test text', g:a)
1093 call assert_equal('n', m)
1094 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1095 nunmap ,a
1096
1097 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1098 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1099 call feedkeys(",b\<F3>", 'xt')
1100 call assert_equal('n', m)
1101 call assert_equal('of alphabetatest text', g:b)
1102 nunmap ,b
1103
1104 call s:cleanupMaps()
1105 %bw!
1106endfunc
1107
1108" Test for <Cmd> mapping with the :normal command
1109func Test_map_cmdkey_normal_cmd()
1110 new
1111 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1112 noremap ,f <Cmd>nosuchcommand<CR>
1113 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1114 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1115 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1116
1117 call setline(1, ['some short lines', 'of test text'])
1118 exe "norm ,x\r"
1119 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1120
1121 call assert_fails('norm ,f', 'E492:')
1122 call assert_fails('norm ,e', 'very error')
1123 call assert_fails('norm ,m', 'The message.')
1124 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1125
1126 %d
1127 let caught_err = 0
1128 try
1129 exe "normal ,w"
1130 catch /Vim(echoerr):Err/
1131 let caught_err = 1
1132 endtry
1133 call assert_equal(1, caught_err)
1134 call assert_equal(['', '0'], getline(1, '$'))
1135
1136 %d
1137 call assert_fails('normal ,w', 'Err')
1138 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1139 call assert_equal(1, line('.'))
1140
1141 nunmap ,x
1142 nunmap ,f
1143 nunmap ,e
1144 nunmap ,m
1145 nunmap ,w
1146 %bw!
1147endfunc
1148
1149" Test for <Cmd> mapping in visual mode
1150func Test_map_cmdkey_visual_mode()
1151 new
1152 set showmode
1153 call s:setupMaps()
1154
1155 call setline(1, ['some short lines', 'of test text'])
1156 call feedkeys("v\<F4>", 'xt!')
1157 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1158
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +01001159 " can invoke an operator, ending the visual mode
Bram Moolenaar957cf672020-11-12 14:21:06 +01001160 let @a = ''
1161 call feedkeys("\<F5>", 'xt!')
1162 call assert_equal('n', mode(1))
1163 call assert_equal('some short l', @a)
1164
1165 " error doesn't interrupt visual mode
1166 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1167 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1168 call feedkeys("\<F7>", 'xt!')
1169 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1170
1171 " startinsert gives "-- (insert) VISUAL --" mode
1172 call feedkeys("\<F8>", 'xt!')
1173 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1174 redraw!
1175 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1176 call feedkeys("\<Esc>new ", 'x')
1177 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1178
1179 call s:cleanupMaps()
1180 set showmode&
1181 %bw!
1182endfunc
1183
1184" Test for <Cmd> mapping in select mode
1185func Test_map_cmdkey_select_mode()
1186 new
1187 set showmode
1188 call s:setupMaps()
1189
1190 snoremap <F1> <cmd>throw "very error"<CR>
1191 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1192 call setline(1, ['some short lines', 'of test text'])
1193
1194 call feedkeys("gh\<F4>", "xt!")
1195 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1196 redraw!
1197 call assert_match('^-- SELECT --', Screenline(&lines))
1198
1199 " visual mapping in select mode restarts select mode after operator
1200 let @a = ''
1201 call feedkeys("\<F5>", 'xt!')
1202 call assert_equal('s', mode(1))
1203 call assert_equal('some short l', @a)
1204
1205 " select mode mapping works, and does not restart select mode
1206 let @b = ''
1207 call feedkeys("\<F2>", 'xt!')
1208 call assert_equal('n', mode(1))
1209 call assert_equal('some short l', @b)
1210
1211 " error doesn't interrupt temporary visual mode
1212 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1213 redraw!
1214 call assert_match('^-- VISUAL --', Screenline(&lines))
1215 " quirk: restoration of select mode is not performed
1216 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1217
1218 " error doesn't interrupt select mode
1219 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1220 redraw!
1221 call assert_match('^-- SELECT --', Screenline(&lines))
1222 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1223
1224 call feedkeys("\<F7>", 'xt!')
1225 redraw!
1226 call assert_match('^-- SELECT --', Screenline(&lines))
1227 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1228
1229 " startinsert gives "-- SELECT (insert) --" mode
1230 call feedkeys("\<F8>", 'xt!')
1231 redraw!
1232 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1233 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1234 call feedkeys("\<Esc>new ", 'x')
1235 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1236
1237 sunmap <F1>
1238 sunmap <F2>
1239 call s:cleanupMaps()
1240 set showmode&
1241 %bw!
1242endfunc
1243
1244" Test for <Cmd> mapping in operator-pending mode
1245func Test_map_cmdkey_op_pending_mode()
1246 new
1247 call s:setupMaps()
1248
1249 call setline(1, ['some short lines', 'of test text'])
1250 call feedkeys("d\<F4>", 'xt')
1251 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1252 call assert_equal(['some short '], getreg('"', 1, 1))
1253 " create a new undo point
1254 let &undolevels = &undolevels
1255
1256 call feedkeys(".", 'xt')
1257 call assert_equal(['test text'], getline(1, '$'))
1258 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1259 " create a new undo point
1260 let &undolevels = &undolevels
1261
1262 call feedkeys("uu", 'xt')
1263 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1264
1265 " error aborts operator-pending, operator not performed
1266 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1267 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1268
1269 call feedkeys("\"bd\<F7>", 'xt')
1270 call assert_equal(['soest text'], getline(1, '$'))
1271 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1272
1273 " startinsert aborts operator
1274 call feedkeys("d\<F8>cc", 'xt')
1275 call assert_equal(['soccest text'], getline(1, '$'))
1276
1277 call s:cleanupMaps()
1278 %bw!
1279endfunc
1280
1281" Test for <Cmd> mapping in insert mode
1282func Test_map_cmdkey_insert_mode()
1283 new
1284 call s:setupMaps()
1285
1286 call setline(1, ['some short lines', 'of test text'])
1287 " works the same as <C-O>w<C-O>w
1288 call feedkeys("iindeed \<F4>little ", 'xt')
1289 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1290 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1291 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1292
1293 " Note when entering visual mode from InsertEnter autocmd, an async event,
1294 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1295 call feedkeys("i\<F7>stuff ", 'xt')
1296 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1297 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1298
1299 call feedkeys("\<F5>", 'xt')
1300 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1301
1302 " also works as part of abbreviation
1303 abbr foo <Cmd>let g:y = 17<CR>bar
1304 exe "normal i\<space>foo "
1305 call assert_equal(17, g:y)
1306 call assert_equal('in bar deed some short little 2 lines', getline(1))
1307 unabbr foo
1308
1309 " :startinsert does nothing
1310 call setline(1, 'foo bar')
1311 call feedkeys("ggi\<F8>vim", 'xt')
1312 call assert_equal('vimfoo bar', getline(1))
1313
1314 " :stopinsert works
1315 call feedkeys("ggi\<F9>Abc", 'xt')
1316 call assert_equal('vimfoo barbc', getline(1))
1317
1318 call s:cleanupMaps()
1319 %bw!
1320endfunc
1321
1322" Test for <Cmd> mapping in insert-completion mode
1323func Test_map_cmdkey_insert_complete_mode()
1324 new
1325 call s:setupMaps()
1326
1327 call setline(1, 'some short lines')
1328 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1329 call assert_equal('ic', m)
1330 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1331
1332 call s:cleanupMaps()
1333 %bw!
1334endfunc
1335
1336" Test for <Cmd> mapping in cmdline mode
1337func Test_map_cmdkey_cmdline_mode()
1338 new
1339 call s:setupMaps()
1340
1341 call setline(1, ['some short lines', 'of test text'])
1342 let x = 0
1343 call feedkeys(":let x\<F3>= 10\r", 'xt')
1344 call assert_equal('c', m)
1345 call assert_equal(10, x)
1346
1347 " exception doesn't leave cmdline mode
1348 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1349 call assert_equal(20, x)
1350
1351 " move cursor in the buffer from cmdline mode
1352 call feedkeys(":let x\<F4>= 30\r", 'xt')
1353 call assert_equal(30, x)
1354 call assert_equal(12, col('.'))
1355
1356 " :startinsert takes effect after leaving cmdline mode
1357 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1358 call assert_equal(40, x)
1359 call assert_equal('some short new lines', getline(1))
1360
1361 call s:cleanupMaps()
1362 %bw!
1363endfunc
1364
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001365func Test_map_cmdkey_redo()
1366 func SelectDash()
1367 call search('^---\n\zs', 'bcW')
1368 norm! V
1369 call search('\n\ze---$', 'W')
1370 endfunc
1371
1372 let text =<< trim END
1373 ---
1374 aaa
1375 ---
1376 bbb
1377 bbb
1378 ---
1379 ccc
1380 ccc
1381 ccc
1382 ---
1383 END
1384 new Xcmdtext
1385 call setline(1, text)
1386
1387 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1388 call feedkeys('2Gdi-', 'xt')
1389 call assert_equal(['---', '---'], getline(1, 2))
1390 call feedkeys('j.', 'xt')
1391 call assert_equal(['---', '---', '---'], getline(1, 3))
1392 call feedkeys('j.', 'xt')
1393 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1394
1395 bwipe!
1396 call delete('Xcmdtext')
1397 delfunc SelectDash
1398 ounmap i-
1399endfunc
1400
Bram Moolenaara9725222022-01-16 13:30:33 +00001401func Test_map_script_cmd_restore()
1402 let lines =<< trim END
1403 vim9script
1404 nnoremap <F3> <ScriptCmd>eval 1 + 2<CR>
1405 END
1406 call CheckScriptSuccess(lines)
1407 call feedkeys("\<F3>:let g:result = 3+4\<CR>", 'xtc')
1408 call assert_equal(7, g:result)
1409
1410 nunmap <F3>
1411 unlet g:result
1412endfunc
1413
Bram Moolenaardc987762022-01-16 15:52:35 +00001414func Test_map_script_cmd_finds_func()
1415 let lines =<< trim END
1416 vim9script
1417 onoremap <F3> <ScriptCmd>Func()<CR>
1418 def Func()
1419 g:func_called = 'yes'
1420 enddef
1421 END
1422 call CheckScriptSuccess(lines)
1423 call feedkeys("y\<F3>\<Esc>", 'xtc')
1424 call assert_equal('yes', g:func_called)
1425
1426 ounmap <F3>
1427 unlet g:func_called
1428endfunc
1429
Bram Moolenaar1f448d92021-03-22 19:37:06 +01001430" Test for using <script> with a map to remap characters in rhs
1431func Test_script_local_remap()
1432 new
1433 inoremap <buffer> <SID>xyz mno
1434 inoremap <buffer> <script> abc st<SID>xyzre
1435 normal iabc
1436 call assert_equal('stmnore', getline(1))
1437 bwipe!
1438endfunc
1439
Bram Moolenaar4934ed32021-04-30 19:43:11 +02001440func Test_abbreviate_multi_byte()
1441 new
1442 iabbrev foo bar
1443 call feedkeys("ifoo\<Esc>", 'xt')
1444 call assert_equal("bar", getline(1))
1445 iunabbrev foo
1446 bwipe!
1447endfunc
1448
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +02001449" Test for abbreviations with 'latin1' encoding
1450func Test_abbreviate_latin1_encoding()
1451 set encoding=latin1
1452 call assert_fails('abbr ab#$c ABC', 'E474:')
1453 new
1454 iabbr <buffer> #i #include
1455 iabbr <buffer> ## #enddef
1456 exe "normal i#i\<C-]>"
1457 call assert_equal('#include', getline(1))
1458 exe "normal 0Di##\<C-]>"
1459 call assert_equal('#enddef', getline(1))
1460 %bw!
1461 set encoding=utf-8
1462endfunc
1463
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001464" vim: shiftwidth=2 sts=2 expandtab