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