blob: e81173d2bc26816f276ceedd268abb2918357b6e [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]
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100423 call writefile(lines, 'Xtest.vim', 'D')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200424
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
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200442 exe buf .. 'bwipe!'
443endfunc
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200444
445func Test_list_mappings()
Bram Moolenaar2559a472019-10-16 23:33:12 +0200446 " Remove default mappings
447 imapclear
Bram Moolenaar4f2f61a2019-10-16 22:27:49 +0200448
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200449 " reset 'isident' to check it isn't used
450 set isident=
451 inoremap <C-m> CtrlM
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200452 inoremap <A-S> AltS
453 inoremap <S-/> ShiftSlash
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200454 set isident&
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200455 call assert_equal([
456 \ 'i <S-/> * ShiftSlash',
457 \ 'i <M-S> * AltS',
458 \ 'i <C-M> * CtrlM',
459 \], execute('imap')->trim()->split("\n"))
460 iunmap <C-M>
461 iunmap <A-S>
462 call assert_equal(['i <S-/> * ShiftSlash'], execute('imap')->trim()->split("\n"))
463 iunmap <S-/>
464 call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100465
466 " List global, buffer local and script local mappings
467 nmap ,f /^\k\+ (<CR>
468 nmap <buffer> ,f /^\k\+ (<CR>
469 nmap <script> ,fs /^\k\+ (<CR>
470 call assert_equal(['n ,f @/^\k\+ (<CR>',
471 \ 'n ,fs & /^\k\+ (<CR>',
472 \ 'n ,f /^\k\+ (<CR>'],
473 \ execute('nmap ,f')->trim()->split("\n"))
474
475 " List <Nop> mapping
476 nmap ,n <Nop>
477 call assert_equal(['n ,n <Nop>'],
478 \ execute('nmap ,n')->trim()->split("\n"))
479
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100480 " verbose map
Bram Moolenaar060b8382022-10-19 14:48:14 +0100481 let lines = execute('verbose map ,n')->trim()->split("\n")
Bram Moolenaarc255b782022-11-26 19:16:48 +0000482
483 " Remove "Seen modifyOtherKeys" and other optional info.
484 if lines[0] =~ 'Seen modifyOtherKeys'
485 call remove(lines, 0)
486 endif
487 if lines[0] =~ 'modifyOtherKeys detected:'
488 call remove(lines, 0)
489 endif
490 if lines[0] =~ 'Kitty keyboard protocol:'
491 call remove(lines, 0)
492 endif
493 if lines[0] == ''
494 call remove(lines, 0)
495 endif
496
Bram Moolenaar060b8382022-10-19 14:48:14 +0100497 let index = indexof(lines, 'v:val =~ "Last set"')
Bram Moolenaarc255b782022-11-26 19:16:48 +0000498 call assert_equal(1, index)
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100499 call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
Bram Moolenaar060b8382022-10-19 14:48:14 +0100500 \ lines[index])
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100501
zeertzjqac402f42022-05-04 18:51:43 +0100502 " character with K_SPECIAL byte in rhs
503 nmap foo …
504 call assert_equal(['n foo …'],
505 \ execute('nmap foo')->trim()->split("\n"))
506
507 " modified character with K_SPECIAL byte in rhs
508 nmap foo <M-…>
509 call assert_equal(['n foo <M-…>'],
510 \ execute('nmap foo')->trim()->split("\n"))
511
512 " character with K_SPECIAL byte in lhs
513 nmap … foo
514 call assert_equal(['n … foo'],
515 \ execute('nmap …')->trim()->split("\n"))
516
517 " modified character with K_SPECIAL byte in lhs
518 nmap <M-…> foo
519 call assert_equal(['n <M-…> foo'],
520 \ execute('nmap <M-…>')->trim()->split("\n"))
521
zeertzjq0519ce02022-05-09 12:16:19 +0100522 " illegal bytes
523 let str = ":\x7f:\x80:\x90:\xd0:"
524 exe 'nmap foo ' .. str
525 call assert_equal(['n foo ' .. strtrans(str)],
526 \ execute('nmap foo')->trim()->split("\n"))
527 unlet str
528
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100529 " map to CTRL-V
530 exe "nmap ,k \<C-V>"
531 call assert_equal(['n ,k <Nop>'],
532 \ execute('nmap ,k')->trim()->split("\n"))
533
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +0200534 " map with space at the beginning
535 exe "nmap \<C-V> w <Nop>"
536 call assert_equal(['n <Space>w <Nop>'],
537 \ execute("nmap \<C-V> w")->trim()->split("\n"))
538
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100539 nmapclear
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200540endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100541
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100542func Test_expr_map_gets_cursor()
543 new
544 call setline(1, ['one', 'some w!rd'])
545 func StoreColumn()
546 let g:exprLine = line('.')
547 let g:exprCol = col('.')
548 return 'x'
549 endfunc
550 nnoremap <expr> x StoreColumn()
551 2
552 nmap ! f!<Ignore>x
553 call feedkeys("!", 'xt')
554 call assert_equal('some wrd', getline(2))
555 call assert_equal(2, g:exprLine)
556 call assert_equal(7, g:exprCol)
557
558 bwipe!
559 unlet g:exprLine
560 unlet g:exprCol
Bram Moolenaar6ccfd992021-03-17 13:39:33 +0100561 delfunc StoreColumn
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100562 nunmap x
563 nunmap !
564endfunc
565
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100566func Test_expr_map_restore_cursor()
567 CheckScreendump
568
569 let lines =<< trim END
570 call setline(1, ['one', 'two', 'three'])
571 2
572 set ls=2
573 hi! link StatusLine ErrorMsg
574 noremap <expr> <C-B> Func()
575 func Func()
576 let g:on = !get(g:, 'on', 0)
577 redraws
578 return ''
579 endfunc
580 func Status()
581 return get(g:, 'on', 0) ? '[on]' : ''
582 endfunc
583 set stl=%{Status()}
584 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100585 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100586 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar9f145572022-11-27 12:45:41 +0000587 call term_sendkeys(buf, GetEscCodeWithModifier('C', 'B'))
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100588 call VerifyScreenDump(buf, 'Test_map_expr_1', {})
589
590 " clean up
591 call StopVimInTerminal(buf)
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100592endfunc
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100593
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000594func Test_map_listing()
595 CheckScreendump
596
597 let lines =<< trim END
598 nmap a b
599 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100600 call writefile(lines, 'XtestMapList', 'D')
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000601 let buf = RunVimInTerminal('-S XtestMapList', #{rows: 6})
602 call term_sendkeys(buf, ": nmap a\<CR>")
603 call VerifyScreenDump(buf, 'Test_map_list_1', {})
604
605 " clean up
606 call StopVimInTerminal(buf)
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000607endfunc
608
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000609func Test_expr_map_error()
610 CheckScreendump
611
612 let lines =<< trim END
613 func Func()
614 throw 'test'
615 return ''
616 endfunc
617
618 nnoremap <expr> <F2> Func()
619 cnoremap <expr> <F2> Func()
620
621 call test_override('ui_delay', 10)
622 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100623 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000624 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000625 call term_sendkeys(buf, "\<F2>")
626 call TermWait(buf)
627 call term_sendkeys(buf, "\<CR>")
628 call VerifyScreenDump(buf, 'Test_map_expr_2', {})
629
630 call term_sendkeys(buf, ":abc\<F2>")
631 call VerifyScreenDump(buf, 'Test_map_expr_3', {})
632 call term_sendkeys(buf, "\<Esc>0")
633 call VerifyScreenDump(buf, 'Test_map_expr_4', {})
634
635 " clean up
636 call StopVimInTerminal(buf)
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000637endfunc
638
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100639" Test for mapping errors
640func Test_map_error()
641 call assert_fails('unmap', 'E474:')
642 call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
643 call assert_fails('unmap abc', 'E31:')
644 call assert_fails('unabbr abc', 'E24:')
645 call assert_equal('', maparg(''))
646 call assert_fails('echo maparg("abc", [])', 'E730:')
647
648 " unique map
649 map ,w /[#&!]<CR>
650 call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
651 " unique buffer-local map
652 call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
653 unmap ,w
654
655 " unique abbreviation
656 abbr SP special
657 call assert_fails("abbr <unique> SP special", 'E226:')
658 " unique buffer-local map
659 call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
660 unabbr SP
661
662 call assert_fails('mapclear abc', 'E474:')
663 call assert_fails('abclear abc', 'E474:')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100664 call assert_fails('abbr $xyz abc', 'E474:')
665
666 " space character in an abbreviation
667 call assert_fails('abbr ab<space> ABC', 'E474:')
668
669 " invalid <expr> map
670 map <expr> ,f abc
671 call assert_fails('normal ,f', 'E121:')
672 unmap <expr> ,f
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100673
674 " Recursive use of :normal in a map
675 set maxmapdepth=100
676 map gq :normal gq<CR>
677 call assert_fails('normal gq', 'E192:')
678 unmap gq
679 set maxmapdepth&
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100680endfunc
681
682" Test for <special> key mapping
683func Test_map_special()
684 new
685 let old_cpo = &cpo
686 set cpo+=<
687 imap <F12> Blue
688 call feedkeys("i\<F12>", "x")
689 call assert_equal("<F12>", getline(1))
690 call feedkeys("ddi<F12>", "x")
691 call assert_equal("Blue", getline(1))
692 iunmap <F12>
693 imap <special> <F12> Green
694 call feedkeys("ddi\<F12>", "x")
695 call assert_equal("Green", getline(1))
696 call feedkeys("ddi<F12>", "x")
697 call assert_equal("<F12>", getline(1))
698 iunmap <special> <F12>
699 let &cpo = old_cpo
700 %bwipe!
701endfunc
702
703" Test for hasmapto()
704func Test_hasmapto()
705 call assert_equal(0, hasmapto('/^\k\+ ('))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100706 map ,f /^\k\+ (<CR>
707 call assert_equal(1, hasmapto('/^\k\+ ('))
708 unmap ,f
709
710 " Insert mode mapping
711 call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
712 imap ,f /^\k\+ (<CR>
713 call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
714 iunmap ,f
715
716 " Normal mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100717 call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
718 nmap ,f /^\k\+ (<CR>
719 call assert_equal(1, hasmapto('/^\k\+ ('))
720 call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100721 nunmap ,f
722
723 " Visual and Select mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100724 call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100725 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
726 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
727 vmap ,f /^\k\+ (<CR>
728 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
729 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
730 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
731 vunmap ,f
732
733 " Visual mode mapping
734 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
735 xmap ,f /^\k\+ (<CR>
736 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
737 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
738 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
739 xunmap ,f
740
741 " Select mode mapping
742 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
743 smap ,f /^\k\+ (<CR>
744 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
745 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
746 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
747 sunmap ,f
748
749 " Operator-pending mode mapping
750 call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
751 omap ,f /^\k\+ (<CR>
752 call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
753 ounmap ,f
754
755 " Language mapping
756 call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
757 lmap ,f /^\k\+ (<CR>
758 call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
759 lunmap ,f
760
761 " Cmdline mode mapping
762 call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
763 cmap ,f /^\k\+ (<CR>
764 call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
765 cunmap ,f
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100766
767 call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
768endfunc
769
770" Test for command-line completion of maps
771func Test_mapcomplete()
772 call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
773 \ '<silent>', '<special>', '<unique>'],
774 \ getcompletion('', 'mapping'))
775 call assert_equal([], getcompletion(',d', 'mapping'))
776
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100777 call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
778 call assert_equal('"unmap <buffer>', @:)
779
780 call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
781 call assert_equal('"unabbr <buffer>', @:)
782
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100783 call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100784 call assert_equal("\"abbr! \x01", @:)
785
zeertzjq997b8a02023-02-19 21:00:31 +0000786 " When multiple matches have the same {lhs}, it should only appear once.
787 " The simplified form should also not be included.
788 nmap ,<C-F> /H<CR>
789 omap ,<C-F> /H<CR>
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100790 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
zeertzjq997b8a02023-02-19 21:00:31 +0000791 call assert_equal('"map ,<C-F>', @:)
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100792 mapclear
793endfunc
794
Bram Moolenaar94075b22022-01-18 20:30:39 +0000795func GetAbbrText()
796 unabbr hola
797 return 'hello'
798endfunc
799
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100800" Test for <expr> in abbreviation
801func Test_expr_abbr()
802 new
803 iabbr <expr> teh "the"
804 call feedkeys("iteh ", "tx")
805 call assert_equal('the ', getline(1))
806 iabclear
807 call setline(1, '')
808
809 " invalid <expr> abbreviation
810 abbr <expr> hte GetAbbr()
811 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100812 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100813 unabbr <expr> hte
814
Bram Moolenaar94075b22022-01-18 20:30:39 +0000815 " evaluating the expression deletes the abbreviation
816 abbr <expr> hola GetAbbrText()
817 call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
818 call feedkeys("ahola \<Esc>", 'xt')
819 call assert_equal('hello ', getline('.'))
820 call assert_equal('', maparg('hola', 'i', '1'))
821
822 bwipe!
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100823endfunc
824
825" Test for storing mappings in different modes in a vimrc file
826func Test_mkvimrc_mapmodes()
827 map a1 /a1
828 nmap a2 /a2
829 vmap a3 /a3
830 smap a4 /a4
831 xmap a5 /a5
832 omap a6 /a6
833 map! a7 /a7
834 imap a8 /a8
835 lmap a9 /a9
836 cmap a10 /a10
837 tmap a11 /a11
838 " Normal + Visual map
839 map a12 /a12
840 sunmap a12
841 ounmap a12
842 " Normal + Selectmode map
843 map a13 /a13
844 xunmap a13
845 ounmap a13
846 " Normal + OpPending map
847 map a14 /a14
848 vunmap a14
849 " Visual + Selectmode map
850 map a15 /a15
851 nunmap a15
852 ounmap a15
853 " Visual + OpPending map
854 map a16 /a16
855 nunmap a16
856 sunmap a16
857 " Selectmode + OpPending map
858 map a17 /a17
859 nunmap a17
860 xunmap a17
861 " Normal + Visual + Selectmode map
862 map a18 /a18
863 ounmap a18
864 " Normal + Visual + OpPending map
865 map a19 /a19
866 sunmap a19
867 " Normal + Selectmode + OpPending map
868 map a20 /a20
869 xunmap a20
870 " Visual + Selectmode + OpPending map
871 map a21 /a21
872 nunmap a21
873 " Mapping to Nop
874 map a22 <Nop>
875 " Script local mapping
876 map <script> a23 /a23
877
878 " Newline in {lhs} and {rhs} of a map
879 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
880
881 " Abbreviation
882 abbr a25 A25
883 cabbr a26 A26
884 iabbr a27 A27
885
886 mkvimrc! Xvimrc
887 let l = readfile('Xvimrc')
888 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
889 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
890 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
891 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
892 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
893 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
894 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
895 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
896 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
897 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
898 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
899 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
900 \ filter(copy(l), 'v:val =~ " a12 "'))
901 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
902 \ filter(copy(l), 'v:val =~ " a13 "'))
903 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
904 \ filter(copy(l), 'v:val =~ " a14 "'))
905 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
906 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
907 \ filter(copy(l), 'v:val =~ " a16 "'))
908 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
909 \ filter(copy(l), 'v:val =~ " a17 "'))
910 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
911 \ filter(copy(l), 'v:val =~ " a18 "'))
912 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
913 \ filter(copy(l), 'v:val =~ " a19 "'))
914 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
915 \ filter(copy(l), 'v:val =~ " a20 "'))
916 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
917 \ filter(copy(l), 'v:val =~ " a21 "'))
918 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
919 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
920 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
921 \ filter(copy(l), 'v:val =~ " a24"'))
922
923 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
924 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
925 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
926 call delete('Xvimrc')
927
928 mapclear
929 nmapclear
930 vmapclear
931 xmapclear
932 smapclear
933 omapclear
934 imapclear
935 lmapclear
936 cmapclear
937 tmapclear
938endfunc
939
940" Test for recursive mapping ('maxmapdepth')
941func Test_map_recursive()
942 map x y
943 map y x
944 call assert_fails('normal x', 'E223:')
945 unmap x
946 unmap y
947endfunc
948
949" Test for removing an abbreviation using {rhs} and with space after {lhs}
950func Test_abbr_remove()
951 abbr foo bar
952 let d = maparg('foo', 'i', 1, 1)
953 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
954 unabbr bar
955 call assert_equal({}, maparg('foo', 'i', 1, 1))
956
957 abbr foo bar
958 unabbr foo<space><tab>
959 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100960endfunc
961
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100962" Trigger an abbreviation using a special key
963func Test_abbr_trigger_special()
964 new
965 iabbr teh the
966 call feedkeys("iteh\<F2>\<Esc>", 'xt')
967 call assert_equal('the<F2>', getline(1))
968 iunab teh
969 close!
970endfunc
971
972" Test for '<' in 'cpoptions'
973func Test_map_cpo_special_keycode()
974 set cpo-=<
975 imap x<Bslash>k Test
976 let d = maparg('x<Bslash>k', 'i', 0, 1)
977 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
978 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
979 call assert_equal('"imap x\k', @:)
980 iunmap x<Bslash>k
981 set cpo+=<
982 imap x<Bslash>k Test
983 let d = maparg('x<Bslash>k', 'i', 0, 1)
984 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
985 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
986 call assert_equal('"imap x<Bslash>k', @:)
987 iunmap x<Bslash>k
988 set cpo-=<
989 " Modifying 'cpo' above adds some default mappings, remove them
990 mapclear
991 mapclear!
992endfunc
993
Bram Moolenaar957cf672020-11-12 14:21:06 +0100994" Test for <Cmd> key in maps to execute commands
995func Test_map_cmdkey()
996 new
997
998 " Error cases
999 let x = 0
1000 noremap <F3> <Cmd><Cmd>let x = 1<CR>
1001 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
1002 call assert_equal(0, x)
1003
Bram Moolenaar957cf672020-11-12 14:21:06 +01001004 noremap <F3> <Cmd>let x = 3
Bram Moolenaar806da512021-12-24 19:54:52 +00001005 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001006 call assert_equal(0, x)
1007
1008 " works in various modes and sees the correct mode()
1009 noremap <F3> <Cmd>let m = mode(1)<CR>
1010 noremap! <F3> <Cmd>let m = mode(1)<CR>
1011
1012 " normal mode
1013 call feedkeys("\<F3>", 'xt')
1014 call assert_equal('n', m)
1015
1016 " visual mode
1017 call feedkeys("v\<F3>", 'xt!')
1018 call assert_equal('v', m)
1019 " shouldn't leave the visual mode
1020 call assert_equal('v', mode(1))
1021 call feedkeys("\<Esc>", 'xt')
1022 call assert_equal('n', mode(1))
1023
1024 " visual mapping in select mode
1025 call feedkeys("gh\<F3>", 'xt!')
1026 call assert_equal('v', m)
1027 " shouldn't leave select mode
1028 call assert_equal('s', mode(1))
1029 call feedkeys("\<Esc>", 'xt')
1030 call assert_equal('n', mode(1))
1031
1032 " select mode mapping
1033 snoremap <F3> <Cmd>let m = mode(1)<cr>
1034 call feedkeys("gh\<F3>", 'xt!')
1035 call assert_equal('s', m)
1036 " shouldn't leave select mode
1037 call assert_equal('s', mode(1))
1038 call feedkeys("\<Esc>", 'xt')
1039 call assert_equal('n', mode(1))
1040
1041 " operator-pending mode
1042 call feedkeys("d\<F3>", 'xt!')
1043 call assert_equal('no', m)
1044 " leaves the operator-pending mode
1045 call assert_equal('n', mode(1))
1046
1047 " insert mode
1048 call feedkeys("i\<F3>abc", 'xt')
1049 call assert_equal('i', m)
1050 call assert_equal('abc', getline('.'))
1051
1052 " replace mode
1053 call feedkeys("0R\<F3>two", 'xt')
1054 call assert_equal('R', m)
1055 call assert_equal('two', getline('.'))
1056
1057 " virtual replace mode
1058 call setline('.', "one\ttwo")
1059 call feedkeys("4|gR\<F3>xxx", 'xt')
1060 call assert_equal('Rv', m)
1061 call assert_equal("onexxx\ttwo", getline('.'))
1062
1063 " cmdline mode
1064 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
1065 call assert_equal('c', m)
1066 call assert_equal('"xxx', @:)
1067
1068 " terminal mode
1069 if CanRunVimInTerminal()
1070 tnoremap <F3> <Cmd>let m = mode(1)<CR>
1071 let buf = Run_shell_in_terminal({})
1072 call feedkeys("\<F3>", 'xt')
1073 call assert_equal('t', m)
1074 call assert_equal('t', mode(1))
1075 call StopShellInTerminal(buf)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001076 close!
1077 tunmap <F3>
1078 endif
1079
1080 " invoke cmdline mode recursively
1081 noremap! <F2> <Cmd>norm! :foo<CR>
1082 %d
1083 call setline(1, ['some short lines', 'of test text'])
1084 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
1085 call assert_equal('"barx', @:)
1086 unmap! <F2>
1087
1088 " test for calling a <SID> function
1089 let lines =<< trim END
1090 map <F2> <Cmd>call <SID>do_it()<CR>
1091 func s:do_it()
1092 let g:x = 32
1093 endfunc
1094 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001095 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001096 source Xscript
1097 call feedkeys("\<F2>", 'xt')
1098 call assert_equal(32, g:x)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001099
1100 unmap <F3>
1101 unmap! <F3>
1102 %bw!
1103endfunc
1104
1105" text object enters visual mode
1106func TextObj()
1107 if mode() !=# "v"
1108 normal! v
1109 end
1110 call cursor(1, 3)
1111 normal! o
1112 call cursor(2, 4)
1113endfunc
1114
1115func s:cmdmap(lhs, rhs)
1116 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1117 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1118endfunc
1119
1120func s:cmdunmap(lhs)
1121 exe 'unmap ' .. a:lhs
1122 exe 'unmap! ' .. a:lhs
1123endfunc
1124
1125" Map various <Fx> keys used by the <Cmd> key tests
1126func s:setupMaps()
1127 call s:cmdmap('<F3>', 'let m = mode(1)')
1128 call s:cmdmap('<F4>', 'normal! ww')
1129 call s:cmdmap('<F5>', 'normal! "ay')
1130 call s:cmdmap('<F6>', 'throw "very error"')
1131 call s:cmdmap('<F7>', 'call TextObj()')
1132 call s:cmdmap('<F8>', 'startinsert')
1133 call s:cmdmap('<F9>', 'stopinsert')
1134endfunc
1135
1136" Remove the mappings setup by setupMaps()
1137func s:cleanupMaps()
1138 call s:cmdunmap('<F3>')
1139 call s:cmdunmap('<F4>')
1140 call s:cmdunmap('<F5>')
1141 call s:cmdunmap('<F6>')
1142 call s:cmdunmap('<F7>')
1143 call s:cmdunmap('<F8>')
1144 call s:cmdunmap('<F9>')
1145endfunc
1146
1147" Test for <Cmd> mapping in normal mode
1148func Test_map_cmdkey_normal_mode()
1149 new
1150 call s:setupMaps()
1151
1152 " check v:count and v:register works
1153 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1154 call feedkeys("\<F2>", 'xt')
1155 call assert_equal(['n', 0, '"'], s)
1156 call feedkeys("7\<F2>", 'xt')
1157 call assert_equal(['n', 7, '"'], s)
1158 call feedkeys("\"e\<F2>", 'xt')
1159 call assert_equal(['n', 0, 'e'], s)
1160 call feedkeys("5\"k\<F2>", 'xt')
1161 call assert_equal(['n', 5, 'k'], s)
1162 call s:cmdunmap('<F2>')
1163
1164 call setline(1, ['some short lines', 'of test text'])
1165 call feedkeys("\<F7>y", 'xt')
1166 call assert_equal("me short lines\nof t", @")
1167 call assert_equal('v', getregtype('"'))
1168 call assert_equal([0, 1, 3, 0], getpos("'<"))
1169 call assert_equal([0, 2, 4, 0], getpos("'>"))
1170
1171 " startinsert
1172 %d
1173 call feedkeys("\<F8>abc", 'xt')
1174 call assert_equal('abc', getline(1))
1175
1176 " feedkeys are not executed immediately
1177 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1178 %d
1179 call setline(1, ['some short lines', 'of test text'])
1180 call cursor(2, 3)
1181 call feedkeys(",a\<F3>", 'xt')
1182 call assert_equal('of test text', g:a)
1183 call assert_equal('n', m)
1184 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1185 nunmap ,a
1186
1187 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1188 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1189 call feedkeys(",b\<F3>", 'xt')
1190 call assert_equal('n', m)
1191 call assert_equal('of alphabetatest text', g:b)
1192 nunmap ,b
1193
1194 call s:cleanupMaps()
1195 %bw!
1196endfunc
1197
1198" Test for <Cmd> mapping with the :normal command
1199func Test_map_cmdkey_normal_cmd()
1200 new
1201 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1202 noremap ,f <Cmd>nosuchcommand<CR>
1203 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1204 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1205 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1206
1207 call setline(1, ['some short lines', 'of test text'])
1208 exe "norm ,x\r"
1209 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1210
1211 call assert_fails('norm ,f', 'E492:')
1212 call assert_fails('norm ,e', 'very error')
1213 call assert_fails('norm ,m', 'The message.')
1214 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1215
1216 %d
1217 let caught_err = 0
1218 try
1219 exe "normal ,w"
1220 catch /Vim(echoerr):Err/
1221 let caught_err = 1
1222 endtry
1223 call assert_equal(1, caught_err)
1224 call assert_equal(['', '0'], getline(1, '$'))
1225
1226 %d
1227 call assert_fails('normal ,w', 'Err')
1228 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1229 call assert_equal(1, line('.'))
1230
1231 nunmap ,x
1232 nunmap ,f
1233 nunmap ,e
1234 nunmap ,m
1235 nunmap ,w
1236 %bw!
1237endfunc
1238
1239" Test for <Cmd> mapping in visual mode
1240func Test_map_cmdkey_visual_mode()
1241 new
1242 set showmode
1243 call s:setupMaps()
1244
1245 call setline(1, ['some short lines', 'of test text'])
1246 call feedkeys("v\<F4>", 'xt!')
1247 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1248
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +01001249 " can invoke an operator, ending the visual mode
Bram Moolenaar957cf672020-11-12 14:21:06 +01001250 let @a = ''
1251 call feedkeys("\<F5>", 'xt!')
1252 call assert_equal('n', mode(1))
1253 call assert_equal('some short l', @a)
1254
1255 " error doesn't interrupt visual mode
1256 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1257 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1258 call feedkeys("\<F7>", 'xt!')
1259 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1260
1261 " startinsert gives "-- (insert) VISUAL --" mode
1262 call feedkeys("\<F8>", 'xt!')
1263 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1264 redraw!
1265 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1266 call feedkeys("\<Esc>new ", 'x')
1267 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1268
1269 call s:cleanupMaps()
1270 set showmode&
1271 %bw!
1272endfunc
1273
1274" Test for <Cmd> mapping in select mode
1275func Test_map_cmdkey_select_mode()
1276 new
1277 set showmode
1278 call s:setupMaps()
1279
1280 snoremap <F1> <cmd>throw "very error"<CR>
1281 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1282 call setline(1, ['some short lines', 'of test text'])
1283
1284 call feedkeys("gh\<F4>", "xt!")
1285 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1286 redraw!
1287 call assert_match('^-- SELECT --', Screenline(&lines))
1288
1289 " visual mapping in select mode restarts select mode after operator
1290 let @a = ''
1291 call feedkeys("\<F5>", 'xt!')
1292 call assert_equal('s', mode(1))
1293 call assert_equal('some short l', @a)
1294
1295 " select mode mapping works, and does not restart select mode
1296 let @b = ''
1297 call feedkeys("\<F2>", 'xt!')
1298 call assert_equal('n', mode(1))
1299 call assert_equal('some short l', @b)
1300
1301 " error doesn't interrupt temporary visual mode
1302 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1303 redraw!
1304 call assert_match('^-- VISUAL --', Screenline(&lines))
1305 " quirk: restoration of select mode is not performed
1306 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1307
1308 " error doesn't interrupt select mode
1309 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1310 redraw!
1311 call assert_match('^-- SELECT --', Screenline(&lines))
1312 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1313
1314 call feedkeys("\<F7>", 'xt!')
1315 redraw!
1316 call assert_match('^-- SELECT --', Screenline(&lines))
1317 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1318
1319 " startinsert gives "-- SELECT (insert) --" mode
1320 call feedkeys("\<F8>", 'xt!')
1321 redraw!
1322 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1323 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1324 call feedkeys("\<Esc>new ", 'x')
1325 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1326
1327 sunmap <F1>
1328 sunmap <F2>
1329 call s:cleanupMaps()
1330 set showmode&
1331 %bw!
1332endfunc
1333
1334" Test for <Cmd> mapping in operator-pending mode
1335func Test_map_cmdkey_op_pending_mode()
1336 new
1337 call s:setupMaps()
1338
1339 call setline(1, ['some short lines', 'of test text'])
1340 call feedkeys("d\<F4>", 'xt')
1341 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1342 call assert_equal(['some short '], getreg('"', 1, 1))
1343 " create a new undo point
Christian Brabandt6efb1982023-08-10 05:44:25 +02001344 let &g:undolevels = &g:undolevels
Bram Moolenaar957cf672020-11-12 14:21:06 +01001345
1346 call feedkeys(".", 'xt')
1347 call assert_equal(['test text'], getline(1, '$'))
1348 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1349 " create a new undo point
Christian Brabandt6efb1982023-08-10 05:44:25 +02001350 let &g:undolevels = &g:undolevels
Bram Moolenaar957cf672020-11-12 14:21:06 +01001351
1352 call feedkeys("uu", 'xt')
1353 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1354
1355 " error aborts operator-pending, operator not performed
1356 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1357 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1358
1359 call feedkeys("\"bd\<F7>", 'xt')
1360 call assert_equal(['soest text'], getline(1, '$'))
1361 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1362
1363 " startinsert aborts operator
1364 call feedkeys("d\<F8>cc", 'xt')
1365 call assert_equal(['soccest text'], getline(1, '$'))
1366
1367 call s:cleanupMaps()
1368 %bw!
1369endfunc
1370
1371" Test for <Cmd> mapping in insert mode
1372func Test_map_cmdkey_insert_mode()
1373 new
1374 call s:setupMaps()
1375
1376 call setline(1, ['some short lines', 'of test text'])
1377 " works the same as <C-O>w<C-O>w
1378 call feedkeys("iindeed \<F4>little ", 'xt')
1379 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1380 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1381 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1382
1383 " Note when entering visual mode from InsertEnter autocmd, an async event,
1384 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1385 call feedkeys("i\<F7>stuff ", 'xt')
1386 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1387 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1388
1389 call feedkeys("\<F5>", 'xt')
1390 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1391
1392 " also works as part of abbreviation
1393 abbr foo <Cmd>let g:y = 17<CR>bar
1394 exe "normal i\<space>foo "
1395 call assert_equal(17, g:y)
1396 call assert_equal('in bar deed some short little 2 lines', getline(1))
1397 unabbr foo
1398
1399 " :startinsert does nothing
1400 call setline(1, 'foo bar')
1401 call feedkeys("ggi\<F8>vim", 'xt')
1402 call assert_equal('vimfoo bar', getline(1))
1403
1404 " :stopinsert works
1405 call feedkeys("ggi\<F9>Abc", 'xt')
1406 call assert_equal('vimfoo barbc', getline(1))
1407
1408 call s:cleanupMaps()
1409 %bw!
1410endfunc
1411
1412" Test for <Cmd> mapping in insert-completion mode
1413func Test_map_cmdkey_insert_complete_mode()
1414 new
1415 call s:setupMaps()
1416
1417 call setline(1, 'some short lines')
1418 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1419 call assert_equal('ic', m)
1420 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1421
1422 call s:cleanupMaps()
1423 %bw!
1424endfunc
1425
1426" Test for <Cmd> mapping in cmdline mode
1427func Test_map_cmdkey_cmdline_mode()
1428 new
1429 call s:setupMaps()
1430
1431 call setline(1, ['some short lines', 'of test text'])
1432 let x = 0
1433 call feedkeys(":let x\<F3>= 10\r", 'xt')
1434 call assert_equal('c', m)
1435 call assert_equal(10, x)
1436
1437 " exception doesn't leave cmdline mode
1438 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1439 call assert_equal(20, x)
1440
1441 " move cursor in the buffer from cmdline mode
1442 call feedkeys(":let x\<F4>= 30\r", 'xt')
1443 call assert_equal(30, x)
1444 call assert_equal(12, col('.'))
1445
1446 " :startinsert takes effect after leaving cmdline mode
1447 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1448 call assert_equal(40, x)
1449 call assert_equal('some short new lines', getline(1))
1450
1451 call s:cleanupMaps()
1452 %bw!
1453endfunc
1454
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001455func Test_map_cmdkey_redo()
1456 func SelectDash()
1457 call search('^---\n\zs', 'bcW')
1458 norm! V
1459 call search('\n\ze---$', 'W')
1460 endfunc
1461
1462 let text =<< trim END
1463 ---
1464 aaa
1465 ---
1466 bbb
1467 bbb
1468 ---
1469 ccc
1470 ccc
1471 ccc
1472 ---
1473 END
1474 new Xcmdtext
1475 call setline(1, text)
1476
1477 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1478 call feedkeys('2Gdi-', 'xt')
1479 call assert_equal(['---', '---'], getline(1, 2))
1480 call feedkeys('j.', 'xt')
1481 call assert_equal(['---', '---', '---'], getline(1, 3))
1482 call feedkeys('j.', 'xt')
1483 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1484
1485 bwipe!
1486 call delete('Xcmdtext')
1487 delfunc SelectDash
1488 ounmap i-
zeertzjq3ab3a862023-05-06 16:22:04 +01001489
1490 new
1491 call setline(1, 'aaa bbb ccc ddd')
1492
1493 " command can contain special keys
1494 onoremap ix <Cmd>let g:foo ..= '…'<Bar>normal! <C-Right><CR>
1495 let g:foo = ''
1496 call feedkeys('0dix.', 'xt')
1497 call assert_equal('……', g:foo)
1498 call assert_equal('ccc ddd', getline(1))
1499 unlet g:foo
1500
1501 " command line ending in "0" is handled without errors
1502 onoremap ix <Cmd>eval 0<CR>
1503 call feedkeys('dix.', 'xt')
1504
1505 ounmap ix
1506 bwipe!
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001507endfunc
1508
Bram Moolenaara9725222022-01-16 13:30:33 +00001509func Test_map_script_cmd_restore()
1510 let lines =<< trim END
1511 vim9script
1512 nnoremap <F3> <ScriptCmd>eval 1 + 2<CR>
1513 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001514 call v9.CheckScriptSuccess(lines)
Bram Moolenaara9725222022-01-16 13:30:33 +00001515 call feedkeys("\<F3>:let g:result = 3+4\<CR>", 'xtc')
1516 call assert_equal(7, g:result)
1517
1518 nunmap <F3>
1519 unlet g:result
1520endfunc
1521
Bram Moolenaardc987762022-01-16 15:52:35 +00001522func Test_map_script_cmd_finds_func()
1523 let lines =<< trim END
1524 vim9script
1525 onoremap <F3> <ScriptCmd>Func()<CR>
1526 def Func()
1527 g:func_called = 'yes'
1528 enddef
1529 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001530 call v9.CheckScriptSuccess(lines)
Bram Moolenaardc987762022-01-16 15:52:35 +00001531 call feedkeys("y\<F3>\<Esc>", 'xtc')
1532 call assert_equal('yes', g:func_called)
1533
1534 ounmap <F3>
1535 unlet g:func_called
1536endfunc
1537
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001538func Test_map_script_cmd_survives_unmap()
1539 let lines =<< trim END
1540 vim9script
1541 var n = 123
1542 nnoremap <F4> <ScriptCmd><CR>
1543 autocmd CmdlineEnter * silent! nunmap <F4>
1544 nnoremap <F3> :<ScriptCmd>eval setbufvar(bufnr(), "result", n)<CR>
1545 feedkeys("\<F3>\<CR>", 'xct')
1546 assert_equal(123, b:result)
1547 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001548 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001549
1550 nunmap <F3>
1551 unlet b:result
Bram Moolenaarca34db32022-01-20 11:17:18 +00001552 autocmd! CmdlineEnter
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001553endfunc
1554
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001555func Test_map_script_cmd_redo()
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001556 call mkdir('Xmapcmd', 'R')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001557 let lines =<< trim END
1558 vim9script
1559 import autoload './script.vim'
1560 onoremap <F3> <ScriptCmd>script.Func()<CR>
1561 END
1562 call writefile(lines, 'Xmapcmd/plugin.vim')
1563
1564 let lines =<< trim END
1565 vim9script
1566 export def Func()
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001567 normal! V
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001568 enddef
1569 END
1570 call writefile(lines, 'Xmapcmd/script.vim')
1571 new
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001572 call setline(1, ['one', 'two', 'three', 'four', 'five'])
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001573 nnoremap j j
1574 source Xmapcmd/plugin.vim
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001575 call feedkeys("d\<F3>j.j.", 'xt')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001576 call assert_equal(['two', 'four'], getline(1, '$'))
1577
1578 ounmap <F3>
1579 nunmap j
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001580 bwipe!
1581endfunc
1582
Bram Moolenaar1f448d92021-03-22 19:37:06 +01001583" Test for using <script> with a map to remap characters in rhs
1584func Test_script_local_remap()
1585 new
1586 inoremap <buffer> <SID>xyz mno
1587 inoremap <buffer> <script> abc st<SID>xyzre
1588 normal iabc
1589 call assert_equal('stmnore', getline(1))
1590 bwipe!
1591endfunc
1592
Bram Moolenaar4934ed32021-04-30 19:43:11 +02001593func Test_abbreviate_multi_byte()
1594 new
1595 iabbrev foo bar
1596 call feedkeys("ifoo…\<Esc>", 'xt')
1597 call assert_equal("bar…", getline(1))
1598 iunabbrev foo
1599 bwipe!
1600endfunc
1601
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +02001602" Test for abbreviations with 'latin1' encoding
1603func Test_abbreviate_latin1_encoding()
1604 set encoding=latin1
1605 call assert_fails('abbr ab#$c ABC', 'E474:')
1606 new
1607 iabbr <buffer> #i #include
1608 iabbr <buffer> ## #enddef
1609 exe "normal i#i\<C-]>"
1610 call assert_equal('#include', getline(1))
1611 exe "normal 0Di##\<C-]>"
1612 call assert_equal('#enddef', getline(1))
1613 %bw!
1614 set encoding=utf-8
1615endfunc
1616
Bram Moolenaar1fc34222022-03-03 13:56:24 +00001617" Test for <Plug> always being mapped, even when used with "noremap".
1618func Test_plug_remap()
1619 let g:foo = 0
1620 nnoremap <Plug>(Increase_x) <Cmd>let g:foo += 1<CR>
1621 nmap <F2> <Plug>(Increase_x)
1622 nnoremap <F3> <Plug>(Increase_x)
1623 call feedkeys("\<F2>", 'xt')
1624 call assert_equal(1, g:foo)
1625 call feedkeys("\<F3>", 'xt')
1626 call assert_equal(2, g:foo)
1627 nnoremap x <Nop>
1628 nmap <F4> x<Plug>(Increase_x)x
1629 nnoremap <F5> x<Plug>(Increase_x)x
1630 call setline(1, 'Some text')
1631 normal! gg$
1632 call feedkeys("\<F4>", 'xt')
1633 call assert_equal(3, g:foo)
1634 call assert_equal('Some text', getline(1))
1635 call feedkeys("\<F5>", 'xt')
1636 call assert_equal(4, g:foo)
1637 call assert_equal('Some te', getline(1))
1638 nunmap <Plug>(Increase_x)
1639 nunmap <F2>
1640 nunmap <F3>
1641 nunmap <F4>
1642 nunmap <F5>
1643 unlet g:foo
1644 %bw!
1645endfunc
1646
zeertzjqac92ab72022-04-24 15:58:30 +01001647func Test_mouse_drag_mapped_start_select()
1648 set mouse=a
1649 set selectmode=key,mouse
1650 func ClickExpr()
1651 call test_setmouse(1, 1)
1652 return "\<LeftMouse>"
1653 endfunc
1654 func DragExpr()
1655 call test_setmouse(1, 2)
1656 return "\<LeftDrag>"
1657 endfunc
1658 nnoremap <expr> <F2> ClickExpr()
1659 nmap <expr> <F3> DragExpr()
1660
1661 nnoremap <LeftDrag> <LeftDrag><Cmd><CR>
1662 exe "normal \<F2>\<F3>"
1663 call assert_equal('s', mode())
1664 exe "normal! \<C-\>\<C-N>"
1665
1666 nunmap <LeftDrag>
1667 nunmap <F2>
1668 nunmap <F3>
1669 delfunc ClickExpr
1670 delfunc DragExpr
1671 set selectmode&
1672 set mouse&
1673endfunc
1674
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001675func Test_mouse_drag_statusline()
1676 set laststatus=2
1677 set mouse=a
1678 func ClickExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001679 call test_setmouse(&lines - 1, 1)
1680 return "\<LeftMouse>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001681 endfunc
1682 func DragExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001683 call test_setmouse(&lines - 2, 1)
1684 return "\<LeftDrag>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001685 endfunc
1686 nnoremap <expr> <F2> ClickExpr()
1687 nnoremap <expr> <F3> DragExpr()
1688
1689 " this was causing a crash in win_drag_status_line()
1690 call feedkeys("\<F2>:tabnew\<CR>\<F3>", 'tx')
zeertzjq873f41a2022-11-01 11:44:43 +00001691
1692 nunmap <F2>
1693 nunmap <F3>
1694 delfunc ClickExpr
1695 delfunc DragExpr
1696 set laststatus& mouse&
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001697endfunc
1698
zeertzjq0f68e6c2022-04-05 13:17:01 +01001699" Test for mapping <LeftDrag> in Insert mode
1700func Test_mouse_drag_insert_map()
1701 set mouse=a
1702 func ClickExpr()
1703 call test_setmouse(1, 1)
1704 return "\<LeftMouse>"
1705 endfunc
1706 func DragExpr()
1707 call test_setmouse(1, 2)
1708 return "\<LeftDrag>"
1709 endfunc
1710 inoremap <expr> <F2> ClickExpr()
1711 imap <expr> <F3> DragExpr()
1712
1713 inoremap <LeftDrag> <LeftDrag><Cmd>let g:dragged = 1<CR>
1714 exe "normal i\<F2>\<F3>"
1715 call assert_equal(1, g:dragged)
1716 call assert_equal('v', mode())
1717 exe "normal! \<C-\>\<C-N>"
1718 unlet g:dragged
1719
1720 inoremap <LeftDrag> <LeftDrag><C-\><C-N>
1721 exe "normal i\<F2>\<F3>"
1722 call assert_equal('n', mode())
1723
1724 iunmap <LeftDrag>
1725 iunmap <F2>
1726 iunmap <F3>
1727 delfunc ClickExpr
1728 delfunc DragExpr
1729 set mouse&
1730endfunc
1731
zeertzjqabeb09b2022-04-26 12:29:43 +01001732func Test_unmap_simplifiable()
zeertzjqa4e33322022-04-24 17:07:53 +01001733 map <C-I> foo
1734 map <Tab> bar
1735 call assert_equal('foo', maparg('<C-I>'))
1736 call assert_equal('bar', maparg('<Tab>'))
1737 unmap <C-I>
1738 call assert_equal('', maparg('<C-I>'))
1739 call assert_equal('bar', maparg('<Tab>'))
1740 unmap <Tab>
zeertzjqabeb09b2022-04-26 12:29:43 +01001741
1742 map <C-I> foo
1743 unmap <Tab>
1744 " This should not error
1745 unmap <C-I>
zeertzjqa4e33322022-04-24 17:07:53 +01001746endfunc
1747
zeertzjqdb088872022-05-02 22:53:45 +01001748func Test_expr_map_escape_special()
1749 nnoremap <Cmd>let g:got_ellipsis += 1<CR>
1750 func Func()
1751 return '…'
1752 endfunc
1753 nmap <expr> <F2> Func()
1754 let g:got_ellipsis = 0
1755 call feedkeys("\<F2>", 'xt')
1756 call assert_equal(1, g:got_ellipsis)
1757 delfunc Func
1758 nunmap <F2>
1759 unlet g:got_ellipsis
1760 nunmap
1761endfunc
1762
zeertzjq3760bfd2022-06-06 16:22:46 +01001763" Testing for mapping after an <Nop> mapping is triggered on timeout.
1764" Test for what patch 8.1.0052 fixes.
1765func Test_map_after_timed_out_nop()
1766 CheckRunVimInTerminal
1767
1768 let lines =<< trim END
1769 set timeout timeoutlen=400
1770 inoremap ab TEST
1771 inoremap a <Nop>
1772 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001773 call writefile(lines, 'Xtest_map_after_timed_out_nop', 'D')
zeertzjq3760bfd2022-06-06 16:22:46 +01001774 let buf = RunVimInTerminal('-S Xtest_map_after_timed_out_nop', #{rows: 6})
1775
1776 " Enter Insert mode
1777 call term_sendkeys(buf, 'i')
1778 " Wait for the "a" mapping to timeout
1779 call term_sendkeys(buf, 'a')
1780 call term_wait(buf, 500)
1781 " Send "a" and wait for a period shorter than 'timeoutlen'
1782 call term_sendkeys(buf, 'a')
1783 call term_wait(buf, 100)
1784 " Send "b", should trigger the "ab" mapping
1785 call term_sendkeys(buf, 'b')
1786 call WaitForAssert({-> assert_equal("TEST", term_getline(buf, 1))})
1787
1788 " clean up
1789 call StopVimInTerminal(buf)
zeertzjq3760bfd2022-06-06 16:22:46 +01001790endfunc
1791
Bram Moolenaar27efc622022-07-01 16:35:45 +01001792func Test_using_past_typeahead()
1793 nnoremap :00 0
1794 exe "norm :set \x80\xfb0=0\<CR>"
1795 exe "sil norm :0\x0f\<C-U>\<CR>"
1796
1797 exe "norm :set \x80\xfb0=\<CR>"
1798 nunmap :00
1799endfunc
1800
Bram Moolenaarbf533e42022-11-13 20:43:19 +00001801func Test_mapclear_while_listing()
1802 CheckRunVimInTerminal
1803
1804 let lines =<< trim END
1805 set nocompatible
1806 mapclear
1807 for i in range(1, 999)
1808 exe 'map ' .. 'foo' .. i .. ' bar'
1809 endfor
1810 au CmdlineLeave : call timer_start(0, {-> execute('mapclear')})
1811 END
1812 call writefile(lines, 'Xmapclear', 'D')
1813 let buf = RunVimInTerminal('-S Xmapclear', {'rows': 10})
1814
1815 " this was using freed memory
1816 call term_sendkeys(buf, ":map\<CR>")
1817 call TermWait(buf, 50)
1818 call term_sendkeys(buf, "G")
1819 call TermWait(buf, 50)
1820 call term_sendkeys(buf, "\<CR>")
1821
1822 call StopVimInTerminal(buf)
1823endfunc
1824
Bram Moolenaar27efc622022-07-01 16:35:45 +01001825
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001826" vim: shiftwidth=2 sts=2 expandtab