blob: 69de22ba4974585da38942c41683206281c99b71 [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
Bram Moolenaar94075b22022-01-18 20:30:39 +0000707func GetAbbrText()
708 unabbr hola
709 return 'hello'
710endfunc
711
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100712" Test for <expr> in abbreviation
713func Test_expr_abbr()
714 new
715 iabbr <expr> teh "the"
716 call feedkeys("iteh ", "tx")
717 call assert_equal('the ', getline(1))
718 iabclear
719 call setline(1, '')
720
721 " invalid <expr> abbreviation
722 abbr <expr> hte GetAbbr()
723 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100724 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100725 unabbr <expr> hte
726
Bram Moolenaar94075b22022-01-18 20:30:39 +0000727 " evaluating the expression deletes the abbreviation
728 abbr <expr> hola GetAbbrText()
729 call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
730 call feedkeys("ahola \<Esc>", 'xt')
731 call assert_equal('hello ', getline('.'))
732 call assert_equal('', maparg('hola', 'i', '1'))
733
734 bwipe!
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100735endfunc
736
737" Test for storing mappings in different modes in a vimrc file
738func Test_mkvimrc_mapmodes()
739 map a1 /a1
740 nmap a2 /a2
741 vmap a3 /a3
742 smap a4 /a4
743 xmap a5 /a5
744 omap a6 /a6
745 map! a7 /a7
746 imap a8 /a8
747 lmap a9 /a9
748 cmap a10 /a10
749 tmap a11 /a11
750 " Normal + Visual map
751 map a12 /a12
752 sunmap a12
753 ounmap a12
754 " Normal + Selectmode map
755 map a13 /a13
756 xunmap a13
757 ounmap a13
758 " Normal + OpPending map
759 map a14 /a14
760 vunmap a14
761 " Visual + Selectmode map
762 map a15 /a15
763 nunmap a15
764 ounmap a15
765 " Visual + OpPending map
766 map a16 /a16
767 nunmap a16
768 sunmap a16
769 " Selectmode + OpPending map
770 map a17 /a17
771 nunmap a17
772 xunmap a17
773 " Normal + Visual + Selectmode map
774 map a18 /a18
775 ounmap a18
776 " Normal + Visual + OpPending map
777 map a19 /a19
778 sunmap a19
779 " Normal + Selectmode + OpPending map
780 map a20 /a20
781 xunmap a20
782 " Visual + Selectmode + OpPending map
783 map a21 /a21
784 nunmap a21
785 " Mapping to Nop
786 map a22 <Nop>
787 " Script local mapping
788 map <script> a23 /a23
789
790 " Newline in {lhs} and {rhs} of a map
791 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
792
793 " Abbreviation
794 abbr a25 A25
795 cabbr a26 A26
796 iabbr a27 A27
797
798 mkvimrc! Xvimrc
799 let l = readfile('Xvimrc')
800 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
801 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
802 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
803 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
804 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
805 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
806 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
807 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
808 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
809 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
810 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
811 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
812 \ filter(copy(l), 'v:val =~ " a12 "'))
813 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
814 \ filter(copy(l), 'v:val =~ " a13 "'))
815 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
816 \ filter(copy(l), 'v:val =~ " a14 "'))
817 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
818 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
819 \ filter(copy(l), 'v:val =~ " a16 "'))
820 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
821 \ filter(copy(l), 'v:val =~ " a17 "'))
822 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
823 \ filter(copy(l), 'v:val =~ " a18 "'))
824 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
825 \ filter(copy(l), 'v:val =~ " a19 "'))
826 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
827 \ filter(copy(l), 'v:val =~ " a20 "'))
828 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
829 \ filter(copy(l), 'v:val =~ " a21 "'))
830 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
831 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
832 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
833 \ filter(copy(l), 'v:val =~ " a24"'))
834
835 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
836 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
837 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
838 call delete('Xvimrc')
839
840 mapclear
841 nmapclear
842 vmapclear
843 xmapclear
844 smapclear
845 omapclear
846 imapclear
847 lmapclear
848 cmapclear
849 tmapclear
850endfunc
851
852" Test for recursive mapping ('maxmapdepth')
853func Test_map_recursive()
854 map x y
855 map y x
856 call assert_fails('normal x', 'E223:')
857 unmap x
858 unmap y
859endfunc
860
861" Test for removing an abbreviation using {rhs} and with space after {lhs}
862func Test_abbr_remove()
863 abbr foo bar
864 let d = maparg('foo', 'i', 1, 1)
865 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
866 unabbr bar
867 call assert_equal({}, maparg('foo', 'i', 1, 1))
868
869 abbr foo bar
870 unabbr foo<space><tab>
871 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100872endfunc
873
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100874" Trigger an abbreviation using a special key
875func Test_abbr_trigger_special()
876 new
877 iabbr teh the
878 call feedkeys("iteh\<F2>\<Esc>", 'xt')
879 call assert_equal('the<F2>', getline(1))
880 iunab teh
881 close!
882endfunc
883
884" Test for '<' in 'cpoptions'
885func Test_map_cpo_special_keycode()
886 set cpo-=<
887 imap x<Bslash>k Test
888 let d = maparg('x<Bslash>k', 'i', 0, 1)
889 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
890 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
891 call assert_equal('"imap x\k', @:)
892 iunmap x<Bslash>k
893 set cpo+=<
894 imap x<Bslash>k Test
895 let d = maparg('x<Bslash>k', 'i', 0, 1)
896 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
897 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
898 call assert_equal('"imap x<Bslash>k', @:)
899 iunmap x<Bslash>k
900 set cpo-=<
901 " Modifying 'cpo' above adds some default mappings, remove them
902 mapclear
903 mapclear!
904endfunc
905
Bram Moolenaar957cf672020-11-12 14:21:06 +0100906" Test for <Cmd> key in maps to execute commands
907func Test_map_cmdkey()
908 new
909
910 " Error cases
911 let x = 0
912 noremap <F3> <Cmd><Cmd>let x = 1<CR>
913 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
914 call assert_equal(0, x)
915
916 noremap <F3> <Cmd><F3>let x = 2<CR>
917 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1137:')
918 call assert_equal(0, x)
919
920 noremap <F3> <Cmd>let x = 3
Bram Moolenaar806da512021-12-24 19:54:52 +0000921 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
Bram Moolenaar957cf672020-11-12 14:21:06 +0100922 call assert_equal(0, x)
923
924 " works in various modes and sees the correct mode()
925 noremap <F3> <Cmd>let m = mode(1)<CR>
926 noremap! <F3> <Cmd>let m = mode(1)<CR>
927
928 " normal mode
929 call feedkeys("\<F3>", 'xt')
930 call assert_equal('n', m)
931
932 " visual mode
933 call feedkeys("v\<F3>", 'xt!')
934 call assert_equal('v', m)
935 " shouldn't leave the visual mode
936 call assert_equal('v', mode(1))
937 call feedkeys("\<Esc>", 'xt')
938 call assert_equal('n', mode(1))
939
940 " visual mapping in select mode
941 call feedkeys("gh\<F3>", 'xt!')
942 call assert_equal('v', m)
943 " shouldn't leave select mode
944 call assert_equal('s', mode(1))
945 call feedkeys("\<Esc>", 'xt')
946 call assert_equal('n', mode(1))
947
948 " select mode mapping
949 snoremap <F3> <Cmd>let m = mode(1)<cr>
950 call feedkeys("gh\<F3>", 'xt!')
951 call assert_equal('s', m)
952 " shouldn't leave select mode
953 call assert_equal('s', mode(1))
954 call feedkeys("\<Esc>", 'xt')
955 call assert_equal('n', mode(1))
956
957 " operator-pending mode
958 call feedkeys("d\<F3>", 'xt!')
959 call assert_equal('no', m)
960 " leaves the operator-pending mode
961 call assert_equal('n', mode(1))
962
963 " insert mode
964 call feedkeys("i\<F3>abc", 'xt')
965 call assert_equal('i', m)
966 call assert_equal('abc', getline('.'))
967
968 " replace mode
969 call feedkeys("0R\<F3>two", 'xt')
970 call assert_equal('R', m)
971 call assert_equal('two', getline('.'))
972
973 " virtual replace mode
974 call setline('.', "one\ttwo")
975 call feedkeys("4|gR\<F3>xxx", 'xt')
976 call assert_equal('Rv', m)
977 call assert_equal("onexxx\ttwo", getline('.'))
978
979 " cmdline mode
980 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
981 call assert_equal('c', m)
982 call assert_equal('"xxx', @:)
983
984 " terminal mode
985 if CanRunVimInTerminal()
986 tnoremap <F3> <Cmd>let m = mode(1)<CR>
987 let buf = Run_shell_in_terminal({})
988 call feedkeys("\<F3>", 'xt')
989 call assert_equal('t', m)
990 call assert_equal('t', mode(1))
991 call StopShellInTerminal(buf)
Bram Moolenaar957cf672020-11-12 14:21:06 +0100992 close!
993 tunmap <F3>
994 endif
995
996 " invoke cmdline mode recursively
997 noremap! <F2> <Cmd>norm! :foo<CR>
998 %d
999 call setline(1, ['some short lines', 'of test text'])
1000 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
1001 call assert_equal('"barx', @:)
1002 unmap! <F2>
1003
1004 " test for calling a <SID> function
1005 let lines =<< trim END
1006 map <F2> <Cmd>call <SID>do_it()<CR>
1007 func s:do_it()
1008 let g:x = 32
1009 endfunc
1010 END
1011 call writefile(lines, 'Xscript')
1012 source Xscript
1013 call feedkeys("\<F2>", 'xt')
1014 call assert_equal(32, g:x)
1015 call delete('Xscript')
1016
1017 unmap <F3>
1018 unmap! <F3>
1019 %bw!
Bram Moolenaar4a441202020-11-28 14:43:26 +01001020
1021 " command line ending in "0" is handled without errors
1022 onoremap ix <cmd>eval 0<cr>
1023 call feedkeys('dix.', 'xt')
1024 ounmap ix
Bram Moolenaar957cf672020-11-12 14:21:06 +01001025endfunc
1026
1027" text object enters visual mode
1028func TextObj()
1029 if mode() !=# "v"
1030 normal! v
1031 end
1032 call cursor(1, 3)
1033 normal! o
1034 call cursor(2, 4)
1035endfunc
1036
1037func s:cmdmap(lhs, rhs)
1038 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1039 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1040endfunc
1041
1042func s:cmdunmap(lhs)
1043 exe 'unmap ' .. a:lhs
1044 exe 'unmap! ' .. a:lhs
1045endfunc
1046
1047" Map various <Fx> keys used by the <Cmd> key tests
1048func s:setupMaps()
1049 call s:cmdmap('<F3>', 'let m = mode(1)')
1050 call s:cmdmap('<F4>', 'normal! ww')
1051 call s:cmdmap('<F5>', 'normal! "ay')
1052 call s:cmdmap('<F6>', 'throw "very error"')
1053 call s:cmdmap('<F7>', 'call TextObj()')
1054 call s:cmdmap('<F8>', 'startinsert')
1055 call s:cmdmap('<F9>', 'stopinsert')
1056endfunc
1057
1058" Remove the mappings setup by setupMaps()
1059func s:cleanupMaps()
1060 call s:cmdunmap('<F3>')
1061 call s:cmdunmap('<F4>')
1062 call s:cmdunmap('<F5>')
1063 call s:cmdunmap('<F6>')
1064 call s:cmdunmap('<F7>')
1065 call s:cmdunmap('<F8>')
1066 call s:cmdunmap('<F9>')
1067endfunc
1068
1069" Test for <Cmd> mapping in normal mode
1070func Test_map_cmdkey_normal_mode()
1071 new
1072 call s:setupMaps()
1073
1074 " check v:count and v:register works
1075 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1076 call feedkeys("\<F2>", 'xt')
1077 call assert_equal(['n', 0, '"'], s)
1078 call feedkeys("7\<F2>", 'xt')
1079 call assert_equal(['n', 7, '"'], s)
1080 call feedkeys("\"e\<F2>", 'xt')
1081 call assert_equal(['n', 0, 'e'], s)
1082 call feedkeys("5\"k\<F2>", 'xt')
1083 call assert_equal(['n', 5, 'k'], s)
1084 call s:cmdunmap('<F2>')
1085
1086 call setline(1, ['some short lines', 'of test text'])
1087 call feedkeys("\<F7>y", 'xt')
1088 call assert_equal("me short lines\nof t", @")
1089 call assert_equal('v', getregtype('"'))
1090 call assert_equal([0, 1, 3, 0], getpos("'<"))
1091 call assert_equal([0, 2, 4, 0], getpos("'>"))
1092
1093 " startinsert
1094 %d
1095 call feedkeys("\<F8>abc", 'xt')
1096 call assert_equal('abc', getline(1))
1097
1098 " feedkeys are not executed immediately
1099 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1100 %d
1101 call setline(1, ['some short lines', 'of test text'])
1102 call cursor(2, 3)
1103 call feedkeys(",a\<F3>", 'xt')
1104 call assert_equal('of test text', g:a)
1105 call assert_equal('n', m)
1106 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1107 nunmap ,a
1108
1109 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1110 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1111 call feedkeys(",b\<F3>", 'xt')
1112 call assert_equal('n', m)
1113 call assert_equal('of alphabetatest text', g:b)
1114 nunmap ,b
1115
1116 call s:cleanupMaps()
1117 %bw!
1118endfunc
1119
1120" Test for <Cmd> mapping with the :normal command
1121func Test_map_cmdkey_normal_cmd()
1122 new
1123 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1124 noremap ,f <Cmd>nosuchcommand<CR>
1125 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1126 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1127 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1128
1129 call setline(1, ['some short lines', 'of test text'])
1130 exe "norm ,x\r"
1131 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1132
1133 call assert_fails('norm ,f', 'E492:')
1134 call assert_fails('norm ,e', 'very error')
1135 call assert_fails('norm ,m', 'The message.')
1136 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1137
1138 %d
1139 let caught_err = 0
1140 try
1141 exe "normal ,w"
1142 catch /Vim(echoerr):Err/
1143 let caught_err = 1
1144 endtry
1145 call assert_equal(1, caught_err)
1146 call assert_equal(['', '0'], getline(1, '$'))
1147
1148 %d
1149 call assert_fails('normal ,w', 'Err')
1150 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1151 call assert_equal(1, line('.'))
1152
1153 nunmap ,x
1154 nunmap ,f
1155 nunmap ,e
1156 nunmap ,m
1157 nunmap ,w
1158 %bw!
1159endfunc
1160
1161" Test for <Cmd> mapping in visual mode
1162func Test_map_cmdkey_visual_mode()
1163 new
1164 set showmode
1165 call s:setupMaps()
1166
1167 call setline(1, ['some short lines', 'of test text'])
1168 call feedkeys("v\<F4>", 'xt!')
1169 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1170
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +01001171 " can invoke an operator, ending the visual mode
Bram Moolenaar957cf672020-11-12 14:21:06 +01001172 let @a = ''
1173 call feedkeys("\<F5>", 'xt!')
1174 call assert_equal('n', mode(1))
1175 call assert_equal('some short l', @a)
1176
1177 " error doesn't interrupt visual mode
1178 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1179 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1180 call feedkeys("\<F7>", 'xt!')
1181 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1182
1183 " startinsert gives "-- (insert) VISUAL --" mode
1184 call feedkeys("\<F8>", 'xt!')
1185 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1186 redraw!
1187 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1188 call feedkeys("\<Esc>new ", 'x')
1189 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1190
1191 call s:cleanupMaps()
1192 set showmode&
1193 %bw!
1194endfunc
1195
1196" Test for <Cmd> mapping in select mode
1197func Test_map_cmdkey_select_mode()
1198 new
1199 set showmode
1200 call s:setupMaps()
1201
1202 snoremap <F1> <cmd>throw "very error"<CR>
1203 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1204 call setline(1, ['some short lines', 'of test text'])
1205
1206 call feedkeys("gh\<F4>", "xt!")
1207 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1208 redraw!
1209 call assert_match('^-- SELECT --', Screenline(&lines))
1210
1211 " visual mapping in select mode restarts select mode after operator
1212 let @a = ''
1213 call feedkeys("\<F5>", 'xt!')
1214 call assert_equal('s', mode(1))
1215 call assert_equal('some short l', @a)
1216
1217 " select mode mapping works, and does not restart select mode
1218 let @b = ''
1219 call feedkeys("\<F2>", 'xt!')
1220 call assert_equal('n', mode(1))
1221 call assert_equal('some short l', @b)
1222
1223 " error doesn't interrupt temporary visual mode
1224 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1225 redraw!
1226 call assert_match('^-- VISUAL --', Screenline(&lines))
1227 " quirk: restoration of select mode is not performed
1228 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1229
1230 " error doesn't interrupt select mode
1231 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1232 redraw!
1233 call assert_match('^-- SELECT --', Screenline(&lines))
1234 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1235
1236 call feedkeys("\<F7>", 'xt!')
1237 redraw!
1238 call assert_match('^-- SELECT --', Screenline(&lines))
1239 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1240
1241 " startinsert gives "-- SELECT (insert) --" mode
1242 call feedkeys("\<F8>", 'xt!')
1243 redraw!
1244 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1245 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1246 call feedkeys("\<Esc>new ", 'x')
1247 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1248
1249 sunmap <F1>
1250 sunmap <F2>
1251 call s:cleanupMaps()
1252 set showmode&
1253 %bw!
1254endfunc
1255
1256" Test for <Cmd> mapping in operator-pending mode
1257func Test_map_cmdkey_op_pending_mode()
1258 new
1259 call s:setupMaps()
1260
1261 call setline(1, ['some short lines', 'of test text'])
1262 call feedkeys("d\<F4>", 'xt')
1263 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1264 call assert_equal(['some short '], getreg('"', 1, 1))
1265 " create a new undo point
1266 let &undolevels = &undolevels
1267
1268 call feedkeys(".", 'xt')
1269 call assert_equal(['test text'], getline(1, '$'))
1270 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1271 " create a new undo point
1272 let &undolevels = &undolevels
1273
1274 call feedkeys("uu", 'xt')
1275 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1276
1277 " error aborts operator-pending, operator not performed
1278 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1279 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1280
1281 call feedkeys("\"bd\<F7>", 'xt')
1282 call assert_equal(['soest text'], getline(1, '$'))
1283 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1284
1285 " startinsert aborts operator
1286 call feedkeys("d\<F8>cc", 'xt')
1287 call assert_equal(['soccest text'], getline(1, '$'))
1288
1289 call s:cleanupMaps()
1290 %bw!
1291endfunc
1292
1293" Test for <Cmd> mapping in insert mode
1294func Test_map_cmdkey_insert_mode()
1295 new
1296 call s:setupMaps()
1297
1298 call setline(1, ['some short lines', 'of test text'])
1299 " works the same as <C-O>w<C-O>w
1300 call feedkeys("iindeed \<F4>little ", 'xt')
1301 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1302 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1303 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1304
1305 " Note when entering visual mode from InsertEnter autocmd, an async event,
1306 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1307 call feedkeys("i\<F7>stuff ", 'xt')
1308 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1309 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1310
1311 call feedkeys("\<F5>", 'xt')
1312 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1313
1314 " also works as part of abbreviation
1315 abbr foo <Cmd>let g:y = 17<CR>bar
1316 exe "normal i\<space>foo "
1317 call assert_equal(17, g:y)
1318 call assert_equal('in bar deed some short little 2 lines', getline(1))
1319 unabbr foo
1320
1321 " :startinsert does nothing
1322 call setline(1, 'foo bar')
1323 call feedkeys("ggi\<F8>vim", 'xt')
1324 call assert_equal('vimfoo bar', getline(1))
1325
1326 " :stopinsert works
1327 call feedkeys("ggi\<F9>Abc", 'xt')
1328 call assert_equal('vimfoo barbc', getline(1))
1329
1330 call s:cleanupMaps()
1331 %bw!
1332endfunc
1333
1334" Test for <Cmd> mapping in insert-completion mode
1335func Test_map_cmdkey_insert_complete_mode()
1336 new
1337 call s:setupMaps()
1338
1339 call setline(1, 'some short lines')
1340 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1341 call assert_equal('ic', m)
1342 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1343
1344 call s:cleanupMaps()
1345 %bw!
1346endfunc
1347
1348" Test for <Cmd> mapping in cmdline mode
1349func Test_map_cmdkey_cmdline_mode()
1350 new
1351 call s:setupMaps()
1352
1353 call setline(1, ['some short lines', 'of test text'])
1354 let x = 0
1355 call feedkeys(":let x\<F3>= 10\r", 'xt')
1356 call assert_equal('c', m)
1357 call assert_equal(10, x)
1358
1359 " exception doesn't leave cmdline mode
1360 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1361 call assert_equal(20, x)
1362
1363 " move cursor in the buffer from cmdline mode
1364 call feedkeys(":let x\<F4>= 30\r", 'xt')
1365 call assert_equal(30, x)
1366 call assert_equal(12, col('.'))
1367
1368 " :startinsert takes effect after leaving cmdline mode
1369 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1370 call assert_equal(40, x)
1371 call assert_equal('some short new lines', getline(1))
1372
1373 call s:cleanupMaps()
1374 %bw!
1375endfunc
1376
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001377func Test_map_cmdkey_redo()
1378 func SelectDash()
1379 call search('^---\n\zs', 'bcW')
1380 norm! V
1381 call search('\n\ze---$', 'W')
1382 endfunc
1383
1384 let text =<< trim END
1385 ---
1386 aaa
1387 ---
1388 bbb
1389 bbb
1390 ---
1391 ccc
1392 ccc
1393 ccc
1394 ---
1395 END
1396 new Xcmdtext
1397 call setline(1, text)
1398
1399 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1400 call feedkeys('2Gdi-', 'xt')
1401 call assert_equal(['---', '---'], getline(1, 2))
1402 call feedkeys('j.', 'xt')
1403 call assert_equal(['---', '---', '---'], getline(1, 3))
1404 call feedkeys('j.', 'xt')
1405 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1406
1407 bwipe!
1408 call delete('Xcmdtext')
1409 delfunc SelectDash
1410 ounmap i-
1411endfunc
1412
Bram Moolenaara9725222022-01-16 13:30:33 +00001413func Test_map_script_cmd_restore()
1414 let lines =<< trim END
1415 vim9script
1416 nnoremap <F3> <ScriptCmd>eval 1 + 2<CR>
1417 END
1418 call CheckScriptSuccess(lines)
1419 call feedkeys("\<F3>:let g:result = 3+4\<CR>", 'xtc')
1420 call assert_equal(7, g:result)
1421
1422 nunmap <F3>
1423 unlet g:result
1424endfunc
1425
Bram Moolenaardc987762022-01-16 15:52:35 +00001426func Test_map_script_cmd_finds_func()
1427 let lines =<< trim END
1428 vim9script
1429 onoremap <F3> <ScriptCmd>Func()<CR>
1430 def Func()
1431 g:func_called = 'yes'
1432 enddef
1433 END
1434 call CheckScriptSuccess(lines)
1435 call feedkeys("y\<F3>\<Esc>", 'xtc')
1436 call assert_equal('yes', g:func_called)
1437
1438 ounmap <F3>
1439 unlet g:func_called
1440endfunc
1441
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001442func Test_map_script_cmd_survives_unmap()
1443 let lines =<< trim END
1444 vim9script
1445 var n = 123
1446 nnoremap <F4> <ScriptCmd><CR>
1447 autocmd CmdlineEnter * silent! nunmap <F4>
1448 nnoremap <F3> :<ScriptCmd>eval setbufvar(bufnr(), "result", n)<CR>
1449 feedkeys("\<F3>\<CR>", 'xct')
1450 assert_equal(123, b:result)
1451 END
1452 call CheckScriptSuccess(lines)
1453
1454 nunmap <F3>
1455 unlet b:result
1456endfunc
1457
Bram Moolenaar1f448d92021-03-22 19:37:06 +01001458" Test for using <script> with a map to remap characters in rhs
1459func Test_script_local_remap()
1460 new
1461 inoremap <buffer> <SID>xyz mno
1462 inoremap <buffer> <script> abc st<SID>xyzre
1463 normal iabc
1464 call assert_equal('stmnore', getline(1))
1465 bwipe!
1466endfunc
1467
Bram Moolenaar4934ed32021-04-30 19:43:11 +02001468func Test_abbreviate_multi_byte()
1469 new
1470 iabbrev foo bar
1471 call feedkeys("ifoo…\<Esc>", 'xt')
1472 call assert_equal("bar…", getline(1))
1473 iunabbrev foo
1474 bwipe!
1475endfunc
1476
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +02001477" Test for abbreviations with 'latin1' encoding
1478func Test_abbreviate_latin1_encoding()
1479 set encoding=latin1
1480 call assert_fails('abbr ab#$c ABC', 'E474:')
1481 new
1482 iabbr <buffer> #i #include
1483 iabbr <buffer> ## #enddef
1484 exe "normal i#i\<C-]>"
1485 call assert_equal('#include', getline(1))
1486 exe "normal 0Di##\<C-]>"
1487 call assert_equal('#enddef', getline(1))
1488 %bw!
1489 set encoding=utf-8
1490endfunc
1491
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001492" vim: shiftwidth=2 sts=2 expandtab