blob: 064f8ac25b72c3af3c5838927255f51a4cb158c4 [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
zeertzjqe7102202024-02-13 20:32:04 +0100123 " 'langnoremap' follows 'langremap' and vice versa
Bram Moolenaar920694c2016-08-21 17:45:02 +0200124 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
Casey Tucker92e90a12024-01-25 22:44:00 +0100250func Test_map_super_quotes()
zeertzjq6b13e3d2024-04-22 21:04:29 +0200251 if "\<D-j>"[-1:] == '>'
252 throw 'Skipped: <D- modifier not supported'
Casey Tucker92e90a12024-01-25 22:44:00 +0100253 endif
zeertzjq6b13e3d2024-04-22 21:04:29 +0200254
255 imap <D-"> foo
256 call feedkeys("Go-\<*D-\">-\<Esc>", "xt")
257 call assert_equal("-foo-", getline('$'))
258 set nomodified
259 iunmap <D-">
Casey Tucker92e90a12024-01-25 22:44:00 +0100260endfunc
261
262func Test_map_super_multibyte()
zeertzjq6b13e3d2024-04-22 21:04:29 +0200263 if "\<D-j>"[-1:] == '>'
264 throw 'Skipped: <D- modifier not supported'
Casey Tucker92e90a12024-01-25 22:44:00 +0100265 endif
zeertzjq6b13e3d2024-04-22 21:04:29 +0200266
267 imap <D-á> foo
268 call assert_match('i <D-á>\s*foo', execute('imap'))
269 iunmap <D-á>
Casey Tucker92e90a12024-01-25 22:44:00 +0100270endfunc
271
Bram Moolenaar878c2632017-04-01 15:15:52 +0200272func Test_abbr_after_line_join()
273 new
274 abbr foo bar
275 set backspace=indent,eol,start
276 exe "normal o\<BS>foo "
277 call assert_equal("bar ", getline(1))
278 bwipe!
279 unabbr foo
280 set backspace&
281endfunc
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200282
283func Test_map_timeout()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200284 CheckFeature timers
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200285 nnoremap aaaa :let got_aaaa = 1<CR>
286 nnoremap bb :let got_bb = 1<CR>
287 nmap b aaa
288 new
289 func ExitInsert(timer)
290 let g:line = getline(1)
291 call feedkeys("\<Esc>", "t")
292 endfunc
293 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100294 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200295 " After the 'b' Vim waits for another character to see if it matches 'bb'.
296 " When it times out it is expanded to "aaa", but there is no wait for
297 " "aaaa". Can't check that reliably though.
298 call feedkeys("b", "xt!")
299 call assert_equal("aa", g:line)
300 call assert_false(exists('got_aaa'))
301 call assert_false(exists('got_bb'))
302
303 bwipe!
304 nunmap aaaa
305 nunmap bb
306 nunmap b
307 set timeoutlen&
308 delfunc ExitInsert
Bram Moolenaar26d98212019-01-27 22:32:55 +0100309 call timer_stop(timer)
310endfunc
311
312func Test_map_timeout_with_timer_interrupt()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200313 CheckFeature job
314 CheckFeature timers
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100315 let g:test_is_flaky = 1
Bram Moolenaar26d98212019-01-27 22:32:55 +0100316
317 " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
318 " sequence.
319 new
320 let g:val = 0
321 nnoremap \12 :let g:val = 1<CR>
322 nnoremap \123 :let g:val = 2<CR>
Bram Moolenaarea94c852019-08-16 21:47:27 +0200323 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100324
325 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100326 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100327 endfunc
328
329 call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
330 call feedkeys('\12', 'xt!')
331 call assert_equal(2, g:val)
332
333 bwipe!
334 nunmap \12
335 nunmap \123
336 set timeoutlen&
337 call WaitFor({-> exists('g:timer')})
338 call timer_stop(g:timer)
339 unlet g:timer
340 unlet g:val
341 delfunc ExitCb
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200342endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200343
344func Test_abbreviation_CR()
345 new
346 func Eatchar(pat)
347 let c = nr2char(getchar(0))
348 return (c =~ a:pat) ? '' : c
349 endfunc
350 iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
351 call feedkeys("GA~~7 \<esc>", 'xt')
352 call assert_equal('~~~~~~~', getline('$'))
353 %d
354 call feedkeys("GA~~7\<cr>\<esc>", 'xt')
355 call assert_equal(['~~~~~~~', ''], getline(1,'$'))
356 delfunc Eatchar
357 bw!
358endfunc
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200359
360func Test_cabbr_visual_mode()
361 cabbr s su
362 call feedkeys(":s \<c-B>\"\<CR>", 'itx')
363 call assert_equal('"su ', getreg(':'))
364 call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
365 let expected = '"'. "'<,'>su "
366 call assert_equal(expected, getreg(':'))
367 call feedkeys(": '<,'>s \<c-B>\"\<CR>", 'itx')
368 let expected = '" '. "'<,'>su "
369 call assert_equal(expected, getreg(':'))
370 call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
371 let expected = '"'. "'a,'bsu "
372 call assert_equal(expected, getreg(':'))
373 cunabbr s
374endfunc
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100375
376func Test_motionforce_omap()
377 func GetCommand()
378 let g:m=mode(1)
379 let [g:lnum1, g:col1] = searchpos('-', 'Wb')
380 if g:lnum1 == 0
381 return "\<Esc>"
382 endif
383 let [g:lnum2, g:col2] = searchpos('-', 'W')
384 if g:lnum2 == 0
385 return "\<Esc>"
386 endif
387 return ":call Select()\<CR>"
388 endfunc
389 func Select()
390 call cursor([g:lnum1, g:col1])
391 exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
392 call cursor([g:lnum2, g:col2])
393 execute "normal! \<BS>"
394 endfunc
395 new
396 onoremap <buffer><expr> i- GetCommand()
397 " 1) default omap mapping
398 %d_
399 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
400 call cursor(2, 1)
401 norm di-
402 call assert_equal('no', g:m)
403 call assert_equal(['aaa -- eee'], getline(1, '$'))
404 " 2) forced characterwise operation
405 %d_
406 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
407 call cursor(2, 1)
408 norm dvi-
409 call assert_equal('nov', g:m)
410 call assert_equal(['aaa -- eee'], getline(1, '$'))
411 " 3) forced linewise operation
412 %d_
413 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
414 call cursor(2, 1)
415 norm dVi-
416 call assert_equal('noV', g:m)
417 call assert_equal([''], getline(1, '$'))
418 " 4) forced blockwise operation
419 %d_
420 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
421 call cursor(2, 1)
422 exe "norm d\<C-V>i-"
423 call assert_equal("no\<C-V>", g:m)
424 call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
425 bwipe!
426 delfunc Select
427 delfunc GetCommand
428endfunc
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200429
430func Test_error_in_map_expr()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200431 " Unlike CheckRunVimInTerminal this does work in a win32 console
432 CheckFeature terminal
433 if has('win32') && has('gui_running')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200434 throw 'Skipped: cannot run Vim in a terminal window'
435 endif
436
437 let lines =<< trim [CODE]
438 func Func()
439 " fail to create list
440 let x = [
441 endfunc
442 nmap <expr> ! Func()
443 set updatetime=50
444 [CODE]
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100445 call writefile(lines, 'Xtest.vim', 'D')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200446
Bram Moolenaar0d702022019-07-04 14:20:41 +0200447 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200448 let job = term_getjob(buf)
449 call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
450
451 " GC must not run during map-expr processing, which can make Vim crash.
452 call term_sendkeys(buf, '!')
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200453 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200454 call term_sendkeys(buf, "\<CR>")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200455 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200456 call assert_equal('run', job_status(job))
457
458 call term_sendkeys(buf, ":qall!\<CR>")
459 call WaitFor({-> job_status(job) ==# 'dead'})
460 if has('unix')
461 call assert_equal('', job_info(job).termsig)
462 endif
463
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200464 exe buf .. 'bwipe!'
465endfunc
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200466
467func Test_list_mappings()
Bram Moolenaar2559a472019-10-16 23:33:12 +0200468 " Remove default mappings
469 imapclear
Bram Moolenaar4f2f61a2019-10-16 22:27:49 +0200470
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200471 " reset 'isident' to check it isn't used
472 set isident=
473 inoremap <C-m> CtrlM
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200474 inoremap <A-S> AltS
475 inoremap <S-/> ShiftSlash
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200476 set isident&
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200477 call assert_equal([
478 \ 'i <S-/> * ShiftSlash',
479 \ 'i <M-S> * AltS',
480 \ 'i <C-M> * CtrlM',
481 \], execute('imap')->trim()->split("\n"))
482 iunmap <C-M>
483 iunmap <A-S>
484 call assert_equal(['i <S-/> * ShiftSlash'], execute('imap')->trim()->split("\n"))
485 iunmap <S-/>
486 call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100487
488 " List global, buffer local and script local mappings
489 nmap ,f /^\k\+ (<CR>
490 nmap <buffer> ,f /^\k\+ (<CR>
491 nmap <script> ,fs /^\k\+ (<CR>
492 call assert_equal(['n ,f @/^\k\+ (<CR>',
493 \ 'n ,fs & /^\k\+ (<CR>',
494 \ 'n ,f /^\k\+ (<CR>'],
495 \ execute('nmap ,f')->trim()->split("\n"))
496
497 " List <Nop> mapping
498 nmap ,n <Nop>
499 call assert_equal(['n ,n <Nop>'],
500 \ execute('nmap ,n')->trim()->split("\n"))
501
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100502 " verbose map
Bram Moolenaar060b8382022-10-19 14:48:14 +0100503 let lines = execute('verbose map ,n')->trim()->split("\n")
Bram Moolenaarc255b782022-11-26 19:16:48 +0000504
505 " Remove "Seen modifyOtherKeys" and other optional info.
506 if lines[0] =~ 'Seen modifyOtherKeys'
507 call remove(lines, 0)
508 endif
509 if lines[0] =~ 'modifyOtherKeys detected:'
510 call remove(lines, 0)
511 endif
512 if lines[0] =~ 'Kitty keyboard protocol:'
513 call remove(lines, 0)
514 endif
515 if lines[0] == ''
516 call remove(lines, 0)
517 endif
518
Bram Moolenaar060b8382022-10-19 14:48:14 +0100519 let index = indexof(lines, 'v:val =~ "Last set"')
Bram Moolenaarc255b782022-11-26 19:16:48 +0000520 call assert_equal(1, index)
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100521 call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
Bram Moolenaar060b8382022-10-19 14:48:14 +0100522 \ lines[index])
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100523
zeertzjqac402f42022-05-04 18:51:43 +0100524 " character with K_SPECIAL byte in rhs
525 nmap foo …
526 call assert_equal(['n foo …'],
527 \ execute('nmap foo')->trim()->split("\n"))
528
529 " modified character with K_SPECIAL byte in rhs
530 nmap foo <M-…>
531 call assert_equal(['n foo <M-…>'],
532 \ execute('nmap foo')->trim()->split("\n"))
533
534 " character with K_SPECIAL byte in lhs
535 nmap … foo
536 call assert_equal(['n … foo'],
537 \ execute('nmap …')->trim()->split("\n"))
538
539 " modified character with K_SPECIAL byte in lhs
540 nmap <M-…> foo
541 call assert_equal(['n <M-…> foo'],
542 \ execute('nmap <M-…>')->trim()->split("\n"))
543
zeertzjq0519ce02022-05-09 12:16:19 +0100544 " illegal bytes
545 let str = ":\x7f:\x80:\x90:\xd0:"
546 exe 'nmap foo ' .. str
547 call assert_equal(['n foo ' .. strtrans(str)],
548 \ execute('nmap foo')->trim()->split("\n"))
549 unlet str
550
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100551 " map to CTRL-V
552 exe "nmap ,k \<C-V>"
553 call assert_equal(['n ,k <Nop>'],
554 \ execute('nmap ,k')->trim()->split("\n"))
555
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +0200556 " map with space at the beginning
557 exe "nmap \<C-V> w <Nop>"
558 call assert_equal(['n <Space>w <Nop>'],
559 \ execute("nmap \<C-V> w")->trim()->split("\n"))
560
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100561 nmapclear
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200562endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100563
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100564func Test_expr_map_gets_cursor()
565 new
566 call setline(1, ['one', 'some w!rd'])
567 func StoreColumn()
568 let g:exprLine = line('.')
569 let g:exprCol = col('.')
570 return 'x'
571 endfunc
572 nnoremap <expr> x StoreColumn()
573 2
574 nmap ! f!<Ignore>x
575 call feedkeys("!", 'xt')
576 call assert_equal('some wrd', getline(2))
577 call assert_equal(2, g:exprLine)
578 call assert_equal(7, g:exprCol)
579
580 bwipe!
581 unlet g:exprLine
582 unlet g:exprCol
Bram Moolenaar6ccfd992021-03-17 13:39:33 +0100583 delfunc StoreColumn
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100584 nunmap x
585 nunmap !
586endfunc
587
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100588func Test_expr_map_restore_cursor()
589 CheckScreendump
590
591 let lines =<< trim END
592 call setline(1, ['one', 'two', 'three'])
593 2
594 set ls=2
595 hi! link StatusLine ErrorMsg
596 noremap <expr> <C-B> Func()
597 func Func()
598 let g:on = !get(g:, 'on', 0)
599 redraws
600 return ''
601 endfunc
602 func Status()
603 return get(g:, 'on', 0) ? '[on]' : ''
604 endfunc
605 set stl=%{Status()}
606 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100607 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100608 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar9f145572022-11-27 12:45:41 +0000609 call term_sendkeys(buf, GetEscCodeWithModifier('C', 'B'))
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100610 call VerifyScreenDump(buf, 'Test_map_expr_1', {})
611
612 " clean up
613 call StopVimInTerminal(buf)
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100614endfunc
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100615
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000616func Test_map_listing()
617 CheckScreendump
618
619 let lines =<< trim END
620 nmap a b
621 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100622 call writefile(lines, 'XtestMapList', 'D')
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000623 let buf = RunVimInTerminal('-S XtestMapList', #{rows: 6})
624 call term_sendkeys(buf, ": nmap a\<CR>")
625 call VerifyScreenDump(buf, 'Test_map_list_1', {})
626
627 " clean up
628 call StopVimInTerminal(buf)
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000629endfunc
630
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000631func Test_expr_map_error()
632 CheckScreendump
633
634 let lines =<< trim END
635 func Func()
636 throw 'test'
637 return ''
638 endfunc
639
640 nnoremap <expr> <F2> Func()
641 cnoremap <expr> <F2> Func()
642
643 call test_override('ui_delay', 10)
644 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100645 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000646 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000647 call term_sendkeys(buf, "\<F2>")
648 call TermWait(buf)
649 call term_sendkeys(buf, "\<CR>")
650 call VerifyScreenDump(buf, 'Test_map_expr_2', {})
651
652 call term_sendkeys(buf, ":abc\<F2>")
653 call VerifyScreenDump(buf, 'Test_map_expr_3', {})
654 call term_sendkeys(buf, "\<Esc>0")
655 call VerifyScreenDump(buf, 'Test_map_expr_4', {})
656
657 " clean up
658 call StopVimInTerminal(buf)
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000659endfunc
660
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100661" Test for mapping errors
662func Test_map_error()
663 call assert_fails('unmap', 'E474:')
664 call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
665 call assert_fails('unmap abc', 'E31:')
666 call assert_fails('unabbr abc', 'E24:')
667 call assert_equal('', maparg(''))
668 call assert_fails('echo maparg("abc", [])', 'E730:')
669
670 " unique map
671 map ,w /[#&!]<CR>
672 call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
673 " unique buffer-local map
674 call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
675 unmap ,w
676
677 " unique abbreviation
678 abbr SP special
679 call assert_fails("abbr <unique> SP special", 'E226:')
680 " unique buffer-local map
681 call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
682 unabbr SP
683
684 call assert_fails('mapclear abc', 'E474:')
685 call assert_fails('abclear abc', 'E474:')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100686 call assert_fails('abbr $xyz abc', 'E474:')
687
688 " space character in an abbreviation
689 call assert_fails('abbr ab<space> ABC', 'E474:')
690
691 " invalid <expr> map
692 map <expr> ,f abc
693 call assert_fails('normal ,f', 'E121:')
694 unmap <expr> ,f
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100695
696 " Recursive use of :normal in a map
697 set maxmapdepth=100
698 map gq :normal gq<CR>
699 call assert_fails('normal gq', 'E192:')
700 unmap gq
701 set maxmapdepth&
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100702endfunc
703
704" Test for <special> key mapping
705func Test_map_special()
706 new
707 let old_cpo = &cpo
708 set cpo+=<
709 imap <F12> Blue
710 call feedkeys("i\<F12>", "x")
711 call assert_equal("<F12>", getline(1))
712 call feedkeys("ddi<F12>", "x")
713 call assert_equal("Blue", getline(1))
714 iunmap <F12>
715 imap <special> <F12> Green
716 call feedkeys("ddi\<F12>", "x")
717 call assert_equal("Green", getline(1))
718 call feedkeys("ddi<F12>", "x")
719 call assert_equal("<F12>", getline(1))
720 iunmap <special> <F12>
721 let &cpo = old_cpo
722 %bwipe!
723endfunc
724
725" Test for hasmapto()
726func Test_hasmapto()
727 call assert_equal(0, hasmapto('/^\k\+ ('))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100728 map ,f /^\k\+ (<CR>
729 call assert_equal(1, hasmapto('/^\k\+ ('))
730 unmap ,f
731
732 " Insert mode mapping
733 call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
734 imap ,f /^\k\+ (<CR>
735 call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
736 iunmap ,f
737
738 " Normal mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100739 call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
740 nmap ,f /^\k\+ (<CR>
741 call assert_equal(1, hasmapto('/^\k\+ ('))
742 call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100743 nunmap ,f
744
745 " Visual and Select mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100746 call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100747 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
748 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
749 vmap ,f /^\k\+ (<CR>
750 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
751 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
752 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
753 vunmap ,f
754
755 " Visual mode mapping
756 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
757 xmap ,f /^\k\+ (<CR>
758 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
759 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
760 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
761 xunmap ,f
762
763 " Select mode mapping
764 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
765 smap ,f /^\k\+ (<CR>
766 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
767 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
768 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
769 sunmap ,f
770
771 " Operator-pending mode mapping
772 call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
773 omap ,f /^\k\+ (<CR>
774 call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
775 ounmap ,f
776
777 " Language mapping
778 call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
779 lmap ,f /^\k\+ (<CR>
780 call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
781 lunmap ,f
782
783 " Cmdline mode mapping
784 call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
785 cmap ,f /^\k\+ (<CR>
786 call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
787 cunmap ,f
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100788
789 call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
790endfunc
791
792" Test for command-line completion of maps
793func Test_mapcomplete()
794 call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
795 \ '<silent>', '<special>', '<unique>'],
796 \ getcompletion('', 'mapping'))
797 call assert_equal([], getcompletion(',d', 'mapping'))
798
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100799 call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
800 call assert_equal('"unmap <buffer>', @:)
801
802 call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
803 call assert_equal('"unabbr <buffer>', @:)
804
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100805 call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100806 call assert_equal("\"abbr! \x01", @:)
807
zeertzjq997b8a02023-02-19 21:00:31 +0000808 " When multiple matches have the same {lhs}, it should only appear once.
809 " The simplified form should also not be included.
810 nmap ,<C-F> /H<CR>
811 omap ,<C-F> /H<CR>
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100812 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
zeertzjq997b8a02023-02-19 21:00:31 +0000813 call assert_equal('"map ,<C-F>', @:)
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100814 mapclear
815endfunc
816
Bram Moolenaar94075b22022-01-18 20:30:39 +0000817func GetAbbrText()
818 unabbr hola
819 return 'hello'
820endfunc
821
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100822" Test for <expr> in abbreviation
823func Test_expr_abbr()
824 new
825 iabbr <expr> teh "the"
826 call feedkeys("iteh ", "tx")
827 call assert_equal('the ', getline(1))
828 iabclear
829 call setline(1, '')
830
831 " invalid <expr> abbreviation
832 abbr <expr> hte GetAbbr()
833 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100834 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100835 unabbr <expr> hte
836
Bram Moolenaar94075b22022-01-18 20:30:39 +0000837 " evaluating the expression deletes the abbreviation
838 abbr <expr> hola GetAbbrText()
839 call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
840 call feedkeys("ahola \<Esc>", 'xt')
841 call assert_equal('hello ', getline('.'))
842 call assert_equal('', maparg('hola', 'i', '1'))
843
844 bwipe!
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100845endfunc
846
847" Test for storing mappings in different modes in a vimrc file
848func Test_mkvimrc_mapmodes()
849 map a1 /a1
850 nmap a2 /a2
851 vmap a3 /a3
852 smap a4 /a4
853 xmap a5 /a5
854 omap a6 /a6
855 map! a7 /a7
856 imap a8 /a8
857 lmap a9 /a9
858 cmap a10 /a10
859 tmap a11 /a11
860 " Normal + Visual map
861 map a12 /a12
862 sunmap a12
863 ounmap a12
864 " Normal + Selectmode map
865 map a13 /a13
866 xunmap a13
867 ounmap a13
868 " Normal + OpPending map
869 map a14 /a14
870 vunmap a14
871 " Visual + Selectmode map
872 map a15 /a15
873 nunmap a15
874 ounmap a15
875 " Visual + OpPending map
876 map a16 /a16
877 nunmap a16
878 sunmap a16
879 " Selectmode + OpPending map
880 map a17 /a17
881 nunmap a17
882 xunmap a17
883 " Normal + Visual + Selectmode map
884 map a18 /a18
885 ounmap a18
886 " Normal + Visual + OpPending map
887 map a19 /a19
888 sunmap a19
889 " Normal + Selectmode + OpPending map
890 map a20 /a20
891 xunmap a20
892 " Visual + Selectmode + OpPending map
893 map a21 /a21
894 nunmap a21
895 " Mapping to Nop
896 map a22 <Nop>
897 " Script local mapping
898 map <script> a23 /a23
899
900 " Newline in {lhs} and {rhs} of a map
901 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
902
903 " Abbreviation
904 abbr a25 A25
905 cabbr a26 A26
906 iabbr a27 A27
907
908 mkvimrc! Xvimrc
909 let l = readfile('Xvimrc')
910 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
911 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
912 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
913 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
914 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
915 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
916 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
917 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
918 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
919 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
920 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
921 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
922 \ filter(copy(l), 'v:val =~ " a12 "'))
923 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
924 \ filter(copy(l), 'v:val =~ " a13 "'))
925 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
926 \ filter(copy(l), 'v:val =~ " a14 "'))
927 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
928 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
929 \ filter(copy(l), 'v:val =~ " a16 "'))
930 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
931 \ filter(copy(l), 'v:val =~ " a17 "'))
932 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
933 \ filter(copy(l), 'v:val =~ " a18 "'))
934 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
935 \ filter(copy(l), 'v:val =~ " a19 "'))
936 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
937 \ filter(copy(l), 'v:val =~ " a20 "'))
938 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
939 \ filter(copy(l), 'v:val =~ " a21 "'))
940 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
941 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
942 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
943 \ filter(copy(l), 'v:val =~ " a24"'))
944
945 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
946 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
947 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
948 call delete('Xvimrc')
949
950 mapclear
951 nmapclear
952 vmapclear
953 xmapclear
954 smapclear
955 omapclear
956 imapclear
957 lmapclear
958 cmapclear
959 tmapclear
960endfunc
961
962" Test for recursive mapping ('maxmapdepth')
963func Test_map_recursive()
964 map x y
965 map y x
966 call assert_fails('normal x', 'E223:')
967 unmap x
968 unmap y
969endfunc
970
971" Test for removing an abbreviation using {rhs} and with space after {lhs}
972func Test_abbr_remove()
973 abbr foo bar
974 let d = maparg('foo', 'i', 1, 1)
975 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
976 unabbr bar
977 call assert_equal({}, maparg('foo', 'i', 1, 1))
978
979 abbr foo bar
980 unabbr foo<space><tab>
981 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100982endfunc
983
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100984" Trigger an abbreviation using a special key
985func Test_abbr_trigger_special()
986 new
987 iabbr teh the
988 call feedkeys("iteh\<F2>\<Esc>", 'xt')
989 call assert_equal('the<F2>', getline(1))
990 iunab teh
991 close!
992endfunc
993
994" Test for '<' in 'cpoptions'
995func Test_map_cpo_special_keycode()
996 set cpo-=<
997 imap x<Bslash>k Test
998 let d = maparg('x<Bslash>k', 'i', 0, 1)
999 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
1000 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
1001 call assert_equal('"imap x\k', @:)
1002 iunmap x<Bslash>k
1003 set cpo+=<
1004 imap x<Bslash>k Test
1005 let d = maparg('x<Bslash>k', 'i', 0, 1)
1006 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
1007 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
1008 call assert_equal('"imap x<Bslash>k', @:)
1009 iunmap x<Bslash>k
1010 set cpo-=<
1011 " Modifying 'cpo' above adds some default mappings, remove them
1012 mapclear
1013 mapclear!
1014endfunc
1015
Bram Moolenaar957cf672020-11-12 14:21:06 +01001016" Test for <Cmd> key in maps to execute commands
1017func Test_map_cmdkey()
1018 new
1019
1020 " Error cases
1021 let x = 0
1022 noremap <F3> <Cmd><Cmd>let x = 1<CR>
1023 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
1024 call assert_equal(0, x)
1025
Bram Moolenaar957cf672020-11-12 14:21:06 +01001026 noremap <F3> <Cmd>let x = 3
Bram Moolenaar806da512021-12-24 19:54:52 +00001027 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001028 call assert_equal(0, x)
1029
1030 " works in various modes and sees the correct mode()
1031 noremap <F3> <Cmd>let m = mode(1)<CR>
1032 noremap! <F3> <Cmd>let m = mode(1)<CR>
1033
1034 " normal mode
1035 call feedkeys("\<F3>", 'xt')
1036 call assert_equal('n', m)
1037
1038 " visual mode
1039 call feedkeys("v\<F3>", 'xt!')
1040 call assert_equal('v', m)
1041 " shouldn't leave the visual mode
1042 call assert_equal('v', mode(1))
1043 call feedkeys("\<Esc>", 'xt')
1044 call assert_equal('n', mode(1))
1045
1046 " visual mapping in select mode
1047 call feedkeys("gh\<F3>", 'xt!')
1048 call assert_equal('v', m)
1049 " shouldn't leave select mode
1050 call assert_equal('s', mode(1))
1051 call feedkeys("\<Esc>", 'xt')
1052 call assert_equal('n', mode(1))
1053
1054 " select mode mapping
1055 snoremap <F3> <Cmd>let m = mode(1)<cr>
1056 call feedkeys("gh\<F3>", 'xt!')
1057 call assert_equal('s', m)
1058 " shouldn't leave select mode
1059 call assert_equal('s', mode(1))
1060 call feedkeys("\<Esc>", 'xt')
1061 call assert_equal('n', mode(1))
1062
1063 " operator-pending mode
1064 call feedkeys("d\<F3>", 'xt!')
1065 call assert_equal('no', m)
1066 " leaves the operator-pending mode
1067 call assert_equal('n', mode(1))
1068
1069 " insert mode
1070 call feedkeys("i\<F3>abc", 'xt')
1071 call assert_equal('i', m)
1072 call assert_equal('abc', getline('.'))
1073
1074 " replace mode
1075 call feedkeys("0R\<F3>two", 'xt')
1076 call assert_equal('R', m)
1077 call assert_equal('two', getline('.'))
1078
1079 " virtual replace mode
1080 call setline('.', "one\ttwo")
1081 call feedkeys("4|gR\<F3>xxx", 'xt')
1082 call assert_equal('Rv', m)
1083 call assert_equal("onexxx\ttwo", getline('.'))
1084
1085 " cmdline mode
1086 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
1087 call assert_equal('c', m)
1088 call assert_equal('"xxx', @:)
1089
1090 " terminal mode
1091 if CanRunVimInTerminal()
1092 tnoremap <F3> <Cmd>let m = mode(1)<CR>
1093 let buf = Run_shell_in_terminal({})
1094 call feedkeys("\<F3>", 'xt')
1095 call assert_equal('t', m)
1096 call assert_equal('t', mode(1))
1097 call StopShellInTerminal(buf)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001098 close!
1099 tunmap <F3>
1100 endif
1101
1102 " invoke cmdline mode recursively
1103 noremap! <F2> <Cmd>norm! :foo<CR>
1104 %d
1105 call setline(1, ['some short lines', 'of test text'])
1106 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
1107 call assert_equal('"barx', @:)
1108 unmap! <F2>
1109
1110 " test for calling a <SID> function
1111 let lines =<< trim END
1112 map <F2> <Cmd>call <SID>do_it()<CR>
1113 func s:do_it()
1114 let g:x = 32
1115 endfunc
1116 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001117 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001118 source Xscript
1119 call feedkeys("\<F2>", 'xt')
1120 call assert_equal(32, g:x)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001121
1122 unmap <F3>
1123 unmap! <F3>
1124 %bw!
1125endfunc
1126
1127" text object enters visual mode
1128func TextObj()
1129 if mode() !=# "v"
1130 normal! v
1131 end
1132 call cursor(1, 3)
1133 normal! o
1134 call cursor(2, 4)
1135endfunc
1136
1137func s:cmdmap(lhs, rhs)
1138 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1139 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1140endfunc
1141
1142func s:cmdunmap(lhs)
1143 exe 'unmap ' .. a:lhs
1144 exe 'unmap! ' .. a:lhs
1145endfunc
1146
1147" Map various <Fx> keys used by the <Cmd> key tests
1148func s:setupMaps()
1149 call s:cmdmap('<F3>', 'let m = mode(1)')
1150 call s:cmdmap('<F4>', 'normal! ww')
1151 call s:cmdmap('<F5>', 'normal! "ay')
1152 call s:cmdmap('<F6>', 'throw "very error"')
1153 call s:cmdmap('<F7>', 'call TextObj()')
1154 call s:cmdmap('<F8>', 'startinsert')
1155 call s:cmdmap('<F9>', 'stopinsert')
1156endfunc
1157
1158" Remove the mappings setup by setupMaps()
1159func s:cleanupMaps()
1160 call s:cmdunmap('<F3>')
1161 call s:cmdunmap('<F4>')
1162 call s:cmdunmap('<F5>')
1163 call s:cmdunmap('<F6>')
1164 call s:cmdunmap('<F7>')
1165 call s:cmdunmap('<F8>')
1166 call s:cmdunmap('<F9>')
1167endfunc
1168
1169" Test for <Cmd> mapping in normal mode
1170func Test_map_cmdkey_normal_mode()
1171 new
1172 call s:setupMaps()
1173
1174 " check v:count and v:register works
1175 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1176 call feedkeys("\<F2>", 'xt')
1177 call assert_equal(['n', 0, '"'], s)
1178 call feedkeys("7\<F2>", 'xt')
1179 call assert_equal(['n', 7, '"'], s)
1180 call feedkeys("\"e\<F2>", 'xt')
1181 call assert_equal(['n', 0, 'e'], s)
1182 call feedkeys("5\"k\<F2>", 'xt')
1183 call assert_equal(['n', 5, 'k'], s)
1184 call s:cmdunmap('<F2>')
1185
1186 call setline(1, ['some short lines', 'of test text'])
1187 call feedkeys("\<F7>y", 'xt')
1188 call assert_equal("me short lines\nof t", @")
1189 call assert_equal('v', getregtype('"'))
1190 call assert_equal([0, 1, 3, 0], getpos("'<"))
1191 call assert_equal([0, 2, 4, 0], getpos("'>"))
1192
1193 " startinsert
1194 %d
1195 call feedkeys("\<F8>abc", 'xt')
1196 call assert_equal('abc', getline(1))
1197
1198 " feedkeys are not executed immediately
1199 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1200 %d
1201 call setline(1, ['some short lines', 'of test text'])
1202 call cursor(2, 3)
1203 call feedkeys(",a\<F3>", 'xt')
1204 call assert_equal('of test text', g:a)
1205 call assert_equal('n', m)
1206 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1207 nunmap ,a
1208
1209 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1210 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1211 call feedkeys(",b\<F3>", 'xt')
1212 call assert_equal('n', m)
1213 call assert_equal('of alphabetatest text', g:b)
1214 nunmap ,b
1215
1216 call s:cleanupMaps()
1217 %bw!
1218endfunc
1219
1220" Test for <Cmd> mapping with the :normal command
1221func Test_map_cmdkey_normal_cmd()
1222 new
1223 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1224 noremap ,f <Cmd>nosuchcommand<CR>
1225 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1226 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1227 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1228
1229 call setline(1, ['some short lines', 'of test text'])
1230 exe "norm ,x\r"
1231 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1232
1233 call assert_fails('norm ,f', 'E492:')
1234 call assert_fails('norm ,e', 'very error')
1235 call assert_fails('norm ,m', 'The message.')
1236 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1237
1238 %d
1239 let caught_err = 0
1240 try
1241 exe "normal ,w"
1242 catch /Vim(echoerr):Err/
1243 let caught_err = 1
1244 endtry
1245 call assert_equal(1, caught_err)
1246 call assert_equal(['', '0'], getline(1, '$'))
1247
1248 %d
1249 call assert_fails('normal ,w', 'Err')
1250 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1251 call assert_equal(1, line('.'))
1252
1253 nunmap ,x
1254 nunmap ,f
1255 nunmap ,e
1256 nunmap ,m
1257 nunmap ,w
1258 %bw!
1259endfunc
1260
1261" Test for <Cmd> mapping in visual mode
1262func Test_map_cmdkey_visual_mode()
1263 new
1264 set showmode
1265 call s:setupMaps()
1266
1267 call setline(1, ['some short lines', 'of test text'])
1268 call feedkeys("v\<F4>", 'xt!')
1269 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1270
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +01001271 " can invoke an operator, ending the visual mode
Bram Moolenaar957cf672020-11-12 14:21:06 +01001272 let @a = ''
1273 call feedkeys("\<F5>", 'xt!')
1274 call assert_equal('n', mode(1))
1275 call assert_equal('some short l', @a)
1276
1277 " error doesn't interrupt visual mode
1278 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1279 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1280 call feedkeys("\<F7>", 'xt!')
1281 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1282
1283 " startinsert gives "-- (insert) VISUAL --" mode
1284 call feedkeys("\<F8>", 'xt!')
1285 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1286 redraw!
1287 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1288 call feedkeys("\<Esc>new ", 'x')
1289 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1290
1291 call s:cleanupMaps()
1292 set showmode&
1293 %bw!
1294endfunc
1295
1296" Test for <Cmd> mapping in select mode
1297func Test_map_cmdkey_select_mode()
1298 new
1299 set showmode
1300 call s:setupMaps()
1301
1302 snoremap <F1> <cmd>throw "very error"<CR>
1303 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1304 call setline(1, ['some short lines', 'of test text'])
1305
1306 call feedkeys("gh\<F4>", "xt!")
1307 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1308 redraw!
1309 call assert_match('^-- SELECT --', Screenline(&lines))
1310
1311 " visual mapping in select mode restarts select mode after operator
1312 let @a = ''
1313 call feedkeys("\<F5>", 'xt!')
1314 call assert_equal('s', mode(1))
1315 call assert_equal('some short l', @a)
1316
1317 " select mode mapping works, and does not restart select mode
1318 let @b = ''
1319 call feedkeys("\<F2>", 'xt!')
1320 call assert_equal('n', mode(1))
1321 call assert_equal('some short l', @b)
1322
1323 " error doesn't interrupt temporary visual mode
1324 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1325 redraw!
1326 call assert_match('^-- VISUAL --', Screenline(&lines))
1327 " quirk: restoration of select mode is not performed
1328 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1329
1330 " error doesn't interrupt select mode
1331 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1332 redraw!
1333 call assert_match('^-- SELECT --', Screenline(&lines))
1334 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1335
1336 call feedkeys("\<F7>", 'xt!')
1337 redraw!
1338 call assert_match('^-- SELECT --', Screenline(&lines))
1339 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1340
1341 " startinsert gives "-- SELECT (insert) --" mode
1342 call feedkeys("\<F8>", 'xt!')
1343 redraw!
1344 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1345 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1346 call feedkeys("\<Esc>new ", 'x')
1347 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1348
1349 sunmap <F1>
1350 sunmap <F2>
1351 call s:cleanupMaps()
1352 set showmode&
1353 %bw!
1354endfunc
1355
1356" Test for <Cmd> mapping in operator-pending mode
1357func Test_map_cmdkey_op_pending_mode()
1358 new
1359 call s:setupMaps()
1360
1361 call setline(1, ['some short lines', 'of test text'])
1362 call feedkeys("d\<F4>", 'xt')
1363 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1364 call assert_equal(['some short '], getreg('"', 1, 1))
1365 " create a new undo point
Christian Brabandt6efb1982023-08-10 05:44:25 +02001366 let &g:undolevels = &g:undolevels
Bram Moolenaar957cf672020-11-12 14:21:06 +01001367
1368 call feedkeys(".", 'xt')
1369 call assert_equal(['test text'], getline(1, '$'))
1370 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1371 " create a new undo point
Christian Brabandt6efb1982023-08-10 05:44:25 +02001372 let &g:undolevels = &g:undolevels
Bram Moolenaar957cf672020-11-12 14:21:06 +01001373
1374 call feedkeys("uu", 'xt')
1375 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1376
1377 " error aborts operator-pending, operator not performed
1378 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1379 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1380
1381 call feedkeys("\"bd\<F7>", 'xt')
1382 call assert_equal(['soest text'], getline(1, '$'))
1383 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1384
1385 " startinsert aborts operator
1386 call feedkeys("d\<F8>cc", 'xt')
1387 call assert_equal(['soccest text'], getline(1, '$'))
1388
1389 call s:cleanupMaps()
1390 %bw!
1391endfunc
1392
1393" Test for <Cmd> mapping in insert mode
1394func Test_map_cmdkey_insert_mode()
1395 new
1396 call s:setupMaps()
1397
1398 call setline(1, ['some short lines', 'of test text'])
1399 " works the same as <C-O>w<C-O>w
1400 call feedkeys("iindeed \<F4>little ", 'xt')
1401 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1402 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1403 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1404
1405 " Note when entering visual mode from InsertEnter autocmd, an async event,
1406 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1407 call feedkeys("i\<F7>stuff ", 'xt')
1408 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1409 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1410
1411 call feedkeys("\<F5>", 'xt')
1412 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1413
1414 " also works as part of abbreviation
1415 abbr foo <Cmd>let g:y = 17<CR>bar
1416 exe "normal i\<space>foo "
1417 call assert_equal(17, g:y)
1418 call assert_equal('in bar deed some short little 2 lines', getline(1))
1419 unabbr foo
1420
1421 " :startinsert does nothing
1422 call setline(1, 'foo bar')
1423 call feedkeys("ggi\<F8>vim", 'xt')
1424 call assert_equal('vimfoo bar', getline(1))
1425
1426 " :stopinsert works
1427 call feedkeys("ggi\<F9>Abc", 'xt')
1428 call assert_equal('vimfoo barbc', getline(1))
1429
1430 call s:cleanupMaps()
1431 %bw!
1432endfunc
1433
1434" Test for <Cmd> mapping in insert-completion mode
1435func Test_map_cmdkey_insert_complete_mode()
1436 new
1437 call s:setupMaps()
1438
1439 call setline(1, 'some short lines')
1440 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1441 call assert_equal('ic', m)
1442 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1443
1444 call s:cleanupMaps()
1445 %bw!
1446endfunc
1447
1448" Test for <Cmd> mapping in cmdline mode
1449func Test_map_cmdkey_cmdline_mode()
1450 new
1451 call s:setupMaps()
1452
1453 call setline(1, ['some short lines', 'of test text'])
1454 let x = 0
1455 call feedkeys(":let x\<F3>= 10\r", 'xt')
1456 call assert_equal('c', m)
1457 call assert_equal(10, x)
1458
1459 " exception doesn't leave cmdline mode
1460 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1461 call assert_equal(20, x)
1462
1463 " move cursor in the buffer from cmdline mode
1464 call feedkeys(":let x\<F4>= 30\r", 'xt')
1465 call assert_equal(30, x)
1466 call assert_equal(12, col('.'))
1467
1468 " :startinsert takes effect after leaving cmdline mode
1469 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1470 call assert_equal(40, x)
1471 call assert_equal('some short new lines', getline(1))
1472
1473 call s:cleanupMaps()
1474 %bw!
1475endfunc
1476
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001477func Test_map_cmdkey_redo()
1478 func SelectDash()
1479 call search('^---\n\zs', 'bcW')
1480 norm! V
1481 call search('\n\ze---$', 'W')
1482 endfunc
1483
1484 let text =<< trim END
1485 ---
1486 aaa
1487 ---
1488 bbb
1489 bbb
1490 ---
1491 ccc
1492 ccc
1493 ccc
1494 ---
1495 END
1496 new Xcmdtext
1497 call setline(1, text)
1498
1499 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1500 call feedkeys('2Gdi-', 'xt')
1501 call assert_equal(['---', '---'], getline(1, 2))
1502 call feedkeys('j.', 'xt')
1503 call assert_equal(['---', '---', '---'], getline(1, 3))
1504 call feedkeys('j.', 'xt')
1505 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1506
1507 bwipe!
1508 call delete('Xcmdtext')
1509 delfunc SelectDash
1510 ounmap i-
zeertzjq3ab3a862023-05-06 16:22:04 +01001511
1512 new
1513 call setline(1, 'aaa bbb ccc ddd')
1514
1515 " command can contain special keys
1516 onoremap ix <Cmd>let g:foo ..= '…'<Bar>normal! <C-Right><CR>
1517 let g:foo = ''
1518 call feedkeys('0dix.', 'xt')
1519 call assert_equal('……', g:foo)
1520 call assert_equal('ccc ddd', getline(1))
1521 unlet g:foo
1522
1523 " command line ending in "0" is handled without errors
1524 onoremap ix <Cmd>eval 0<CR>
1525 call feedkeys('dix.', 'xt')
1526
1527 ounmap ix
1528 bwipe!
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001529endfunc
1530
Bram Moolenaara9725222022-01-16 13:30:33 +00001531func Test_map_script_cmd_restore()
1532 let lines =<< trim END
1533 vim9script
1534 nnoremap <F3> <ScriptCmd>eval 1 + 2<CR>
1535 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001536 call v9.CheckScriptSuccess(lines)
Bram Moolenaara9725222022-01-16 13:30:33 +00001537 call feedkeys("\<F3>:let g:result = 3+4\<CR>", 'xtc')
1538 call assert_equal(7, g:result)
1539
1540 nunmap <F3>
1541 unlet g:result
1542endfunc
1543
Bram Moolenaardc987762022-01-16 15:52:35 +00001544func Test_map_script_cmd_finds_func()
1545 let lines =<< trim END
1546 vim9script
1547 onoremap <F3> <ScriptCmd>Func()<CR>
1548 def Func()
1549 g:func_called = 'yes'
1550 enddef
1551 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001552 call v9.CheckScriptSuccess(lines)
Bram Moolenaardc987762022-01-16 15:52:35 +00001553 call feedkeys("y\<F3>\<Esc>", 'xtc')
1554 call assert_equal('yes', g:func_called)
1555
1556 ounmap <F3>
1557 unlet g:func_called
1558endfunc
1559
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001560func Test_map_script_cmd_survives_unmap()
1561 let lines =<< trim END
1562 vim9script
1563 var n = 123
1564 nnoremap <F4> <ScriptCmd><CR>
1565 autocmd CmdlineEnter * silent! nunmap <F4>
1566 nnoremap <F3> :<ScriptCmd>eval setbufvar(bufnr(), "result", n)<CR>
1567 feedkeys("\<F3>\<CR>", 'xct')
1568 assert_equal(123, b:result)
1569 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001570 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001571
1572 nunmap <F3>
1573 unlet b:result
Bram Moolenaarca34db32022-01-20 11:17:18 +00001574 autocmd! CmdlineEnter
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001575endfunc
1576
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001577func Test_map_script_cmd_redo()
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001578 call mkdir('Xmapcmd', 'R')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001579 let lines =<< trim END
1580 vim9script
1581 import autoload './script.vim'
1582 onoremap <F3> <ScriptCmd>script.Func()<CR>
1583 END
1584 call writefile(lines, 'Xmapcmd/plugin.vim')
1585
1586 let lines =<< trim END
1587 vim9script
1588 export def Func()
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001589 normal! V
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001590 enddef
1591 END
1592 call writefile(lines, 'Xmapcmd/script.vim')
1593 new
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001594 call setline(1, ['one', 'two', 'three', 'four', 'five'])
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001595 nnoremap j j
1596 source Xmapcmd/plugin.vim
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001597 call feedkeys("d\<F3>j.j.", 'xt')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001598 call assert_equal(['two', 'four'], getline(1, '$'))
1599
1600 ounmap <F3>
1601 nunmap j
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001602 bwipe!
1603endfunc
1604
Bram Moolenaar1f448d92021-03-22 19:37:06 +01001605" Test for using <script> with a map to remap characters in rhs
1606func Test_script_local_remap()
1607 new
1608 inoremap <buffer> <SID>xyz mno
1609 inoremap <buffer> <script> abc st<SID>xyzre
1610 normal iabc
1611 call assert_equal('stmnore', getline(1))
1612 bwipe!
1613endfunc
1614
Bram Moolenaar4934ed32021-04-30 19:43:11 +02001615func Test_abbreviate_multi_byte()
1616 new
1617 iabbrev foo bar
1618 call feedkeys("ifoo…\<Esc>", 'xt')
1619 call assert_equal("bar…", getline(1))
1620 iunabbrev foo
1621 bwipe!
1622endfunc
1623
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +02001624" Test for abbreviations with 'latin1' encoding
1625func Test_abbreviate_latin1_encoding()
1626 set encoding=latin1
1627 call assert_fails('abbr ab#$c ABC', 'E474:')
1628 new
1629 iabbr <buffer> #i #include
1630 iabbr <buffer> ## #enddef
1631 exe "normal i#i\<C-]>"
1632 call assert_equal('#include', getline(1))
1633 exe "normal 0Di##\<C-]>"
1634 call assert_equal('#enddef', getline(1))
1635 %bw!
1636 set encoding=utf-8
1637endfunc
1638
Bram Moolenaar1fc34222022-03-03 13:56:24 +00001639" Test for <Plug> always being mapped, even when used with "noremap".
1640func Test_plug_remap()
1641 let g:foo = 0
1642 nnoremap <Plug>(Increase_x) <Cmd>let g:foo += 1<CR>
1643 nmap <F2> <Plug>(Increase_x)
1644 nnoremap <F3> <Plug>(Increase_x)
1645 call feedkeys("\<F2>", 'xt')
1646 call assert_equal(1, g:foo)
1647 call feedkeys("\<F3>", 'xt')
1648 call assert_equal(2, g:foo)
1649 nnoremap x <Nop>
1650 nmap <F4> x<Plug>(Increase_x)x
1651 nnoremap <F5> x<Plug>(Increase_x)x
1652 call setline(1, 'Some text')
1653 normal! gg$
1654 call feedkeys("\<F4>", 'xt')
1655 call assert_equal(3, g:foo)
1656 call assert_equal('Some text', getline(1))
1657 call feedkeys("\<F5>", 'xt')
1658 call assert_equal(4, g:foo)
1659 call assert_equal('Some te', getline(1))
1660 nunmap <Plug>(Increase_x)
1661 nunmap <F2>
1662 nunmap <F3>
1663 nunmap <F4>
1664 nunmap <F5>
1665 unlet g:foo
1666 %bw!
1667endfunc
1668
zeertzjqac92ab72022-04-24 15:58:30 +01001669func Test_mouse_drag_mapped_start_select()
1670 set mouse=a
1671 set selectmode=key,mouse
1672 func ClickExpr()
1673 call test_setmouse(1, 1)
1674 return "\<LeftMouse>"
1675 endfunc
1676 func DragExpr()
1677 call test_setmouse(1, 2)
1678 return "\<LeftDrag>"
1679 endfunc
1680 nnoremap <expr> <F2> ClickExpr()
1681 nmap <expr> <F3> DragExpr()
1682
1683 nnoremap <LeftDrag> <LeftDrag><Cmd><CR>
1684 exe "normal \<F2>\<F3>"
1685 call assert_equal('s', mode())
1686 exe "normal! \<C-\>\<C-N>"
1687
1688 nunmap <LeftDrag>
1689 nunmap <F2>
1690 nunmap <F3>
1691 delfunc ClickExpr
1692 delfunc DragExpr
1693 set selectmode&
1694 set mouse&
1695endfunc
1696
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001697func Test_mouse_drag_statusline()
1698 set laststatus=2
1699 set mouse=a
1700 func ClickExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001701 call test_setmouse(&lines - 1, 1)
1702 return "\<LeftMouse>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001703 endfunc
1704 func DragExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001705 call test_setmouse(&lines - 2, 1)
1706 return "\<LeftDrag>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001707 endfunc
1708 nnoremap <expr> <F2> ClickExpr()
1709 nnoremap <expr> <F3> DragExpr()
1710
1711 " this was causing a crash in win_drag_status_line()
1712 call feedkeys("\<F2>:tabnew\<CR>\<F3>", 'tx')
zeertzjq873f41a2022-11-01 11:44:43 +00001713
1714 nunmap <F2>
1715 nunmap <F3>
1716 delfunc ClickExpr
1717 delfunc DragExpr
1718 set laststatus& mouse&
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001719endfunc
1720
zeertzjq0f68e6c2022-04-05 13:17:01 +01001721" Test for mapping <LeftDrag> in Insert mode
1722func Test_mouse_drag_insert_map()
1723 set mouse=a
1724 func ClickExpr()
1725 call test_setmouse(1, 1)
1726 return "\<LeftMouse>"
1727 endfunc
1728 func DragExpr()
1729 call test_setmouse(1, 2)
1730 return "\<LeftDrag>"
1731 endfunc
1732 inoremap <expr> <F2> ClickExpr()
1733 imap <expr> <F3> DragExpr()
1734
1735 inoremap <LeftDrag> <LeftDrag><Cmd>let g:dragged = 1<CR>
1736 exe "normal i\<F2>\<F3>"
1737 call assert_equal(1, g:dragged)
1738 call assert_equal('v', mode())
1739 exe "normal! \<C-\>\<C-N>"
1740 unlet g:dragged
1741
1742 inoremap <LeftDrag> <LeftDrag><C-\><C-N>
1743 exe "normal i\<F2>\<F3>"
1744 call assert_equal('n', mode())
1745
1746 iunmap <LeftDrag>
1747 iunmap <F2>
1748 iunmap <F3>
1749 delfunc ClickExpr
1750 delfunc DragExpr
1751 set mouse&
1752endfunc
1753
zeertzjqabeb09b2022-04-26 12:29:43 +01001754func Test_unmap_simplifiable()
zeertzjqa4e33322022-04-24 17:07:53 +01001755 map <C-I> foo
1756 map <Tab> bar
1757 call assert_equal('foo', maparg('<C-I>'))
1758 call assert_equal('bar', maparg('<Tab>'))
1759 unmap <C-I>
1760 call assert_equal('', maparg('<C-I>'))
1761 call assert_equal('bar', maparg('<Tab>'))
1762 unmap <Tab>
zeertzjqabeb09b2022-04-26 12:29:43 +01001763
1764 map <C-I> foo
1765 unmap <Tab>
1766 " This should not error
1767 unmap <C-I>
zeertzjqa4e33322022-04-24 17:07:53 +01001768endfunc
1769
zeertzjq9d997ad2024-07-29 21:10:07 +02001770" Test that the first byte of rhs is not remapped if rhs starts with lhs.
1771func Test_map_rhs_starts_with_lhs()
1772 new
1773 func MapExpr()
1774 return "\<C-R>\<C-P>"
1775 endfunc
1776
1777 for expr in [v:false, v:true]
1778 if expr
1779 imap <buffer><expr> <C-R> MapExpr()
1780 else
1781 imap <buffer> <C-R> <C-R><C-P>
1782 endif
1783
1784 for restore in [v:false, v:true]
1785 if restore
1786 let saved = maparg('<C-R>', 'i', v:false, v:true)
1787 iunmap <buffer> <C-R>
1788 call mapset(saved)
1789 endif
1790
1791 let @a = 'foo'
zeertzjq74011dc2024-07-30 19:17:56 +02001792 call assert_nobeep('call feedkeys("S\<C-R>a", "tx")')
zeertzjq9d997ad2024-07-29 21:10:07 +02001793 call assert_equal('foo', getline('.'))
1794
1795 let @a = 'bar'
zeertzjq74011dc2024-07-30 19:17:56 +02001796 call assert_nobeep('call feedkeys("S\<*C-R>a", "tx")')
zeertzjq9d997ad2024-07-29 21:10:07 +02001797 call assert_equal('bar', getline('.'))
1798 endfor
1799 endfor
1800
1801 " When two mappings are used for <C-I> and <Tab>, remapping should work.
1802 imap <buffer> <C-I> <Tab>bar
1803 imap <buffer> <Tab> foo
1804 call feedkeys("S\<Tab>", 'xt')
1805 call assert_equal('foo', getline('.'))
1806 call feedkeys("S\<*C-I>", 'xt')
1807 call assert_equal('foobar', getline('.'))
1808
1809 delfunc MapExpr
1810 bwipe!
1811endfunc
1812
zeertzjqdb088872022-05-02 22:53:45 +01001813func Test_expr_map_escape_special()
1814 nnoremap <Cmd>let g:got_ellipsis += 1<CR>
1815 func Func()
1816 return '…'
1817 endfunc
1818 nmap <expr> <F2> Func()
1819 let g:got_ellipsis = 0
1820 call feedkeys("\<F2>", 'xt')
1821 call assert_equal(1, g:got_ellipsis)
1822 delfunc Func
1823 nunmap <F2>
1824 unlet g:got_ellipsis
1825 nunmap
1826endfunc
1827
zeertzjq3760bfd2022-06-06 16:22:46 +01001828" Testing for mapping after an <Nop> mapping is triggered on timeout.
1829" Test for what patch 8.1.0052 fixes.
1830func Test_map_after_timed_out_nop()
1831 CheckRunVimInTerminal
1832
1833 let lines =<< trim END
1834 set timeout timeoutlen=400
1835 inoremap ab TEST
1836 inoremap a <Nop>
1837 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001838 call writefile(lines, 'Xtest_map_after_timed_out_nop', 'D')
zeertzjq3760bfd2022-06-06 16:22:46 +01001839 let buf = RunVimInTerminal('-S Xtest_map_after_timed_out_nop', #{rows: 6})
1840
1841 " Enter Insert mode
1842 call term_sendkeys(buf, 'i')
1843 " Wait for the "a" mapping to timeout
1844 call term_sendkeys(buf, 'a')
1845 call term_wait(buf, 500)
1846 " Send "a" and wait for a period shorter than 'timeoutlen'
1847 call term_sendkeys(buf, 'a')
1848 call term_wait(buf, 100)
1849 " Send "b", should trigger the "ab" mapping
1850 call term_sendkeys(buf, 'b')
1851 call WaitForAssert({-> assert_equal("TEST", term_getline(buf, 1))})
1852
1853 " clean up
1854 call StopVimInTerminal(buf)
zeertzjq3760bfd2022-06-06 16:22:46 +01001855endfunc
1856
zeertzjqacdfb8a2024-04-17 21:28:54 +02001857" Test 'showcmd' behavior with a partial mapping
1858func Test_showcmd_part_map()
1859 CheckRunVimInTerminal
1860
zeertzjq094c4392024-04-18 22:09:37 +02001861 let lines =<< trim END
zeertzjqacdfb8a2024-04-17 21:28:54 +02001862 set notimeout showcmd
1863 nnoremap ,a <Ignore>
1864 nnoremap ;a <Ignore>
1865 nnoremap Àa <Ignore>
1866 nnoremap Ëa <Ignore>
1867 nnoremap βa <Ignore>
1868 nnoremap ωa <Ignore>
1869 nnoremap a <Ignore>
1870 nnoremap <C-W>a <Ignore>
1871 END
1872 call writefile(lines, 'Xtest_showcmd_part_map', 'D')
1873 let buf = RunVimInTerminal('-S Xtest_showcmd_part_map', #{rows: 6})
1874
1875 call term_sendkeys(buf, ":set noruler | echo\<CR>")
1876 call WaitForAssert({-> assert_equal('', term_getline(buf, 6))})
1877
1878 for c in [',', ';', 'À', 'Ë', 'β', 'ω', '…']
1879 call term_sendkeys(buf, c)
1880 call WaitForAssert({-> assert_equal(c, trim(term_getline(buf, 6)))})
zeertzjq094c4392024-04-18 22:09:37 +02001881 call term_sendkeys(buf, 'a')
1882 call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))})
zeertzjqacdfb8a2024-04-17 21:28:54 +02001883 endfor
1884
1885 call term_sendkeys(buf, "\<C-W>")
1886 call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))})
zeertzjq094c4392024-04-18 22:09:37 +02001887 call term_sendkeys(buf, 'a')
1888 call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))})
zeertzjqacdfb8a2024-04-17 21:28:54 +02001889
zeertzjq094c4392024-04-18 22:09:37 +02001890 " Use feedkeys() as terminal buffer cannot forward unsimplified Ctrl-W.
1891 " This is like typing Ctrl-W with modifyOtherKeys enabled.
zeertzjqacdfb8a2024-04-17 21:28:54 +02001892 call term_sendkeys(buf, ':call feedkeys("\<*C-W>", "m")' .. " | echo\<CR>")
1893 call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))})
zeertzjq094c4392024-04-18 22:09:37 +02001894 call term_sendkeys(buf, 'a')
1895 call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))})
zeertzjqacdfb8a2024-04-17 21:28:54 +02001896
1897 call StopVimInTerminal(buf)
1898endfunc
1899
Bram Moolenaar27efc622022-07-01 16:35:45 +01001900func Test_using_past_typeahead()
1901 nnoremap :00 0
1902 exe "norm :set \x80\xfb0=0\<CR>"
1903 exe "sil norm :0\x0f\<C-U>\<CR>"
1904
1905 exe "norm :set \x80\xfb0=\<CR>"
1906 nunmap :00
1907endfunc
1908
Bram Moolenaarbf533e42022-11-13 20:43:19 +00001909func Test_mapclear_while_listing()
1910 CheckRunVimInTerminal
1911
1912 let lines =<< trim END
1913 set nocompatible
1914 mapclear
1915 for i in range(1, 999)
1916 exe 'map ' .. 'foo' .. i .. ' bar'
1917 endfor
1918 au CmdlineLeave : call timer_start(0, {-> execute('mapclear')})
1919 END
1920 call writefile(lines, 'Xmapclear', 'D')
1921 let buf = RunVimInTerminal('-S Xmapclear', {'rows': 10})
1922
1923 " this was using freed memory
1924 call term_sendkeys(buf, ":map\<CR>")
1925 call TermWait(buf, 50)
1926 call term_sendkeys(buf, "G")
1927 call TermWait(buf, 50)
1928 call term_sendkeys(buf, "\<CR>")
1929
1930 call StopVimInTerminal(buf)
1931endfunc
1932
Bram Moolenaar27efc622022-07-01 16:35:45 +01001933
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001934" vim: shiftwidth=2 sts=2 expandtab