blob: 309be7122691cbd549d04b6422fc1b79dd64b491 [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()
251 if has('gui_gtk') || has('gui_gtk3') || has("macos")
252 imap <D-"> foo
253 call feedkeys("Go-\<*D-\">-\<Esc>", "xt")
254 call assert_equal("-foo-", getline('$'))
255 set nomodified
256 iunmap <D-">
257 endif
258endfunc
259
260func Test_map_super_multibyte()
261 if has('gui_gtk') || has('gui_gtk3') || has("macos")
262 imap <D-á> foo
263 call assert_match('i <D-á>\s*foo', execute('imap'))
264 iunmap <D-á>
265 endif
266endfunc
267
Bram Moolenaar878c2632017-04-01 15:15:52 +0200268func Test_abbr_after_line_join()
269 new
270 abbr foo bar
271 set backspace=indent,eol,start
272 exe "normal o\<BS>foo "
273 call assert_equal("bar ", getline(1))
274 bwipe!
275 unabbr foo
276 set backspace&
277endfunc
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200278
279func Test_map_timeout()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200280 CheckFeature timers
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200281 nnoremap aaaa :let got_aaaa = 1<CR>
282 nnoremap bb :let got_bb = 1<CR>
283 nmap b aaa
284 new
285 func ExitInsert(timer)
286 let g:line = getline(1)
287 call feedkeys("\<Esc>", "t")
288 endfunc
289 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100290 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200291 " After the 'b' Vim waits for another character to see if it matches 'bb'.
292 " When it times out it is expanded to "aaa", but there is no wait for
293 " "aaaa". Can't check that reliably though.
294 call feedkeys("b", "xt!")
295 call assert_equal("aa", g:line)
296 call assert_false(exists('got_aaa'))
297 call assert_false(exists('got_bb'))
298
299 bwipe!
300 nunmap aaaa
301 nunmap bb
302 nunmap b
303 set timeoutlen&
304 delfunc ExitInsert
Bram Moolenaar26d98212019-01-27 22:32:55 +0100305 call timer_stop(timer)
306endfunc
307
308func Test_map_timeout_with_timer_interrupt()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200309 CheckFeature job
310 CheckFeature timers
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100311 let g:test_is_flaky = 1
Bram Moolenaar26d98212019-01-27 22:32:55 +0100312
313 " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
314 " sequence.
315 new
316 let g:val = 0
317 nnoremap \12 :let g:val = 1<CR>
318 nnoremap \123 :let g:val = 2<CR>
Bram Moolenaarea94c852019-08-16 21:47:27 +0200319 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100320
321 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100322 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100323 endfunc
324
325 call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
326 call feedkeys('\12', 'xt!')
327 call assert_equal(2, g:val)
328
329 bwipe!
330 nunmap \12
331 nunmap \123
332 set timeoutlen&
333 call WaitFor({-> exists('g:timer')})
334 call timer_stop(g:timer)
335 unlet g:timer
336 unlet g:val
337 delfunc ExitCb
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200338endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200339
340func Test_abbreviation_CR()
341 new
342 func Eatchar(pat)
343 let c = nr2char(getchar(0))
344 return (c =~ a:pat) ? '' : c
345 endfunc
346 iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
347 call feedkeys("GA~~7 \<esc>", 'xt')
348 call assert_equal('~~~~~~~', getline('$'))
349 %d
350 call feedkeys("GA~~7\<cr>\<esc>", 'xt')
351 call assert_equal(['~~~~~~~', ''], getline(1,'$'))
352 delfunc Eatchar
353 bw!
354endfunc
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200355
356func Test_cabbr_visual_mode()
357 cabbr s su
358 call feedkeys(":s \<c-B>\"\<CR>", 'itx')
359 call assert_equal('"su ', getreg(':'))
360 call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
361 let expected = '"'. "'<,'>su "
362 call assert_equal(expected, getreg(':'))
363 call feedkeys(": '<,'>s \<c-B>\"\<CR>", 'itx')
364 let expected = '" '. "'<,'>su "
365 call assert_equal(expected, getreg(':'))
366 call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
367 let expected = '"'. "'a,'bsu "
368 call assert_equal(expected, getreg(':'))
369 cunabbr s
370endfunc
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100371
372func Test_motionforce_omap()
373 func GetCommand()
374 let g:m=mode(1)
375 let [g:lnum1, g:col1] = searchpos('-', 'Wb')
376 if g:lnum1 == 0
377 return "\<Esc>"
378 endif
379 let [g:lnum2, g:col2] = searchpos('-', 'W')
380 if g:lnum2 == 0
381 return "\<Esc>"
382 endif
383 return ":call Select()\<CR>"
384 endfunc
385 func Select()
386 call cursor([g:lnum1, g:col1])
387 exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
388 call cursor([g:lnum2, g:col2])
389 execute "normal! \<BS>"
390 endfunc
391 new
392 onoremap <buffer><expr> i- GetCommand()
393 " 1) default omap mapping
394 %d_
395 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
396 call cursor(2, 1)
397 norm di-
398 call assert_equal('no', g:m)
399 call assert_equal(['aaa -- eee'], getline(1, '$'))
400 " 2) forced characterwise operation
401 %d_
402 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
403 call cursor(2, 1)
404 norm dvi-
405 call assert_equal('nov', g:m)
406 call assert_equal(['aaa -- eee'], getline(1, '$'))
407 " 3) forced linewise operation
408 %d_
409 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
410 call cursor(2, 1)
411 norm dVi-
412 call assert_equal('noV', g:m)
413 call assert_equal([''], getline(1, '$'))
414 " 4) forced blockwise operation
415 %d_
416 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
417 call cursor(2, 1)
418 exe "norm d\<C-V>i-"
419 call assert_equal("no\<C-V>", g:m)
420 call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
421 bwipe!
422 delfunc Select
423 delfunc GetCommand
424endfunc
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200425
426func Test_error_in_map_expr()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200427 " Unlike CheckRunVimInTerminal this does work in a win32 console
428 CheckFeature terminal
429 if has('win32') && has('gui_running')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200430 throw 'Skipped: cannot run Vim in a terminal window'
431 endif
432
433 let lines =<< trim [CODE]
434 func Func()
435 " fail to create list
436 let x = [
437 endfunc
438 nmap <expr> ! Func()
439 set updatetime=50
440 [CODE]
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100441 call writefile(lines, 'Xtest.vim', 'D')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200442
Bram Moolenaar0d702022019-07-04 14:20:41 +0200443 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200444 let job = term_getjob(buf)
445 call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
446
447 " GC must not run during map-expr processing, which can make Vim crash.
448 call term_sendkeys(buf, '!')
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200449 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200450 call term_sendkeys(buf, "\<CR>")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200451 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200452 call assert_equal('run', job_status(job))
453
454 call term_sendkeys(buf, ":qall!\<CR>")
455 call WaitFor({-> job_status(job) ==# 'dead'})
456 if has('unix')
457 call assert_equal('', job_info(job).termsig)
458 endif
459
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200460 exe buf .. 'bwipe!'
461endfunc
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200462
463func Test_list_mappings()
Bram Moolenaar2559a472019-10-16 23:33:12 +0200464 " Remove default mappings
465 imapclear
Bram Moolenaar4f2f61a2019-10-16 22:27:49 +0200466
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200467 " reset 'isident' to check it isn't used
468 set isident=
469 inoremap <C-m> CtrlM
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200470 inoremap <A-S> AltS
471 inoremap <S-/> ShiftSlash
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200472 set isident&
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200473 call assert_equal([
474 \ 'i <S-/> * ShiftSlash',
475 \ 'i <M-S> * AltS',
476 \ 'i <C-M> * CtrlM',
477 \], execute('imap')->trim()->split("\n"))
478 iunmap <C-M>
479 iunmap <A-S>
480 call assert_equal(['i <S-/> * ShiftSlash'], execute('imap')->trim()->split("\n"))
481 iunmap <S-/>
482 call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100483
484 " List global, buffer local and script local mappings
485 nmap ,f /^\k\+ (<CR>
486 nmap <buffer> ,f /^\k\+ (<CR>
487 nmap <script> ,fs /^\k\+ (<CR>
488 call assert_equal(['n ,f @/^\k\+ (<CR>',
489 \ 'n ,fs & /^\k\+ (<CR>',
490 \ 'n ,f /^\k\+ (<CR>'],
491 \ execute('nmap ,f')->trim()->split("\n"))
492
493 " List <Nop> mapping
494 nmap ,n <Nop>
495 call assert_equal(['n ,n <Nop>'],
496 \ execute('nmap ,n')->trim()->split("\n"))
497
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100498 " verbose map
Bram Moolenaar060b8382022-10-19 14:48:14 +0100499 let lines = execute('verbose map ,n')->trim()->split("\n")
Bram Moolenaarc255b782022-11-26 19:16:48 +0000500
501 " Remove "Seen modifyOtherKeys" and other optional info.
502 if lines[0] =~ 'Seen modifyOtherKeys'
503 call remove(lines, 0)
504 endif
505 if lines[0] =~ 'modifyOtherKeys detected:'
506 call remove(lines, 0)
507 endif
508 if lines[0] =~ 'Kitty keyboard protocol:'
509 call remove(lines, 0)
510 endif
511 if lines[0] == ''
512 call remove(lines, 0)
513 endif
514
Bram Moolenaar060b8382022-10-19 14:48:14 +0100515 let index = indexof(lines, 'v:val =~ "Last set"')
Bram Moolenaarc255b782022-11-26 19:16:48 +0000516 call assert_equal(1, index)
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100517 call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
Bram Moolenaar060b8382022-10-19 14:48:14 +0100518 \ lines[index])
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100519
zeertzjqac402f42022-05-04 18:51:43 +0100520 " character with K_SPECIAL byte in rhs
521 nmap foo …
522 call assert_equal(['n foo …'],
523 \ execute('nmap foo')->trim()->split("\n"))
524
525 " modified character with K_SPECIAL byte in rhs
526 nmap foo <M-…>
527 call assert_equal(['n foo <M-…>'],
528 \ execute('nmap foo')->trim()->split("\n"))
529
530 " character with K_SPECIAL byte in lhs
531 nmap … foo
532 call assert_equal(['n … foo'],
533 \ execute('nmap …')->trim()->split("\n"))
534
535 " modified character with K_SPECIAL byte in lhs
536 nmap <M-…> foo
537 call assert_equal(['n <M-…> foo'],
538 \ execute('nmap <M-…>')->trim()->split("\n"))
539
zeertzjq0519ce02022-05-09 12:16:19 +0100540 " illegal bytes
541 let str = ":\x7f:\x80:\x90:\xd0:"
542 exe 'nmap foo ' .. str
543 call assert_equal(['n foo ' .. strtrans(str)],
544 \ execute('nmap foo')->trim()->split("\n"))
545 unlet str
546
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100547 " map to CTRL-V
548 exe "nmap ,k \<C-V>"
549 call assert_equal(['n ,k <Nop>'],
550 \ execute('nmap ,k')->trim()->split("\n"))
551
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +0200552 " map with space at the beginning
553 exe "nmap \<C-V> w <Nop>"
554 call assert_equal(['n <Space>w <Nop>'],
555 \ execute("nmap \<C-V> w")->trim()->split("\n"))
556
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100557 nmapclear
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200558endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100559
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100560func Test_expr_map_gets_cursor()
561 new
562 call setline(1, ['one', 'some w!rd'])
563 func StoreColumn()
564 let g:exprLine = line('.')
565 let g:exprCol = col('.')
566 return 'x'
567 endfunc
568 nnoremap <expr> x StoreColumn()
569 2
570 nmap ! f!<Ignore>x
571 call feedkeys("!", 'xt')
572 call assert_equal('some wrd', getline(2))
573 call assert_equal(2, g:exprLine)
574 call assert_equal(7, g:exprCol)
575
576 bwipe!
577 unlet g:exprLine
578 unlet g:exprCol
Bram Moolenaar6ccfd992021-03-17 13:39:33 +0100579 delfunc StoreColumn
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100580 nunmap x
581 nunmap !
582endfunc
583
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100584func Test_expr_map_restore_cursor()
585 CheckScreendump
586
587 let lines =<< trim END
588 call setline(1, ['one', 'two', 'three'])
589 2
590 set ls=2
591 hi! link StatusLine ErrorMsg
592 noremap <expr> <C-B> Func()
593 func Func()
594 let g:on = !get(g:, 'on', 0)
595 redraws
596 return ''
597 endfunc
598 func Status()
599 return get(g:, 'on', 0) ? '[on]' : ''
600 endfunc
601 set stl=%{Status()}
602 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100603 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100604 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar9f145572022-11-27 12:45:41 +0000605 call term_sendkeys(buf, GetEscCodeWithModifier('C', 'B'))
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100606 call VerifyScreenDump(buf, 'Test_map_expr_1', {})
607
608 " clean up
609 call StopVimInTerminal(buf)
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100610endfunc
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100611
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000612func Test_map_listing()
613 CheckScreendump
614
615 let lines =<< trim END
616 nmap a b
617 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100618 call writefile(lines, 'XtestMapList', 'D')
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000619 let buf = RunVimInTerminal('-S XtestMapList', #{rows: 6})
620 call term_sendkeys(buf, ": nmap a\<CR>")
621 call VerifyScreenDump(buf, 'Test_map_list_1', {})
622
623 " clean up
624 call StopVimInTerminal(buf)
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000625endfunc
626
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000627func Test_expr_map_error()
628 CheckScreendump
629
630 let lines =<< trim END
631 func Func()
632 throw 'test'
633 return ''
634 endfunc
635
636 nnoremap <expr> <F2> Func()
637 cnoremap <expr> <F2> Func()
638
639 call test_override('ui_delay', 10)
640 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100641 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000642 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000643 call term_sendkeys(buf, "\<F2>")
644 call TermWait(buf)
645 call term_sendkeys(buf, "\<CR>")
646 call VerifyScreenDump(buf, 'Test_map_expr_2', {})
647
648 call term_sendkeys(buf, ":abc\<F2>")
649 call VerifyScreenDump(buf, 'Test_map_expr_3', {})
650 call term_sendkeys(buf, "\<Esc>0")
651 call VerifyScreenDump(buf, 'Test_map_expr_4', {})
652
653 " clean up
654 call StopVimInTerminal(buf)
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000655endfunc
656
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100657" Test for mapping errors
658func Test_map_error()
659 call assert_fails('unmap', 'E474:')
660 call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
661 call assert_fails('unmap abc', 'E31:')
662 call assert_fails('unabbr abc', 'E24:')
663 call assert_equal('', maparg(''))
664 call assert_fails('echo maparg("abc", [])', 'E730:')
665
666 " unique map
667 map ,w /[#&!]<CR>
668 call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
669 " unique buffer-local map
670 call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
671 unmap ,w
672
673 " unique abbreviation
674 abbr SP special
675 call assert_fails("abbr <unique> SP special", 'E226:')
676 " unique buffer-local map
677 call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
678 unabbr SP
679
680 call assert_fails('mapclear abc', 'E474:')
681 call assert_fails('abclear abc', 'E474:')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100682 call assert_fails('abbr $xyz abc', 'E474:')
683
684 " space character in an abbreviation
685 call assert_fails('abbr ab<space> ABC', 'E474:')
686
687 " invalid <expr> map
688 map <expr> ,f abc
689 call assert_fails('normal ,f', 'E121:')
690 unmap <expr> ,f
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100691
692 " Recursive use of :normal in a map
693 set maxmapdepth=100
694 map gq :normal gq<CR>
695 call assert_fails('normal gq', 'E192:')
696 unmap gq
697 set maxmapdepth&
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100698endfunc
699
700" Test for <special> key mapping
701func Test_map_special()
702 new
703 let old_cpo = &cpo
704 set cpo+=<
705 imap <F12> Blue
706 call feedkeys("i\<F12>", "x")
707 call assert_equal("<F12>", getline(1))
708 call feedkeys("ddi<F12>", "x")
709 call assert_equal("Blue", getline(1))
710 iunmap <F12>
711 imap <special> <F12> Green
712 call feedkeys("ddi\<F12>", "x")
713 call assert_equal("Green", getline(1))
714 call feedkeys("ddi<F12>", "x")
715 call assert_equal("<F12>", getline(1))
716 iunmap <special> <F12>
717 let &cpo = old_cpo
718 %bwipe!
719endfunc
720
721" Test for hasmapto()
722func Test_hasmapto()
723 call assert_equal(0, hasmapto('/^\k\+ ('))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100724 map ,f /^\k\+ (<CR>
725 call assert_equal(1, hasmapto('/^\k\+ ('))
726 unmap ,f
727
728 " Insert mode mapping
729 call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
730 imap ,f /^\k\+ (<CR>
731 call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
732 iunmap ,f
733
734 " Normal mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100735 call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
736 nmap ,f /^\k\+ (<CR>
737 call assert_equal(1, hasmapto('/^\k\+ ('))
738 call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100739 nunmap ,f
740
741 " Visual and Select mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100742 call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100743 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
744 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
745 vmap ,f /^\k\+ (<CR>
746 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
747 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
748 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
749 vunmap ,f
750
751 " Visual mode mapping
752 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
753 xmap ,f /^\k\+ (<CR>
754 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
755 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
756 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
757 xunmap ,f
758
759 " Select mode mapping
760 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
761 smap ,f /^\k\+ (<CR>
762 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
763 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
764 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
765 sunmap ,f
766
767 " Operator-pending mode mapping
768 call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
769 omap ,f /^\k\+ (<CR>
770 call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
771 ounmap ,f
772
773 " Language mapping
774 call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
775 lmap ,f /^\k\+ (<CR>
776 call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
777 lunmap ,f
778
779 " Cmdline mode mapping
780 call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
781 cmap ,f /^\k\+ (<CR>
782 call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
783 cunmap ,f
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100784
785 call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
786endfunc
787
788" Test for command-line completion of maps
789func Test_mapcomplete()
790 call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
791 \ '<silent>', '<special>', '<unique>'],
792 \ getcompletion('', 'mapping'))
793 call assert_equal([], getcompletion(',d', 'mapping'))
794
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100795 call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
796 call assert_equal('"unmap <buffer>', @:)
797
798 call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
799 call assert_equal('"unabbr <buffer>', @:)
800
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100801 call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100802 call assert_equal("\"abbr! \x01", @:)
803
zeertzjq997b8a02023-02-19 21:00:31 +0000804 " When multiple matches have the same {lhs}, it should only appear once.
805 " The simplified form should also not be included.
806 nmap ,<C-F> /H<CR>
807 omap ,<C-F> /H<CR>
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100808 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
zeertzjq997b8a02023-02-19 21:00:31 +0000809 call assert_equal('"map ,<C-F>', @:)
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100810 mapclear
811endfunc
812
Bram Moolenaar94075b22022-01-18 20:30:39 +0000813func GetAbbrText()
814 unabbr hola
815 return 'hello'
816endfunc
817
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100818" Test for <expr> in abbreviation
819func Test_expr_abbr()
820 new
821 iabbr <expr> teh "the"
822 call feedkeys("iteh ", "tx")
823 call assert_equal('the ', getline(1))
824 iabclear
825 call setline(1, '')
826
827 " invalid <expr> abbreviation
828 abbr <expr> hte GetAbbr()
829 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100830 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100831 unabbr <expr> hte
832
Bram Moolenaar94075b22022-01-18 20:30:39 +0000833 " evaluating the expression deletes the abbreviation
834 abbr <expr> hola GetAbbrText()
835 call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
836 call feedkeys("ahola \<Esc>", 'xt')
837 call assert_equal('hello ', getline('.'))
838 call assert_equal('', maparg('hola', 'i', '1'))
839
840 bwipe!
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100841endfunc
842
843" Test for storing mappings in different modes in a vimrc file
844func Test_mkvimrc_mapmodes()
845 map a1 /a1
846 nmap a2 /a2
847 vmap a3 /a3
848 smap a4 /a4
849 xmap a5 /a5
850 omap a6 /a6
851 map! a7 /a7
852 imap a8 /a8
853 lmap a9 /a9
854 cmap a10 /a10
855 tmap a11 /a11
856 " Normal + Visual map
857 map a12 /a12
858 sunmap a12
859 ounmap a12
860 " Normal + Selectmode map
861 map a13 /a13
862 xunmap a13
863 ounmap a13
864 " Normal + OpPending map
865 map a14 /a14
866 vunmap a14
867 " Visual + Selectmode map
868 map a15 /a15
869 nunmap a15
870 ounmap a15
871 " Visual + OpPending map
872 map a16 /a16
873 nunmap a16
874 sunmap a16
875 " Selectmode + OpPending map
876 map a17 /a17
877 nunmap a17
878 xunmap a17
879 " Normal + Visual + Selectmode map
880 map a18 /a18
881 ounmap a18
882 " Normal + Visual + OpPending map
883 map a19 /a19
884 sunmap a19
885 " Normal + Selectmode + OpPending map
886 map a20 /a20
887 xunmap a20
888 " Visual + Selectmode + OpPending map
889 map a21 /a21
890 nunmap a21
891 " Mapping to Nop
892 map a22 <Nop>
893 " Script local mapping
894 map <script> a23 /a23
895
896 " Newline in {lhs} and {rhs} of a map
897 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
898
899 " Abbreviation
900 abbr a25 A25
901 cabbr a26 A26
902 iabbr a27 A27
903
904 mkvimrc! Xvimrc
905 let l = readfile('Xvimrc')
906 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
907 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
908 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
909 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
910 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
911 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
912 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
913 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
914 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
915 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
916 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
917 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
918 \ filter(copy(l), 'v:val =~ " a12 "'))
919 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
920 \ filter(copy(l), 'v:val =~ " a13 "'))
921 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
922 \ filter(copy(l), 'v:val =~ " a14 "'))
923 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
924 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
925 \ filter(copy(l), 'v:val =~ " a16 "'))
926 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
927 \ filter(copy(l), 'v:val =~ " a17 "'))
928 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
929 \ filter(copy(l), 'v:val =~ " a18 "'))
930 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
931 \ filter(copy(l), 'v:val =~ " a19 "'))
932 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
933 \ filter(copy(l), 'v:val =~ " a20 "'))
934 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
935 \ filter(copy(l), 'v:val =~ " a21 "'))
936 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
937 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
938 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
939 \ filter(copy(l), 'v:val =~ " a24"'))
940
941 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
942 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
943 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
944 call delete('Xvimrc')
945
946 mapclear
947 nmapclear
948 vmapclear
949 xmapclear
950 smapclear
951 omapclear
952 imapclear
953 lmapclear
954 cmapclear
955 tmapclear
956endfunc
957
958" Test for recursive mapping ('maxmapdepth')
959func Test_map_recursive()
960 map x y
961 map y x
962 call assert_fails('normal x', 'E223:')
963 unmap x
964 unmap y
965endfunc
966
967" Test for removing an abbreviation using {rhs} and with space after {lhs}
968func Test_abbr_remove()
969 abbr foo bar
970 let d = maparg('foo', 'i', 1, 1)
971 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
972 unabbr bar
973 call assert_equal({}, maparg('foo', 'i', 1, 1))
974
975 abbr foo bar
976 unabbr foo<space><tab>
977 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100978endfunc
979
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100980" Trigger an abbreviation using a special key
981func Test_abbr_trigger_special()
982 new
983 iabbr teh the
984 call feedkeys("iteh\<F2>\<Esc>", 'xt')
985 call assert_equal('the<F2>', getline(1))
986 iunab teh
987 close!
988endfunc
989
990" Test for '<' in 'cpoptions'
991func Test_map_cpo_special_keycode()
992 set cpo-=<
993 imap x<Bslash>k Test
994 let d = maparg('x<Bslash>k', 'i', 0, 1)
995 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
996 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
997 call assert_equal('"imap x\k', @:)
998 iunmap x<Bslash>k
999 set cpo+=<
1000 imap x<Bslash>k Test
1001 let d = maparg('x<Bslash>k', 'i', 0, 1)
1002 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
1003 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
1004 call assert_equal('"imap x<Bslash>k', @:)
1005 iunmap x<Bslash>k
1006 set cpo-=<
1007 " Modifying 'cpo' above adds some default mappings, remove them
1008 mapclear
1009 mapclear!
1010endfunc
1011
Bram Moolenaar957cf672020-11-12 14:21:06 +01001012" Test for <Cmd> key in maps to execute commands
1013func Test_map_cmdkey()
1014 new
1015
1016 " Error cases
1017 let x = 0
1018 noremap <F3> <Cmd><Cmd>let x = 1<CR>
1019 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
1020 call assert_equal(0, x)
1021
Bram Moolenaar957cf672020-11-12 14:21:06 +01001022 noremap <F3> <Cmd>let x = 3
Bram Moolenaar806da512021-12-24 19:54:52 +00001023 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001024 call assert_equal(0, x)
1025
1026 " works in various modes and sees the correct mode()
1027 noremap <F3> <Cmd>let m = mode(1)<CR>
1028 noremap! <F3> <Cmd>let m = mode(1)<CR>
1029
1030 " normal mode
1031 call feedkeys("\<F3>", 'xt')
1032 call assert_equal('n', m)
1033
1034 " visual mode
1035 call feedkeys("v\<F3>", 'xt!')
1036 call assert_equal('v', m)
1037 " shouldn't leave the visual mode
1038 call assert_equal('v', mode(1))
1039 call feedkeys("\<Esc>", 'xt')
1040 call assert_equal('n', mode(1))
1041
1042 " visual mapping in select mode
1043 call feedkeys("gh\<F3>", 'xt!')
1044 call assert_equal('v', m)
1045 " shouldn't leave select mode
1046 call assert_equal('s', mode(1))
1047 call feedkeys("\<Esc>", 'xt')
1048 call assert_equal('n', mode(1))
1049
1050 " select mode mapping
1051 snoremap <F3> <Cmd>let m = mode(1)<cr>
1052 call feedkeys("gh\<F3>", 'xt!')
1053 call assert_equal('s', m)
1054 " shouldn't leave select mode
1055 call assert_equal('s', mode(1))
1056 call feedkeys("\<Esc>", 'xt')
1057 call assert_equal('n', mode(1))
1058
1059 " operator-pending mode
1060 call feedkeys("d\<F3>", 'xt!')
1061 call assert_equal('no', m)
1062 " leaves the operator-pending mode
1063 call assert_equal('n', mode(1))
1064
1065 " insert mode
1066 call feedkeys("i\<F3>abc", 'xt')
1067 call assert_equal('i', m)
1068 call assert_equal('abc', getline('.'))
1069
1070 " replace mode
1071 call feedkeys("0R\<F3>two", 'xt')
1072 call assert_equal('R', m)
1073 call assert_equal('two', getline('.'))
1074
1075 " virtual replace mode
1076 call setline('.', "one\ttwo")
1077 call feedkeys("4|gR\<F3>xxx", 'xt')
1078 call assert_equal('Rv', m)
1079 call assert_equal("onexxx\ttwo", getline('.'))
1080
1081 " cmdline mode
1082 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
1083 call assert_equal('c', m)
1084 call assert_equal('"xxx', @:)
1085
1086 " terminal mode
1087 if CanRunVimInTerminal()
1088 tnoremap <F3> <Cmd>let m = mode(1)<CR>
1089 let buf = Run_shell_in_terminal({})
1090 call feedkeys("\<F3>", 'xt')
1091 call assert_equal('t', m)
1092 call assert_equal('t', mode(1))
1093 call StopShellInTerminal(buf)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001094 close!
1095 tunmap <F3>
1096 endif
1097
1098 " invoke cmdline mode recursively
1099 noremap! <F2> <Cmd>norm! :foo<CR>
1100 %d
1101 call setline(1, ['some short lines', 'of test text'])
1102 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
1103 call assert_equal('"barx', @:)
1104 unmap! <F2>
1105
1106 " test for calling a <SID> function
1107 let lines =<< trim END
1108 map <F2> <Cmd>call <SID>do_it()<CR>
1109 func s:do_it()
1110 let g:x = 32
1111 endfunc
1112 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001113 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001114 source Xscript
1115 call feedkeys("\<F2>", 'xt')
1116 call assert_equal(32, g:x)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001117
1118 unmap <F3>
1119 unmap! <F3>
1120 %bw!
1121endfunc
1122
1123" text object enters visual mode
1124func TextObj()
1125 if mode() !=# "v"
1126 normal! v
1127 end
1128 call cursor(1, 3)
1129 normal! o
1130 call cursor(2, 4)
1131endfunc
1132
1133func s:cmdmap(lhs, rhs)
1134 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1135 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1136endfunc
1137
1138func s:cmdunmap(lhs)
1139 exe 'unmap ' .. a:lhs
1140 exe 'unmap! ' .. a:lhs
1141endfunc
1142
1143" Map various <Fx> keys used by the <Cmd> key tests
1144func s:setupMaps()
1145 call s:cmdmap('<F3>', 'let m = mode(1)')
1146 call s:cmdmap('<F4>', 'normal! ww')
1147 call s:cmdmap('<F5>', 'normal! "ay')
1148 call s:cmdmap('<F6>', 'throw "very error"')
1149 call s:cmdmap('<F7>', 'call TextObj()')
1150 call s:cmdmap('<F8>', 'startinsert')
1151 call s:cmdmap('<F9>', 'stopinsert')
1152endfunc
1153
1154" Remove the mappings setup by setupMaps()
1155func s:cleanupMaps()
1156 call s:cmdunmap('<F3>')
1157 call s:cmdunmap('<F4>')
1158 call s:cmdunmap('<F5>')
1159 call s:cmdunmap('<F6>')
1160 call s:cmdunmap('<F7>')
1161 call s:cmdunmap('<F8>')
1162 call s:cmdunmap('<F9>')
1163endfunc
1164
1165" Test for <Cmd> mapping in normal mode
1166func Test_map_cmdkey_normal_mode()
1167 new
1168 call s:setupMaps()
1169
1170 " check v:count and v:register works
1171 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1172 call feedkeys("\<F2>", 'xt')
1173 call assert_equal(['n', 0, '"'], s)
1174 call feedkeys("7\<F2>", 'xt')
1175 call assert_equal(['n', 7, '"'], s)
1176 call feedkeys("\"e\<F2>", 'xt')
1177 call assert_equal(['n', 0, 'e'], s)
1178 call feedkeys("5\"k\<F2>", 'xt')
1179 call assert_equal(['n', 5, 'k'], s)
1180 call s:cmdunmap('<F2>')
1181
1182 call setline(1, ['some short lines', 'of test text'])
1183 call feedkeys("\<F7>y", 'xt')
1184 call assert_equal("me short lines\nof t", @")
1185 call assert_equal('v', getregtype('"'))
1186 call assert_equal([0, 1, 3, 0], getpos("'<"))
1187 call assert_equal([0, 2, 4, 0], getpos("'>"))
1188
1189 " startinsert
1190 %d
1191 call feedkeys("\<F8>abc", 'xt')
1192 call assert_equal('abc', getline(1))
1193
1194 " feedkeys are not executed immediately
1195 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1196 %d
1197 call setline(1, ['some short lines', 'of test text'])
1198 call cursor(2, 3)
1199 call feedkeys(",a\<F3>", 'xt')
1200 call assert_equal('of test text', g:a)
1201 call assert_equal('n', m)
1202 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1203 nunmap ,a
1204
1205 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1206 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1207 call feedkeys(",b\<F3>", 'xt')
1208 call assert_equal('n', m)
1209 call assert_equal('of alphabetatest text', g:b)
1210 nunmap ,b
1211
1212 call s:cleanupMaps()
1213 %bw!
1214endfunc
1215
1216" Test for <Cmd> mapping with the :normal command
1217func Test_map_cmdkey_normal_cmd()
1218 new
1219 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1220 noremap ,f <Cmd>nosuchcommand<CR>
1221 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1222 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1223 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1224
1225 call setline(1, ['some short lines', 'of test text'])
1226 exe "norm ,x\r"
1227 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1228
1229 call assert_fails('norm ,f', 'E492:')
1230 call assert_fails('norm ,e', 'very error')
1231 call assert_fails('norm ,m', 'The message.')
1232 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1233
1234 %d
1235 let caught_err = 0
1236 try
1237 exe "normal ,w"
1238 catch /Vim(echoerr):Err/
1239 let caught_err = 1
1240 endtry
1241 call assert_equal(1, caught_err)
1242 call assert_equal(['', '0'], getline(1, '$'))
1243
1244 %d
1245 call assert_fails('normal ,w', 'Err')
1246 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1247 call assert_equal(1, line('.'))
1248
1249 nunmap ,x
1250 nunmap ,f
1251 nunmap ,e
1252 nunmap ,m
1253 nunmap ,w
1254 %bw!
1255endfunc
1256
1257" Test for <Cmd> mapping in visual mode
1258func Test_map_cmdkey_visual_mode()
1259 new
1260 set showmode
1261 call s:setupMaps()
1262
1263 call setline(1, ['some short lines', 'of test text'])
1264 call feedkeys("v\<F4>", 'xt!')
1265 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1266
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +01001267 " can invoke an operator, ending the visual mode
Bram Moolenaar957cf672020-11-12 14:21:06 +01001268 let @a = ''
1269 call feedkeys("\<F5>", 'xt!')
1270 call assert_equal('n', mode(1))
1271 call assert_equal('some short l', @a)
1272
1273 " error doesn't interrupt visual mode
1274 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1275 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1276 call feedkeys("\<F7>", 'xt!')
1277 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1278
1279 " startinsert gives "-- (insert) VISUAL --" mode
1280 call feedkeys("\<F8>", 'xt!')
1281 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1282 redraw!
1283 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1284 call feedkeys("\<Esc>new ", 'x')
1285 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1286
1287 call s:cleanupMaps()
1288 set showmode&
1289 %bw!
1290endfunc
1291
1292" Test for <Cmd> mapping in select mode
1293func Test_map_cmdkey_select_mode()
1294 new
1295 set showmode
1296 call s:setupMaps()
1297
1298 snoremap <F1> <cmd>throw "very error"<CR>
1299 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1300 call setline(1, ['some short lines', 'of test text'])
1301
1302 call feedkeys("gh\<F4>", "xt!")
1303 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1304 redraw!
1305 call assert_match('^-- SELECT --', Screenline(&lines))
1306
1307 " visual mapping in select mode restarts select mode after operator
1308 let @a = ''
1309 call feedkeys("\<F5>", 'xt!')
1310 call assert_equal('s', mode(1))
1311 call assert_equal('some short l', @a)
1312
1313 " select mode mapping works, and does not restart select mode
1314 let @b = ''
1315 call feedkeys("\<F2>", 'xt!')
1316 call assert_equal('n', mode(1))
1317 call assert_equal('some short l', @b)
1318
1319 " error doesn't interrupt temporary visual mode
1320 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1321 redraw!
1322 call assert_match('^-- VISUAL --', Screenline(&lines))
1323 " quirk: restoration of select mode is not performed
1324 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1325
1326 " error doesn't interrupt select mode
1327 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1328 redraw!
1329 call assert_match('^-- SELECT --', Screenline(&lines))
1330 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1331
1332 call feedkeys("\<F7>", 'xt!')
1333 redraw!
1334 call assert_match('^-- SELECT --', Screenline(&lines))
1335 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1336
1337 " startinsert gives "-- SELECT (insert) --" mode
1338 call feedkeys("\<F8>", 'xt!')
1339 redraw!
1340 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1341 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1342 call feedkeys("\<Esc>new ", 'x')
1343 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1344
1345 sunmap <F1>
1346 sunmap <F2>
1347 call s:cleanupMaps()
1348 set showmode&
1349 %bw!
1350endfunc
1351
1352" Test for <Cmd> mapping in operator-pending mode
1353func Test_map_cmdkey_op_pending_mode()
1354 new
1355 call s:setupMaps()
1356
1357 call setline(1, ['some short lines', 'of test text'])
1358 call feedkeys("d\<F4>", 'xt')
1359 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1360 call assert_equal(['some short '], getreg('"', 1, 1))
1361 " create a new undo point
Christian Brabandt6efb1982023-08-10 05:44:25 +02001362 let &g:undolevels = &g:undolevels
Bram Moolenaar957cf672020-11-12 14:21:06 +01001363
1364 call feedkeys(".", 'xt')
1365 call assert_equal(['test text'], getline(1, '$'))
1366 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1367 " create a new undo point
Christian Brabandt6efb1982023-08-10 05:44:25 +02001368 let &g:undolevels = &g:undolevels
Bram Moolenaar957cf672020-11-12 14:21:06 +01001369
1370 call feedkeys("uu", 'xt')
1371 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1372
1373 " error aborts operator-pending, operator not performed
1374 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1375 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1376
1377 call feedkeys("\"bd\<F7>", 'xt')
1378 call assert_equal(['soest text'], getline(1, '$'))
1379 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1380
1381 " startinsert aborts operator
1382 call feedkeys("d\<F8>cc", 'xt')
1383 call assert_equal(['soccest text'], getline(1, '$'))
1384
1385 call s:cleanupMaps()
1386 %bw!
1387endfunc
1388
1389" Test for <Cmd> mapping in insert mode
1390func Test_map_cmdkey_insert_mode()
1391 new
1392 call s:setupMaps()
1393
1394 call setline(1, ['some short lines', 'of test text'])
1395 " works the same as <C-O>w<C-O>w
1396 call feedkeys("iindeed \<F4>little ", 'xt')
1397 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1398 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1399 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1400
1401 " Note when entering visual mode from InsertEnter autocmd, an async event,
1402 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1403 call feedkeys("i\<F7>stuff ", 'xt')
1404 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1405 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1406
1407 call feedkeys("\<F5>", 'xt')
1408 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1409
1410 " also works as part of abbreviation
1411 abbr foo <Cmd>let g:y = 17<CR>bar
1412 exe "normal i\<space>foo "
1413 call assert_equal(17, g:y)
1414 call assert_equal('in bar deed some short little 2 lines', getline(1))
1415 unabbr foo
1416
1417 " :startinsert does nothing
1418 call setline(1, 'foo bar')
1419 call feedkeys("ggi\<F8>vim", 'xt')
1420 call assert_equal('vimfoo bar', getline(1))
1421
1422 " :stopinsert works
1423 call feedkeys("ggi\<F9>Abc", 'xt')
1424 call assert_equal('vimfoo barbc', getline(1))
1425
1426 call s:cleanupMaps()
1427 %bw!
1428endfunc
1429
1430" Test for <Cmd> mapping in insert-completion mode
1431func Test_map_cmdkey_insert_complete_mode()
1432 new
1433 call s:setupMaps()
1434
1435 call setline(1, 'some short lines')
1436 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1437 call assert_equal('ic', m)
1438 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1439
1440 call s:cleanupMaps()
1441 %bw!
1442endfunc
1443
1444" Test for <Cmd> mapping in cmdline mode
1445func Test_map_cmdkey_cmdline_mode()
1446 new
1447 call s:setupMaps()
1448
1449 call setline(1, ['some short lines', 'of test text'])
1450 let x = 0
1451 call feedkeys(":let x\<F3>= 10\r", 'xt')
1452 call assert_equal('c', m)
1453 call assert_equal(10, x)
1454
1455 " exception doesn't leave cmdline mode
1456 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1457 call assert_equal(20, x)
1458
1459 " move cursor in the buffer from cmdline mode
1460 call feedkeys(":let x\<F4>= 30\r", 'xt')
1461 call assert_equal(30, x)
1462 call assert_equal(12, col('.'))
1463
1464 " :startinsert takes effect after leaving cmdline mode
1465 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1466 call assert_equal(40, x)
1467 call assert_equal('some short new lines', getline(1))
1468
1469 call s:cleanupMaps()
1470 %bw!
1471endfunc
1472
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001473func Test_map_cmdkey_redo()
1474 func SelectDash()
1475 call search('^---\n\zs', 'bcW')
1476 norm! V
1477 call search('\n\ze---$', 'W')
1478 endfunc
1479
1480 let text =<< trim END
1481 ---
1482 aaa
1483 ---
1484 bbb
1485 bbb
1486 ---
1487 ccc
1488 ccc
1489 ccc
1490 ---
1491 END
1492 new Xcmdtext
1493 call setline(1, text)
1494
1495 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1496 call feedkeys('2Gdi-', 'xt')
1497 call assert_equal(['---', '---'], getline(1, 2))
1498 call feedkeys('j.', 'xt')
1499 call assert_equal(['---', '---', '---'], getline(1, 3))
1500 call feedkeys('j.', 'xt')
1501 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1502
1503 bwipe!
1504 call delete('Xcmdtext')
1505 delfunc SelectDash
1506 ounmap i-
zeertzjq3ab3a862023-05-06 16:22:04 +01001507
1508 new
1509 call setline(1, 'aaa bbb ccc ddd')
1510
1511 " command can contain special keys
1512 onoremap ix <Cmd>let g:foo ..= '…'<Bar>normal! <C-Right><CR>
1513 let g:foo = ''
1514 call feedkeys('0dix.', 'xt')
1515 call assert_equal('……', g:foo)
1516 call assert_equal('ccc ddd', getline(1))
1517 unlet g:foo
1518
1519 " command line ending in "0" is handled without errors
1520 onoremap ix <Cmd>eval 0<CR>
1521 call feedkeys('dix.', 'xt')
1522
1523 ounmap ix
1524 bwipe!
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001525endfunc
1526
Bram Moolenaara9725222022-01-16 13:30:33 +00001527func Test_map_script_cmd_restore()
1528 let lines =<< trim END
1529 vim9script
1530 nnoremap <F3> <ScriptCmd>eval 1 + 2<CR>
1531 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001532 call v9.CheckScriptSuccess(lines)
Bram Moolenaara9725222022-01-16 13:30:33 +00001533 call feedkeys("\<F3>:let g:result = 3+4\<CR>", 'xtc')
1534 call assert_equal(7, g:result)
1535
1536 nunmap <F3>
1537 unlet g:result
1538endfunc
1539
Bram Moolenaardc987762022-01-16 15:52:35 +00001540func Test_map_script_cmd_finds_func()
1541 let lines =<< trim END
1542 vim9script
1543 onoremap <F3> <ScriptCmd>Func()<CR>
1544 def Func()
1545 g:func_called = 'yes'
1546 enddef
1547 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001548 call v9.CheckScriptSuccess(lines)
Bram Moolenaardc987762022-01-16 15:52:35 +00001549 call feedkeys("y\<F3>\<Esc>", 'xtc')
1550 call assert_equal('yes', g:func_called)
1551
1552 ounmap <F3>
1553 unlet g:func_called
1554endfunc
1555
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001556func Test_map_script_cmd_survives_unmap()
1557 let lines =<< trim END
1558 vim9script
1559 var n = 123
1560 nnoremap <F4> <ScriptCmd><CR>
1561 autocmd CmdlineEnter * silent! nunmap <F4>
1562 nnoremap <F3> :<ScriptCmd>eval setbufvar(bufnr(), "result", n)<CR>
1563 feedkeys("\<F3>\<CR>", 'xct')
1564 assert_equal(123, b:result)
1565 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001566 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001567
1568 nunmap <F3>
1569 unlet b:result
Bram Moolenaarca34db32022-01-20 11:17:18 +00001570 autocmd! CmdlineEnter
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001571endfunc
1572
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001573func Test_map_script_cmd_redo()
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001574 call mkdir('Xmapcmd', 'R')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001575 let lines =<< trim END
1576 vim9script
1577 import autoload './script.vim'
1578 onoremap <F3> <ScriptCmd>script.Func()<CR>
1579 END
1580 call writefile(lines, 'Xmapcmd/plugin.vim')
1581
1582 let lines =<< trim END
1583 vim9script
1584 export def Func()
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001585 normal! V
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001586 enddef
1587 END
1588 call writefile(lines, 'Xmapcmd/script.vim')
1589 new
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001590 call setline(1, ['one', 'two', 'three', 'four', 'five'])
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001591 nnoremap j j
1592 source Xmapcmd/plugin.vim
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001593 call feedkeys("d\<F3>j.j.", 'xt')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001594 call assert_equal(['two', 'four'], getline(1, '$'))
1595
1596 ounmap <F3>
1597 nunmap j
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001598 bwipe!
1599endfunc
1600
Bram Moolenaar1f448d92021-03-22 19:37:06 +01001601" Test for using <script> with a map to remap characters in rhs
1602func Test_script_local_remap()
1603 new
1604 inoremap <buffer> <SID>xyz mno
1605 inoremap <buffer> <script> abc st<SID>xyzre
1606 normal iabc
1607 call assert_equal('stmnore', getline(1))
1608 bwipe!
1609endfunc
1610
Bram Moolenaar4934ed32021-04-30 19:43:11 +02001611func Test_abbreviate_multi_byte()
1612 new
1613 iabbrev foo bar
1614 call feedkeys("ifoo…\<Esc>", 'xt')
1615 call assert_equal("bar…", getline(1))
1616 iunabbrev foo
1617 bwipe!
1618endfunc
1619
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +02001620" Test for abbreviations with 'latin1' encoding
1621func Test_abbreviate_latin1_encoding()
1622 set encoding=latin1
1623 call assert_fails('abbr ab#$c ABC', 'E474:')
1624 new
1625 iabbr <buffer> #i #include
1626 iabbr <buffer> ## #enddef
1627 exe "normal i#i\<C-]>"
1628 call assert_equal('#include', getline(1))
1629 exe "normal 0Di##\<C-]>"
1630 call assert_equal('#enddef', getline(1))
1631 %bw!
1632 set encoding=utf-8
1633endfunc
1634
Bram Moolenaar1fc34222022-03-03 13:56:24 +00001635" Test for <Plug> always being mapped, even when used with "noremap".
1636func Test_plug_remap()
1637 let g:foo = 0
1638 nnoremap <Plug>(Increase_x) <Cmd>let g:foo += 1<CR>
1639 nmap <F2> <Plug>(Increase_x)
1640 nnoremap <F3> <Plug>(Increase_x)
1641 call feedkeys("\<F2>", 'xt')
1642 call assert_equal(1, g:foo)
1643 call feedkeys("\<F3>", 'xt')
1644 call assert_equal(2, g:foo)
1645 nnoremap x <Nop>
1646 nmap <F4> x<Plug>(Increase_x)x
1647 nnoremap <F5> x<Plug>(Increase_x)x
1648 call setline(1, 'Some text')
1649 normal! gg$
1650 call feedkeys("\<F4>", 'xt')
1651 call assert_equal(3, g:foo)
1652 call assert_equal('Some text', getline(1))
1653 call feedkeys("\<F5>", 'xt')
1654 call assert_equal(4, g:foo)
1655 call assert_equal('Some te', getline(1))
1656 nunmap <Plug>(Increase_x)
1657 nunmap <F2>
1658 nunmap <F3>
1659 nunmap <F4>
1660 nunmap <F5>
1661 unlet g:foo
1662 %bw!
1663endfunc
1664
zeertzjqac92ab72022-04-24 15:58:30 +01001665func Test_mouse_drag_mapped_start_select()
1666 set mouse=a
1667 set selectmode=key,mouse
1668 func ClickExpr()
1669 call test_setmouse(1, 1)
1670 return "\<LeftMouse>"
1671 endfunc
1672 func DragExpr()
1673 call test_setmouse(1, 2)
1674 return "\<LeftDrag>"
1675 endfunc
1676 nnoremap <expr> <F2> ClickExpr()
1677 nmap <expr> <F3> DragExpr()
1678
1679 nnoremap <LeftDrag> <LeftDrag><Cmd><CR>
1680 exe "normal \<F2>\<F3>"
1681 call assert_equal('s', mode())
1682 exe "normal! \<C-\>\<C-N>"
1683
1684 nunmap <LeftDrag>
1685 nunmap <F2>
1686 nunmap <F3>
1687 delfunc ClickExpr
1688 delfunc DragExpr
1689 set selectmode&
1690 set mouse&
1691endfunc
1692
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001693func Test_mouse_drag_statusline()
1694 set laststatus=2
1695 set mouse=a
1696 func ClickExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001697 call test_setmouse(&lines - 1, 1)
1698 return "\<LeftMouse>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001699 endfunc
1700 func DragExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001701 call test_setmouse(&lines - 2, 1)
1702 return "\<LeftDrag>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001703 endfunc
1704 nnoremap <expr> <F2> ClickExpr()
1705 nnoremap <expr> <F3> DragExpr()
1706
1707 " this was causing a crash in win_drag_status_line()
1708 call feedkeys("\<F2>:tabnew\<CR>\<F3>", 'tx')
zeertzjq873f41a2022-11-01 11:44:43 +00001709
1710 nunmap <F2>
1711 nunmap <F3>
1712 delfunc ClickExpr
1713 delfunc DragExpr
1714 set laststatus& mouse&
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001715endfunc
1716
zeertzjq0f68e6c2022-04-05 13:17:01 +01001717" Test for mapping <LeftDrag> in Insert mode
1718func Test_mouse_drag_insert_map()
1719 set mouse=a
1720 func ClickExpr()
1721 call test_setmouse(1, 1)
1722 return "\<LeftMouse>"
1723 endfunc
1724 func DragExpr()
1725 call test_setmouse(1, 2)
1726 return "\<LeftDrag>"
1727 endfunc
1728 inoremap <expr> <F2> ClickExpr()
1729 imap <expr> <F3> DragExpr()
1730
1731 inoremap <LeftDrag> <LeftDrag><Cmd>let g:dragged = 1<CR>
1732 exe "normal i\<F2>\<F3>"
1733 call assert_equal(1, g:dragged)
1734 call assert_equal('v', mode())
1735 exe "normal! \<C-\>\<C-N>"
1736 unlet g:dragged
1737
1738 inoremap <LeftDrag> <LeftDrag><C-\><C-N>
1739 exe "normal i\<F2>\<F3>"
1740 call assert_equal('n', mode())
1741
1742 iunmap <LeftDrag>
1743 iunmap <F2>
1744 iunmap <F3>
1745 delfunc ClickExpr
1746 delfunc DragExpr
1747 set mouse&
1748endfunc
1749
zeertzjqabeb09b2022-04-26 12:29:43 +01001750func Test_unmap_simplifiable()
zeertzjqa4e33322022-04-24 17:07:53 +01001751 map <C-I> foo
1752 map <Tab> bar
1753 call assert_equal('foo', maparg('<C-I>'))
1754 call assert_equal('bar', maparg('<Tab>'))
1755 unmap <C-I>
1756 call assert_equal('', maparg('<C-I>'))
1757 call assert_equal('bar', maparg('<Tab>'))
1758 unmap <Tab>
zeertzjqabeb09b2022-04-26 12:29:43 +01001759
1760 map <C-I> foo
1761 unmap <Tab>
1762 " This should not error
1763 unmap <C-I>
zeertzjqa4e33322022-04-24 17:07:53 +01001764endfunc
1765
zeertzjqdb088872022-05-02 22:53:45 +01001766func Test_expr_map_escape_special()
1767 nnoremap <Cmd>let g:got_ellipsis += 1<CR>
1768 func Func()
1769 return '…'
1770 endfunc
1771 nmap <expr> <F2> Func()
1772 let g:got_ellipsis = 0
1773 call feedkeys("\<F2>", 'xt')
1774 call assert_equal(1, g:got_ellipsis)
1775 delfunc Func
1776 nunmap <F2>
1777 unlet g:got_ellipsis
1778 nunmap
1779endfunc
1780
zeertzjq3760bfd2022-06-06 16:22:46 +01001781" Testing for mapping after an <Nop> mapping is triggered on timeout.
1782" Test for what patch 8.1.0052 fixes.
1783func Test_map_after_timed_out_nop()
1784 CheckRunVimInTerminal
1785
1786 let lines =<< trim END
1787 set timeout timeoutlen=400
1788 inoremap ab TEST
1789 inoremap a <Nop>
1790 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001791 call writefile(lines, 'Xtest_map_after_timed_out_nop', 'D')
zeertzjq3760bfd2022-06-06 16:22:46 +01001792 let buf = RunVimInTerminal('-S Xtest_map_after_timed_out_nop', #{rows: 6})
1793
1794 " Enter Insert mode
1795 call term_sendkeys(buf, 'i')
1796 " Wait for the "a" mapping to timeout
1797 call term_sendkeys(buf, 'a')
1798 call term_wait(buf, 500)
1799 " Send "a" and wait for a period shorter than 'timeoutlen'
1800 call term_sendkeys(buf, 'a')
1801 call term_wait(buf, 100)
1802 " Send "b", should trigger the "ab" mapping
1803 call term_sendkeys(buf, 'b')
1804 call WaitForAssert({-> assert_equal("TEST", term_getline(buf, 1))})
1805
1806 " clean up
1807 call StopVimInTerminal(buf)
zeertzjq3760bfd2022-06-06 16:22:46 +01001808endfunc
1809
zeertzjqacdfb8a2024-04-17 21:28:54 +02001810" Test 'showcmd' behavior with a partial mapping
1811func Test_showcmd_part_map()
1812 CheckRunVimInTerminal
1813
1814 let lines =<< trim eval END
1815 set notimeout showcmd
1816 nnoremap ,a <Ignore>
1817 nnoremap ;a <Ignore>
1818 nnoremap Àa <Ignore>
1819 nnoremap Ëa <Ignore>
1820 nnoremap βa <Ignore>
1821 nnoremap ωa <Ignore>
1822 nnoremap a <Ignore>
1823 nnoremap <C-W>a <Ignore>
1824 END
1825 call writefile(lines, 'Xtest_showcmd_part_map', 'D')
1826 let buf = RunVimInTerminal('-S Xtest_showcmd_part_map', #{rows: 6})
1827
1828 call term_sendkeys(buf, ":set noruler | echo\<CR>")
1829 call WaitForAssert({-> assert_equal('', term_getline(buf, 6))})
1830
1831 for c in [',', ';', 'À', 'Ë', 'β', 'ω', '…']
1832 call term_sendkeys(buf, c)
1833 call WaitForAssert({-> assert_equal(c, trim(term_getline(buf, 6)))})
1834 call term_sendkeys(buf, "\<C-C>:echo\<CR>")
1835 call WaitForAssert({-> assert_equal('', term_getline(buf, 6))})
1836 endfor
1837
1838 call term_sendkeys(buf, "\<C-W>")
1839 call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))})
1840 call term_sendkeys(buf, "\<C-C>:echo\<CR>")
1841 call WaitForAssert({-> assert_equal('', term_getline(buf, 6))})
1842
1843 " Use feedkeys() as terminal buffer cannot forward this
1844 call term_sendkeys(buf, ':call feedkeys("\<*C-W>", "m")' .. " | echo\<CR>")
1845 call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))})
1846 call term_sendkeys(buf, "\<C-C>:echo\<CR>")
1847 call WaitForAssert({-> assert_equal('', term_getline(buf, 6))})
1848
1849 call StopVimInTerminal(buf)
1850endfunc
1851
Bram Moolenaar27efc622022-07-01 16:35:45 +01001852func Test_using_past_typeahead()
1853 nnoremap :00 0
1854 exe "norm :set \x80\xfb0=0\<CR>"
1855 exe "sil norm :0\x0f\<C-U>\<CR>"
1856
1857 exe "norm :set \x80\xfb0=\<CR>"
1858 nunmap :00
1859endfunc
1860
Bram Moolenaarbf533e42022-11-13 20:43:19 +00001861func Test_mapclear_while_listing()
1862 CheckRunVimInTerminal
1863
1864 let lines =<< trim END
1865 set nocompatible
1866 mapclear
1867 for i in range(1, 999)
1868 exe 'map ' .. 'foo' .. i .. ' bar'
1869 endfor
1870 au CmdlineLeave : call timer_start(0, {-> execute('mapclear')})
1871 END
1872 call writefile(lines, 'Xmapclear', 'D')
1873 let buf = RunVimInTerminal('-S Xmapclear', {'rows': 10})
1874
1875 " this was using freed memory
1876 call term_sendkeys(buf, ":map\<CR>")
1877 call TermWait(buf, 50)
1878 call term_sendkeys(buf, "G")
1879 call TermWait(buf, 50)
1880 call term_sendkeys(buf, "\<CR>")
1881
1882 call StopVimInTerminal(buf)
1883endfunc
1884
Bram Moolenaar27efc622022-07-01 16:35:45 +01001885
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001886" vim: shiftwidth=2 sts=2 expandtab