blob: 4ecdac62dd0983de75594147cafcbb6a557e1ff2 [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 Moolenaar4ebe0e62019-11-22 20:55:40 +0100587 call term_sendkeys(buf, "\<C-B>")
588 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
786 " Multiple matches for a map
787 nmap ,f /H<CR>
788 omap ,f /H<CR>
789 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
790 call assert_equal('"map ,f', @:)
791 mapclear
792endfunc
793
Bram Moolenaar94075b22022-01-18 20:30:39 +0000794func GetAbbrText()
795 unabbr hola
796 return 'hello'
797endfunc
798
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100799" Test for <expr> in abbreviation
800func Test_expr_abbr()
801 new
802 iabbr <expr> teh "the"
803 call feedkeys("iteh ", "tx")
804 call assert_equal('the ', getline(1))
805 iabclear
806 call setline(1, '')
807
808 " invalid <expr> abbreviation
809 abbr <expr> hte GetAbbr()
810 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100811 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100812 unabbr <expr> hte
813
Bram Moolenaar94075b22022-01-18 20:30:39 +0000814 " evaluating the expression deletes the abbreviation
815 abbr <expr> hola GetAbbrText()
816 call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
817 call feedkeys("ahola \<Esc>", 'xt')
818 call assert_equal('hello ', getline('.'))
819 call assert_equal('', maparg('hola', 'i', '1'))
820
821 bwipe!
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100822endfunc
823
824" Test for storing mappings in different modes in a vimrc file
825func Test_mkvimrc_mapmodes()
826 map a1 /a1
827 nmap a2 /a2
828 vmap a3 /a3
829 smap a4 /a4
830 xmap a5 /a5
831 omap a6 /a6
832 map! a7 /a7
833 imap a8 /a8
834 lmap a9 /a9
835 cmap a10 /a10
836 tmap a11 /a11
837 " Normal + Visual map
838 map a12 /a12
839 sunmap a12
840 ounmap a12
841 " Normal + Selectmode map
842 map a13 /a13
843 xunmap a13
844 ounmap a13
845 " Normal + OpPending map
846 map a14 /a14
847 vunmap a14
848 " Visual + Selectmode map
849 map a15 /a15
850 nunmap a15
851 ounmap a15
852 " Visual + OpPending map
853 map a16 /a16
854 nunmap a16
855 sunmap a16
856 " Selectmode + OpPending map
857 map a17 /a17
858 nunmap a17
859 xunmap a17
860 " Normal + Visual + Selectmode map
861 map a18 /a18
862 ounmap a18
863 " Normal + Visual + OpPending map
864 map a19 /a19
865 sunmap a19
866 " Normal + Selectmode + OpPending map
867 map a20 /a20
868 xunmap a20
869 " Visual + Selectmode + OpPending map
870 map a21 /a21
871 nunmap a21
872 " Mapping to Nop
873 map a22 <Nop>
874 " Script local mapping
875 map <script> a23 /a23
876
877 " Newline in {lhs} and {rhs} of a map
878 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
879
880 " Abbreviation
881 abbr a25 A25
882 cabbr a26 A26
883 iabbr a27 A27
884
885 mkvimrc! Xvimrc
886 let l = readfile('Xvimrc')
887 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
888 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
889 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
890 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
891 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
892 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
893 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
894 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
895 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
896 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
897 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
898 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
899 \ filter(copy(l), 'v:val =~ " a12 "'))
900 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
901 \ filter(copy(l), 'v:val =~ " a13 "'))
902 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
903 \ filter(copy(l), 'v:val =~ " a14 "'))
904 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
905 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
906 \ filter(copy(l), 'v:val =~ " a16 "'))
907 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
908 \ filter(copy(l), 'v:val =~ " a17 "'))
909 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
910 \ filter(copy(l), 'v:val =~ " a18 "'))
911 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
912 \ filter(copy(l), 'v:val =~ " a19 "'))
913 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
914 \ filter(copy(l), 'v:val =~ " a20 "'))
915 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
916 \ filter(copy(l), 'v:val =~ " a21 "'))
917 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
918 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
919 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
920 \ filter(copy(l), 'v:val =~ " a24"'))
921
922 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
923 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
924 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
925 call delete('Xvimrc')
926
927 mapclear
928 nmapclear
929 vmapclear
930 xmapclear
931 smapclear
932 omapclear
933 imapclear
934 lmapclear
935 cmapclear
936 tmapclear
937endfunc
938
939" Test for recursive mapping ('maxmapdepth')
940func Test_map_recursive()
941 map x y
942 map y x
943 call assert_fails('normal x', 'E223:')
944 unmap x
945 unmap y
946endfunc
947
948" Test for removing an abbreviation using {rhs} and with space after {lhs}
949func Test_abbr_remove()
950 abbr foo bar
951 let d = maparg('foo', 'i', 1, 1)
952 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
953 unabbr bar
954 call assert_equal({}, maparg('foo', 'i', 1, 1))
955
956 abbr foo bar
957 unabbr foo<space><tab>
958 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100959endfunc
960
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100961" Trigger an abbreviation using a special key
962func Test_abbr_trigger_special()
963 new
964 iabbr teh the
965 call feedkeys("iteh\<F2>\<Esc>", 'xt')
966 call assert_equal('the<F2>', getline(1))
967 iunab teh
968 close!
969endfunc
970
971" Test for '<' in 'cpoptions'
972func Test_map_cpo_special_keycode()
973 set cpo-=<
974 imap x<Bslash>k Test
975 let d = maparg('x<Bslash>k', 'i', 0, 1)
976 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
977 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
978 call assert_equal('"imap x\k', @:)
979 iunmap x<Bslash>k
980 set cpo+=<
981 imap x<Bslash>k Test
982 let d = maparg('x<Bslash>k', 'i', 0, 1)
983 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
984 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
985 call assert_equal('"imap x<Bslash>k', @:)
986 iunmap x<Bslash>k
987 set cpo-=<
988 " Modifying 'cpo' above adds some default mappings, remove them
989 mapclear
990 mapclear!
991endfunc
992
Bram Moolenaar957cf672020-11-12 14:21:06 +0100993" Test for <Cmd> key in maps to execute commands
994func Test_map_cmdkey()
995 new
996
997 " Error cases
998 let x = 0
999 noremap <F3> <Cmd><Cmd>let x = 1<CR>
1000 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
1001 call assert_equal(0, x)
1002
1003 noremap <F3> <Cmd><F3>let x = 2<CR>
1004 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1137:')
1005 call assert_equal(0, x)
1006
1007 noremap <F3> <Cmd>let x = 3
Bram Moolenaar806da512021-12-24 19:54:52 +00001008 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001009 call assert_equal(0, x)
1010
1011 " works in various modes and sees the correct mode()
1012 noremap <F3> <Cmd>let m = mode(1)<CR>
1013 noremap! <F3> <Cmd>let m = mode(1)<CR>
1014
1015 " normal mode
1016 call feedkeys("\<F3>", 'xt')
1017 call assert_equal('n', m)
1018
1019 " visual mode
1020 call feedkeys("v\<F3>", 'xt!')
1021 call assert_equal('v', m)
1022 " shouldn't leave the visual mode
1023 call assert_equal('v', mode(1))
1024 call feedkeys("\<Esc>", 'xt')
1025 call assert_equal('n', mode(1))
1026
1027 " visual mapping in select mode
1028 call feedkeys("gh\<F3>", 'xt!')
1029 call assert_equal('v', m)
1030 " shouldn't leave select mode
1031 call assert_equal('s', mode(1))
1032 call feedkeys("\<Esc>", 'xt')
1033 call assert_equal('n', mode(1))
1034
1035 " select mode mapping
1036 snoremap <F3> <Cmd>let m = mode(1)<cr>
1037 call feedkeys("gh\<F3>", 'xt!')
1038 call assert_equal('s', m)
1039 " shouldn't leave select mode
1040 call assert_equal('s', mode(1))
1041 call feedkeys("\<Esc>", 'xt')
1042 call assert_equal('n', mode(1))
1043
1044 " operator-pending mode
1045 call feedkeys("d\<F3>", 'xt!')
1046 call assert_equal('no', m)
1047 " leaves the operator-pending mode
1048 call assert_equal('n', mode(1))
1049
1050 " insert mode
1051 call feedkeys("i\<F3>abc", 'xt')
1052 call assert_equal('i', m)
1053 call assert_equal('abc', getline('.'))
1054
1055 " replace mode
1056 call feedkeys("0R\<F3>two", 'xt')
1057 call assert_equal('R', m)
1058 call assert_equal('two', getline('.'))
1059
1060 " virtual replace mode
1061 call setline('.', "one\ttwo")
1062 call feedkeys("4|gR\<F3>xxx", 'xt')
1063 call assert_equal('Rv', m)
1064 call assert_equal("onexxx\ttwo", getline('.'))
1065
1066 " cmdline mode
1067 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
1068 call assert_equal('c', m)
1069 call assert_equal('"xxx', @:)
1070
1071 " terminal mode
1072 if CanRunVimInTerminal()
1073 tnoremap <F3> <Cmd>let m = mode(1)<CR>
1074 let buf = Run_shell_in_terminal({})
1075 call feedkeys("\<F3>", 'xt')
1076 call assert_equal('t', m)
1077 call assert_equal('t', mode(1))
1078 call StopShellInTerminal(buf)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001079 close!
1080 tunmap <F3>
1081 endif
1082
1083 " invoke cmdline mode recursively
1084 noremap! <F2> <Cmd>norm! :foo<CR>
1085 %d
1086 call setline(1, ['some short lines', 'of test text'])
1087 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
1088 call assert_equal('"barx', @:)
1089 unmap! <F2>
1090
1091 " test for calling a <SID> function
1092 let lines =<< trim END
1093 map <F2> <Cmd>call <SID>do_it()<CR>
1094 func s:do_it()
1095 let g:x = 32
1096 endfunc
1097 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001098 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001099 source Xscript
1100 call feedkeys("\<F2>", 'xt')
1101 call assert_equal(32, g:x)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001102
1103 unmap <F3>
1104 unmap! <F3>
1105 %bw!
Bram Moolenaar4a441202020-11-28 14:43:26 +01001106
1107 " command line ending in "0" is handled without errors
1108 onoremap ix <cmd>eval 0<cr>
1109 call feedkeys('dix.', 'xt')
1110 ounmap ix
Bram Moolenaar957cf672020-11-12 14:21:06 +01001111endfunc
1112
1113" text object enters visual mode
1114func TextObj()
1115 if mode() !=# "v"
1116 normal! v
1117 end
1118 call cursor(1, 3)
1119 normal! o
1120 call cursor(2, 4)
1121endfunc
1122
1123func s:cmdmap(lhs, rhs)
1124 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1125 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1126endfunc
1127
1128func s:cmdunmap(lhs)
1129 exe 'unmap ' .. a:lhs
1130 exe 'unmap! ' .. a:lhs
1131endfunc
1132
1133" Map various <Fx> keys used by the <Cmd> key tests
1134func s:setupMaps()
1135 call s:cmdmap('<F3>', 'let m = mode(1)')
1136 call s:cmdmap('<F4>', 'normal! ww')
1137 call s:cmdmap('<F5>', 'normal! "ay')
1138 call s:cmdmap('<F6>', 'throw "very error"')
1139 call s:cmdmap('<F7>', 'call TextObj()')
1140 call s:cmdmap('<F8>', 'startinsert')
1141 call s:cmdmap('<F9>', 'stopinsert')
1142endfunc
1143
1144" Remove the mappings setup by setupMaps()
1145func s:cleanupMaps()
1146 call s:cmdunmap('<F3>')
1147 call s:cmdunmap('<F4>')
1148 call s:cmdunmap('<F5>')
1149 call s:cmdunmap('<F6>')
1150 call s:cmdunmap('<F7>')
1151 call s:cmdunmap('<F8>')
1152 call s:cmdunmap('<F9>')
1153endfunc
1154
1155" Test for <Cmd> mapping in normal mode
1156func Test_map_cmdkey_normal_mode()
1157 new
1158 call s:setupMaps()
1159
1160 " check v:count and v:register works
1161 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1162 call feedkeys("\<F2>", 'xt')
1163 call assert_equal(['n', 0, '"'], s)
1164 call feedkeys("7\<F2>", 'xt')
1165 call assert_equal(['n', 7, '"'], s)
1166 call feedkeys("\"e\<F2>", 'xt')
1167 call assert_equal(['n', 0, 'e'], s)
1168 call feedkeys("5\"k\<F2>", 'xt')
1169 call assert_equal(['n', 5, 'k'], s)
1170 call s:cmdunmap('<F2>')
1171
1172 call setline(1, ['some short lines', 'of test text'])
1173 call feedkeys("\<F7>y", 'xt')
1174 call assert_equal("me short lines\nof t", @")
1175 call assert_equal('v', getregtype('"'))
1176 call assert_equal([0, 1, 3, 0], getpos("'<"))
1177 call assert_equal([0, 2, 4, 0], getpos("'>"))
1178
1179 " startinsert
1180 %d
1181 call feedkeys("\<F8>abc", 'xt')
1182 call assert_equal('abc', getline(1))
1183
1184 " feedkeys are not executed immediately
1185 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1186 %d
1187 call setline(1, ['some short lines', 'of test text'])
1188 call cursor(2, 3)
1189 call feedkeys(",a\<F3>", 'xt')
1190 call assert_equal('of test text', g:a)
1191 call assert_equal('n', m)
1192 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1193 nunmap ,a
1194
1195 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1196 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1197 call feedkeys(",b\<F3>", 'xt')
1198 call assert_equal('n', m)
1199 call assert_equal('of alphabetatest text', g:b)
1200 nunmap ,b
1201
1202 call s:cleanupMaps()
1203 %bw!
1204endfunc
1205
1206" Test for <Cmd> mapping with the :normal command
1207func Test_map_cmdkey_normal_cmd()
1208 new
1209 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1210 noremap ,f <Cmd>nosuchcommand<CR>
1211 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1212 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1213 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1214
1215 call setline(1, ['some short lines', 'of test text'])
1216 exe "norm ,x\r"
1217 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1218
1219 call assert_fails('norm ,f', 'E492:')
1220 call assert_fails('norm ,e', 'very error')
1221 call assert_fails('norm ,m', 'The message.')
1222 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1223
1224 %d
1225 let caught_err = 0
1226 try
1227 exe "normal ,w"
1228 catch /Vim(echoerr):Err/
1229 let caught_err = 1
1230 endtry
1231 call assert_equal(1, caught_err)
1232 call assert_equal(['', '0'], getline(1, '$'))
1233
1234 %d
1235 call assert_fails('normal ,w', 'Err')
1236 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1237 call assert_equal(1, line('.'))
1238
1239 nunmap ,x
1240 nunmap ,f
1241 nunmap ,e
1242 nunmap ,m
1243 nunmap ,w
1244 %bw!
1245endfunc
1246
1247" Test for <Cmd> mapping in visual mode
1248func Test_map_cmdkey_visual_mode()
1249 new
1250 set showmode
1251 call s:setupMaps()
1252
1253 call setline(1, ['some short lines', 'of test text'])
1254 call feedkeys("v\<F4>", 'xt!')
1255 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1256
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +01001257 " can invoke an operator, ending the visual mode
Bram Moolenaar957cf672020-11-12 14:21:06 +01001258 let @a = ''
1259 call feedkeys("\<F5>", 'xt!')
1260 call assert_equal('n', mode(1))
1261 call assert_equal('some short l', @a)
1262
1263 " error doesn't interrupt visual mode
1264 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1265 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1266 call feedkeys("\<F7>", 'xt!')
1267 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1268
1269 " startinsert gives "-- (insert) VISUAL --" mode
1270 call feedkeys("\<F8>", 'xt!')
1271 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1272 redraw!
1273 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1274 call feedkeys("\<Esc>new ", 'x')
1275 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1276
1277 call s:cleanupMaps()
1278 set showmode&
1279 %bw!
1280endfunc
1281
1282" Test for <Cmd> mapping in select mode
1283func Test_map_cmdkey_select_mode()
1284 new
1285 set showmode
1286 call s:setupMaps()
1287
1288 snoremap <F1> <cmd>throw "very error"<CR>
1289 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1290 call setline(1, ['some short lines', 'of test text'])
1291
1292 call feedkeys("gh\<F4>", "xt!")
1293 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1294 redraw!
1295 call assert_match('^-- SELECT --', Screenline(&lines))
1296
1297 " visual mapping in select mode restarts select mode after operator
1298 let @a = ''
1299 call feedkeys("\<F5>", 'xt!')
1300 call assert_equal('s', mode(1))
1301 call assert_equal('some short l', @a)
1302
1303 " select mode mapping works, and does not restart select mode
1304 let @b = ''
1305 call feedkeys("\<F2>", 'xt!')
1306 call assert_equal('n', mode(1))
1307 call assert_equal('some short l', @b)
1308
1309 " error doesn't interrupt temporary visual mode
1310 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1311 redraw!
1312 call assert_match('^-- VISUAL --', Screenline(&lines))
1313 " quirk: restoration of select mode is not performed
1314 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1315
1316 " error doesn't interrupt select mode
1317 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1318 redraw!
1319 call assert_match('^-- SELECT --', Screenline(&lines))
1320 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1321
1322 call feedkeys("\<F7>", 'xt!')
1323 redraw!
1324 call assert_match('^-- SELECT --', Screenline(&lines))
1325 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1326
1327 " startinsert gives "-- SELECT (insert) --" mode
1328 call feedkeys("\<F8>", 'xt!')
1329 redraw!
1330 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1331 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1332 call feedkeys("\<Esc>new ", 'x')
1333 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1334
1335 sunmap <F1>
1336 sunmap <F2>
1337 call s:cleanupMaps()
1338 set showmode&
1339 %bw!
1340endfunc
1341
1342" Test for <Cmd> mapping in operator-pending mode
1343func Test_map_cmdkey_op_pending_mode()
1344 new
1345 call s:setupMaps()
1346
1347 call setline(1, ['some short lines', 'of test text'])
1348 call feedkeys("d\<F4>", 'xt')
1349 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1350 call assert_equal(['some short '], getreg('"', 1, 1))
1351 " create a new undo point
1352 let &undolevels = &undolevels
1353
1354 call feedkeys(".", 'xt')
1355 call assert_equal(['test text'], getline(1, '$'))
1356 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1357 " create a new undo point
1358 let &undolevels = &undolevels
1359
1360 call feedkeys("uu", 'xt')
1361 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1362
1363 " error aborts operator-pending, operator not performed
1364 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1365 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1366
1367 call feedkeys("\"bd\<F7>", 'xt')
1368 call assert_equal(['soest text'], getline(1, '$'))
1369 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1370
1371 " startinsert aborts operator
1372 call feedkeys("d\<F8>cc", 'xt')
1373 call assert_equal(['soccest text'], getline(1, '$'))
1374
1375 call s:cleanupMaps()
1376 %bw!
1377endfunc
1378
1379" Test for <Cmd> mapping in insert mode
1380func Test_map_cmdkey_insert_mode()
1381 new
1382 call s:setupMaps()
1383
1384 call setline(1, ['some short lines', 'of test text'])
1385 " works the same as <C-O>w<C-O>w
1386 call feedkeys("iindeed \<F4>little ", 'xt')
1387 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1388 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1389 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1390
1391 " Note when entering visual mode from InsertEnter autocmd, an async event,
1392 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1393 call feedkeys("i\<F7>stuff ", 'xt')
1394 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1395 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1396
1397 call feedkeys("\<F5>", 'xt')
1398 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1399
1400 " also works as part of abbreviation
1401 abbr foo <Cmd>let g:y = 17<CR>bar
1402 exe "normal i\<space>foo "
1403 call assert_equal(17, g:y)
1404 call assert_equal('in bar deed some short little 2 lines', getline(1))
1405 unabbr foo
1406
1407 " :startinsert does nothing
1408 call setline(1, 'foo bar')
1409 call feedkeys("ggi\<F8>vim", 'xt')
1410 call assert_equal('vimfoo bar', getline(1))
1411
1412 " :stopinsert works
1413 call feedkeys("ggi\<F9>Abc", 'xt')
1414 call assert_equal('vimfoo barbc', getline(1))
1415
1416 call s:cleanupMaps()
1417 %bw!
1418endfunc
1419
1420" Test for <Cmd> mapping in insert-completion mode
1421func Test_map_cmdkey_insert_complete_mode()
1422 new
1423 call s:setupMaps()
1424
1425 call setline(1, 'some short lines')
1426 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1427 call assert_equal('ic', m)
1428 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1429
1430 call s:cleanupMaps()
1431 %bw!
1432endfunc
1433
1434" Test for <Cmd> mapping in cmdline mode
1435func Test_map_cmdkey_cmdline_mode()
1436 new
1437 call s:setupMaps()
1438
1439 call setline(1, ['some short lines', 'of test text'])
1440 let x = 0
1441 call feedkeys(":let x\<F3>= 10\r", 'xt')
1442 call assert_equal('c', m)
1443 call assert_equal(10, x)
1444
1445 " exception doesn't leave cmdline mode
1446 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1447 call assert_equal(20, x)
1448
1449 " move cursor in the buffer from cmdline mode
1450 call feedkeys(":let x\<F4>= 30\r", 'xt')
1451 call assert_equal(30, x)
1452 call assert_equal(12, col('.'))
1453
1454 " :startinsert takes effect after leaving cmdline mode
1455 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1456 call assert_equal(40, x)
1457 call assert_equal('some short new lines', getline(1))
1458
1459 call s:cleanupMaps()
1460 %bw!
1461endfunc
1462
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001463func Test_map_cmdkey_redo()
1464 func SelectDash()
1465 call search('^---\n\zs', 'bcW')
1466 norm! V
1467 call search('\n\ze---$', 'W')
1468 endfunc
1469
1470 let text =<< trim END
1471 ---
1472 aaa
1473 ---
1474 bbb
1475 bbb
1476 ---
1477 ccc
1478 ccc
1479 ccc
1480 ---
1481 END
1482 new Xcmdtext
1483 call setline(1, text)
1484
1485 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1486 call feedkeys('2Gdi-', 'xt')
1487 call assert_equal(['---', '---'], getline(1, 2))
1488 call feedkeys('j.', 'xt')
1489 call assert_equal(['---', '---', '---'], getline(1, 3))
1490 call feedkeys('j.', 'xt')
1491 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1492
1493 bwipe!
1494 call delete('Xcmdtext')
1495 delfunc SelectDash
1496 ounmap i-
1497endfunc
1498
Bram Moolenaara9725222022-01-16 13:30:33 +00001499func Test_map_script_cmd_restore()
1500 let lines =<< trim END
1501 vim9script
1502 nnoremap <F3> <ScriptCmd>eval 1 + 2<CR>
1503 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001504 call v9.CheckScriptSuccess(lines)
Bram Moolenaara9725222022-01-16 13:30:33 +00001505 call feedkeys("\<F3>:let g:result = 3+4\<CR>", 'xtc')
1506 call assert_equal(7, g:result)
1507
1508 nunmap <F3>
1509 unlet g:result
1510endfunc
1511
Bram Moolenaardc987762022-01-16 15:52:35 +00001512func Test_map_script_cmd_finds_func()
1513 let lines =<< trim END
1514 vim9script
1515 onoremap <F3> <ScriptCmd>Func()<CR>
1516 def Func()
1517 g:func_called = 'yes'
1518 enddef
1519 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001520 call v9.CheckScriptSuccess(lines)
Bram Moolenaardc987762022-01-16 15:52:35 +00001521 call feedkeys("y\<F3>\<Esc>", 'xtc')
1522 call assert_equal('yes', g:func_called)
1523
1524 ounmap <F3>
1525 unlet g:func_called
1526endfunc
1527
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001528func Test_map_script_cmd_survives_unmap()
1529 let lines =<< trim END
1530 vim9script
1531 var n = 123
1532 nnoremap <F4> <ScriptCmd><CR>
1533 autocmd CmdlineEnter * silent! nunmap <F4>
1534 nnoremap <F3> :<ScriptCmd>eval setbufvar(bufnr(), "result", n)<CR>
1535 feedkeys("\<F3>\<CR>", 'xct')
1536 assert_equal(123, b:result)
1537 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001538 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001539
1540 nunmap <F3>
1541 unlet b:result
Bram Moolenaarca34db32022-01-20 11:17:18 +00001542 autocmd! CmdlineEnter
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001543endfunc
1544
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001545func Test_map_script_cmd_redo()
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001546 call mkdir('Xmapcmd', 'R')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001547 let lines =<< trim END
1548 vim9script
1549 import autoload './script.vim'
1550 onoremap <F3> <ScriptCmd>script.Func()<CR>
1551 END
1552 call writefile(lines, 'Xmapcmd/plugin.vim')
1553
1554 let lines =<< trim END
1555 vim9script
1556 export def Func()
1557 normal! dd
1558 enddef
1559 END
1560 call writefile(lines, 'Xmapcmd/script.vim')
1561 new
1562 call setline(1, ['one', 'two', 'three', 'four'])
1563 nnoremap j j
1564 source Xmapcmd/plugin.vim
1565 call feedkeys("d\<F3>j.", 'xt')
1566 call assert_equal(['two', 'four'], getline(1, '$'))
1567
1568 ounmap <F3>
1569 nunmap j
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001570 bwipe!
1571endfunc
1572
Bram Moolenaar1f448d92021-03-22 19:37:06 +01001573" Test for using <script> with a map to remap characters in rhs
1574func Test_script_local_remap()
1575 new
1576 inoremap <buffer> <SID>xyz mno
1577 inoremap <buffer> <script> abc st<SID>xyzre
1578 normal iabc
1579 call assert_equal('stmnore', getline(1))
1580 bwipe!
1581endfunc
1582
Bram Moolenaar4934ed32021-04-30 19:43:11 +02001583func Test_abbreviate_multi_byte()
1584 new
1585 iabbrev foo bar
1586 call feedkeys("ifoo…\<Esc>", 'xt')
1587 call assert_equal("bar…", getline(1))
1588 iunabbrev foo
1589 bwipe!
1590endfunc
1591
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +02001592" Test for abbreviations with 'latin1' encoding
1593func Test_abbreviate_latin1_encoding()
1594 set encoding=latin1
1595 call assert_fails('abbr ab#$c ABC', 'E474:')
1596 new
1597 iabbr <buffer> #i #include
1598 iabbr <buffer> ## #enddef
1599 exe "normal i#i\<C-]>"
1600 call assert_equal('#include', getline(1))
1601 exe "normal 0Di##\<C-]>"
1602 call assert_equal('#enddef', getline(1))
1603 %bw!
1604 set encoding=utf-8
1605endfunc
1606
Bram Moolenaar1fc34222022-03-03 13:56:24 +00001607" Test for <Plug> always being mapped, even when used with "noremap".
1608func Test_plug_remap()
1609 let g:foo = 0
1610 nnoremap <Plug>(Increase_x) <Cmd>let g:foo += 1<CR>
1611 nmap <F2> <Plug>(Increase_x)
1612 nnoremap <F3> <Plug>(Increase_x)
1613 call feedkeys("\<F2>", 'xt')
1614 call assert_equal(1, g:foo)
1615 call feedkeys("\<F3>", 'xt')
1616 call assert_equal(2, g:foo)
1617 nnoremap x <Nop>
1618 nmap <F4> x<Plug>(Increase_x)x
1619 nnoremap <F5> x<Plug>(Increase_x)x
1620 call setline(1, 'Some text')
1621 normal! gg$
1622 call feedkeys("\<F4>", 'xt')
1623 call assert_equal(3, g:foo)
1624 call assert_equal('Some text', getline(1))
1625 call feedkeys("\<F5>", 'xt')
1626 call assert_equal(4, g:foo)
1627 call assert_equal('Some te', getline(1))
1628 nunmap <Plug>(Increase_x)
1629 nunmap <F2>
1630 nunmap <F3>
1631 nunmap <F4>
1632 nunmap <F5>
1633 unlet g:foo
1634 %bw!
1635endfunc
1636
zeertzjqac92ab72022-04-24 15:58:30 +01001637func Test_mouse_drag_mapped_start_select()
1638 set mouse=a
1639 set selectmode=key,mouse
1640 func ClickExpr()
1641 call test_setmouse(1, 1)
1642 return "\<LeftMouse>"
1643 endfunc
1644 func DragExpr()
1645 call test_setmouse(1, 2)
1646 return "\<LeftDrag>"
1647 endfunc
1648 nnoremap <expr> <F2> ClickExpr()
1649 nmap <expr> <F3> DragExpr()
1650
1651 nnoremap <LeftDrag> <LeftDrag><Cmd><CR>
1652 exe "normal \<F2>\<F3>"
1653 call assert_equal('s', mode())
1654 exe "normal! \<C-\>\<C-N>"
1655
1656 nunmap <LeftDrag>
1657 nunmap <F2>
1658 nunmap <F3>
1659 delfunc ClickExpr
1660 delfunc DragExpr
1661 set selectmode&
1662 set mouse&
1663endfunc
1664
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001665func Test_mouse_drag_statusline()
1666 set laststatus=2
1667 set mouse=a
1668 func ClickExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001669 call test_setmouse(&lines - 1, 1)
1670 return "\<LeftMouse>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001671 endfunc
1672 func DragExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001673 call test_setmouse(&lines - 2, 1)
1674 return "\<LeftDrag>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001675 endfunc
1676 nnoremap <expr> <F2> ClickExpr()
1677 nnoremap <expr> <F3> DragExpr()
1678
1679 " this was causing a crash in win_drag_status_line()
1680 call feedkeys("\<F2>:tabnew\<CR>\<F3>", 'tx')
zeertzjq873f41a2022-11-01 11:44:43 +00001681
1682 nunmap <F2>
1683 nunmap <F3>
1684 delfunc ClickExpr
1685 delfunc DragExpr
1686 set laststatus& mouse&
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001687endfunc
1688
zeertzjq0f68e6c2022-04-05 13:17:01 +01001689" Test for mapping <LeftDrag> in Insert mode
1690func Test_mouse_drag_insert_map()
1691 set mouse=a
1692 func ClickExpr()
1693 call test_setmouse(1, 1)
1694 return "\<LeftMouse>"
1695 endfunc
1696 func DragExpr()
1697 call test_setmouse(1, 2)
1698 return "\<LeftDrag>"
1699 endfunc
1700 inoremap <expr> <F2> ClickExpr()
1701 imap <expr> <F3> DragExpr()
1702
1703 inoremap <LeftDrag> <LeftDrag><Cmd>let g:dragged = 1<CR>
1704 exe "normal i\<F2>\<F3>"
1705 call assert_equal(1, g:dragged)
1706 call assert_equal('v', mode())
1707 exe "normal! \<C-\>\<C-N>"
1708 unlet g:dragged
1709
1710 inoremap <LeftDrag> <LeftDrag><C-\><C-N>
1711 exe "normal i\<F2>\<F3>"
1712 call assert_equal('n', mode())
1713
1714 iunmap <LeftDrag>
1715 iunmap <F2>
1716 iunmap <F3>
1717 delfunc ClickExpr
1718 delfunc DragExpr
1719 set mouse&
1720endfunc
1721
zeertzjqabeb09b2022-04-26 12:29:43 +01001722func Test_unmap_simplifiable()
zeertzjqa4e33322022-04-24 17:07:53 +01001723 map <C-I> foo
1724 map <Tab> bar
1725 call assert_equal('foo', maparg('<C-I>'))
1726 call assert_equal('bar', maparg('<Tab>'))
1727 unmap <C-I>
1728 call assert_equal('', maparg('<C-I>'))
1729 call assert_equal('bar', maparg('<Tab>'))
1730 unmap <Tab>
zeertzjqabeb09b2022-04-26 12:29:43 +01001731
1732 map <C-I> foo
1733 unmap <Tab>
1734 " This should not error
1735 unmap <C-I>
zeertzjqa4e33322022-04-24 17:07:53 +01001736endfunc
1737
zeertzjqdb088872022-05-02 22:53:45 +01001738func Test_expr_map_escape_special()
1739 nnoremap <Cmd>let g:got_ellipsis += 1<CR>
1740 func Func()
1741 return '…'
1742 endfunc
1743 nmap <expr> <F2> Func()
1744 let g:got_ellipsis = 0
1745 call feedkeys("\<F2>", 'xt')
1746 call assert_equal(1, g:got_ellipsis)
1747 delfunc Func
1748 nunmap <F2>
1749 unlet g:got_ellipsis
1750 nunmap
1751endfunc
1752
zeertzjq3760bfd2022-06-06 16:22:46 +01001753" Testing for mapping after an <Nop> mapping is triggered on timeout.
1754" Test for what patch 8.1.0052 fixes.
1755func Test_map_after_timed_out_nop()
1756 CheckRunVimInTerminal
1757
1758 let lines =<< trim END
1759 set timeout timeoutlen=400
1760 inoremap ab TEST
1761 inoremap a <Nop>
1762 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001763 call writefile(lines, 'Xtest_map_after_timed_out_nop', 'D')
zeertzjq3760bfd2022-06-06 16:22:46 +01001764 let buf = RunVimInTerminal('-S Xtest_map_after_timed_out_nop', #{rows: 6})
1765
1766 " Enter Insert mode
1767 call term_sendkeys(buf, 'i')
1768 " Wait for the "a" mapping to timeout
1769 call term_sendkeys(buf, 'a')
1770 call term_wait(buf, 500)
1771 " Send "a" and wait for a period shorter than 'timeoutlen'
1772 call term_sendkeys(buf, 'a')
1773 call term_wait(buf, 100)
1774 " Send "b", should trigger the "ab" mapping
1775 call term_sendkeys(buf, 'b')
1776 call WaitForAssert({-> assert_equal("TEST", term_getline(buf, 1))})
1777
1778 " clean up
1779 call StopVimInTerminal(buf)
zeertzjq3760bfd2022-06-06 16:22:46 +01001780endfunc
1781
Bram Moolenaar27efc622022-07-01 16:35:45 +01001782func Test_using_past_typeahead()
1783 nnoremap :00 0
1784 exe "norm :set \x80\xfb0=0\<CR>"
1785 exe "sil norm :0\x0f\<C-U>\<CR>"
1786
1787 exe "norm :set \x80\xfb0=\<CR>"
1788 nunmap :00
1789endfunc
1790
Bram Moolenaarbf533e42022-11-13 20:43:19 +00001791func Test_mapclear_while_listing()
1792 CheckRunVimInTerminal
1793
1794 let lines =<< trim END
1795 set nocompatible
1796 mapclear
1797 for i in range(1, 999)
1798 exe 'map ' .. 'foo' .. i .. ' bar'
1799 endfor
1800 au CmdlineLeave : call timer_start(0, {-> execute('mapclear')})
1801 END
1802 call writefile(lines, 'Xmapclear', 'D')
1803 let buf = RunVimInTerminal('-S Xmapclear', {'rows': 10})
1804
1805 " this was using freed memory
1806 call term_sendkeys(buf, ":map\<CR>")
1807 call TermWait(buf, 50)
1808 call term_sendkeys(buf, "G")
1809 call TermWait(buf, 50)
1810 call term_sendkeys(buf, "\<CR>")
1811
1812 call StopVimInTerminal(buf)
1813endfunc
1814
Bram Moolenaar27efc622022-07-01 16:35:45 +01001815
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001816" vim: shiftwidth=2 sts=2 expandtab