blob: d631274d3735529a8a0d1b72cc1512beca1b95c4 [file] [log] [blame]
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02001" Tests for mappings and abbreviations
2
Bram Moolenaar26d98212019-01-27 22:32:55 +01003source shared.vim
Bram Moolenaar8c5a2782019-08-07 23:07:07 +02004source check.vim
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +01005source screendump.vim
Bram Moolenaar957cf672020-11-12 14:21:06 +01006source term_util.vim
Bram Moolenaar62aec932022-01-29 21:45:34 +00007import './vim9.vim' as v9
Bram Moolenaar26d98212019-01-27 22:32:55 +01008
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02009func Test_abbreviation()
10 " abbreviation with 0x80 should work
11 inoreab чкпр vim
12 call feedkeys("Goчкпр \<Esc>", "xt")
13 call assert_equal('vim ', getline('$'))
14 iunab чкпр
15 set nomodified
16endfunc
17
Bram Moolenaar8485be42019-04-23 16:36:05 +020018func Test_abclear()
19 abbrev foo foobar
20 iabbrev fooi foobari
21 cabbrev fooc foobarc
22 call assert_equal("\n\n"
23 \ .. "c fooc foobarc\n"
24 \ .. "i fooi foobari\n"
25 \ .. "! foo foobar", execute('abbrev'))
26
27 iabclear
28 call assert_equal("\n\n"
29 \ .. "c fooc foobarc\n"
30 \ .. "c foo foobar", execute('abbrev'))
31 abbrev foo foobar
32 iabbrev fooi foobari
33
34 cabclear
35 call assert_equal("\n\n"
36 \ .. "i fooi foobari\n"
37 \ .. "i foo foobar", execute('abbrev'))
38 abbrev foo foobar
39 cabbrev fooc foobarc
40
41 abclear
42 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
Bram Moolenaarf0cee192020-02-16 13:33:56 +010043 call assert_fails('%abclear', 'E481:')
Bram Moolenaar8485be42019-04-23 16:36:05 +020044endfunc
45
46func Test_abclear_buffer()
47 abbrev foo foobar
48 new X1
49 abbrev <buffer> foo1 foobar1
50 new X2
51 abbrev <buffer> foo2 foobar2
52
53 call assert_equal("\n\n"
54 \ .. "! foo2 @foobar2\n"
55 \ .. "! foo foobar", execute('abbrev'))
56
57 abclear <buffer>
58 call assert_equal("\n\n"
59 \ .. "! foo foobar", execute('abbrev'))
60
61 b X1
62 call assert_equal("\n\n"
63 \ .. "! foo1 @foobar1\n"
64 \ .. "! foo foobar", execute('abbrev'))
65 abclear <buffer>
66 call assert_equal("\n\n"
67 \ .. "! foo foobar", execute('abbrev'))
68
69 abclear
70 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
71
72 %bwipe
73endfunc
74
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020075func Test_map_ctrl_c_insert()
76 " mapping of ctrl-c in Insert mode
77 set cpo-=< cpo-=k
78 inoremap <c-c> <ctrl-c>
79 cnoremap <c-c> dummy
80 cunmap <c-c>
Bram Moolenaarfccd93f2020-05-31 22:06:51 +020081 call feedkeys("GoTEST2: CTRL-C |\<*C-C>A|\<Esc>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020082 call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
83 unmap! <c-c>
84 set nomodified
85endfunc
86
87func Test_map_ctrl_c_visual()
88 " mapping of ctrl-c in Visual mode
89 vnoremap <c-c> :<C-u>$put ='vmap works'
Bram Moolenaarfccd93f2020-05-31 22:06:51 +020090 call feedkeys("GV\<*C-C>\<CR>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020091 call assert_equal('vmap works', getline('$'))
92 vunmap <c-c>
93 set nomodified
94endfunc
95
96func Test_map_langmap()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +020097 CheckFeature langmap
Bram Moolenaar920694c2016-08-21 17:45:02 +020098
99 " check langmap applies in normal mode
100 set langmap=+- nolangremap
101 new
102 call setline(1, ['a', 'b', 'c'])
103 2
104 call assert_equal('b', getline('.'))
105 call feedkeys("+", "xt")
106 call assert_equal('a', getline('.'))
107
108 " check no remapping
109 map x +
110 2
111 call feedkeys("x", "xt")
112 call assert_equal('c', getline('.'))
113
114 " check with remapping
115 set langremap
116 2
117 call feedkeys("x", "xt")
118 call assert_equal('a', getline('.'))
119
120 unmap x
121 bwipe!
122
123 " 'langnoremap' follows 'langremap' and vise versa
124 set langremap
125 set langnoremap
126 call assert_equal(0, &langremap)
127 set langremap
128 call assert_equal(0, &langnoremap)
129 set nolangremap
130 call assert_equal(1, &langnoremap)
131
Bram Moolenaarda9ce2c2016-09-02 19:34:10 +0200132 " check default values
133 set langnoremap&
134 call assert_equal(0, &langnoremap)
135 call assert_equal(1, &langremap)
136 set langremap&
137 call assert_equal(0, &langnoremap)
138 call assert_equal(1, &langremap)
139
Bram Moolenaar920694c2016-08-21 17:45:02 +0200140 " langmap should not apply in insert mode, 'langremap' doesn't matter
141 set langmap=+{ nolangremap
142 call feedkeys("Go+\<Esc>", "xt")
143 call assert_equal('+', getline('$'))
144 set langmap=+{ langremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200145 call feedkeys("Go+\<Esc>", "xt")
146 call assert_equal('+', getline('$'))
147
Bram Moolenaar920694c2016-08-21 17:45:02 +0200148 " langmap used for register name in insert mode.
149 call setreg('a', 'aaaa')
150 call setreg('b', 'bbbb')
151 call setreg('c', 'cccc')
152 set langmap=ab langremap
153 call feedkeys("Go\<C-R>a\<Esc>", "xt")
154 call assert_equal('bbbb', getline('$'))
155 call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt")
156 call assert_equal('bbbb', getline('$'))
157 " mapping does not apply
158 imap c a
159 call feedkeys("Go\<C-R>c\<Esc>", "xt")
160 call assert_equal('cccc', getline('$'))
161 imap a c
162 call feedkeys("Go\<C-R>a\<Esc>", "xt")
163 call assert_equal('bbbb', getline('$'))
164
165 " langmap should not apply in Command-line mode
166 set langmap=+{ nolangremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200167 call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
168 call assert_equal('+', getline('$'))
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200169
Bram Moolenaare90858d2017-02-01 17:24:34 +0100170 iunmap a
171 iunmap c
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200172 set nomodified
173endfunc
174
175func Test_map_feedkeys()
176 " issue #212 (feedkeys insert mapping at current position)
177 nnoremap . :call feedkeys(".", "in")<cr>
178 call setline('$', ['a b c d', 'a b c d'])
179 $-1
180 call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt")
181 call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$')))
Bram Moolenaare90858d2017-02-01 17:24:34 +0100182 nunmap .
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200183 set nomodified
184endfunc
185
186func Test_map_cursor()
187 " <c-g>U<cursor> works only within a single line
188 imapclear
189 imap ( ()<c-g>U<left>
190 call feedkeys("G2o\<Esc>ki\<CR>Test1: text with a (here some more text\<Esc>k.", "xt")
191 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 2))
192 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 1))
193
194 " test undo
195 call feedkeys("G2o\<Esc>ki\<CR>Test2: text wit a (here some more text [und undo]\<C-G>u\<Esc>k.u", "xt")
196 call assert_equal('', getline(line('$') - 2))
197 call assert_equal('Test2: text wit a (here some more text [und undo])', getline(line('$') - 1))
198 set nomodified
199 imapclear
200endfunc
201
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100202func Test_map_cursor_ctrl_gU()
203 " <c-g>U<cursor> works only within a single line
204 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left>
205 call setline(1, ['foo', 'foobar', '', 'foo'])
206 call cursor(1,2)
207 call feedkeys("c<*PREFIX\<esc>.", 'xt')
208 call assert_equal(['PREFIXfoo', 'foobar', '', 'PREFIXfoo'], getline(1,'$'))
209 " break undo manually
210 set ul=1000
211 exe ":norm! uu"
212 call assert_equal(['foo', 'foobar', '', 'foo'], getline(1,'$'))
213
214 " Test that it does not work if the cursor moves to the previous line
215 " 2 times <S-Left> move to the previous line
216 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left><C-G>U<S-Left>
217 call setline(1, ['', ' foo', 'foobar', '', 'foo'])
218 call cursor(2,3)
219 call feedkeys("c<*PREFIX\<esc>.", 'xt')
220 call assert_equal(['PREFIXPREFIX', ' foo', 'foobar', '', 'foo'], getline(1,'$'))
221 nmapclear
222endfunc
223
224
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200225" This isn't actually testing a mapping, but similar use of CTRL-G U as above.
226func Test_break_undo()
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100227 set whichwrap=<,>,[,]
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200228 call feedkeys("G4o2k", "xt")
229 exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."
230 call assert_equal('new line here', getline(line('$') - 3))
231 call assert_equal('Test3: text with a (parenthesis here', getline(line('$') - 2))
232 call assert_equal('new line here', getline(line('$') - 1))
233 set nomodified
234endfunc
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200235
236func Test_map_meta_quotes()
237 imap <M-"> foo
Bram Moolenaarfccd93f2020-05-31 22:06:51 +0200238 call feedkeys("Go-\<*M-\">-\<Esc>", "xt")
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200239 call assert_equal("-foo-", getline('$'))
240 set nomodified
241 iunmap <M-">
242endfunc
Bram Moolenaar878c2632017-04-01 15:15:52 +0200243
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200244func Test_map_meta_multibyte()
245 imap <M-á> foo
Bram Moolenaar2f710af2019-08-16 20:56:03 +0200246 call assert_match('i <M-á>\s*foo', execute('imap'))
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200247 iunmap <M-á>
248endfunc
249
Bram Moolenaar878c2632017-04-01 15:15:52 +0200250func Test_abbr_after_line_join()
251 new
252 abbr foo bar
253 set backspace=indent,eol,start
254 exe "normal o\<BS>foo "
255 call assert_equal("bar ", getline(1))
256 bwipe!
257 unabbr foo
258 set backspace&
259endfunc
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200260
261func Test_map_timeout()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200262 CheckFeature timers
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200263 nnoremap aaaa :let got_aaaa = 1<CR>
264 nnoremap bb :let got_bb = 1<CR>
265 nmap b aaa
266 new
267 func ExitInsert(timer)
268 let g:line = getline(1)
269 call feedkeys("\<Esc>", "t")
270 endfunc
271 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100272 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200273 " After the 'b' Vim waits for another character to see if it matches 'bb'.
274 " When it times out it is expanded to "aaa", but there is no wait for
275 " "aaaa". Can't check that reliably though.
276 call feedkeys("b", "xt!")
277 call assert_equal("aa", g:line)
278 call assert_false(exists('got_aaa'))
279 call assert_false(exists('got_bb'))
280
281 bwipe!
282 nunmap aaaa
283 nunmap bb
284 nunmap b
285 set timeoutlen&
286 delfunc ExitInsert
Bram Moolenaar26d98212019-01-27 22:32:55 +0100287 call timer_stop(timer)
288endfunc
289
290func Test_map_timeout_with_timer_interrupt()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200291 CheckFeature job
292 CheckFeature timers
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100293 let g:test_is_flaky = 1
Bram Moolenaar26d98212019-01-27 22:32:55 +0100294
295 " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
296 " sequence.
297 new
298 let g:val = 0
299 nnoremap \12 :let g:val = 1<CR>
300 nnoremap \123 :let g:val = 2<CR>
Bram Moolenaarea94c852019-08-16 21:47:27 +0200301 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100302
303 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100304 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100305 endfunc
306
307 call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
308 call feedkeys('\12', 'xt!')
309 call assert_equal(2, g:val)
310
311 bwipe!
312 nunmap \12
313 nunmap \123
314 set timeoutlen&
315 call WaitFor({-> exists('g:timer')})
316 call timer_stop(g:timer)
317 unlet g:timer
318 unlet g:val
319 delfunc ExitCb
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200320endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200321
322func Test_abbreviation_CR()
323 new
324 func Eatchar(pat)
325 let c = nr2char(getchar(0))
326 return (c =~ a:pat) ? '' : c
327 endfunc
328 iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
329 call feedkeys("GA~~7 \<esc>", 'xt')
330 call assert_equal('~~~~~~~', getline('$'))
331 %d
332 call feedkeys("GA~~7\<cr>\<esc>", 'xt')
333 call assert_equal(['~~~~~~~', ''], getline(1,'$'))
334 delfunc Eatchar
335 bw!
336endfunc
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200337
338func Test_cabbr_visual_mode()
339 cabbr s su
340 call feedkeys(":s \<c-B>\"\<CR>", 'itx')
341 call assert_equal('"su ', getreg(':'))
342 call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
343 let expected = '"'. "'<,'>su "
344 call assert_equal(expected, getreg(':'))
345 call feedkeys(": '<,'>s \<c-B>\"\<CR>", 'itx')
346 let expected = '" '. "'<,'>su "
347 call assert_equal(expected, getreg(':'))
348 call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
349 let expected = '"'. "'a,'bsu "
350 call assert_equal(expected, getreg(':'))
351 cunabbr s
352endfunc
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100353
354func Test_motionforce_omap()
355 func GetCommand()
356 let g:m=mode(1)
357 let [g:lnum1, g:col1] = searchpos('-', 'Wb')
358 if g:lnum1 == 0
359 return "\<Esc>"
360 endif
361 let [g:lnum2, g:col2] = searchpos('-', 'W')
362 if g:lnum2 == 0
363 return "\<Esc>"
364 endif
365 return ":call Select()\<CR>"
366 endfunc
367 func Select()
368 call cursor([g:lnum1, g:col1])
369 exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
370 call cursor([g:lnum2, g:col2])
371 execute "normal! \<BS>"
372 endfunc
373 new
374 onoremap <buffer><expr> i- GetCommand()
375 " 1) default omap mapping
376 %d_
377 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
378 call cursor(2, 1)
379 norm di-
380 call assert_equal('no', g:m)
381 call assert_equal(['aaa -- eee'], getline(1, '$'))
382 " 2) forced characterwise operation
383 %d_
384 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
385 call cursor(2, 1)
386 norm dvi-
387 call assert_equal('nov', g:m)
388 call assert_equal(['aaa -- eee'], getline(1, '$'))
389 " 3) forced linewise operation
390 %d_
391 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
392 call cursor(2, 1)
393 norm dVi-
394 call assert_equal('noV', g:m)
395 call assert_equal([''], getline(1, '$'))
396 " 4) forced blockwise operation
397 %d_
398 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
399 call cursor(2, 1)
400 exe "norm d\<C-V>i-"
401 call assert_equal("no\<C-V>", g:m)
402 call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
403 bwipe!
404 delfunc Select
405 delfunc GetCommand
406endfunc
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200407
408func Test_error_in_map_expr()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200409 " Unlike CheckRunVimInTerminal this does work in a win32 console
410 CheckFeature terminal
411 if has('win32') && has('gui_running')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200412 throw 'Skipped: cannot run Vim in a terminal window'
413 endif
414
415 let lines =<< trim [CODE]
416 func Func()
417 " fail to create list
418 let x = [
419 endfunc
420 nmap <expr> ! Func()
421 set updatetime=50
422 [CODE]
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100423 call writefile(lines, 'Xtest.vim', 'D')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200424
Bram Moolenaar0d702022019-07-04 14:20:41 +0200425 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200426 let job = term_getjob(buf)
427 call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
428
429 " GC must not run during map-expr processing, which can make Vim crash.
430 call term_sendkeys(buf, '!')
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200431 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200432 call term_sendkeys(buf, "\<CR>")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200433 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200434 call assert_equal('run', job_status(job))
435
436 call term_sendkeys(buf, ":qall!\<CR>")
437 call WaitFor({-> job_status(job) ==# 'dead'})
438 if has('unix')
439 call assert_equal('', job_info(job).termsig)
440 endif
441
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200442 exe buf .. 'bwipe!'
443endfunc
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200444
445func Test_list_mappings()
Bram Moolenaar2559a472019-10-16 23:33:12 +0200446 " Remove default mappings
447 imapclear
Bram Moolenaar4f2f61a2019-10-16 22:27:49 +0200448
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200449 " reset 'isident' to check it isn't used
450 set isident=
451 inoremap <C-m> CtrlM
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200452 inoremap <A-S> AltS
453 inoremap <S-/> ShiftSlash
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200454 set isident&
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200455 call assert_equal([
456 \ 'i <S-/> * ShiftSlash',
457 \ 'i <M-S> * AltS',
458 \ 'i <C-M> * CtrlM',
459 \], execute('imap')->trim()->split("\n"))
460 iunmap <C-M>
461 iunmap <A-S>
462 call assert_equal(['i <S-/> * ShiftSlash'], execute('imap')->trim()->split("\n"))
463 iunmap <S-/>
464 call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100465
466 " List global, buffer local and script local mappings
467 nmap ,f /^\k\+ (<CR>
468 nmap <buffer> ,f /^\k\+ (<CR>
469 nmap <script> ,fs /^\k\+ (<CR>
470 call assert_equal(['n ,f @/^\k\+ (<CR>',
471 \ 'n ,fs & /^\k\+ (<CR>',
472 \ 'n ,f /^\k\+ (<CR>'],
473 \ execute('nmap ,f')->trim()->split("\n"))
474
475 " List <Nop> mapping
476 nmap ,n <Nop>
477 call assert_equal(['n ,n <Nop>'],
478 \ execute('nmap ,n')->trim()->split("\n"))
479
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100480 " verbose map
Bram Moolenaar060b8382022-10-19 14:48:14 +0100481 let lines = execute('verbose map ,n')->trim()->split("\n")
Bram Moolenaarc255b782022-11-26 19:16:48 +0000482
483 " Remove "Seen modifyOtherKeys" and other optional info.
484 if lines[0] =~ 'Seen modifyOtherKeys'
485 call remove(lines, 0)
486 endif
487 if lines[0] =~ 'modifyOtherKeys detected:'
488 call remove(lines, 0)
489 endif
490 if lines[0] =~ 'Kitty keyboard protocol:'
491 call remove(lines, 0)
492 endif
493 if lines[0] == ''
494 call remove(lines, 0)
495 endif
496
Bram Moolenaar060b8382022-10-19 14:48:14 +0100497 let index = indexof(lines, 'v:val =~ "Last set"')
Bram Moolenaarc255b782022-11-26 19:16:48 +0000498 call assert_equal(1, index)
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100499 call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
Bram Moolenaar060b8382022-10-19 14:48:14 +0100500 \ lines[index])
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100501
zeertzjqac402f42022-05-04 18:51:43 +0100502 " character with K_SPECIAL byte in rhs
503 nmap foo …
504 call assert_equal(['n foo …'],
505 \ execute('nmap foo')->trim()->split("\n"))
506
507 " modified character with K_SPECIAL byte in rhs
508 nmap foo <M-…>
509 call assert_equal(['n foo <M-…>'],
510 \ execute('nmap foo')->trim()->split("\n"))
511
512 " character with K_SPECIAL byte in lhs
513 nmap … foo
514 call assert_equal(['n … foo'],
515 \ execute('nmap …')->trim()->split("\n"))
516
517 " modified character with K_SPECIAL byte in lhs
518 nmap <M-…> foo
519 call assert_equal(['n <M-…> foo'],
520 \ execute('nmap <M-…>')->trim()->split("\n"))
521
zeertzjq0519ce02022-05-09 12:16:19 +0100522 " illegal bytes
523 let str = ":\x7f:\x80:\x90:\xd0:"
524 exe 'nmap foo ' .. str
525 call assert_equal(['n foo ' .. strtrans(str)],
526 \ execute('nmap foo')->trim()->split("\n"))
527 unlet str
528
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100529 " map to CTRL-V
530 exe "nmap ,k \<C-V>"
531 call assert_equal(['n ,k <Nop>'],
532 \ execute('nmap ,k')->trim()->split("\n"))
533
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +0200534 " map with space at the beginning
535 exe "nmap \<C-V> w <Nop>"
536 call assert_equal(['n <Space>w <Nop>'],
537 \ execute("nmap \<C-V> w")->trim()->split("\n"))
538
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100539 nmapclear
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200540endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100541
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100542func Test_expr_map_gets_cursor()
543 new
544 call setline(1, ['one', 'some w!rd'])
545 func StoreColumn()
546 let g:exprLine = line('.')
547 let g:exprCol = col('.')
548 return 'x'
549 endfunc
550 nnoremap <expr> x StoreColumn()
551 2
552 nmap ! f!<Ignore>x
553 call feedkeys("!", 'xt')
554 call assert_equal('some wrd', getline(2))
555 call assert_equal(2, g:exprLine)
556 call assert_equal(7, g:exprCol)
557
558 bwipe!
559 unlet g:exprLine
560 unlet g:exprCol
Bram Moolenaar6ccfd992021-03-17 13:39:33 +0100561 delfunc StoreColumn
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100562 nunmap x
563 nunmap !
564endfunc
565
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100566func Test_expr_map_restore_cursor()
567 CheckScreendump
568
569 let lines =<< trim END
570 call setline(1, ['one', 'two', 'three'])
571 2
572 set ls=2
573 hi! link StatusLine ErrorMsg
574 noremap <expr> <C-B> Func()
575 func Func()
576 let g:on = !get(g:, 'on', 0)
577 redraws
578 return ''
579 endfunc
580 func Status()
581 return get(g:, 'on', 0) ? '[on]' : ''
582 endfunc
583 set stl=%{Status()}
584 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100585 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100586 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar9f145572022-11-27 12:45:41 +0000587 call term_sendkeys(buf, GetEscCodeWithModifier('C', 'B'))
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100588 call VerifyScreenDump(buf, 'Test_map_expr_1', {})
589
590 " clean up
591 call StopVimInTerminal(buf)
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100592endfunc
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100593
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000594func Test_map_listing()
595 CheckScreendump
596
597 let lines =<< trim END
598 nmap a b
599 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100600 call writefile(lines, 'XtestMapList', 'D')
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000601 let buf = RunVimInTerminal('-S XtestMapList', #{rows: 6})
602 call term_sendkeys(buf, ": nmap a\<CR>")
603 call VerifyScreenDump(buf, 'Test_map_list_1', {})
604
605 " clean up
606 call StopVimInTerminal(buf)
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000607endfunc
608
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000609func Test_expr_map_error()
610 CheckScreendump
611
612 let lines =<< trim END
613 func Func()
614 throw 'test'
615 return ''
616 endfunc
617
618 nnoremap <expr> <F2> Func()
619 cnoremap <expr> <F2> Func()
620
621 call test_override('ui_delay', 10)
622 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100623 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000624 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000625 call term_sendkeys(buf, "\<F2>")
626 call TermWait(buf)
627 call term_sendkeys(buf, "\<CR>")
628 call VerifyScreenDump(buf, 'Test_map_expr_2', {})
629
630 call term_sendkeys(buf, ":abc\<F2>")
631 call VerifyScreenDump(buf, 'Test_map_expr_3', {})
632 call term_sendkeys(buf, "\<Esc>0")
633 call VerifyScreenDump(buf, 'Test_map_expr_4', {})
634
635 " clean up
636 call StopVimInTerminal(buf)
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000637endfunc
638
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100639" Test for mapping errors
640func Test_map_error()
641 call assert_fails('unmap', 'E474:')
642 call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
643 call assert_fails('unmap abc', 'E31:')
644 call assert_fails('unabbr abc', 'E24:')
645 call assert_equal('', maparg(''))
646 call assert_fails('echo maparg("abc", [])', 'E730:')
647
648 " unique map
649 map ,w /[#&!]<CR>
650 call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
651 " unique buffer-local map
652 call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
653 unmap ,w
654
655 " unique abbreviation
656 abbr SP special
657 call assert_fails("abbr <unique> SP special", 'E226:')
658 " unique buffer-local map
659 call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
660 unabbr SP
661
662 call assert_fails('mapclear abc', 'E474:')
663 call assert_fails('abclear abc', 'E474:')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100664 call assert_fails('abbr $xyz abc', 'E474:')
665
666 " space character in an abbreviation
667 call assert_fails('abbr ab<space> ABC', 'E474:')
668
669 " invalid <expr> map
670 map <expr> ,f abc
671 call assert_fails('normal ,f', 'E121:')
672 unmap <expr> ,f
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100673
674 " Recursive use of :normal in a map
675 set maxmapdepth=100
676 map gq :normal gq<CR>
677 call assert_fails('normal gq', 'E192:')
678 unmap gq
679 set maxmapdepth&
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100680endfunc
681
682" Test for <special> key mapping
683func Test_map_special()
684 new
685 let old_cpo = &cpo
686 set cpo+=<
687 imap <F12> Blue
688 call feedkeys("i\<F12>", "x")
689 call assert_equal("<F12>", getline(1))
690 call feedkeys("ddi<F12>", "x")
691 call assert_equal("Blue", getline(1))
692 iunmap <F12>
693 imap <special> <F12> Green
694 call feedkeys("ddi\<F12>", "x")
695 call assert_equal("Green", getline(1))
696 call feedkeys("ddi<F12>", "x")
697 call assert_equal("<F12>", getline(1))
698 iunmap <special> <F12>
699 let &cpo = old_cpo
700 %bwipe!
701endfunc
702
703" Test for hasmapto()
704func Test_hasmapto()
705 call assert_equal(0, hasmapto('/^\k\+ ('))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100706 map ,f /^\k\+ (<CR>
707 call assert_equal(1, hasmapto('/^\k\+ ('))
708 unmap ,f
709
710 " Insert mode mapping
711 call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
712 imap ,f /^\k\+ (<CR>
713 call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
714 iunmap ,f
715
716 " Normal mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100717 call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
718 nmap ,f /^\k\+ (<CR>
719 call assert_equal(1, hasmapto('/^\k\+ ('))
720 call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100721 nunmap ,f
722
723 " Visual and Select mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100724 call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100725 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
726 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
727 vmap ,f /^\k\+ (<CR>
728 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
729 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
730 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
731 vunmap ,f
732
733 " Visual mode mapping
734 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
735 xmap ,f /^\k\+ (<CR>
736 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
737 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
738 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
739 xunmap ,f
740
741 " Select mode mapping
742 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
743 smap ,f /^\k\+ (<CR>
744 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
745 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
746 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
747 sunmap ,f
748
749 " Operator-pending mode mapping
750 call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
751 omap ,f /^\k\+ (<CR>
752 call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
753 ounmap ,f
754
755 " Language mapping
756 call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
757 lmap ,f /^\k\+ (<CR>
758 call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
759 lunmap ,f
760
761 " Cmdline mode mapping
762 call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
763 cmap ,f /^\k\+ (<CR>
764 call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
765 cunmap ,f
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100766
767 call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
768endfunc
769
770" Test for command-line completion of maps
771func Test_mapcomplete()
772 call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
773 \ '<silent>', '<special>', '<unique>'],
774 \ getcompletion('', 'mapping'))
775 call assert_equal([], getcompletion(',d', 'mapping'))
776
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100777 call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
778 call assert_equal('"unmap <buffer>', @:)
779
780 call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
781 call assert_equal('"unabbr <buffer>', @:)
782
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100783 call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100784 call assert_equal("\"abbr! \x01", @:)
785
zeertzjq997b8a02023-02-19 21:00:31 +0000786 " When multiple matches have the same {lhs}, it should only appear once.
787 " The simplified form should also not be included.
788 nmap ,<C-F> /H<CR>
789 omap ,<C-F> /H<CR>
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100790 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
zeertzjq997b8a02023-02-19 21:00:31 +0000791 call assert_equal('"map ,<C-F>', @:)
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100792 mapclear
793endfunc
794
Bram Moolenaar94075b22022-01-18 20:30:39 +0000795func GetAbbrText()
796 unabbr hola
797 return 'hello'
798endfunc
799
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100800" Test for <expr> in abbreviation
801func Test_expr_abbr()
802 new
803 iabbr <expr> teh "the"
804 call feedkeys("iteh ", "tx")
805 call assert_equal('the ', getline(1))
806 iabclear
807 call setline(1, '')
808
809 " invalid <expr> abbreviation
810 abbr <expr> hte GetAbbr()
811 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100812 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100813 unabbr <expr> hte
814
Bram Moolenaar94075b22022-01-18 20:30:39 +0000815 " evaluating the expression deletes the abbreviation
816 abbr <expr> hola GetAbbrText()
817 call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
818 call feedkeys("ahola \<Esc>", 'xt')
819 call assert_equal('hello ', getline('.'))
820 call assert_equal('', maparg('hola', 'i', '1'))
821
822 bwipe!
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100823endfunc
824
825" Test for storing mappings in different modes in a vimrc file
826func Test_mkvimrc_mapmodes()
827 map a1 /a1
828 nmap a2 /a2
829 vmap a3 /a3
830 smap a4 /a4
831 xmap a5 /a5
832 omap a6 /a6
833 map! a7 /a7
834 imap a8 /a8
835 lmap a9 /a9
836 cmap a10 /a10
837 tmap a11 /a11
838 " Normal + Visual map
839 map a12 /a12
840 sunmap a12
841 ounmap a12
842 " Normal + Selectmode map
843 map a13 /a13
844 xunmap a13
845 ounmap a13
846 " Normal + OpPending map
847 map a14 /a14
848 vunmap a14
849 " Visual + Selectmode map
850 map a15 /a15
851 nunmap a15
852 ounmap a15
853 " Visual + OpPending map
854 map a16 /a16
855 nunmap a16
856 sunmap a16
857 " Selectmode + OpPending map
858 map a17 /a17
859 nunmap a17
860 xunmap a17
861 " Normal + Visual + Selectmode map
862 map a18 /a18
863 ounmap a18
864 " Normal + Visual + OpPending map
865 map a19 /a19
866 sunmap a19
867 " Normal + Selectmode + OpPending map
868 map a20 /a20
869 xunmap a20
870 " Visual + Selectmode + OpPending map
871 map a21 /a21
872 nunmap a21
873 " Mapping to Nop
874 map a22 <Nop>
875 " Script local mapping
876 map <script> a23 /a23
877
878 " Newline in {lhs} and {rhs} of a map
879 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
880
881 " Abbreviation
882 abbr a25 A25
883 cabbr a26 A26
884 iabbr a27 A27
885
886 mkvimrc! Xvimrc
887 let l = readfile('Xvimrc')
888 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
889 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
890 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
891 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
892 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
893 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
894 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
895 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
896 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
897 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
898 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
899 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
900 \ filter(copy(l), 'v:val =~ " a12 "'))
901 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
902 \ filter(copy(l), 'v:val =~ " a13 "'))
903 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
904 \ filter(copy(l), 'v:val =~ " a14 "'))
905 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
906 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
907 \ filter(copy(l), 'v:val =~ " a16 "'))
908 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
909 \ filter(copy(l), 'v:val =~ " a17 "'))
910 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
911 \ filter(copy(l), 'v:val =~ " a18 "'))
912 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
913 \ filter(copy(l), 'v:val =~ " a19 "'))
914 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
915 \ filter(copy(l), 'v:val =~ " a20 "'))
916 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
917 \ filter(copy(l), 'v:val =~ " a21 "'))
918 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
919 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
920 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
921 \ filter(copy(l), 'v:val =~ " a24"'))
922
923 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
924 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
925 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
926 call delete('Xvimrc')
927
928 mapclear
929 nmapclear
930 vmapclear
931 xmapclear
932 smapclear
933 omapclear
934 imapclear
935 lmapclear
936 cmapclear
937 tmapclear
938endfunc
939
940" Test for recursive mapping ('maxmapdepth')
941func Test_map_recursive()
942 map x y
943 map y x
944 call assert_fails('normal x', 'E223:')
945 unmap x
946 unmap y
947endfunc
948
949" Test for removing an abbreviation using {rhs} and with space after {lhs}
950func Test_abbr_remove()
951 abbr foo bar
952 let d = maparg('foo', 'i', 1, 1)
953 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
954 unabbr bar
955 call assert_equal({}, maparg('foo', 'i', 1, 1))
956
957 abbr foo bar
958 unabbr foo<space><tab>
959 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100960endfunc
961
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100962" Trigger an abbreviation using a special key
963func Test_abbr_trigger_special()
964 new
965 iabbr teh the
966 call feedkeys("iteh\<F2>\<Esc>", 'xt')
967 call assert_equal('the<F2>', getline(1))
968 iunab teh
969 close!
970endfunc
971
972" Test for '<' in 'cpoptions'
973func Test_map_cpo_special_keycode()
974 set cpo-=<
975 imap x<Bslash>k Test
976 let d = maparg('x<Bslash>k', 'i', 0, 1)
977 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
978 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
979 call assert_equal('"imap x\k', @:)
980 iunmap x<Bslash>k
981 set cpo+=<
982 imap x<Bslash>k Test
983 let d = maparg('x<Bslash>k', 'i', 0, 1)
984 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
985 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
986 call assert_equal('"imap x<Bslash>k', @:)
987 iunmap x<Bslash>k
988 set cpo-=<
989 " Modifying 'cpo' above adds some default mappings, remove them
990 mapclear
991 mapclear!
992endfunc
993
Bram Moolenaar957cf672020-11-12 14:21:06 +0100994" Test for <Cmd> key in maps to execute commands
995func Test_map_cmdkey()
996 new
997
998 " Error cases
999 let x = 0
1000 noremap <F3> <Cmd><Cmd>let x = 1<CR>
1001 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
1002 call assert_equal(0, x)
1003
1004 noremap <F3> <Cmd><F3>let x = 2<CR>
1005 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1137:')
1006 call assert_equal(0, x)
1007
1008 noremap <F3> <Cmd>let x = 3
Bram Moolenaar806da512021-12-24 19:54:52 +00001009 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001010 call assert_equal(0, x)
1011
1012 " works in various modes and sees the correct mode()
1013 noremap <F3> <Cmd>let m = mode(1)<CR>
1014 noremap! <F3> <Cmd>let m = mode(1)<CR>
1015
1016 " normal mode
1017 call feedkeys("\<F3>", 'xt')
1018 call assert_equal('n', m)
1019
1020 " visual mode
1021 call feedkeys("v\<F3>", 'xt!')
1022 call assert_equal('v', m)
1023 " shouldn't leave the visual mode
1024 call assert_equal('v', mode(1))
1025 call feedkeys("\<Esc>", 'xt')
1026 call assert_equal('n', mode(1))
1027
1028 " visual mapping in select mode
1029 call feedkeys("gh\<F3>", 'xt!')
1030 call assert_equal('v', m)
1031 " shouldn't leave select mode
1032 call assert_equal('s', mode(1))
1033 call feedkeys("\<Esc>", 'xt')
1034 call assert_equal('n', mode(1))
1035
1036 " select mode mapping
1037 snoremap <F3> <Cmd>let m = mode(1)<cr>
1038 call feedkeys("gh\<F3>", 'xt!')
1039 call assert_equal('s', m)
1040 " shouldn't leave select mode
1041 call assert_equal('s', mode(1))
1042 call feedkeys("\<Esc>", 'xt')
1043 call assert_equal('n', mode(1))
1044
1045 " operator-pending mode
1046 call feedkeys("d\<F3>", 'xt!')
1047 call assert_equal('no', m)
1048 " leaves the operator-pending mode
1049 call assert_equal('n', mode(1))
1050
1051 " insert mode
1052 call feedkeys("i\<F3>abc", 'xt')
1053 call assert_equal('i', m)
1054 call assert_equal('abc', getline('.'))
1055
1056 " replace mode
1057 call feedkeys("0R\<F3>two", 'xt')
1058 call assert_equal('R', m)
1059 call assert_equal('two', getline('.'))
1060
1061 " virtual replace mode
1062 call setline('.', "one\ttwo")
1063 call feedkeys("4|gR\<F3>xxx", 'xt')
1064 call assert_equal('Rv', m)
1065 call assert_equal("onexxx\ttwo", getline('.'))
1066
1067 " cmdline mode
1068 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
1069 call assert_equal('c', m)
1070 call assert_equal('"xxx', @:)
1071
1072 " terminal mode
1073 if CanRunVimInTerminal()
1074 tnoremap <F3> <Cmd>let m = mode(1)<CR>
1075 let buf = Run_shell_in_terminal({})
1076 call feedkeys("\<F3>", 'xt')
1077 call assert_equal('t', m)
1078 call assert_equal('t', mode(1))
1079 call StopShellInTerminal(buf)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001080 close!
1081 tunmap <F3>
1082 endif
1083
1084 " invoke cmdline mode recursively
1085 noremap! <F2> <Cmd>norm! :foo<CR>
1086 %d
1087 call setline(1, ['some short lines', 'of test text'])
1088 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
1089 call assert_equal('"barx', @:)
1090 unmap! <F2>
1091
1092 " test for calling a <SID> function
1093 let lines =<< trim END
1094 map <F2> <Cmd>call <SID>do_it()<CR>
1095 func s:do_it()
1096 let g:x = 32
1097 endfunc
1098 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001099 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001100 source Xscript
1101 call feedkeys("\<F2>", 'xt')
1102 call assert_equal(32, g:x)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001103
1104 unmap <F3>
1105 unmap! <F3>
1106 %bw!
Bram Moolenaar4a441202020-11-28 14:43:26 +01001107
1108 " command line ending in "0" is handled without errors
1109 onoremap ix <cmd>eval 0<cr>
1110 call feedkeys('dix.', 'xt')
1111 ounmap ix
Bram Moolenaar957cf672020-11-12 14:21:06 +01001112endfunc
1113
1114" text object enters visual mode
1115func TextObj()
1116 if mode() !=# "v"
1117 normal! v
1118 end
1119 call cursor(1, 3)
1120 normal! o
1121 call cursor(2, 4)
1122endfunc
1123
1124func s:cmdmap(lhs, rhs)
1125 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1126 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1127endfunc
1128
1129func s:cmdunmap(lhs)
1130 exe 'unmap ' .. a:lhs
1131 exe 'unmap! ' .. a:lhs
1132endfunc
1133
1134" Map various <Fx> keys used by the <Cmd> key tests
1135func s:setupMaps()
1136 call s:cmdmap('<F3>', 'let m = mode(1)')
1137 call s:cmdmap('<F4>', 'normal! ww')
1138 call s:cmdmap('<F5>', 'normal! "ay')
1139 call s:cmdmap('<F6>', 'throw "very error"')
1140 call s:cmdmap('<F7>', 'call TextObj()')
1141 call s:cmdmap('<F8>', 'startinsert')
1142 call s:cmdmap('<F9>', 'stopinsert')
1143endfunc
1144
1145" Remove the mappings setup by setupMaps()
1146func s:cleanupMaps()
1147 call s:cmdunmap('<F3>')
1148 call s:cmdunmap('<F4>')
1149 call s:cmdunmap('<F5>')
1150 call s:cmdunmap('<F6>')
1151 call s:cmdunmap('<F7>')
1152 call s:cmdunmap('<F8>')
1153 call s:cmdunmap('<F9>')
1154endfunc
1155
1156" Test for <Cmd> mapping in normal mode
1157func Test_map_cmdkey_normal_mode()
1158 new
1159 call s:setupMaps()
1160
1161 " check v:count and v:register works
1162 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1163 call feedkeys("\<F2>", 'xt')
1164 call assert_equal(['n', 0, '"'], s)
1165 call feedkeys("7\<F2>", 'xt')
1166 call assert_equal(['n', 7, '"'], s)
1167 call feedkeys("\"e\<F2>", 'xt')
1168 call assert_equal(['n', 0, 'e'], s)
1169 call feedkeys("5\"k\<F2>", 'xt')
1170 call assert_equal(['n', 5, 'k'], s)
1171 call s:cmdunmap('<F2>')
1172
1173 call setline(1, ['some short lines', 'of test text'])
1174 call feedkeys("\<F7>y", 'xt')
1175 call assert_equal("me short lines\nof t", @")
1176 call assert_equal('v', getregtype('"'))
1177 call assert_equal([0, 1, 3, 0], getpos("'<"))
1178 call assert_equal([0, 2, 4, 0], getpos("'>"))
1179
1180 " startinsert
1181 %d
1182 call feedkeys("\<F8>abc", 'xt')
1183 call assert_equal('abc', getline(1))
1184
1185 " feedkeys are not executed immediately
1186 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1187 %d
1188 call setline(1, ['some short lines', 'of test text'])
1189 call cursor(2, 3)
1190 call feedkeys(",a\<F3>", 'xt')
1191 call assert_equal('of test text', g:a)
1192 call assert_equal('n', m)
1193 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1194 nunmap ,a
1195
1196 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1197 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1198 call feedkeys(",b\<F3>", 'xt')
1199 call assert_equal('n', m)
1200 call assert_equal('of alphabetatest text', g:b)
1201 nunmap ,b
1202
1203 call s:cleanupMaps()
1204 %bw!
1205endfunc
1206
1207" Test for <Cmd> mapping with the :normal command
1208func Test_map_cmdkey_normal_cmd()
1209 new
1210 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1211 noremap ,f <Cmd>nosuchcommand<CR>
1212 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1213 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1214 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1215
1216 call setline(1, ['some short lines', 'of test text'])
1217 exe "norm ,x\r"
1218 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1219
1220 call assert_fails('norm ,f', 'E492:')
1221 call assert_fails('norm ,e', 'very error')
1222 call assert_fails('norm ,m', 'The message.')
1223 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1224
1225 %d
1226 let caught_err = 0
1227 try
1228 exe "normal ,w"
1229 catch /Vim(echoerr):Err/
1230 let caught_err = 1
1231 endtry
1232 call assert_equal(1, caught_err)
1233 call assert_equal(['', '0'], getline(1, '$'))
1234
1235 %d
1236 call assert_fails('normal ,w', 'Err')
1237 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1238 call assert_equal(1, line('.'))
1239
1240 nunmap ,x
1241 nunmap ,f
1242 nunmap ,e
1243 nunmap ,m
1244 nunmap ,w
1245 %bw!
1246endfunc
1247
1248" Test for <Cmd> mapping in visual mode
1249func Test_map_cmdkey_visual_mode()
1250 new
1251 set showmode
1252 call s:setupMaps()
1253
1254 call setline(1, ['some short lines', 'of test text'])
1255 call feedkeys("v\<F4>", 'xt!')
1256 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1257
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +01001258 " can invoke an operator, ending the visual mode
Bram Moolenaar957cf672020-11-12 14:21:06 +01001259 let @a = ''
1260 call feedkeys("\<F5>", 'xt!')
1261 call assert_equal('n', mode(1))
1262 call assert_equal('some short l', @a)
1263
1264 " error doesn't interrupt visual mode
1265 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1266 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1267 call feedkeys("\<F7>", 'xt!')
1268 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1269
1270 " startinsert gives "-- (insert) VISUAL --" mode
1271 call feedkeys("\<F8>", 'xt!')
1272 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1273 redraw!
1274 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1275 call feedkeys("\<Esc>new ", 'x')
1276 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1277
1278 call s:cleanupMaps()
1279 set showmode&
1280 %bw!
1281endfunc
1282
1283" Test for <Cmd> mapping in select mode
1284func Test_map_cmdkey_select_mode()
1285 new
1286 set showmode
1287 call s:setupMaps()
1288
1289 snoremap <F1> <cmd>throw "very error"<CR>
1290 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1291 call setline(1, ['some short lines', 'of test text'])
1292
1293 call feedkeys("gh\<F4>", "xt!")
1294 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1295 redraw!
1296 call assert_match('^-- SELECT --', Screenline(&lines))
1297
1298 " visual mapping in select mode restarts select mode after operator
1299 let @a = ''
1300 call feedkeys("\<F5>", 'xt!')
1301 call assert_equal('s', mode(1))
1302 call assert_equal('some short l', @a)
1303
1304 " select mode mapping works, and does not restart select mode
1305 let @b = ''
1306 call feedkeys("\<F2>", 'xt!')
1307 call assert_equal('n', mode(1))
1308 call assert_equal('some short l', @b)
1309
1310 " error doesn't interrupt temporary visual mode
1311 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1312 redraw!
1313 call assert_match('^-- VISUAL --', Screenline(&lines))
1314 " quirk: restoration of select mode is not performed
1315 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1316
1317 " error doesn't interrupt select mode
1318 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1319 redraw!
1320 call assert_match('^-- SELECT --', Screenline(&lines))
1321 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1322
1323 call feedkeys("\<F7>", 'xt!')
1324 redraw!
1325 call assert_match('^-- SELECT --', Screenline(&lines))
1326 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1327
1328 " startinsert gives "-- SELECT (insert) --" mode
1329 call feedkeys("\<F8>", 'xt!')
1330 redraw!
1331 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1332 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1333 call feedkeys("\<Esc>new ", 'x')
1334 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1335
1336 sunmap <F1>
1337 sunmap <F2>
1338 call s:cleanupMaps()
1339 set showmode&
1340 %bw!
1341endfunc
1342
1343" Test for <Cmd> mapping in operator-pending mode
1344func Test_map_cmdkey_op_pending_mode()
1345 new
1346 call s:setupMaps()
1347
1348 call setline(1, ['some short lines', 'of test text'])
1349 call feedkeys("d\<F4>", 'xt')
1350 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1351 call assert_equal(['some short '], getreg('"', 1, 1))
1352 " create a new undo point
1353 let &undolevels = &undolevels
1354
1355 call feedkeys(".", 'xt')
1356 call assert_equal(['test text'], getline(1, '$'))
1357 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1358 " create a new undo point
1359 let &undolevels = &undolevels
1360
1361 call feedkeys("uu", 'xt')
1362 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1363
1364 " error aborts operator-pending, operator not performed
1365 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1366 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1367
1368 call feedkeys("\"bd\<F7>", 'xt')
1369 call assert_equal(['soest text'], getline(1, '$'))
1370 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1371
1372 " startinsert aborts operator
1373 call feedkeys("d\<F8>cc", 'xt')
1374 call assert_equal(['soccest text'], getline(1, '$'))
1375
1376 call s:cleanupMaps()
1377 %bw!
1378endfunc
1379
1380" Test for <Cmd> mapping in insert mode
1381func Test_map_cmdkey_insert_mode()
1382 new
1383 call s:setupMaps()
1384
1385 call setline(1, ['some short lines', 'of test text'])
1386 " works the same as <C-O>w<C-O>w
1387 call feedkeys("iindeed \<F4>little ", 'xt')
1388 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1389 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1390 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1391
1392 " Note when entering visual mode from InsertEnter autocmd, an async event,
1393 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1394 call feedkeys("i\<F7>stuff ", 'xt')
1395 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1396 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1397
1398 call feedkeys("\<F5>", 'xt')
1399 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1400
1401 " also works as part of abbreviation
1402 abbr foo <Cmd>let g:y = 17<CR>bar
1403 exe "normal i\<space>foo "
1404 call assert_equal(17, g:y)
1405 call assert_equal('in bar deed some short little 2 lines', getline(1))
1406 unabbr foo
1407
1408 " :startinsert does nothing
1409 call setline(1, 'foo bar')
1410 call feedkeys("ggi\<F8>vim", 'xt')
1411 call assert_equal('vimfoo bar', getline(1))
1412
1413 " :stopinsert works
1414 call feedkeys("ggi\<F9>Abc", 'xt')
1415 call assert_equal('vimfoo barbc', getline(1))
1416
1417 call s:cleanupMaps()
1418 %bw!
1419endfunc
1420
1421" Test for <Cmd> mapping in insert-completion mode
1422func Test_map_cmdkey_insert_complete_mode()
1423 new
1424 call s:setupMaps()
1425
1426 call setline(1, 'some short lines')
1427 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1428 call assert_equal('ic', m)
1429 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1430
1431 call s:cleanupMaps()
1432 %bw!
1433endfunc
1434
1435" Test for <Cmd> mapping in cmdline mode
1436func Test_map_cmdkey_cmdline_mode()
1437 new
1438 call s:setupMaps()
1439
1440 call setline(1, ['some short lines', 'of test text'])
1441 let x = 0
1442 call feedkeys(":let x\<F3>= 10\r", 'xt')
1443 call assert_equal('c', m)
1444 call assert_equal(10, x)
1445
1446 " exception doesn't leave cmdline mode
1447 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1448 call assert_equal(20, x)
1449
1450 " move cursor in the buffer from cmdline mode
1451 call feedkeys(":let x\<F4>= 30\r", 'xt')
1452 call assert_equal(30, x)
1453 call assert_equal(12, col('.'))
1454
1455 " :startinsert takes effect after leaving cmdline mode
1456 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1457 call assert_equal(40, x)
1458 call assert_equal('some short new lines', getline(1))
1459
1460 call s:cleanupMaps()
1461 %bw!
1462endfunc
1463
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001464func Test_map_cmdkey_redo()
1465 func SelectDash()
1466 call search('^---\n\zs', 'bcW')
1467 norm! V
1468 call search('\n\ze---$', 'W')
1469 endfunc
1470
1471 let text =<< trim END
1472 ---
1473 aaa
1474 ---
1475 bbb
1476 bbb
1477 ---
1478 ccc
1479 ccc
1480 ccc
1481 ---
1482 END
1483 new Xcmdtext
1484 call setline(1, text)
1485
1486 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1487 call feedkeys('2Gdi-', 'xt')
1488 call assert_equal(['---', '---'], getline(1, 2))
1489 call feedkeys('j.', 'xt')
1490 call assert_equal(['---', '---', '---'], getline(1, 3))
1491 call feedkeys('j.', 'xt')
1492 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1493
1494 bwipe!
1495 call delete('Xcmdtext')
1496 delfunc SelectDash
1497 ounmap i-
1498endfunc
1499
Bram Moolenaara9725222022-01-16 13:30:33 +00001500func Test_map_script_cmd_restore()
1501 let lines =<< trim END
1502 vim9script
1503 nnoremap <F3> <ScriptCmd>eval 1 + 2<CR>
1504 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001505 call v9.CheckScriptSuccess(lines)
Bram Moolenaara9725222022-01-16 13:30:33 +00001506 call feedkeys("\<F3>:let g:result = 3+4\<CR>", 'xtc')
1507 call assert_equal(7, g:result)
1508
1509 nunmap <F3>
1510 unlet g:result
1511endfunc
1512
Bram Moolenaardc987762022-01-16 15:52:35 +00001513func Test_map_script_cmd_finds_func()
1514 let lines =<< trim END
1515 vim9script
1516 onoremap <F3> <ScriptCmd>Func()<CR>
1517 def Func()
1518 g:func_called = 'yes'
1519 enddef
1520 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001521 call v9.CheckScriptSuccess(lines)
Bram Moolenaardc987762022-01-16 15:52:35 +00001522 call feedkeys("y\<F3>\<Esc>", 'xtc')
1523 call assert_equal('yes', g:func_called)
1524
1525 ounmap <F3>
1526 unlet g:func_called
1527endfunc
1528
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001529func Test_map_script_cmd_survives_unmap()
1530 let lines =<< trim END
1531 vim9script
1532 var n = 123
1533 nnoremap <F4> <ScriptCmd><CR>
1534 autocmd CmdlineEnter * silent! nunmap <F4>
1535 nnoremap <F3> :<ScriptCmd>eval setbufvar(bufnr(), "result", n)<CR>
1536 feedkeys("\<F3>\<CR>", 'xct')
1537 assert_equal(123, b:result)
1538 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001539 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001540
1541 nunmap <F3>
1542 unlet b:result
Bram Moolenaarca34db32022-01-20 11:17:18 +00001543 autocmd! CmdlineEnter
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001544endfunc
1545
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001546func Test_map_script_cmd_redo()
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001547 call mkdir('Xmapcmd', 'R')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001548 let lines =<< trim END
1549 vim9script
1550 import autoload './script.vim'
1551 onoremap <F3> <ScriptCmd>script.Func()<CR>
1552 END
1553 call writefile(lines, 'Xmapcmd/plugin.vim')
1554
1555 let lines =<< trim END
1556 vim9script
1557 export def Func()
1558 normal! dd
1559 enddef
1560 END
1561 call writefile(lines, 'Xmapcmd/script.vim')
1562 new
1563 call setline(1, ['one', 'two', 'three', 'four'])
1564 nnoremap j j
1565 source Xmapcmd/plugin.vim
1566 call feedkeys("d\<F3>j.", 'xt')
1567 call assert_equal(['two', 'four'], getline(1, '$'))
1568
1569 ounmap <F3>
1570 nunmap j
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001571 bwipe!
1572endfunc
1573
Bram Moolenaar1f448d92021-03-22 19:37:06 +01001574" Test for using <script> with a map to remap characters in rhs
1575func Test_script_local_remap()
1576 new
1577 inoremap <buffer> <SID>xyz mno
1578 inoremap <buffer> <script> abc st<SID>xyzre
1579 normal iabc
1580 call assert_equal('stmnore', getline(1))
1581 bwipe!
1582endfunc
1583
Bram Moolenaar4934ed32021-04-30 19:43:11 +02001584func Test_abbreviate_multi_byte()
1585 new
1586 iabbrev foo bar
1587 call feedkeys("ifoo…\<Esc>", 'xt')
1588 call assert_equal("bar…", getline(1))
1589 iunabbrev foo
1590 bwipe!
1591endfunc
1592
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +02001593" Test for abbreviations with 'latin1' encoding
1594func Test_abbreviate_latin1_encoding()
1595 set encoding=latin1
1596 call assert_fails('abbr ab#$c ABC', 'E474:')
1597 new
1598 iabbr <buffer> #i #include
1599 iabbr <buffer> ## #enddef
1600 exe "normal i#i\<C-]>"
1601 call assert_equal('#include', getline(1))
1602 exe "normal 0Di##\<C-]>"
1603 call assert_equal('#enddef', getline(1))
1604 %bw!
1605 set encoding=utf-8
1606endfunc
1607
Bram Moolenaar1fc34222022-03-03 13:56:24 +00001608" Test for <Plug> always being mapped, even when used with "noremap".
1609func Test_plug_remap()
1610 let g:foo = 0
1611 nnoremap <Plug>(Increase_x) <Cmd>let g:foo += 1<CR>
1612 nmap <F2> <Plug>(Increase_x)
1613 nnoremap <F3> <Plug>(Increase_x)
1614 call feedkeys("\<F2>", 'xt')
1615 call assert_equal(1, g:foo)
1616 call feedkeys("\<F3>", 'xt')
1617 call assert_equal(2, g:foo)
1618 nnoremap x <Nop>
1619 nmap <F4> x<Plug>(Increase_x)x
1620 nnoremap <F5> x<Plug>(Increase_x)x
1621 call setline(1, 'Some text')
1622 normal! gg$
1623 call feedkeys("\<F4>", 'xt')
1624 call assert_equal(3, g:foo)
1625 call assert_equal('Some text', getline(1))
1626 call feedkeys("\<F5>", 'xt')
1627 call assert_equal(4, g:foo)
1628 call assert_equal('Some te', getline(1))
1629 nunmap <Plug>(Increase_x)
1630 nunmap <F2>
1631 nunmap <F3>
1632 nunmap <F4>
1633 nunmap <F5>
1634 unlet g:foo
1635 %bw!
1636endfunc
1637
zeertzjqac92ab72022-04-24 15:58:30 +01001638func Test_mouse_drag_mapped_start_select()
1639 set mouse=a
1640 set selectmode=key,mouse
1641 func ClickExpr()
1642 call test_setmouse(1, 1)
1643 return "\<LeftMouse>"
1644 endfunc
1645 func DragExpr()
1646 call test_setmouse(1, 2)
1647 return "\<LeftDrag>"
1648 endfunc
1649 nnoremap <expr> <F2> ClickExpr()
1650 nmap <expr> <F3> DragExpr()
1651
1652 nnoremap <LeftDrag> <LeftDrag><Cmd><CR>
1653 exe "normal \<F2>\<F3>"
1654 call assert_equal('s', mode())
1655 exe "normal! \<C-\>\<C-N>"
1656
1657 nunmap <LeftDrag>
1658 nunmap <F2>
1659 nunmap <F3>
1660 delfunc ClickExpr
1661 delfunc DragExpr
1662 set selectmode&
1663 set mouse&
1664endfunc
1665
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001666func Test_mouse_drag_statusline()
1667 set laststatus=2
1668 set mouse=a
1669 func ClickExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001670 call test_setmouse(&lines - 1, 1)
1671 return "\<LeftMouse>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001672 endfunc
1673 func DragExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001674 call test_setmouse(&lines - 2, 1)
1675 return "\<LeftDrag>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001676 endfunc
1677 nnoremap <expr> <F2> ClickExpr()
1678 nnoremap <expr> <F3> DragExpr()
1679
1680 " this was causing a crash in win_drag_status_line()
1681 call feedkeys("\<F2>:tabnew\<CR>\<F3>", 'tx')
zeertzjq873f41a2022-11-01 11:44:43 +00001682
1683 nunmap <F2>
1684 nunmap <F3>
1685 delfunc ClickExpr
1686 delfunc DragExpr
1687 set laststatus& mouse&
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001688endfunc
1689
zeertzjq0f68e6c2022-04-05 13:17:01 +01001690" Test for mapping <LeftDrag> in Insert mode
1691func Test_mouse_drag_insert_map()
1692 set mouse=a
1693 func ClickExpr()
1694 call test_setmouse(1, 1)
1695 return "\<LeftMouse>"
1696 endfunc
1697 func DragExpr()
1698 call test_setmouse(1, 2)
1699 return "\<LeftDrag>"
1700 endfunc
1701 inoremap <expr> <F2> ClickExpr()
1702 imap <expr> <F3> DragExpr()
1703
1704 inoremap <LeftDrag> <LeftDrag><Cmd>let g:dragged = 1<CR>
1705 exe "normal i\<F2>\<F3>"
1706 call assert_equal(1, g:dragged)
1707 call assert_equal('v', mode())
1708 exe "normal! \<C-\>\<C-N>"
1709 unlet g:dragged
1710
1711 inoremap <LeftDrag> <LeftDrag><C-\><C-N>
1712 exe "normal i\<F2>\<F3>"
1713 call assert_equal('n', mode())
1714
1715 iunmap <LeftDrag>
1716 iunmap <F2>
1717 iunmap <F3>
1718 delfunc ClickExpr
1719 delfunc DragExpr
1720 set mouse&
1721endfunc
1722
zeertzjqabeb09b2022-04-26 12:29:43 +01001723func Test_unmap_simplifiable()
zeertzjqa4e33322022-04-24 17:07:53 +01001724 map <C-I> foo
1725 map <Tab> bar
1726 call assert_equal('foo', maparg('<C-I>'))
1727 call assert_equal('bar', maparg('<Tab>'))
1728 unmap <C-I>
1729 call assert_equal('', maparg('<C-I>'))
1730 call assert_equal('bar', maparg('<Tab>'))
1731 unmap <Tab>
zeertzjqabeb09b2022-04-26 12:29:43 +01001732
1733 map <C-I> foo
1734 unmap <Tab>
1735 " This should not error
1736 unmap <C-I>
zeertzjqa4e33322022-04-24 17:07:53 +01001737endfunc
1738
zeertzjqdb088872022-05-02 22:53:45 +01001739func Test_expr_map_escape_special()
1740 nnoremap <Cmd>let g:got_ellipsis += 1<CR>
1741 func Func()
1742 return '…'
1743 endfunc
1744 nmap <expr> <F2> Func()
1745 let g:got_ellipsis = 0
1746 call feedkeys("\<F2>", 'xt')
1747 call assert_equal(1, g:got_ellipsis)
1748 delfunc Func
1749 nunmap <F2>
1750 unlet g:got_ellipsis
1751 nunmap
1752endfunc
1753
zeertzjq3760bfd2022-06-06 16:22:46 +01001754" Testing for mapping after an <Nop> mapping is triggered on timeout.
1755" Test for what patch 8.1.0052 fixes.
1756func Test_map_after_timed_out_nop()
1757 CheckRunVimInTerminal
1758
1759 let lines =<< trim END
1760 set timeout timeoutlen=400
1761 inoremap ab TEST
1762 inoremap a <Nop>
1763 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001764 call writefile(lines, 'Xtest_map_after_timed_out_nop', 'D')
zeertzjq3760bfd2022-06-06 16:22:46 +01001765 let buf = RunVimInTerminal('-S Xtest_map_after_timed_out_nop', #{rows: 6})
1766
1767 " Enter Insert mode
1768 call term_sendkeys(buf, 'i')
1769 " Wait for the "a" mapping to timeout
1770 call term_sendkeys(buf, 'a')
1771 call term_wait(buf, 500)
1772 " Send "a" and wait for a period shorter than 'timeoutlen'
1773 call term_sendkeys(buf, 'a')
1774 call term_wait(buf, 100)
1775 " Send "b", should trigger the "ab" mapping
1776 call term_sendkeys(buf, 'b')
1777 call WaitForAssert({-> assert_equal("TEST", term_getline(buf, 1))})
1778
1779 " clean up
1780 call StopVimInTerminal(buf)
zeertzjq3760bfd2022-06-06 16:22:46 +01001781endfunc
1782
Bram Moolenaar27efc622022-07-01 16:35:45 +01001783func Test_using_past_typeahead()
1784 nnoremap :00 0
1785 exe "norm :set \x80\xfb0=0\<CR>"
1786 exe "sil norm :0\x0f\<C-U>\<CR>"
1787
1788 exe "norm :set \x80\xfb0=\<CR>"
1789 nunmap :00
1790endfunc
1791
Bram Moolenaarbf533e42022-11-13 20:43:19 +00001792func Test_mapclear_while_listing()
1793 CheckRunVimInTerminal
1794
1795 let lines =<< trim END
1796 set nocompatible
1797 mapclear
1798 for i in range(1, 999)
1799 exe 'map ' .. 'foo' .. i .. ' bar'
1800 endfor
1801 au CmdlineLeave : call timer_start(0, {-> execute('mapclear')})
1802 END
1803 call writefile(lines, 'Xmapclear', 'D')
1804 let buf = RunVimInTerminal('-S Xmapclear', {'rows': 10})
1805
1806 " this was using freed memory
1807 call term_sendkeys(buf, ":map\<CR>")
1808 call TermWait(buf, 50)
1809 call term_sendkeys(buf, "G")
1810 call TermWait(buf, 50)
1811 call term_sendkeys(buf, "\<CR>")
1812
1813 call StopVimInTerminal(buf)
1814endfunc
1815
Bram Moolenaar27efc622022-07-01 16:35:45 +01001816
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001817" vim: shiftwidth=2 sts=2 expandtab