blob: 28b0188b7d30bf649ba61d1173b507a558b31b9c [file] [log] [blame]
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02001" Tests for mappings and abbreviations
2
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +01003source screendump.vim
Bram Moolenaar62aec932022-01-29 21:45:34 +00004import './vim9.vim' as v9
Bram Moolenaar26d98212019-01-27 22:32:55 +01005
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02006func Test_abbreviation()
zeertzjq5df3cb22024-10-07 21:05:06 +02007 new
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02008 " abbreviation with 0x80 should work
9 inoreab чкпр vim
10 call feedkeys("Goчкпр \<Esc>", "xt")
11 call assert_equal('vim ', getline('$'))
12 iunab чкпр
zeertzjq5df3cb22024-10-07 21:05:06 +020013 bwipe!
14endfunc
15
16func Test_abbreviation_with_noremap()
17 nnoremap <F2> :echo "cheese"
18 cabbr cheese xxx
19 call feedkeys(":echo \"cheese\"\<C-B>\"\<CR>", 'tx')
20 call assert_equal('"echo "xxx"', @:)
21 call feedkeys("\<F2>\<C-B>\"\<CR>", 'tx')
22 call assert_equal('"echo "cheese"', @:)
23 nnoremap <F2> :echo "cheese<C-]>"
24 call feedkeys("\<F2>\<C-B>\"\<CR>", 'tx')
25 call assert_equal('"echo "xxx"', @:)
26 nunmap <F2>
27 cunabbr cheese
28
29 new
30 inoremap <buffer> ( <C-]>()
31 iabbr <buffer> fnu fun
32 call feedkeys("ifnu(", 'tx')
33 call assert_equal('fun()', getline(1))
34 bwipe!
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020035endfunc
36
Bram Moolenaar8485be42019-04-23 16:36:05 +020037func Test_abclear()
zeertzjq5df3cb22024-10-07 21:05:06 +020038 abbrev foo foobar
39 iabbrev fooi foobari
40 cabbrev fooc foobarc
41 call assert_equal("\n\n"
42 \ .. "c fooc foobarc\n"
43 \ .. "i fooi foobari\n"
44 \ .. "! foo foobar", execute('abbrev'))
Bram Moolenaar8485be42019-04-23 16:36:05 +020045
zeertzjq5df3cb22024-10-07 21:05:06 +020046 iabclear
47 call assert_equal("\n\n"
48 \ .. "c fooc foobarc\n"
49 \ .. "c foo foobar", execute('abbrev'))
50 abbrev foo foobar
51 iabbrev fooi foobari
Bram Moolenaar8485be42019-04-23 16:36:05 +020052
zeertzjq5df3cb22024-10-07 21:05:06 +020053 cabclear
54 call assert_equal("\n\n"
55 \ .. "i fooi foobari\n"
56 \ .. "i foo foobar", execute('abbrev'))
57 abbrev foo foobar
58 cabbrev fooc foobarc
Bram Moolenaar8485be42019-04-23 16:36:05 +020059
zeertzjq5df3cb22024-10-07 21:05:06 +020060 abclear
61 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
62 call assert_fails('%abclear', 'E481:')
Bram Moolenaar8485be42019-04-23 16:36:05 +020063endfunc
64
65func Test_abclear_buffer()
66 abbrev foo foobar
67 new X1
68 abbrev <buffer> foo1 foobar1
69 new X2
70 abbrev <buffer> foo2 foobar2
71
72 call assert_equal("\n\n"
73 \ .. "! foo2 @foobar2\n"
74 \ .. "! foo foobar", execute('abbrev'))
75
76 abclear <buffer>
77 call assert_equal("\n\n"
78 \ .. "! foo foobar", execute('abbrev'))
79
80 b X1
81 call assert_equal("\n\n"
82 \ .. "! foo1 @foobar1\n"
83 \ .. "! foo foobar", execute('abbrev'))
84 abclear <buffer>
85 call assert_equal("\n\n"
86 \ .. "! foo foobar", execute('abbrev'))
87
88 abclear
zeertzjqc9aa6e42024-10-08 21:04:19 +020089 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
Bram Moolenaar8485be42019-04-23 16:36:05 +020090
91 %bwipe
92endfunc
93
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020094func Test_map_ctrl_c_insert()
95 " mapping of ctrl-c in Insert mode
96 set cpo-=< cpo-=k
97 inoremap <c-c> <ctrl-c>
98 cnoremap <c-c> dummy
99 cunmap <c-c>
Bram Moolenaarfccd93f2020-05-31 22:06:51 +0200100 call feedkeys("GoTEST2: CTRL-C |\<*C-C>A|\<Esc>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200101 call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
102 unmap! <c-c>
103 set nomodified
104endfunc
105
106func Test_map_ctrl_c_visual()
107 " mapping of ctrl-c in Visual mode
108 vnoremap <c-c> :<C-u>$put ='vmap works'
Bram Moolenaarfccd93f2020-05-31 22:06:51 +0200109 call feedkeys("GV\<*C-C>\<CR>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200110 call assert_equal('vmap works', getline('$'))
111 vunmap <c-c>
112 set nomodified
113endfunc
114
115func Test_map_langmap()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200116 CheckFeature langmap
Bram Moolenaar920694c2016-08-21 17:45:02 +0200117
118 " check langmap applies in normal mode
119 set langmap=+- nolangremap
120 new
121 call setline(1, ['a', 'b', 'c'])
122 2
123 call assert_equal('b', getline('.'))
124 call feedkeys("+", "xt")
125 call assert_equal('a', getline('.'))
126
127 " check no remapping
128 map x +
129 2
130 call feedkeys("x", "xt")
131 call assert_equal('c', getline('.'))
132
133 " check with remapping
134 set langremap
135 2
136 call feedkeys("x", "xt")
137 call assert_equal('a', getline('.'))
138
139 unmap x
140 bwipe!
141
zeertzjqe7102202024-02-13 20:32:04 +0100142 " 'langnoremap' follows 'langremap' and vice versa
Bram Moolenaar920694c2016-08-21 17:45:02 +0200143 set langremap
144 set langnoremap
145 call assert_equal(0, &langremap)
146 set langremap
147 call assert_equal(0, &langnoremap)
148 set nolangremap
149 call assert_equal(1, &langnoremap)
150
Bram Moolenaarda9ce2c2016-09-02 19:34:10 +0200151 " check default values
152 set langnoremap&
153 call assert_equal(0, &langnoremap)
154 call assert_equal(1, &langremap)
155 set langremap&
156 call assert_equal(0, &langnoremap)
157 call assert_equal(1, &langremap)
158
Bram Moolenaar920694c2016-08-21 17:45:02 +0200159 " langmap should not apply in insert mode, 'langremap' doesn't matter
160 set langmap=+{ nolangremap
161 call feedkeys("Go+\<Esc>", "xt")
162 call assert_equal('+', getline('$'))
163 set langmap=+{ langremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200164 call feedkeys("Go+\<Esc>", "xt")
165 call assert_equal('+', getline('$'))
166
Bram Moolenaar920694c2016-08-21 17:45:02 +0200167 " langmap used for register name in insert mode.
168 call setreg('a', 'aaaa')
169 call setreg('b', 'bbbb')
170 call setreg('c', 'cccc')
171 set langmap=ab langremap
172 call feedkeys("Go\<C-R>a\<Esc>", "xt")
173 call assert_equal('bbbb', getline('$'))
174 call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt")
175 call assert_equal('bbbb', getline('$'))
176 " mapping does not apply
177 imap c a
178 call feedkeys("Go\<C-R>c\<Esc>", "xt")
179 call assert_equal('cccc', getline('$'))
180 imap a c
181 call feedkeys("Go\<C-R>a\<Esc>", "xt")
182 call assert_equal('bbbb', getline('$'))
zeertzjq5df3cb22024-10-07 21:05:06 +0200183
Bram Moolenaar920694c2016-08-21 17:45:02 +0200184 " langmap should not apply in Command-line mode
185 set langmap=+{ nolangremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200186 call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
187 call assert_equal('+', getline('$'))
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200188
Bram Moolenaare90858d2017-02-01 17:24:34 +0100189 iunmap a
190 iunmap c
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200191 set nomodified
192endfunc
193
194func Test_map_feedkeys()
195 " issue #212 (feedkeys insert mapping at current position)
196 nnoremap . :call feedkeys(".", "in")<cr>
197 call setline('$', ['a b c d', 'a b c d'])
198 $-1
199 call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt")
200 call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$')))
Bram Moolenaare90858d2017-02-01 17:24:34 +0100201 nunmap .
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200202 set nomodified
203endfunc
204
205func Test_map_cursor()
206 " <c-g>U<cursor> works only within a single line
207 imapclear
208 imap ( ()<c-g>U<left>
209 call feedkeys("G2o\<Esc>ki\<CR>Test1: text with a (here some more text\<Esc>k.", "xt")
210 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 2))
211 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 1))
212
213 " test undo
214 call feedkeys("G2o\<Esc>ki\<CR>Test2: text wit a (here some more text [und undo]\<C-G>u\<Esc>k.u", "xt")
215 call assert_equal('', getline(line('$') - 2))
216 call assert_equal('Test2: text wit a (here some more text [und undo])', getline(line('$') - 1))
217 set nomodified
218 imapclear
219endfunc
220
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100221func Test_map_cursor_ctrl_gU()
222 " <c-g>U<cursor> works only within a single line
223 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left>
224 call setline(1, ['foo', 'foobar', '', 'foo'])
225 call cursor(1,2)
226 call feedkeys("c<*PREFIX\<esc>.", 'xt')
227 call assert_equal(['PREFIXfoo', 'foobar', '', 'PREFIXfoo'], getline(1,'$'))
228 " break undo manually
229 set ul=1000
230 exe ":norm! uu"
231 call assert_equal(['foo', 'foobar', '', 'foo'], getline(1,'$'))
232
233 " Test that it does not work if the cursor moves to the previous line
234 " 2 times <S-Left> move to the previous line
235 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left><C-G>U<S-Left>
236 call setline(1, ['', ' foo', 'foobar', '', 'foo'])
237 call cursor(2,3)
238 call feedkeys("c<*PREFIX\<esc>.", 'xt')
239 call assert_equal(['PREFIXPREFIX', ' foo', 'foobar', '', 'foo'], getline(1,'$'))
240 nmapclear
241endfunc
242
243
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200244" This isn't actually testing a mapping, but similar use of CTRL-G U as above.
245func Test_break_undo()
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100246 set whichwrap=<,>,[,]
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200247 call feedkeys("G4o2k", "xt")
248 exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."
249 call assert_equal('new line here', getline(line('$') - 3))
250 call assert_equal('Test3: text with a (parenthesis here', getline(line('$') - 2))
251 call assert_equal('new line here', getline(line('$') - 1))
252 set nomodified
253endfunc
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200254
255func Test_map_meta_quotes()
256 imap <M-"> foo
Bram Moolenaarfccd93f2020-05-31 22:06:51 +0200257 call feedkeys("Go-\<*M-\">-\<Esc>", "xt")
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200258 call assert_equal("-foo-", getline('$'))
259 set nomodified
260 iunmap <M-">
261endfunc
Bram Moolenaar878c2632017-04-01 15:15:52 +0200262
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200263func Test_map_meta_multibyte()
264 imap <M-á> foo
Bram Moolenaar2f710af2019-08-16 20:56:03 +0200265 call assert_match('i <M-á>\s*foo', execute('imap'))
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200266 iunmap <M-á>
267endfunc
268
Casey Tucker92e90a12024-01-25 22:44:00 +0100269func Test_map_super_quotes()
zeertzjq6b13e3d2024-04-22 21:04:29 +0200270 if "\<D-j>"[-1:] == '>'
271 throw 'Skipped: <D- modifier not supported'
Casey Tucker92e90a12024-01-25 22:44:00 +0100272 endif
zeertzjq6b13e3d2024-04-22 21:04:29 +0200273
274 imap <D-"> foo
275 call feedkeys("Go-\<*D-\">-\<Esc>", "xt")
276 call assert_equal("-foo-", getline('$'))
277 set nomodified
278 iunmap <D-">
Casey Tucker92e90a12024-01-25 22:44:00 +0100279endfunc
280
281func Test_map_super_multibyte()
zeertzjq6b13e3d2024-04-22 21:04:29 +0200282 if "\<D-j>"[-1:] == '>'
283 throw 'Skipped: <D- modifier not supported'
Casey Tucker92e90a12024-01-25 22:44:00 +0100284 endif
zeertzjq6b13e3d2024-04-22 21:04:29 +0200285
286 imap <D-á> foo
287 call assert_match('i <D-á>\s*foo', execute('imap'))
288 iunmap <D-á>
Casey Tucker92e90a12024-01-25 22:44:00 +0100289endfunc
290
Bram Moolenaar878c2632017-04-01 15:15:52 +0200291func Test_abbr_after_line_join()
292 new
293 abbr foo bar
294 set backspace=indent,eol,start
295 exe "normal o\<BS>foo "
296 call assert_equal("bar ", getline(1))
297 bwipe!
298 unabbr foo
299 set backspace&
300endfunc
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200301
302func Test_map_timeout()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200303 CheckFeature timers
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200304 nnoremap aaaa :let got_aaaa = 1<CR>
305 nnoremap bb :let got_bb = 1<CR>
306 nmap b aaa
307 new
308 func ExitInsert(timer)
309 let g:line = getline(1)
310 call feedkeys("\<Esc>", "t")
311 endfunc
312 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100313 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200314 " After the 'b' Vim waits for another character to see if it matches 'bb'.
315 " When it times out it is expanded to "aaa", but there is no wait for
316 " "aaaa". Can't check that reliably though.
317 call feedkeys("b", "xt!")
318 call assert_equal("aa", g:line)
319 call assert_false(exists('got_aaa'))
320 call assert_false(exists('got_bb'))
321
322 bwipe!
323 nunmap aaaa
324 nunmap bb
325 nunmap b
326 set timeoutlen&
327 delfunc ExitInsert
Bram Moolenaar26d98212019-01-27 22:32:55 +0100328 call timer_stop(timer)
329endfunc
330
331func Test_map_timeout_with_timer_interrupt()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200332 CheckFeature job
333 CheckFeature timers
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100334 let g:test_is_flaky = 1
Bram Moolenaar26d98212019-01-27 22:32:55 +0100335
336 " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
337 " sequence.
338 new
339 let g:val = 0
340 nnoremap \12 :let g:val = 1<CR>
341 nnoremap \123 :let g:val = 2<CR>
Bram Moolenaarea94c852019-08-16 21:47:27 +0200342 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100343
344 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100345 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100346 endfunc
347
348 call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
349 call feedkeys('\12', 'xt!')
350 call assert_equal(2, g:val)
351
352 bwipe!
353 nunmap \12
354 nunmap \123
355 set timeoutlen&
356 call WaitFor({-> exists('g:timer')})
357 call timer_stop(g:timer)
358 unlet g:timer
359 unlet g:val
360 delfunc ExitCb
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200361endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200362
363func Test_abbreviation_CR()
364 new
365 func Eatchar(pat)
366 let c = nr2char(getchar(0))
367 return (c =~ a:pat) ? '' : c
368 endfunc
369 iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
370 call feedkeys("GA~~7 \<esc>", 'xt')
371 call assert_equal('~~~~~~~', getline('$'))
372 %d
373 call feedkeys("GA~~7\<cr>\<esc>", 'xt')
374 call assert_equal(['~~~~~~~', ''], getline(1,'$'))
375 delfunc Eatchar
376 bw!
377endfunc
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200378
379func Test_cabbr_visual_mode()
380 cabbr s su
381 call feedkeys(":s \<c-B>\"\<CR>", 'itx')
382 call assert_equal('"su ', getreg(':'))
383 call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
384 let expected = '"'. "'<,'>su "
385 call assert_equal(expected, getreg(':'))
386 call feedkeys(": '<,'>s \<c-B>\"\<CR>", 'itx')
387 let expected = '" '. "'<,'>su "
388 call assert_equal(expected, getreg(':'))
389 call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
390 let expected = '"'. "'a,'bsu "
391 call assert_equal(expected, getreg(':'))
392 cunabbr s
393endfunc
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100394
395func Test_motionforce_omap()
396 func GetCommand()
397 let g:m=mode(1)
398 let [g:lnum1, g:col1] = searchpos('-', 'Wb')
399 if g:lnum1 == 0
400 return "\<Esc>"
401 endif
402 let [g:lnum2, g:col2] = searchpos('-', 'W')
403 if g:lnum2 == 0
404 return "\<Esc>"
405 endif
406 return ":call Select()\<CR>"
407 endfunc
408 func Select()
409 call cursor([g:lnum1, g:col1])
410 exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
411 call cursor([g:lnum2, g:col2])
412 execute "normal! \<BS>"
413 endfunc
414 new
415 onoremap <buffer><expr> i- GetCommand()
416 " 1) default omap mapping
417 %d_
418 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
419 call cursor(2, 1)
420 norm di-
421 call assert_equal('no', g:m)
422 call assert_equal(['aaa -- eee'], getline(1, '$'))
423 " 2) forced characterwise operation
424 %d_
425 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
426 call cursor(2, 1)
427 norm dvi-
428 call assert_equal('nov', g:m)
429 call assert_equal(['aaa -- eee'], getline(1, '$'))
430 " 3) forced linewise operation
431 %d_
432 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
433 call cursor(2, 1)
434 norm dVi-
435 call assert_equal('noV', g:m)
436 call assert_equal([''], getline(1, '$'))
437 " 4) forced blockwise operation
438 %d_
439 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
440 call cursor(2, 1)
441 exe "norm d\<C-V>i-"
442 call assert_equal("no\<C-V>", g:m)
443 call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
444 bwipe!
445 delfunc Select
446 delfunc GetCommand
447endfunc
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200448
449func Test_error_in_map_expr()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200450 " Unlike CheckRunVimInTerminal this does work in a win32 console
451 CheckFeature terminal
452 if has('win32') && has('gui_running')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200453 throw 'Skipped: cannot run Vim in a terminal window'
454 endif
455
456 let lines =<< trim [CODE]
457 func Func()
458 " fail to create list
459 let x = [
460 endfunc
461 nmap <expr> ! Func()
462 set updatetime=50
463 [CODE]
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100464 call writefile(lines, 'Xtest.vim', 'D')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200465
Bram Moolenaar0d702022019-07-04 14:20:41 +0200466 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200467 let job = term_getjob(buf)
468 call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
469
470 " GC must not run during map-expr processing, which can make Vim crash.
471 call term_sendkeys(buf, '!')
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200472 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200473 call term_sendkeys(buf, "\<CR>")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200474 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200475 call assert_equal('run', job_status(job))
476
477 call term_sendkeys(buf, ":qall!\<CR>")
478 call WaitFor({-> job_status(job) ==# 'dead'})
479 if has('unix')
480 call assert_equal('', job_info(job).termsig)
481 endif
482
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200483 exe buf .. 'bwipe!'
484endfunc
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200485
486func Test_list_mappings()
Bram Moolenaar2559a472019-10-16 23:33:12 +0200487 " Remove default mappings
488 imapclear
Bram Moolenaar4f2f61a2019-10-16 22:27:49 +0200489
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200490 " reset 'isident' to check it isn't used
491 set isident=
492 inoremap <C-m> CtrlM
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200493 inoremap <A-S> AltS
494 inoremap <S-/> ShiftSlash
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200495 set isident&
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200496 call assert_equal([
497 \ 'i <S-/> * ShiftSlash',
498 \ 'i <M-S> * AltS',
499 \ 'i <C-M> * CtrlM',
500 \], execute('imap')->trim()->split("\n"))
501 iunmap <C-M>
502 iunmap <A-S>
503 call assert_equal(['i <S-/> * ShiftSlash'], execute('imap')->trim()->split("\n"))
504 iunmap <S-/>
505 call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100506
507 " List global, buffer local and script local mappings
508 nmap ,f /^\k\+ (<CR>
509 nmap <buffer> ,f /^\k\+ (<CR>
510 nmap <script> ,fs /^\k\+ (<CR>
511 call assert_equal(['n ,f @/^\k\+ (<CR>',
512 \ 'n ,fs & /^\k\+ (<CR>',
513 \ 'n ,f /^\k\+ (<CR>'],
514 \ execute('nmap ,f')->trim()->split("\n"))
515
516 " List <Nop> mapping
517 nmap ,n <Nop>
518 call assert_equal(['n ,n <Nop>'],
519 \ execute('nmap ,n')->trim()->split("\n"))
520
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100521 " verbose map
Bram Moolenaar060b8382022-10-19 14:48:14 +0100522 let lines = execute('verbose map ,n')->trim()->split("\n")
Bram Moolenaarc255b782022-11-26 19:16:48 +0000523
524 " Remove "Seen modifyOtherKeys" and other optional info.
525 if lines[0] =~ 'Seen modifyOtherKeys'
526 call remove(lines, 0)
527 endif
528 if lines[0] =~ 'modifyOtherKeys detected:'
529 call remove(lines, 0)
530 endif
531 if lines[0] =~ 'Kitty keyboard protocol:'
532 call remove(lines, 0)
533 endif
534 if lines[0] == ''
535 call remove(lines, 0)
536 endif
537
Bram Moolenaar060b8382022-10-19 14:48:14 +0100538 let index = indexof(lines, 'v:val =~ "Last set"')
Bram Moolenaarc255b782022-11-26 19:16:48 +0000539 call assert_equal(1, index)
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100540 call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
Bram Moolenaar060b8382022-10-19 14:48:14 +0100541 \ lines[index])
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100542
zeertzjqac402f42022-05-04 18:51:43 +0100543 " character with K_SPECIAL byte in rhs
544 nmap foo …
545 call assert_equal(['n foo …'],
546 \ execute('nmap foo')->trim()->split("\n"))
547
548 " modified character with K_SPECIAL byte in rhs
549 nmap foo <M-…>
550 call assert_equal(['n foo <M-…>'],
551 \ execute('nmap foo')->trim()->split("\n"))
552
553 " character with K_SPECIAL byte in lhs
554 nmap … foo
555 call assert_equal(['n … foo'],
556 \ execute('nmap …')->trim()->split("\n"))
557
558 " modified character with K_SPECIAL byte in lhs
559 nmap <M-…> foo
560 call assert_equal(['n <M-…> foo'],
561 \ execute('nmap <M-…>')->trim()->split("\n"))
562
zeertzjq0519ce02022-05-09 12:16:19 +0100563 " illegal bytes
564 let str = ":\x7f:\x80:\x90:\xd0:"
565 exe 'nmap foo ' .. str
566 call assert_equal(['n foo ' .. strtrans(str)],
567 \ execute('nmap foo')->trim()->split("\n"))
568 unlet str
569
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100570 " map to CTRL-V
571 exe "nmap ,k \<C-V>"
572 call assert_equal(['n ,k <Nop>'],
573 \ execute('nmap ,k')->trim()->split("\n"))
574
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +0200575 " map with space at the beginning
576 exe "nmap \<C-V> w <Nop>"
577 call assert_equal(['n <Space>w <Nop>'],
578 \ execute("nmap \<C-V> w")->trim()->split("\n"))
579
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100580 nmapclear
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200581endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100582
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100583func Test_expr_map_gets_cursor()
584 new
585 call setline(1, ['one', 'some w!rd'])
586 func StoreColumn()
587 let g:exprLine = line('.')
588 let g:exprCol = col('.')
589 return 'x'
590 endfunc
591 nnoremap <expr> x StoreColumn()
592 2
593 nmap ! f!<Ignore>x
594 call feedkeys("!", 'xt')
595 call assert_equal('some wrd', getline(2))
596 call assert_equal(2, g:exprLine)
597 call assert_equal(7, g:exprCol)
598
599 bwipe!
600 unlet g:exprLine
601 unlet g:exprCol
Bram Moolenaar6ccfd992021-03-17 13:39:33 +0100602 delfunc StoreColumn
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100603 nunmap x
604 nunmap !
605endfunc
606
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100607func Test_expr_map_restore_cursor()
608 CheckScreendump
609
610 let lines =<< trim END
611 call setline(1, ['one', 'two', 'three'])
612 2
613 set ls=2
614 hi! link StatusLine ErrorMsg
615 noremap <expr> <C-B> Func()
616 func Func()
617 let g:on = !get(g:, 'on', 0)
618 redraws
619 return ''
620 endfunc
621 func Status()
622 return get(g:, 'on', 0) ? '[on]' : ''
623 endfunc
624 set stl=%{Status()}
625 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100626 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100627 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar9f145572022-11-27 12:45:41 +0000628 call term_sendkeys(buf, GetEscCodeWithModifier('C', 'B'))
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100629 call VerifyScreenDump(buf, 'Test_map_expr_1', {})
630
631 " clean up
632 call StopVimInTerminal(buf)
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100633endfunc
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100634
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000635func Test_map_listing()
636 CheckScreendump
637
638 let lines =<< trim END
639 nmap a b
640 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100641 call writefile(lines, 'XtestMapList', 'D')
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000642 let buf = RunVimInTerminal('-S XtestMapList', #{rows: 6})
643 call term_sendkeys(buf, ": nmap a\<CR>")
644 call VerifyScreenDump(buf, 'Test_map_list_1', {})
645
646 " clean up
647 call StopVimInTerminal(buf)
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000648endfunc
649
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000650func Test_expr_map_error()
651 CheckScreendump
652
653 let lines =<< trim END
654 func Func()
655 throw 'test'
656 return ''
657 endfunc
658
659 nnoremap <expr> <F2> Func()
660 cnoremap <expr> <F2> Func()
661
662 call test_override('ui_delay', 10)
663 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100664 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000665 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000666 call term_sendkeys(buf, "\<F2>")
667 call TermWait(buf)
668 call term_sendkeys(buf, "\<CR>")
669 call VerifyScreenDump(buf, 'Test_map_expr_2', {})
670
671 call term_sendkeys(buf, ":abc\<F2>")
672 call VerifyScreenDump(buf, 'Test_map_expr_3', {})
673 call term_sendkeys(buf, "\<Esc>0")
674 call VerifyScreenDump(buf, 'Test_map_expr_4', {})
675
676 " clean up
677 call StopVimInTerminal(buf)
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000678endfunc
679
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100680" Test for mapping errors
681func Test_map_error()
682 call assert_fails('unmap', 'E474:')
683 call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
684 call assert_fails('unmap abc', 'E31:')
685 call assert_fails('unabbr abc', 'E24:')
686 call assert_equal('', maparg(''))
687 call assert_fails('echo maparg("abc", [])', 'E730:')
688
689 " unique map
690 map ,w /[#&!]<CR>
691 call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
692 " unique buffer-local map
693 call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
694 unmap ,w
695
696 " unique abbreviation
697 abbr SP special
698 call assert_fails("abbr <unique> SP special", 'E226:')
699 " unique buffer-local map
700 call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
701 unabbr SP
702
703 call assert_fails('mapclear abc', 'E474:')
704 call assert_fails('abclear abc', 'E474:')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100705 call assert_fails('abbr $xyz abc', 'E474:')
706
707 " space character in an abbreviation
708 call assert_fails('abbr ab<space> ABC', 'E474:')
709
710 " invalid <expr> map
711 map <expr> ,f abc
712 call assert_fails('normal ,f', 'E121:')
713 unmap <expr> ,f
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100714
715 " Recursive use of :normal in a map
716 set maxmapdepth=100
717 map gq :normal gq<CR>
718 call assert_fails('normal gq', 'E192:')
719 unmap gq
720 set maxmapdepth&
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100721endfunc
722
723" Test for <special> key mapping
724func Test_map_special()
725 new
726 let old_cpo = &cpo
727 set cpo+=<
728 imap <F12> Blue
729 call feedkeys("i\<F12>", "x")
730 call assert_equal("<F12>", getline(1))
731 call feedkeys("ddi<F12>", "x")
732 call assert_equal("Blue", getline(1))
733 iunmap <F12>
734 imap <special> <F12> Green
735 call feedkeys("ddi\<F12>", "x")
736 call assert_equal("Green", getline(1))
737 call feedkeys("ddi<F12>", "x")
738 call assert_equal("<F12>", getline(1))
739 iunmap <special> <F12>
740 let &cpo = old_cpo
741 %bwipe!
742endfunc
743
744" Test for hasmapto()
745func Test_hasmapto()
746 call assert_equal(0, hasmapto('/^\k\+ ('))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100747 map ,f /^\k\+ (<CR>
748 call assert_equal(1, hasmapto('/^\k\+ ('))
749 unmap ,f
750
751 " Insert mode mapping
752 call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
753 imap ,f /^\k\+ (<CR>
754 call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
755 iunmap ,f
756
757 " Normal mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100758 call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
759 nmap ,f /^\k\+ (<CR>
760 call assert_equal(1, hasmapto('/^\k\+ ('))
761 call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100762 nunmap ,f
763
764 " Visual and Select mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100765 call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100766 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
767 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
768 vmap ,f /^\k\+ (<CR>
769 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
770 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
771 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
772 vunmap ,f
773
774 " Visual mode mapping
775 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
776 xmap ,f /^\k\+ (<CR>
777 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
778 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
779 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
780 xunmap ,f
781
782 " Select mode mapping
783 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
784 smap ,f /^\k\+ (<CR>
785 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
786 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
787 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
788 sunmap ,f
789
790 " Operator-pending mode mapping
791 call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
792 omap ,f /^\k\+ (<CR>
793 call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
794 ounmap ,f
795
796 " Language mapping
797 call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
798 lmap ,f /^\k\+ (<CR>
799 call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
800 lunmap ,f
801
802 " Cmdline mode mapping
803 call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
804 cmap ,f /^\k\+ (<CR>
805 call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
806 cunmap ,f
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100807
808 call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
809endfunc
810
811" Test for command-line completion of maps
812func Test_mapcomplete()
813 call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
814 \ '<silent>', '<special>', '<unique>'],
815 \ getcompletion('', 'mapping'))
816 call assert_equal([], getcompletion(',d', 'mapping'))
817
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100818 call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
819 call assert_equal('"unmap <buffer>', @:)
820
821 call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
822 call assert_equal('"unabbr <buffer>', @:)
823
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100824 call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100825 call assert_equal("\"abbr! \x01", @:)
826
zeertzjq997b8a02023-02-19 21:00:31 +0000827 " When multiple matches have the same {lhs}, it should only appear once.
828 " The simplified form should also not be included.
829 nmap ,<C-F> /H<CR>
830 omap ,<C-F> /H<CR>
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100831 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
zeertzjq997b8a02023-02-19 21:00:31 +0000832 call assert_equal('"map ,<C-F>', @:)
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100833 mapclear
834endfunc
835
Bram Moolenaar94075b22022-01-18 20:30:39 +0000836func GetAbbrText()
837 unabbr hola
838 return 'hello'
839endfunc
840
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100841" Test for <expr> in abbreviation
842func Test_expr_abbr()
843 new
844 iabbr <expr> teh "the"
845 call feedkeys("iteh ", "tx")
846 call assert_equal('the ', getline(1))
847 iabclear
848 call setline(1, '')
849
850 " invalid <expr> abbreviation
851 abbr <expr> hte GetAbbr()
852 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100853 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100854 unabbr <expr> hte
855
Bram Moolenaar94075b22022-01-18 20:30:39 +0000856 " evaluating the expression deletes the abbreviation
857 abbr <expr> hola GetAbbrText()
858 call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
859 call feedkeys("ahola \<Esc>", 'xt')
860 call assert_equal('hello ', getline('.'))
861 call assert_equal('', maparg('hola', 'i', '1'))
862
863 bwipe!
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100864endfunc
865
866" Test for storing mappings in different modes in a vimrc file
867func Test_mkvimrc_mapmodes()
868 map a1 /a1
869 nmap a2 /a2
870 vmap a3 /a3
871 smap a4 /a4
872 xmap a5 /a5
873 omap a6 /a6
874 map! a7 /a7
875 imap a8 /a8
876 lmap a9 /a9
877 cmap a10 /a10
878 tmap a11 /a11
879 " Normal + Visual map
880 map a12 /a12
881 sunmap a12
882 ounmap a12
883 " Normal + Selectmode map
884 map a13 /a13
885 xunmap a13
886 ounmap a13
887 " Normal + OpPending map
888 map a14 /a14
889 vunmap a14
890 " Visual + Selectmode map
891 map a15 /a15
892 nunmap a15
893 ounmap a15
894 " Visual + OpPending map
895 map a16 /a16
896 nunmap a16
897 sunmap a16
898 " Selectmode + OpPending map
899 map a17 /a17
900 nunmap a17
901 xunmap a17
902 " Normal + Visual + Selectmode map
903 map a18 /a18
904 ounmap a18
905 " Normal + Visual + OpPending map
906 map a19 /a19
907 sunmap a19
908 " Normal + Selectmode + OpPending map
909 map a20 /a20
910 xunmap a20
911 " Visual + Selectmode + OpPending map
912 map a21 /a21
913 nunmap a21
914 " Mapping to Nop
915 map a22 <Nop>
916 " Script local mapping
917 map <script> a23 /a23
918
919 " Newline in {lhs} and {rhs} of a map
920 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
921
922 " Abbreviation
923 abbr a25 A25
924 cabbr a26 A26
925 iabbr a27 A27
926
927 mkvimrc! Xvimrc
928 let l = readfile('Xvimrc')
929 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
930 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
931 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
932 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
933 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
934 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
935 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
936 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
937 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
938 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
939 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
940 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
941 \ filter(copy(l), 'v:val =~ " a12 "'))
942 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
943 \ filter(copy(l), 'v:val =~ " a13 "'))
944 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
945 \ filter(copy(l), 'v:val =~ " a14 "'))
946 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
947 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
948 \ filter(copy(l), 'v:val =~ " a16 "'))
949 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
950 \ filter(copy(l), 'v:val =~ " a17 "'))
951 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
952 \ filter(copy(l), 'v:val =~ " a18 "'))
953 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
954 \ filter(copy(l), 'v:val =~ " a19 "'))
955 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
956 \ filter(copy(l), 'v:val =~ " a20 "'))
957 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
958 \ filter(copy(l), 'v:val =~ " a21 "'))
959 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
960 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
961 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
962 \ filter(copy(l), 'v:val =~ " a24"'))
963
964 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
965 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
966 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
967 call delete('Xvimrc')
968
969 mapclear
970 nmapclear
971 vmapclear
972 xmapclear
973 smapclear
974 omapclear
975 imapclear
976 lmapclear
977 cmapclear
978 tmapclear
979endfunc
980
981" Test for recursive mapping ('maxmapdepth')
982func Test_map_recursive()
983 map x y
984 map y x
985 call assert_fails('normal x', 'E223:')
986 unmap x
987 unmap y
988endfunc
989
990" Test for removing an abbreviation using {rhs} and with space after {lhs}
991func Test_abbr_remove()
992 abbr foo bar
993 let d = maparg('foo', 'i', 1, 1)
994 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
995 unabbr bar
996 call assert_equal({}, maparg('foo', 'i', 1, 1))
997
998 abbr foo bar
999 unabbr foo<space><tab>
1000 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001001endfunc
1002
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +01001003" Trigger an abbreviation using a special key
1004func Test_abbr_trigger_special()
1005 new
1006 iabbr teh the
1007 call feedkeys("iteh\<F2>\<Esc>", 'xt')
1008 call assert_equal('the<F2>', getline(1))
1009 iunab teh
1010 close!
1011endfunc
1012
1013" Test for '<' in 'cpoptions'
1014func Test_map_cpo_special_keycode()
1015 set cpo-=<
1016 imap x<Bslash>k Test
1017 let d = maparg('x<Bslash>k', 'i', 0, 1)
1018 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
1019 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
1020 call assert_equal('"imap x\k', @:)
1021 iunmap x<Bslash>k
1022 set cpo+=<
1023 imap x<Bslash>k Test
1024 let d = maparg('x<Bslash>k', 'i', 0, 1)
1025 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
1026 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
1027 call assert_equal('"imap x<Bslash>k', @:)
1028 iunmap x<Bslash>k
1029 set cpo-=<
1030 " Modifying 'cpo' above adds some default mappings, remove them
1031 mapclear
1032 mapclear!
1033endfunc
1034
Bram Moolenaar957cf672020-11-12 14:21:06 +01001035" Test for <Cmd> key in maps to execute commands
1036func Test_map_cmdkey()
1037 new
1038
1039 " Error cases
1040 let x = 0
1041 noremap <F3> <Cmd><Cmd>let x = 1<CR>
1042 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
1043 call assert_equal(0, x)
1044
Bram Moolenaar957cf672020-11-12 14:21:06 +01001045 noremap <F3> <Cmd>let x = 3
Bram Moolenaar806da512021-12-24 19:54:52 +00001046 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001047 call assert_equal(0, x)
1048
1049 " works in various modes and sees the correct mode()
1050 noremap <F3> <Cmd>let m = mode(1)<CR>
1051 noremap! <F3> <Cmd>let m = mode(1)<CR>
1052
1053 " normal mode
1054 call feedkeys("\<F3>", 'xt')
1055 call assert_equal('n', m)
1056
1057 " visual mode
1058 call feedkeys("v\<F3>", 'xt!')
1059 call assert_equal('v', m)
1060 " shouldn't leave the visual mode
1061 call assert_equal('v', mode(1))
1062 call feedkeys("\<Esc>", 'xt')
1063 call assert_equal('n', mode(1))
1064
1065 " visual mapping in select mode
1066 call feedkeys("gh\<F3>", 'xt!')
1067 call assert_equal('v', m)
1068 " shouldn't leave select mode
1069 call assert_equal('s', mode(1))
1070 call feedkeys("\<Esc>", 'xt')
1071 call assert_equal('n', mode(1))
1072
1073 " select mode mapping
1074 snoremap <F3> <Cmd>let m = mode(1)<cr>
1075 call feedkeys("gh\<F3>", 'xt!')
1076 call assert_equal('s', m)
1077 " shouldn't leave select mode
1078 call assert_equal('s', mode(1))
1079 call feedkeys("\<Esc>", 'xt')
1080 call assert_equal('n', mode(1))
1081
1082 " operator-pending mode
1083 call feedkeys("d\<F3>", 'xt!')
1084 call assert_equal('no', m)
1085 " leaves the operator-pending mode
1086 call assert_equal('n', mode(1))
1087
1088 " insert mode
1089 call feedkeys("i\<F3>abc", 'xt')
1090 call assert_equal('i', m)
1091 call assert_equal('abc', getline('.'))
1092
1093 " replace mode
1094 call feedkeys("0R\<F3>two", 'xt')
1095 call assert_equal('R', m)
1096 call assert_equal('two', getline('.'))
1097
1098 " virtual replace mode
1099 call setline('.', "one\ttwo")
1100 call feedkeys("4|gR\<F3>xxx", 'xt')
1101 call assert_equal('Rv', m)
1102 call assert_equal("onexxx\ttwo", getline('.'))
1103
1104 " cmdline mode
1105 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
1106 call assert_equal('c', m)
1107 call assert_equal('"xxx', @:)
1108
1109 " terminal mode
1110 if CanRunVimInTerminal()
1111 tnoremap <F3> <Cmd>let m = mode(1)<CR>
1112 let buf = Run_shell_in_terminal({})
1113 call feedkeys("\<F3>", 'xt')
1114 call assert_equal('t', m)
1115 call assert_equal('t', mode(1))
1116 call StopShellInTerminal(buf)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001117 close!
1118 tunmap <F3>
1119 endif
1120
1121 " invoke cmdline mode recursively
1122 noremap! <F2> <Cmd>norm! :foo<CR>
1123 %d
1124 call setline(1, ['some short lines', 'of test text'])
1125 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
1126 call assert_equal('"barx', @:)
1127 unmap! <F2>
1128
1129 " test for calling a <SID> function
1130 let lines =<< trim END
1131 map <F2> <Cmd>call <SID>do_it()<CR>
1132 func s:do_it()
1133 let g:x = 32
1134 endfunc
1135 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001136 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001137 source Xscript
1138 call feedkeys("\<F2>", 'xt')
1139 call assert_equal(32, g:x)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001140
1141 unmap <F3>
1142 unmap! <F3>
1143 %bw!
1144endfunc
1145
1146" text object enters visual mode
1147func TextObj()
1148 if mode() !=# "v"
1149 normal! v
1150 end
1151 call cursor(1, 3)
1152 normal! o
1153 call cursor(2, 4)
1154endfunc
1155
1156func s:cmdmap(lhs, rhs)
1157 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1158 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1159endfunc
1160
1161func s:cmdunmap(lhs)
1162 exe 'unmap ' .. a:lhs
1163 exe 'unmap! ' .. a:lhs
1164endfunc
1165
1166" Map various <Fx> keys used by the <Cmd> key tests
1167func s:setupMaps()
1168 call s:cmdmap('<F3>', 'let m = mode(1)')
1169 call s:cmdmap('<F4>', 'normal! ww')
1170 call s:cmdmap('<F5>', 'normal! "ay')
1171 call s:cmdmap('<F6>', 'throw "very error"')
1172 call s:cmdmap('<F7>', 'call TextObj()')
1173 call s:cmdmap('<F8>', 'startinsert')
1174 call s:cmdmap('<F9>', 'stopinsert')
1175endfunc
1176
1177" Remove the mappings setup by setupMaps()
1178func s:cleanupMaps()
1179 call s:cmdunmap('<F3>')
1180 call s:cmdunmap('<F4>')
1181 call s:cmdunmap('<F5>')
1182 call s:cmdunmap('<F6>')
1183 call s:cmdunmap('<F7>')
1184 call s:cmdunmap('<F8>')
1185 call s:cmdunmap('<F9>')
1186endfunc
1187
1188" Test for <Cmd> mapping in normal mode
1189func Test_map_cmdkey_normal_mode()
1190 new
1191 call s:setupMaps()
1192
1193 " check v:count and v:register works
1194 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1195 call feedkeys("\<F2>", 'xt')
1196 call assert_equal(['n', 0, '"'], s)
1197 call feedkeys("7\<F2>", 'xt')
1198 call assert_equal(['n', 7, '"'], s)
1199 call feedkeys("\"e\<F2>", 'xt')
1200 call assert_equal(['n', 0, 'e'], s)
1201 call feedkeys("5\"k\<F2>", 'xt')
1202 call assert_equal(['n', 5, 'k'], s)
1203 call s:cmdunmap('<F2>')
1204
1205 call setline(1, ['some short lines', 'of test text'])
1206 call feedkeys("\<F7>y", 'xt')
1207 call assert_equal("me short lines\nof t", @")
1208 call assert_equal('v', getregtype('"'))
1209 call assert_equal([0, 1, 3, 0], getpos("'<"))
1210 call assert_equal([0, 2, 4, 0], getpos("'>"))
1211
1212 " startinsert
1213 %d
1214 call feedkeys("\<F8>abc", 'xt')
1215 call assert_equal('abc', getline(1))
1216
1217 " feedkeys are not executed immediately
1218 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1219 %d
1220 call setline(1, ['some short lines', 'of test text'])
1221 call cursor(2, 3)
1222 call feedkeys(",a\<F3>", 'xt')
1223 call assert_equal('of test text', g:a)
1224 call assert_equal('n', m)
1225 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1226 nunmap ,a
1227
1228 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1229 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1230 call feedkeys(",b\<F3>", 'xt')
1231 call assert_equal('n', m)
1232 call assert_equal('of alphabetatest text', g:b)
1233 nunmap ,b
1234
1235 call s:cleanupMaps()
1236 %bw!
1237endfunc
1238
1239" Test for <Cmd> mapping with the :normal command
1240func Test_map_cmdkey_normal_cmd()
1241 new
1242 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1243 noremap ,f <Cmd>nosuchcommand<CR>
1244 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1245 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1246 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1247
1248 call setline(1, ['some short lines', 'of test text'])
1249 exe "norm ,x\r"
1250 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1251
1252 call assert_fails('norm ,f', 'E492:')
1253 call assert_fails('norm ,e', 'very error')
1254 call assert_fails('norm ,m', 'The message.')
1255 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1256
1257 %d
1258 let caught_err = 0
1259 try
1260 exe "normal ,w"
1261 catch /Vim(echoerr):Err/
1262 let caught_err = 1
1263 endtry
1264 call assert_equal(1, caught_err)
1265 call assert_equal(['', '0'], getline(1, '$'))
1266
1267 %d
1268 call assert_fails('normal ,w', 'Err')
1269 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1270 call assert_equal(1, line('.'))
1271
1272 nunmap ,x
1273 nunmap ,f
1274 nunmap ,e
1275 nunmap ,m
1276 nunmap ,w
1277 %bw!
1278endfunc
1279
1280" Test for <Cmd> mapping in visual mode
1281func Test_map_cmdkey_visual_mode()
1282 new
1283 set showmode
1284 call s:setupMaps()
1285
1286 call setline(1, ['some short lines', 'of test text'])
1287 call feedkeys("v\<F4>", 'xt!')
1288 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1289
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +01001290 " can invoke an operator, ending the visual mode
Bram Moolenaar957cf672020-11-12 14:21:06 +01001291 let @a = ''
1292 call feedkeys("\<F5>", 'xt!')
1293 call assert_equal('n', mode(1))
1294 call assert_equal('some short l', @a)
1295
1296 " error doesn't interrupt visual mode
1297 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1298 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1299 call feedkeys("\<F7>", 'xt!')
1300 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1301
1302 " startinsert gives "-- (insert) VISUAL --" mode
1303 call feedkeys("\<F8>", 'xt!')
1304 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1305 redraw!
1306 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1307 call feedkeys("\<Esc>new ", 'x')
1308 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1309
1310 call s:cleanupMaps()
1311 set showmode&
1312 %bw!
1313endfunc
1314
1315" Test for <Cmd> mapping in select mode
1316func Test_map_cmdkey_select_mode()
1317 new
1318 set showmode
1319 call s:setupMaps()
1320
1321 snoremap <F1> <cmd>throw "very error"<CR>
1322 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1323 call setline(1, ['some short lines', 'of test text'])
1324
1325 call feedkeys("gh\<F4>", "xt!")
1326 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1327 redraw!
1328 call assert_match('^-- SELECT --', Screenline(&lines))
1329
1330 " visual mapping in select mode restarts select mode after operator
1331 let @a = ''
1332 call feedkeys("\<F5>", 'xt!')
1333 call assert_equal('s', mode(1))
1334 call assert_equal('some short l', @a)
1335
1336 " select mode mapping works, and does not restart select mode
1337 let @b = ''
1338 call feedkeys("\<F2>", 'xt!')
1339 call assert_equal('n', mode(1))
1340 call assert_equal('some short l', @b)
1341
1342 " error doesn't interrupt temporary visual mode
1343 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1344 redraw!
1345 call assert_match('^-- VISUAL --', Screenline(&lines))
1346 " quirk: restoration of select mode is not performed
1347 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1348
1349 " error doesn't interrupt select mode
1350 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1351 redraw!
1352 call assert_match('^-- SELECT --', Screenline(&lines))
1353 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1354
1355 call feedkeys("\<F7>", 'xt!')
1356 redraw!
1357 call assert_match('^-- SELECT --', Screenline(&lines))
1358 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1359
1360 " startinsert gives "-- SELECT (insert) --" mode
1361 call feedkeys("\<F8>", 'xt!')
1362 redraw!
1363 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1364 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1365 call feedkeys("\<Esc>new ", 'x')
1366 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1367
1368 sunmap <F1>
1369 sunmap <F2>
1370 call s:cleanupMaps()
1371 set showmode&
1372 %bw!
1373endfunc
1374
1375" Test for <Cmd> mapping in operator-pending mode
1376func Test_map_cmdkey_op_pending_mode()
1377 new
1378 call s:setupMaps()
1379
1380 call setline(1, ['some short lines', 'of test text'])
1381 call feedkeys("d\<F4>", 'xt')
1382 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1383 call assert_equal(['some short '], getreg('"', 1, 1))
1384 " create a new undo point
Christian Brabandt6efb1982023-08-10 05:44:25 +02001385 let &g:undolevels = &g:undolevels
Bram Moolenaar957cf672020-11-12 14:21:06 +01001386
1387 call feedkeys(".", 'xt')
1388 call assert_equal(['test text'], getline(1, '$'))
1389 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1390 " create a new undo point
Christian Brabandt6efb1982023-08-10 05:44:25 +02001391 let &g:undolevels = &g:undolevels
Bram Moolenaar957cf672020-11-12 14:21:06 +01001392
1393 call feedkeys("uu", 'xt')
1394 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1395
1396 " error aborts operator-pending, operator not performed
1397 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1398 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1399
1400 call feedkeys("\"bd\<F7>", 'xt')
1401 call assert_equal(['soest text'], getline(1, '$'))
1402 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1403
1404 " startinsert aborts operator
1405 call feedkeys("d\<F8>cc", 'xt')
1406 call assert_equal(['soccest text'], getline(1, '$'))
1407
1408 call s:cleanupMaps()
1409 %bw!
1410endfunc
1411
1412" Test for <Cmd> mapping in insert mode
1413func Test_map_cmdkey_insert_mode()
1414 new
1415 call s:setupMaps()
1416
1417 call setline(1, ['some short lines', 'of test text'])
1418 " works the same as <C-O>w<C-O>w
1419 call feedkeys("iindeed \<F4>little ", 'xt')
1420 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1421 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1422 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1423
1424 " Note when entering visual mode from InsertEnter autocmd, an async event,
1425 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1426 call feedkeys("i\<F7>stuff ", 'xt')
1427 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1428 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1429
1430 call feedkeys("\<F5>", 'xt')
1431 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1432
1433 " also works as part of abbreviation
1434 abbr foo <Cmd>let g:y = 17<CR>bar
1435 exe "normal i\<space>foo "
1436 call assert_equal(17, g:y)
1437 call assert_equal('in bar deed some short little 2 lines', getline(1))
1438 unabbr foo
1439
1440 " :startinsert does nothing
1441 call setline(1, 'foo bar')
1442 call feedkeys("ggi\<F8>vim", 'xt')
1443 call assert_equal('vimfoo bar', getline(1))
1444
1445 " :stopinsert works
1446 call feedkeys("ggi\<F9>Abc", 'xt')
1447 call assert_equal('vimfoo barbc', getline(1))
1448
1449 call s:cleanupMaps()
1450 %bw!
1451endfunc
1452
1453" Test for <Cmd> mapping in insert-completion mode
1454func Test_map_cmdkey_insert_complete_mode()
1455 new
1456 call s:setupMaps()
1457
1458 call setline(1, 'some short lines')
1459 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1460 call assert_equal('ic', m)
1461 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1462
1463 call s:cleanupMaps()
1464 %bw!
1465endfunc
1466
1467" Test for <Cmd> mapping in cmdline mode
1468func Test_map_cmdkey_cmdline_mode()
1469 new
1470 call s:setupMaps()
1471
1472 call setline(1, ['some short lines', 'of test text'])
1473 let x = 0
1474 call feedkeys(":let x\<F3>= 10\r", 'xt')
1475 call assert_equal('c', m)
1476 call assert_equal(10, x)
1477
1478 " exception doesn't leave cmdline mode
1479 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1480 call assert_equal(20, x)
1481
1482 " move cursor in the buffer from cmdline mode
1483 call feedkeys(":let x\<F4>= 30\r", 'xt')
1484 call assert_equal(30, x)
1485 call assert_equal(12, col('.'))
1486
1487 " :startinsert takes effect after leaving cmdline mode
1488 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1489 call assert_equal(40, x)
1490 call assert_equal('some short new lines', getline(1))
1491
1492 call s:cleanupMaps()
1493 %bw!
1494endfunc
1495
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001496func Test_map_cmdkey_redo()
1497 func SelectDash()
1498 call search('^---\n\zs', 'bcW')
1499 norm! V
1500 call search('\n\ze---$', 'W')
1501 endfunc
1502
1503 let text =<< trim END
1504 ---
1505 aaa
1506 ---
1507 bbb
1508 bbb
1509 ---
1510 ccc
1511 ccc
1512 ccc
1513 ---
1514 END
1515 new Xcmdtext
1516 call setline(1, text)
1517
1518 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1519 call feedkeys('2Gdi-', 'xt')
1520 call assert_equal(['---', '---'], getline(1, 2))
1521 call feedkeys('j.', 'xt')
1522 call assert_equal(['---', '---', '---'], getline(1, 3))
1523 call feedkeys('j.', 'xt')
1524 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1525
1526 bwipe!
1527 call delete('Xcmdtext')
1528 delfunc SelectDash
1529 ounmap i-
zeertzjq3ab3a862023-05-06 16:22:04 +01001530
1531 new
1532 call setline(1, 'aaa bbb ccc ddd')
1533
1534 " command can contain special keys
1535 onoremap ix <Cmd>let g:foo ..= '…'<Bar>normal! <C-Right><CR>
1536 let g:foo = ''
1537 call feedkeys('0dix.', 'xt')
1538 call assert_equal('……', g:foo)
1539 call assert_equal('ccc ddd', getline(1))
1540 unlet g:foo
1541
1542 " command line ending in "0" is handled without errors
1543 onoremap ix <Cmd>eval 0<CR>
1544 call feedkeys('dix.', 'xt')
1545
1546 ounmap ix
1547 bwipe!
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001548endfunc
1549
Bram Moolenaara9725222022-01-16 13:30:33 +00001550func Test_map_script_cmd_restore()
1551 let lines =<< trim END
1552 vim9script
1553 nnoremap <F3> <ScriptCmd>eval 1 + 2<CR>
1554 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001555 call v9.CheckScriptSuccess(lines)
Bram Moolenaara9725222022-01-16 13:30:33 +00001556 call feedkeys("\<F3>:let g:result = 3+4\<CR>", 'xtc')
1557 call assert_equal(7, g:result)
1558
1559 nunmap <F3>
1560 unlet g:result
1561endfunc
1562
Bram Moolenaardc987762022-01-16 15:52:35 +00001563func Test_map_script_cmd_finds_func()
1564 let lines =<< trim END
1565 vim9script
1566 onoremap <F3> <ScriptCmd>Func()<CR>
1567 def Func()
1568 g:func_called = 'yes'
1569 enddef
1570 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001571 call v9.CheckScriptSuccess(lines)
Bram Moolenaardc987762022-01-16 15:52:35 +00001572 call feedkeys("y\<F3>\<Esc>", 'xtc')
1573 call assert_equal('yes', g:func_called)
1574
1575 ounmap <F3>
1576 unlet g:func_called
1577endfunc
1578
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001579func Test_map_script_cmd_survives_unmap()
1580 let lines =<< trim END
1581 vim9script
1582 var n = 123
1583 nnoremap <F4> <ScriptCmd><CR>
1584 autocmd CmdlineEnter * silent! nunmap <F4>
1585 nnoremap <F3> :<ScriptCmd>eval setbufvar(bufnr(), "result", n)<CR>
1586 feedkeys("\<F3>\<CR>", 'xct')
1587 assert_equal(123, b:result)
1588 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001589 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001590
1591 nunmap <F3>
1592 unlet b:result
Bram Moolenaarca34db32022-01-20 11:17:18 +00001593 autocmd! CmdlineEnter
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001594endfunc
1595
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001596func Test_map_script_cmd_redo()
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001597 call mkdir('Xmapcmd', 'R')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001598 let lines =<< trim END
1599 vim9script
1600 import autoload './script.vim'
1601 onoremap <F3> <ScriptCmd>script.Func()<CR>
1602 END
1603 call writefile(lines, 'Xmapcmd/plugin.vim')
1604
1605 let lines =<< trim END
1606 vim9script
1607 export def Func()
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001608 normal! V
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001609 enddef
1610 END
1611 call writefile(lines, 'Xmapcmd/script.vim')
1612 new
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001613 call setline(1, ['one', 'two', 'three', 'four', 'five'])
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001614 nnoremap j j
1615 source Xmapcmd/plugin.vim
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001616 call feedkeys("d\<F3>j.j.", 'xt')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001617 call assert_equal(['two', 'four'], getline(1, '$'))
1618
1619 ounmap <F3>
1620 nunmap j
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001621 bwipe!
1622endfunc
1623
Bram Moolenaar1f448d92021-03-22 19:37:06 +01001624" Test for using <script> with a map to remap characters in rhs
1625func Test_script_local_remap()
1626 new
1627 inoremap <buffer> <SID>xyz mno
1628 inoremap <buffer> <script> abc st<SID>xyzre
1629 normal iabc
1630 call assert_equal('stmnore', getline(1))
1631 bwipe!
1632endfunc
1633
Bram Moolenaar4934ed32021-04-30 19:43:11 +02001634func Test_abbreviate_multi_byte()
1635 new
1636 iabbrev foo bar
1637 call feedkeys("ifoo…\<Esc>", 'xt')
1638 call assert_equal("bar…", getline(1))
1639 iunabbrev foo
1640 bwipe!
1641endfunc
1642
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +02001643" Test for abbreviations with 'latin1' encoding
1644func Test_abbreviate_latin1_encoding()
1645 set encoding=latin1
1646 call assert_fails('abbr ab#$c ABC', 'E474:')
1647 new
1648 iabbr <buffer> #i #include
1649 iabbr <buffer> ## #enddef
1650 exe "normal i#i\<C-]>"
1651 call assert_equal('#include', getline(1))
1652 exe "normal 0Di##\<C-]>"
1653 call assert_equal('#enddef', getline(1))
1654 %bw!
1655 set encoding=utf-8
1656endfunc
1657
Bram Moolenaar1fc34222022-03-03 13:56:24 +00001658" Test for <Plug> always being mapped, even when used with "noremap".
1659func Test_plug_remap()
1660 let g:foo = 0
1661 nnoremap <Plug>(Increase_x) <Cmd>let g:foo += 1<CR>
1662 nmap <F2> <Plug>(Increase_x)
1663 nnoremap <F3> <Plug>(Increase_x)
1664 call feedkeys("\<F2>", 'xt')
1665 call assert_equal(1, g:foo)
1666 call feedkeys("\<F3>", 'xt')
1667 call assert_equal(2, g:foo)
1668 nnoremap x <Nop>
1669 nmap <F4> x<Plug>(Increase_x)x
1670 nnoremap <F5> x<Plug>(Increase_x)x
1671 call setline(1, 'Some text')
1672 normal! gg$
1673 call feedkeys("\<F4>", 'xt')
1674 call assert_equal(3, g:foo)
1675 call assert_equal('Some text', getline(1))
1676 call feedkeys("\<F5>", 'xt')
1677 call assert_equal(4, g:foo)
1678 call assert_equal('Some te', getline(1))
1679 nunmap <Plug>(Increase_x)
1680 nunmap <F2>
1681 nunmap <F3>
1682 nunmap <F4>
1683 nunmap <F5>
1684 unlet g:foo
1685 %bw!
1686endfunc
1687
zeertzjqac92ab72022-04-24 15:58:30 +01001688func Test_mouse_drag_mapped_start_select()
1689 set mouse=a
1690 set selectmode=key,mouse
1691 func ClickExpr()
1692 call test_setmouse(1, 1)
1693 return "\<LeftMouse>"
1694 endfunc
1695 func DragExpr()
1696 call test_setmouse(1, 2)
1697 return "\<LeftDrag>"
1698 endfunc
1699 nnoremap <expr> <F2> ClickExpr()
1700 nmap <expr> <F3> DragExpr()
1701
1702 nnoremap <LeftDrag> <LeftDrag><Cmd><CR>
1703 exe "normal \<F2>\<F3>"
1704 call assert_equal('s', mode())
1705 exe "normal! \<C-\>\<C-N>"
1706
1707 nunmap <LeftDrag>
1708 nunmap <F2>
1709 nunmap <F3>
1710 delfunc ClickExpr
1711 delfunc DragExpr
1712 set selectmode&
1713 set mouse&
1714endfunc
1715
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001716func Test_mouse_drag_statusline()
1717 set laststatus=2
1718 set mouse=a
1719 func ClickExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001720 call test_setmouse(&lines - 1, 1)
1721 return "\<LeftMouse>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001722 endfunc
1723 func DragExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001724 call test_setmouse(&lines - 2, 1)
1725 return "\<LeftDrag>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001726 endfunc
1727 nnoremap <expr> <F2> ClickExpr()
1728 nnoremap <expr> <F3> DragExpr()
1729
1730 " this was causing a crash in win_drag_status_line()
1731 call feedkeys("\<F2>:tabnew\<CR>\<F3>", 'tx')
zeertzjq873f41a2022-11-01 11:44:43 +00001732
1733 nunmap <F2>
1734 nunmap <F3>
1735 delfunc ClickExpr
1736 delfunc DragExpr
1737 set laststatus& mouse&
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001738endfunc
1739
zeertzjq0f68e6c2022-04-05 13:17:01 +01001740" Test for mapping <LeftDrag> in Insert mode
1741func Test_mouse_drag_insert_map()
1742 set mouse=a
1743 func ClickExpr()
1744 call test_setmouse(1, 1)
1745 return "\<LeftMouse>"
1746 endfunc
1747 func DragExpr()
1748 call test_setmouse(1, 2)
1749 return "\<LeftDrag>"
1750 endfunc
1751 inoremap <expr> <F2> ClickExpr()
1752 imap <expr> <F3> DragExpr()
1753
1754 inoremap <LeftDrag> <LeftDrag><Cmd>let g:dragged = 1<CR>
1755 exe "normal i\<F2>\<F3>"
1756 call assert_equal(1, g:dragged)
1757 call assert_equal('v', mode())
1758 exe "normal! \<C-\>\<C-N>"
1759 unlet g:dragged
1760
1761 inoremap <LeftDrag> <LeftDrag><C-\><C-N>
1762 exe "normal i\<F2>\<F3>"
1763 call assert_equal('n', mode())
1764
1765 iunmap <LeftDrag>
1766 iunmap <F2>
1767 iunmap <F3>
1768 delfunc ClickExpr
1769 delfunc DragExpr
1770 set mouse&
1771endfunc
1772
zeertzjqabeb09b2022-04-26 12:29:43 +01001773func Test_unmap_simplifiable()
zeertzjqa4e33322022-04-24 17:07:53 +01001774 map <C-I> foo
1775 map <Tab> bar
1776 call assert_equal('foo', maparg('<C-I>'))
1777 call assert_equal('bar', maparg('<Tab>'))
1778 unmap <C-I>
1779 call assert_equal('', maparg('<C-I>'))
1780 call assert_equal('bar', maparg('<Tab>'))
1781 unmap <Tab>
zeertzjqabeb09b2022-04-26 12:29:43 +01001782
1783 map <C-I> foo
1784 unmap <Tab>
1785 " This should not error
1786 unmap <C-I>
zeertzjqa4e33322022-04-24 17:07:53 +01001787endfunc
1788
zeertzjq9d997ad2024-07-29 21:10:07 +02001789" Test that the first byte of rhs is not remapped if rhs starts with lhs.
1790func Test_map_rhs_starts_with_lhs()
1791 new
1792 func MapExpr()
1793 return "\<C-R>\<C-P>"
1794 endfunc
1795
1796 for expr in [v:false, v:true]
1797 if expr
1798 imap <buffer><expr> <C-R> MapExpr()
1799 else
1800 imap <buffer> <C-R> <C-R><C-P>
1801 endif
1802
1803 for restore in [v:false, v:true]
1804 if restore
1805 let saved = maparg('<C-R>', 'i', v:false, v:true)
1806 iunmap <buffer> <C-R>
1807 call mapset(saved)
1808 endif
1809
1810 let @a = 'foo'
zeertzjq74011dc2024-07-30 19:17:56 +02001811 call assert_nobeep('call feedkeys("S\<C-R>a", "tx")')
zeertzjq9d997ad2024-07-29 21:10:07 +02001812 call assert_equal('foo', getline('.'))
1813
1814 let @a = 'bar'
zeertzjq74011dc2024-07-30 19:17:56 +02001815 call assert_nobeep('call feedkeys("S\<*C-R>a", "tx")')
zeertzjq9d997ad2024-07-29 21:10:07 +02001816 call assert_equal('bar', getline('.'))
1817 endfor
1818 endfor
1819
1820 " When two mappings are used for <C-I> and <Tab>, remapping should work.
1821 imap <buffer> <C-I> <Tab>bar
1822 imap <buffer> <Tab> foo
1823 call feedkeys("S\<Tab>", 'xt')
1824 call assert_equal('foo', getline('.'))
1825 call feedkeys("S\<*C-I>", 'xt')
1826 call assert_equal('foobar', getline('.'))
1827
1828 delfunc MapExpr
1829 bwipe!
1830endfunc
1831
zeertzjqdb088872022-05-02 22:53:45 +01001832func Test_expr_map_escape_special()
1833 nnoremap <Cmd>let g:got_ellipsis += 1<CR>
1834 func Func()
1835 return '…'
1836 endfunc
1837 nmap <expr> <F2> Func()
1838 let g:got_ellipsis = 0
1839 call feedkeys("\<F2>", 'xt')
1840 call assert_equal(1, g:got_ellipsis)
1841 delfunc Func
1842 nunmap <F2>
1843 unlet g:got_ellipsis
1844 nunmap
1845endfunc
1846
zeertzjq3760bfd2022-06-06 16:22:46 +01001847" Testing for mapping after an <Nop> mapping is triggered on timeout.
1848" Test for what patch 8.1.0052 fixes.
1849func Test_map_after_timed_out_nop()
1850 CheckRunVimInTerminal
1851
1852 let lines =<< trim END
1853 set timeout timeoutlen=400
1854 inoremap ab TEST
1855 inoremap a <Nop>
1856 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001857 call writefile(lines, 'Xtest_map_after_timed_out_nop', 'D')
zeertzjq3760bfd2022-06-06 16:22:46 +01001858 let buf = RunVimInTerminal('-S Xtest_map_after_timed_out_nop', #{rows: 6})
1859
1860 " Enter Insert mode
1861 call term_sendkeys(buf, 'i')
1862 " Wait for the "a" mapping to timeout
1863 call term_sendkeys(buf, 'a')
1864 call term_wait(buf, 500)
1865 " Send "a" and wait for a period shorter than 'timeoutlen'
1866 call term_sendkeys(buf, 'a')
1867 call term_wait(buf, 100)
1868 " Send "b", should trigger the "ab" mapping
1869 call term_sendkeys(buf, 'b')
1870 call WaitForAssert({-> assert_equal("TEST", term_getline(buf, 1))})
1871
1872 " clean up
1873 call StopVimInTerminal(buf)
zeertzjq3760bfd2022-06-06 16:22:46 +01001874endfunc
1875
zeertzjqacdfb8a2024-04-17 21:28:54 +02001876" Test 'showcmd' behavior with a partial mapping
1877func Test_showcmd_part_map()
1878 CheckRunVimInTerminal
1879
zeertzjq094c4392024-04-18 22:09:37 +02001880 let lines =<< trim END
zeertzjqacdfb8a2024-04-17 21:28:54 +02001881 set notimeout showcmd
1882 nnoremap ,a <Ignore>
1883 nnoremap ;a <Ignore>
1884 nnoremap Àa <Ignore>
1885 nnoremap Ëa <Ignore>
1886 nnoremap βa <Ignore>
1887 nnoremap ωa <Ignore>
1888 nnoremap a <Ignore>
1889 nnoremap <C-W>a <Ignore>
1890 END
1891 call writefile(lines, 'Xtest_showcmd_part_map', 'D')
1892 let buf = RunVimInTerminal('-S Xtest_showcmd_part_map', #{rows: 6})
1893
1894 call term_sendkeys(buf, ":set noruler | echo\<CR>")
1895 call WaitForAssert({-> assert_equal('', term_getline(buf, 6))})
1896
1897 for c in [',', ';', 'À', 'Ë', 'β', 'ω', '…']
1898 call term_sendkeys(buf, c)
1899 call WaitForAssert({-> assert_equal(c, trim(term_getline(buf, 6)))})
zeertzjq094c4392024-04-18 22:09:37 +02001900 call term_sendkeys(buf, 'a')
1901 call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))})
zeertzjqacdfb8a2024-04-17 21:28:54 +02001902 endfor
1903
1904 call term_sendkeys(buf, "\<C-W>")
1905 call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))})
zeertzjq094c4392024-04-18 22:09:37 +02001906 call term_sendkeys(buf, 'a')
1907 call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))})
zeertzjqacdfb8a2024-04-17 21:28:54 +02001908
zeertzjq094c4392024-04-18 22:09:37 +02001909 " Use feedkeys() as terminal buffer cannot forward unsimplified Ctrl-W.
1910 " This is like typing Ctrl-W with modifyOtherKeys enabled.
zeertzjqacdfb8a2024-04-17 21:28:54 +02001911 call term_sendkeys(buf, ':call feedkeys("\<*C-W>", "m")' .. " | echo\<CR>")
1912 call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))})
zeertzjq094c4392024-04-18 22:09:37 +02001913 call term_sendkeys(buf, 'a')
1914 call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))})
zeertzjqacdfb8a2024-04-17 21:28:54 +02001915
1916 call StopVimInTerminal(buf)
1917endfunc
1918
Bram Moolenaar27efc622022-07-01 16:35:45 +01001919func Test_using_past_typeahead()
1920 nnoremap :00 0
1921 exe "norm :set \x80\xfb0=0\<CR>"
1922 exe "sil norm :0\x0f\<C-U>\<CR>"
1923
1924 exe "norm :set \x80\xfb0=\<CR>"
1925 nunmap :00
1926endfunc
1927
Bram Moolenaarbf533e42022-11-13 20:43:19 +00001928func Test_mapclear_while_listing()
1929 CheckRunVimInTerminal
1930
1931 let lines =<< trim END
1932 set nocompatible
1933 mapclear
1934 for i in range(1, 999)
1935 exe 'map ' .. 'foo' .. i .. ' bar'
1936 endfor
1937 au CmdlineLeave : call timer_start(0, {-> execute('mapclear')})
1938 END
1939 call writefile(lines, 'Xmapclear', 'D')
1940 let buf = RunVimInTerminal('-S Xmapclear', {'rows': 10})
1941
1942 " this was using freed memory
1943 call term_sendkeys(buf, ":map\<CR>")
1944 call TermWait(buf, 50)
1945 call term_sendkeys(buf, "G")
1946 call TermWait(buf, 50)
1947 call term_sendkeys(buf, "\<CR>")
1948
1949 call StopVimInTerminal(buf)
1950endfunc
1951
Bram Moolenaar27efc622022-07-01 16:35:45 +01001952
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001953" vim: shiftwidth=2 sts=2 expandtab