blob: 122793c4da132c9502738a51ac4d327337a188be [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()
zeertzjq5df3cb22024-10-07 21:05:06 +020010 new
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020011 " abbreviation with 0x80 should work
12 inoreab чкпр vim
13 call feedkeys("Goчкпр \<Esc>", "xt")
14 call assert_equal('vim ', getline('$'))
15 iunab чкпр
zeertzjq5df3cb22024-10-07 21:05:06 +020016 bwipe!
17endfunc
18
19func Test_abbreviation_with_noremap()
20 nnoremap <F2> :echo "cheese"
21 cabbr cheese xxx
22 call feedkeys(":echo \"cheese\"\<C-B>\"\<CR>", 'tx')
23 call assert_equal('"echo "xxx"', @:)
24 call feedkeys("\<F2>\<C-B>\"\<CR>", 'tx')
25 call assert_equal('"echo "cheese"', @:)
26 nnoremap <F2> :echo "cheese<C-]>"
27 call feedkeys("\<F2>\<C-B>\"\<CR>", 'tx')
28 call assert_equal('"echo "xxx"', @:)
29 nunmap <F2>
30 cunabbr cheese
31
32 new
33 inoremap <buffer> ( <C-]>()
34 iabbr <buffer> fnu fun
35 call feedkeys("ifnu(", 'tx')
36 call assert_equal('fun()', getline(1))
37 bwipe!
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020038endfunc
39
Bram Moolenaar8485be42019-04-23 16:36:05 +020040func Test_abclear()
zeertzjq5df3cb22024-10-07 21:05:06 +020041 abbrev foo foobar
42 iabbrev fooi foobari
43 cabbrev fooc foobarc
44 call assert_equal("\n\n"
45 \ .. "c fooc foobarc\n"
46 \ .. "i fooi foobari\n"
47 \ .. "! foo foobar", execute('abbrev'))
Bram Moolenaar8485be42019-04-23 16:36:05 +020048
zeertzjq5df3cb22024-10-07 21:05:06 +020049 iabclear
50 call assert_equal("\n\n"
51 \ .. "c fooc foobarc\n"
52 \ .. "c foo foobar", execute('abbrev'))
53 abbrev foo foobar
54 iabbrev fooi foobari
Bram Moolenaar8485be42019-04-23 16:36:05 +020055
zeertzjq5df3cb22024-10-07 21:05:06 +020056 cabclear
57 call assert_equal("\n\n"
58 \ .. "i fooi foobari\n"
59 \ .. "i foo foobar", execute('abbrev'))
60 abbrev foo foobar
61 cabbrev fooc foobarc
Bram Moolenaar8485be42019-04-23 16:36:05 +020062
zeertzjq5df3cb22024-10-07 21:05:06 +020063 abclear
64 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
65 call assert_fails('%abclear', 'E481:')
Bram Moolenaar8485be42019-04-23 16:36:05 +020066endfunc
67
68func Test_abclear_buffer()
69 abbrev foo foobar
70 new X1
71 abbrev <buffer> foo1 foobar1
72 new X2
73 abbrev <buffer> foo2 foobar2
74
75 call assert_equal("\n\n"
76 \ .. "! foo2 @foobar2\n"
77 \ .. "! foo foobar", execute('abbrev'))
78
79 abclear <buffer>
80 call assert_equal("\n\n"
81 \ .. "! foo foobar", execute('abbrev'))
82
83 b X1
84 call assert_equal("\n\n"
85 \ .. "! foo1 @foobar1\n"
86 \ .. "! foo foobar", execute('abbrev'))
87 abclear <buffer>
88 call assert_equal("\n\n"
89 \ .. "! foo foobar", execute('abbrev'))
90
91 abclear
92 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
93
94 %bwipe
95endfunc
96
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020097func Test_map_ctrl_c_insert()
98 " mapping of ctrl-c in Insert mode
99 set cpo-=< cpo-=k
100 inoremap <c-c> <ctrl-c>
101 cnoremap <c-c> dummy
102 cunmap <c-c>
Bram Moolenaarfccd93f2020-05-31 22:06:51 +0200103 call feedkeys("GoTEST2: CTRL-C |\<*C-C>A|\<Esc>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200104 call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
105 unmap! <c-c>
106 set nomodified
107endfunc
108
109func Test_map_ctrl_c_visual()
110 " mapping of ctrl-c in Visual mode
111 vnoremap <c-c> :<C-u>$put ='vmap works'
Bram Moolenaarfccd93f2020-05-31 22:06:51 +0200112 call feedkeys("GV\<*C-C>\<CR>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200113 call assert_equal('vmap works', getline('$'))
114 vunmap <c-c>
115 set nomodified
116endfunc
117
118func Test_map_langmap()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200119 CheckFeature langmap
Bram Moolenaar920694c2016-08-21 17:45:02 +0200120
121 " check langmap applies in normal mode
122 set langmap=+- nolangremap
123 new
124 call setline(1, ['a', 'b', 'c'])
125 2
126 call assert_equal('b', getline('.'))
127 call feedkeys("+", "xt")
128 call assert_equal('a', getline('.'))
129
130 " check no remapping
131 map x +
132 2
133 call feedkeys("x", "xt")
134 call assert_equal('c', getline('.'))
135
136 " check with remapping
137 set langremap
138 2
139 call feedkeys("x", "xt")
140 call assert_equal('a', getline('.'))
141
142 unmap x
143 bwipe!
144
zeertzjqe7102202024-02-13 20:32:04 +0100145 " 'langnoremap' follows 'langremap' and vice versa
Bram Moolenaar920694c2016-08-21 17:45:02 +0200146 set langremap
147 set langnoremap
148 call assert_equal(0, &langremap)
149 set langremap
150 call assert_equal(0, &langnoremap)
151 set nolangremap
152 call assert_equal(1, &langnoremap)
153
Bram Moolenaarda9ce2c2016-09-02 19:34:10 +0200154 " check default values
155 set langnoremap&
156 call assert_equal(0, &langnoremap)
157 call assert_equal(1, &langremap)
158 set langremap&
159 call assert_equal(0, &langnoremap)
160 call assert_equal(1, &langremap)
161
Bram Moolenaar920694c2016-08-21 17:45:02 +0200162 " langmap should not apply in insert mode, 'langremap' doesn't matter
163 set langmap=+{ nolangremap
164 call feedkeys("Go+\<Esc>", "xt")
165 call assert_equal('+', getline('$'))
166 set langmap=+{ langremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200167 call feedkeys("Go+\<Esc>", "xt")
168 call assert_equal('+', getline('$'))
169
Bram Moolenaar920694c2016-08-21 17:45:02 +0200170 " langmap used for register name in insert mode.
171 call setreg('a', 'aaaa')
172 call setreg('b', 'bbbb')
173 call setreg('c', 'cccc')
174 set langmap=ab langremap
175 call feedkeys("Go\<C-R>a\<Esc>", "xt")
176 call assert_equal('bbbb', getline('$'))
177 call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt")
178 call assert_equal('bbbb', getline('$'))
179 " mapping does not apply
180 imap c a
181 call feedkeys("Go\<C-R>c\<Esc>", "xt")
182 call assert_equal('cccc', getline('$'))
183 imap a c
184 call feedkeys("Go\<C-R>a\<Esc>", "xt")
185 call assert_equal('bbbb', getline('$'))
zeertzjq5df3cb22024-10-07 21:05:06 +0200186
Bram Moolenaar920694c2016-08-21 17:45:02 +0200187 " langmap should not apply in Command-line mode
188 set langmap=+{ nolangremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200189 call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
190 call assert_equal('+', getline('$'))
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200191
Bram Moolenaare90858d2017-02-01 17:24:34 +0100192 iunmap a
193 iunmap c
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200194 set nomodified
195endfunc
196
197func Test_map_feedkeys()
198 " issue #212 (feedkeys insert mapping at current position)
199 nnoremap . :call feedkeys(".", "in")<cr>
200 call setline('$', ['a b c d', 'a b c d'])
201 $-1
202 call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt")
203 call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$')))
Bram Moolenaare90858d2017-02-01 17:24:34 +0100204 nunmap .
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200205 set nomodified
206endfunc
207
208func Test_map_cursor()
209 " <c-g>U<cursor> works only within a single line
210 imapclear
211 imap ( ()<c-g>U<left>
212 call feedkeys("G2o\<Esc>ki\<CR>Test1: text with a (here some more text\<Esc>k.", "xt")
213 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 2))
214 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 1))
215
216 " test undo
217 call feedkeys("G2o\<Esc>ki\<CR>Test2: text wit a (here some more text [und undo]\<C-G>u\<Esc>k.u", "xt")
218 call assert_equal('', getline(line('$') - 2))
219 call assert_equal('Test2: text wit a (here some more text [und undo])', getline(line('$') - 1))
220 set nomodified
221 imapclear
222endfunc
223
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100224func Test_map_cursor_ctrl_gU()
225 " <c-g>U<cursor> works only within a single line
226 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left>
227 call setline(1, ['foo', 'foobar', '', 'foo'])
228 call cursor(1,2)
229 call feedkeys("c<*PREFIX\<esc>.", 'xt')
230 call assert_equal(['PREFIXfoo', 'foobar', '', 'PREFIXfoo'], getline(1,'$'))
231 " break undo manually
232 set ul=1000
233 exe ":norm! uu"
234 call assert_equal(['foo', 'foobar', '', 'foo'], getline(1,'$'))
235
236 " Test that it does not work if the cursor moves to the previous line
237 " 2 times <S-Left> move to the previous line
238 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left><C-G>U<S-Left>
239 call setline(1, ['', ' foo', 'foobar', '', 'foo'])
240 call cursor(2,3)
241 call feedkeys("c<*PREFIX\<esc>.", 'xt')
242 call assert_equal(['PREFIXPREFIX', ' foo', 'foobar', '', 'foo'], getline(1,'$'))
243 nmapclear
244endfunc
245
246
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200247" This isn't actually testing a mapping, but similar use of CTRL-G U as above.
248func Test_break_undo()
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100249 set whichwrap=<,>,[,]
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200250 call feedkeys("G4o2k", "xt")
251 exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."
252 call assert_equal('new line here', getline(line('$') - 3))
253 call assert_equal('Test3: text with a (parenthesis here', getline(line('$') - 2))
254 call assert_equal('new line here', getline(line('$') - 1))
255 set nomodified
256endfunc
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200257
258func Test_map_meta_quotes()
259 imap <M-"> foo
Bram Moolenaarfccd93f2020-05-31 22:06:51 +0200260 call feedkeys("Go-\<*M-\">-\<Esc>", "xt")
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200261 call assert_equal("-foo-", getline('$'))
262 set nomodified
263 iunmap <M-">
264endfunc
Bram Moolenaar878c2632017-04-01 15:15:52 +0200265
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200266func Test_map_meta_multibyte()
267 imap <M-á> foo
Bram Moolenaar2f710af2019-08-16 20:56:03 +0200268 call assert_match('i <M-á>\s*foo', execute('imap'))
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200269 iunmap <M-á>
270endfunc
271
Casey Tucker92e90a12024-01-25 22:44:00 +0100272func Test_map_super_quotes()
zeertzjq6b13e3d2024-04-22 21:04:29 +0200273 if "\<D-j>"[-1:] == '>'
274 throw 'Skipped: <D- modifier not supported'
Casey Tucker92e90a12024-01-25 22:44:00 +0100275 endif
zeertzjq6b13e3d2024-04-22 21:04:29 +0200276
277 imap <D-"> foo
278 call feedkeys("Go-\<*D-\">-\<Esc>", "xt")
279 call assert_equal("-foo-", getline('$'))
280 set nomodified
281 iunmap <D-">
Casey Tucker92e90a12024-01-25 22:44:00 +0100282endfunc
283
284func Test_map_super_multibyte()
zeertzjq6b13e3d2024-04-22 21:04:29 +0200285 if "\<D-j>"[-1:] == '>'
286 throw 'Skipped: <D- modifier not supported'
Casey Tucker92e90a12024-01-25 22:44:00 +0100287 endif
zeertzjq6b13e3d2024-04-22 21:04:29 +0200288
289 imap <D-á> foo
290 call assert_match('i <D-á>\s*foo', execute('imap'))
291 iunmap <D-á>
Casey Tucker92e90a12024-01-25 22:44:00 +0100292endfunc
293
Bram Moolenaar878c2632017-04-01 15:15:52 +0200294func Test_abbr_after_line_join()
295 new
296 abbr foo bar
297 set backspace=indent,eol,start
298 exe "normal o\<BS>foo "
299 call assert_equal("bar ", getline(1))
300 bwipe!
301 unabbr foo
302 set backspace&
303endfunc
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200304
305func Test_map_timeout()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200306 CheckFeature timers
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200307 nnoremap aaaa :let got_aaaa = 1<CR>
308 nnoremap bb :let got_bb = 1<CR>
309 nmap b aaa
310 new
311 func ExitInsert(timer)
312 let g:line = getline(1)
313 call feedkeys("\<Esc>", "t")
314 endfunc
315 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100316 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200317 " After the 'b' Vim waits for another character to see if it matches 'bb'.
318 " When it times out it is expanded to "aaa", but there is no wait for
319 " "aaaa". Can't check that reliably though.
320 call feedkeys("b", "xt!")
321 call assert_equal("aa", g:line)
322 call assert_false(exists('got_aaa'))
323 call assert_false(exists('got_bb'))
324
325 bwipe!
326 nunmap aaaa
327 nunmap bb
328 nunmap b
329 set timeoutlen&
330 delfunc ExitInsert
Bram Moolenaar26d98212019-01-27 22:32:55 +0100331 call timer_stop(timer)
332endfunc
333
334func Test_map_timeout_with_timer_interrupt()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200335 CheckFeature job
336 CheckFeature timers
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100337 let g:test_is_flaky = 1
Bram Moolenaar26d98212019-01-27 22:32:55 +0100338
339 " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
340 " sequence.
341 new
342 let g:val = 0
343 nnoremap \12 :let g:val = 1<CR>
344 nnoremap \123 :let g:val = 2<CR>
Bram Moolenaarea94c852019-08-16 21:47:27 +0200345 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100346
347 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100348 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100349 endfunc
350
351 call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
352 call feedkeys('\12', 'xt!')
353 call assert_equal(2, g:val)
354
355 bwipe!
356 nunmap \12
357 nunmap \123
358 set timeoutlen&
359 call WaitFor({-> exists('g:timer')})
360 call timer_stop(g:timer)
361 unlet g:timer
362 unlet g:val
363 delfunc ExitCb
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200364endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200365
366func Test_abbreviation_CR()
367 new
368 func Eatchar(pat)
369 let c = nr2char(getchar(0))
370 return (c =~ a:pat) ? '' : c
371 endfunc
372 iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
373 call feedkeys("GA~~7 \<esc>", 'xt')
374 call assert_equal('~~~~~~~', getline('$'))
375 %d
376 call feedkeys("GA~~7\<cr>\<esc>", 'xt')
377 call assert_equal(['~~~~~~~', ''], getline(1,'$'))
378 delfunc Eatchar
379 bw!
380endfunc
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200381
382func Test_cabbr_visual_mode()
383 cabbr s su
384 call feedkeys(":s \<c-B>\"\<CR>", 'itx')
385 call assert_equal('"su ', getreg(':'))
386 call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
387 let expected = '"'. "'<,'>su "
388 call assert_equal(expected, getreg(':'))
389 call feedkeys(": '<,'>s \<c-B>\"\<CR>", 'itx')
390 let expected = '" '. "'<,'>su "
391 call assert_equal(expected, getreg(':'))
392 call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
393 let expected = '"'. "'a,'bsu "
394 call assert_equal(expected, getreg(':'))
395 cunabbr s
396endfunc
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100397
398func Test_motionforce_omap()
399 func GetCommand()
400 let g:m=mode(1)
401 let [g:lnum1, g:col1] = searchpos('-', 'Wb')
402 if g:lnum1 == 0
403 return "\<Esc>"
404 endif
405 let [g:lnum2, g:col2] = searchpos('-', 'W')
406 if g:lnum2 == 0
407 return "\<Esc>"
408 endif
409 return ":call Select()\<CR>"
410 endfunc
411 func Select()
412 call cursor([g:lnum1, g:col1])
413 exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
414 call cursor([g:lnum2, g:col2])
415 execute "normal! \<BS>"
416 endfunc
417 new
418 onoremap <buffer><expr> i- GetCommand()
419 " 1) default omap mapping
420 %d_
421 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
422 call cursor(2, 1)
423 norm di-
424 call assert_equal('no', g:m)
425 call assert_equal(['aaa -- eee'], getline(1, '$'))
426 " 2) forced characterwise operation
427 %d_
428 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
429 call cursor(2, 1)
430 norm dvi-
431 call assert_equal('nov', g:m)
432 call assert_equal(['aaa -- eee'], getline(1, '$'))
433 " 3) forced linewise operation
434 %d_
435 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
436 call cursor(2, 1)
437 norm dVi-
438 call assert_equal('noV', g:m)
439 call assert_equal([''], getline(1, '$'))
440 " 4) forced blockwise operation
441 %d_
442 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
443 call cursor(2, 1)
444 exe "norm d\<C-V>i-"
445 call assert_equal("no\<C-V>", g:m)
446 call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
447 bwipe!
448 delfunc Select
449 delfunc GetCommand
450endfunc
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200451
452func Test_error_in_map_expr()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200453 " Unlike CheckRunVimInTerminal this does work in a win32 console
454 CheckFeature terminal
455 if has('win32') && has('gui_running')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200456 throw 'Skipped: cannot run Vim in a terminal window'
457 endif
458
459 let lines =<< trim [CODE]
460 func Func()
461 " fail to create list
462 let x = [
463 endfunc
464 nmap <expr> ! Func()
465 set updatetime=50
466 [CODE]
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100467 call writefile(lines, 'Xtest.vim', 'D')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200468
Bram Moolenaar0d702022019-07-04 14:20:41 +0200469 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200470 let job = term_getjob(buf)
471 call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
472
473 " GC must not run during map-expr processing, which can make Vim crash.
474 call term_sendkeys(buf, '!')
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200475 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200476 call term_sendkeys(buf, "\<CR>")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200477 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200478 call assert_equal('run', job_status(job))
479
480 call term_sendkeys(buf, ":qall!\<CR>")
481 call WaitFor({-> job_status(job) ==# 'dead'})
482 if has('unix')
483 call assert_equal('', job_info(job).termsig)
484 endif
485
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200486 exe buf .. 'bwipe!'
487endfunc
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200488
489func Test_list_mappings()
Bram Moolenaar2559a472019-10-16 23:33:12 +0200490 " Remove default mappings
491 imapclear
Bram Moolenaar4f2f61a2019-10-16 22:27:49 +0200492
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200493 " reset 'isident' to check it isn't used
494 set isident=
495 inoremap <C-m> CtrlM
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200496 inoremap <A-S> AltS
497 inoremap <S-/> ShiftSlash
Bram Moolenaare3d1f4c2021-04-06 20:21:59 +0200498 set isident&
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200499 call assert_equal([
500 \ 'i <S-/> * ShiftSlash',
501 \ 'i <M-S> * AltS',
502 \ 'i <C-M> * CtrlM',
503 \], execute('imap')->trim()->split("\n"))
504 iunmap <C-M>
505 iunmap <A-S>
506 call assert_equal(['i <S-/> * ShiftSlash'], execute('imap')->trim()->split("\n"))
507 iunmap <S-/>
508 call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100509
510 " List global, buffer local and script local mappings
511 nmap ,f /^\k\+ (<CR>
512 nmap <buffer> ,f /^\k\+ (<CR>
513 nmap <script> ,fs /^\k\+ (<CR>
514 call assert_equal(['n ,f @/^\k\+ (<CR>',
515 \ 'n ,fs & /^\k\+ (<CR>',
516 \ 'n ,f /^\k\+ (<CR>'],
517 \ execute('nmap ,f')->trim()->split("\n"))
518
519 " List <Nop> mapping
520 nmap ,n <Nop>
521 call assert_equal(['n ,n <Nop>'],
522 \ execute('nmap ,n')->trim()->split("\n"))
523
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100524 " verbose map
Bram Moolenaar060b8382022-10-19 14:48:14 +0100525 let lines = execute('verbose map ,n')->trim()->split("\n")
Bram Moolenaarc255b782022-11-26 19:16:48 +0000526
527 " Remove "Seen modifyOtherKeys" and other optional info.
528 if lines[0] =~ 'Seen modifyOtherKeys'
529 call remove(lines, 0)
530 endif
531 if lines[0] =~ 'modifyOtherKeys detected:'
532 call remove(lines, 0)
533 endif
534 if lines[0] =~ 'Kitty keyboard protocol:'
535 call remove(lines, 0)
536 endif
537 if lines[0] == ''
538 call remove(lines, 0)
539 endif
540
Bram Moolenaar060b8382022-10-19 14:48:14 +0100541 let index = indexof(lines, 'v:val =~ "Last set"')
Bram Moolenaarc255b782022-11-26 19:16:48 +0000542 call assert_equal(1, index)
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100543 call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
Bram Moolenaar060b8382022-10-19 14:48:14 +0100544 \ lines[index])
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100545
zeertzjqac402f42022-05-04 18:51:43 +0100546 " character with K_SPECIAL byte in rhs
547 nmap foo …
548 call assert_equal(['n foo …'],
549 \ execute('nmap foo')->trim()->split("\n"))
550
551 " modified character with K_SPECIAL byte in rhs
552 nmap foo <M-…>
553 call assert_equal(['n foo <M-…>'],
554 \ execute('nmap foo')->trim()->split("\n"))
555
556 " character with K_SPECIAL byte in lhs
557 nmap … foo
558 call assert_equal(['n … foo'],
559 \ execute('nmap …')->trim()->split("\n"))
560
561 " modified character with K_SPECIAL byte in lhs
562 nmap <M-…> foo
563 call assert_equal(['n <M-…> foo'],
564 \ execute('nmap <M-…>')->trim()->split("\n"))
565
zeertzjq0519ce02022-05-09 12:16:19 +0100566 " illegal bytes
567 let str = ":\x7f:\x80:\x90:\xd0:"
568 exe 'nmap foo ' .. str
569 call assert_equal(['n foo ' .. strtrans(str)],
570 \ execute('nmap foo')->trim()->split("\n"))
571 unlet str
572
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100573 " map to CTRL-V
574 exe "nmap ,k \<C-V>"
575 call assert_equal(['n ,k <Nop>'],
576 \ execute('nmap ,k')->trim()->split("\n"))
577
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +0200578 " map with space at the beginning
579 exe "nmap \<C-V> w <Nop>"
580 call assert_equal(['n <Space>w <Nop>'],
581 \ execute("nmap \<C-V> w")->trim()->split("\n"))
582
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100583 nmapclear
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200584endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100585
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100586func Test_expr_map_gets_cursor()
587 new
588 call setline(1, ['one', 'some w!rd'])
589 func StoreColumn()
590 let g:exprLine = line('.')
591 let g:exprCol = col('.')
592 return 'x'
593 endfunc
594 nnoremap <expr> x StoreColumn()
595 2
596 nmap ! f!<Ignore>x
597 call feedkeys("!", 'xt')
598 call assert_equal('some wrd', getline(2))
599 call assert_equal(2, g:exprLine)
600 call assert_equal(7, g:exprCol)
601
602 bwipe!
603 unlet g:exprLine
604 unlet g:exprCol
Bram Moolenaar6ccfd992021-03-17 13:39:33 +0100605 delfunc StoreColumn
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100606 nunmap x
607 nunmap !
608endfunc
609
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100610func Test_expr_map_restore_cursor()
611 CheckScreendump
612
613 let lines =<< trim END
614 call setline(1, ['one', 'two', 'three'])
615 2
616 set ls=2
617 hi! link StatusLine ErrorMsg
618 noremap <expr> <C-B> Func()
619 func Func()
620 let g:on = !get(g:, 'on', 0)
621 redraws
622 return ''
623 endfunc
624 func Status()
625 return get(g:, 'on', 0) ? '[on]' : ''
626 endfunc
627 set stl=%{Status()}
628 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100629 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100630 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar9f145572022-11-27 12:45:41 +0000631 call term_sendkeys(buf, GetEscCodeWithModifier('C', 'B'))
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100632 call VerifyScreenDump(buf, 'Test_map_expr_1', {})
633
634 " clean up
635 call StopVimInTerminal(buf)
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100636endfunc
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100637
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000638func Test_map_listing()
639 CheckScreendump
640
641 let lines =<< trim END
642 nmap a b
643 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100644 call writefile(lines, 'XtestMapList', 'D')
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000645 let buf = RunVimInTerminal('-S XtestMapList', #{rows: 6})
646 call term_sendkeys(buf, ": nmap a\<CR>")
647 call VerifyScreenDump(buf, 'Test_map_list_1', {})
648
649 " clean up
650 call StopVimInTerminal(buf)
Bram Moolenaard288eaa2022-02-16 18:27:55 +0000651endfunc
652
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000653func Test_expr_map_error()
654 CheckScreendump
655
656 let lines =<< trim END
657 func Func()
658 throw 'test'
659 return ''
660 endfunc
661
662 nnoremap <expr> <F2> Func()
663 cnoremap <expr> <F2> Func()
664
665 call test_override('ui_delay', 10)
666 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +0100667 call writefile(lines, 'XtestExprMap', 'D')
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000668 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000669 call term_sendkeys(buf, "\<F2>")
670 call TermWait(buf)
671 call term_sendkeys(buf, "\<CR>")
672 call VerifyScreenDump(buf, 'Test_map_expr_2', {})
673
674 call term_sendkeys(buf, ":abc\<F2>")
675 call VerifyScreenDump(buf, 'Test_map_expr_3', {})
676 call term_sendkeys(buf, "\<Esc>0")
677 call VerifyScreenDump(buf, 'Test_map_expr_4', {})
678
679 " clean up
680 call StopVimInTerminal(buf)
Bram Moolenaar74a0a5b2022-02-10 14:07:41 +0000681endfunc
682
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100683" Test for mapping errors
684func Test_map_error()
685 call assert_fails('unmap', 'E474:')
686 call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
687 call assert_fails('unmap abc', 'E31:')
688 call assert_fails('unabbr abc', 'E24:')
689 call assert_equal('', maparg(''))
690 call assert_fails('echo maparg("abc", [])', 'E730:')
691
692 " unique map
693 map ,w /[#&!]<CR>
694 call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
695 " unique buffer-local map
696 call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
697 unmap ,w
698
699 " unique abbreviation
700 abbr SP special
701 call assert_fails("abbr <unique> SP special", 'E226:')
702 " unique buffer-local map
703 call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
704 unabbr SP
705
706 call assert_fails('mapclear abc', 'E474:')
707 call assert_fails('abclear abc', 'E474:')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100708 call assert_fails('abbr $xyz abc', 'E474:')
709
710 " space character in an abbreviation
711 call assert_fails('abbr ab<space> ABC', 'E474:')
712
713 " invalid <expr> map
714 map <expr> ,f abc
715 call assert_fails('normal ,f', 'E121:')
716 unmap <expr> ,f
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100717
718 " Recursive use of :normal in a map
719 set maxmapdepth=100
720 map gq :normal gq<CR>
721 call assert_fails('normal gq', 'E192:')
722 unmap gq
723 set maxmapdepth&
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100724endfunc
725
726" Test for <special> key mapping
727func Test_map_special()
728 new
729 let old_cpo = &cpo
730 set cpo+=<
731 imap <F12> Blue
732 call feedkeys("i\<F12>", "x")
733 call assert_equal("<F12>", getline(1))
734 call feedkeys("ddi<F12>", "x")
735 call assert_equal("Blue", getline(1))
736 iunmap <F12>
737 imap <special> <F12> Green
738 call feedkeys("ddi\<F12>", "x")
739 call assert_equal("Green", getline(1))
740 call feedkeys("ddi<F12>", "x")
741 call assert_equal("<F12>", getline(1))
742 iunmap <special> <F12>
743 let &cpo = old_cpo
744 %bwipe!
745endfunc
746
747" Test for hasmapto()
748func Test_hasmapto()
749 call assert_equal(0, hasmapto('/^\k\+ ('))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100750 map ,f /^\k\+ (<CR>
751 call assert_equal(1, hasmapto('/^\k\+ ('))
752 unmap ,f
753
754 " Insert mode mapping
755 call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
756 imap ,f /^\k\+ (<CR>
757 call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
758 iunmap ,f
759
760 " Normal mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100761 call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
762 nmap ,f /^\k\+ (<CR>
763 call assert_equal(1, hasmapto('/^\k\+ ('))
764 call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100765 nunmap ,f
766
767 " Visual and Select mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100768 call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100769 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
770 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
771 vmap ,f /^\k\+ (<CR>
772 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
773 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
774 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
775 vunmap ,f
776
777 " Visual mode mapping
778 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
779 xmap ,f /^\k\+ (<CR>
780 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
781 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
782 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
783 xunmap ,f
784
785 " Select mode mapping
786 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
787 smap ,f /^\k\+ (<CR>
788 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
789 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
790 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
791 sunmap ,f
792
793 " Operator-pending mode mapping
794 call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
795 omap ,f /^\k\+ (<CR>
796 call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
797 ounmap ,f
798
799 " Language mapping
800 call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
801 lmap ,f /^\k\+ (<CR>
802 call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
803 lunmap ,f
804
805 " Cmdline mode mapping
806 call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
807 cmap ,f /^\k\+ (<CR>
808 call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
809 cunmap ,f
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100810
811 call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
812endfunc
813
814" Test for command-line completion of maps
815func Test_mapcomplete()
816 call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
817 \ '<silent>', '<special>', '<unique>'],
818 \ getcompletion('', 'mapping'))
819 call assert_equal([], getcompletion(',d', 'mapping'))
820
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100821 call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
822 call assert_equal('"unmap <buffer>', @:)
823
824 call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
825 call assert_equal('"unabbr <buffer>', @:)
826
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100827 call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100828 call assert_equal("\"abbr! \x01", @:)
829
zeertzjq997b8a02023-02-19 21:00:31 +0000830 " When multiple matches have the same {lhs}, it should only appear once.
831 " The simplified form should also not be included.
832 nmap ,<C-F> /H<CR>
833 omap ,<C-F> /H<CR>
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100834 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
zeertzjq997b8a02023-02-19 21:00:31 +0000835 call assert_equal('"map ,<C-F>', @:)
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100836 mapclear
837endfunc
838
Bram Moolenaar94075b22022-01-18 20:30:39 +0000839func GetAbbrText()
840 unabbr hola
841 return 'hello'
842endfunc
843
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100844" Test for <expr> in abbreviation
845func Test_expr_abbr()
846 new
847 iabbr <expr> teh "the"
848 call feedkeys("iteh ", "tx")
849 call assert_equal('the ', getline(1))
850 iabclear
851 call setline(1, '')
852
853 " invalid <expr> abbreviation
854 abbr <expr> hte GetAbbr()
855 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100856 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100857 unabbr <expr> hte
858
Bram Moolenaar94075b22022-01-18 20:30:39 +0000859 " evaluating the expression deletes the abbreviation
860 abbr <expr> hola GetAbbrText()
861 call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
862 call feedkeys("ahola \<Esc>", 'xt')
863 call assert_equal('hello ', getline('.'))
864 call assert_equal('', maparg('hola', 'i', '1'))
865
866 bwipe!
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100867endfunc
868
869" Test for storing mappings in different modes in a vimrc file
870func Test_mkvimrc_mapmodes()
871 map a1 /a1
872 nmap a2 /a2
873 vmap a3 /a3
874 smap a4 /a4
875 xmap a5 /a5
876 omap a6 /a6
877 map! a7 /a7
878 imap a8 /a8
879 lmap a9 /a9
880 cmap a10 /a10
881 tmap a11 /a11
882 " Normal + Visual map
883 map a12 /a12
884 sunmap a12
885 ounmap a12
886 " Normal + Selectmode map
887 map a13 /a13
888 xunmap a13
889 ounmap a13
890 " Normal + OpPending map
891 map a14 /a14
892 vunmap a14
893 " Visual + Selectmode map
894 map a15 /a15
895 nunmap a15
896 ounmap a15
897 " Visual + OpPending map
898 map a16 /a16
899 nunmap a16
900 sunmap a16
901 " Selectmode + OpPending map
902 map a17 /a17
903 nunmap a17
904 xunmap a17
905 " Normal + Visual + Selectmode map
906 map a18 /a18
907 ounmap a18
908 " Normal + Visual + OpPending map
909 map a19 /a19
910 sunmap a19
911 " Normal + Selectmode + OpPending map
912 map a20 /a20
913 xunmap a20
914 " Visual + Selectmode + OpPending map
915 map a21 /a21
916 nunmap a21
917 " Mapping to Nop
918 map a22 <Nop>
919 " Script local mapping
920 map <script> a23 /a23
921
922 " Newline in {lhs} and {rhs} of a map
923 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
924
925 " Abbreviation
926 abbr a25 A25
927 cabbr a26 A26
928 iabbr a27 A27
929
930 mkvimrc! Xvimrc
931 let l = readfile('Xvimrc')
932 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
933 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
934 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
935 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
936 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
937 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
938 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
939 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
940 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
941 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
942 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
943 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
944 \ filter(copy(l), 'v:val =~ " a12 "'))
945 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
946 \ filter(copy(l), 'v:val =~ " a13 "'))
947 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
948 \ filter(copy(l), 'v:val =~ " a14 "'))
949 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
950 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
951 \ filter(copy(l), 'v:val =~ " a16 "'))
952 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
953 \ filter(copy(l), 'v:val =~ " a17 "'))
954 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
955 \ filter(copy(l), 'v:val =~ " a18 "'))
956 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
957 \ filter(copy(l), 'v:val =~ " a19 "'))
958 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
959 \ filter(copy(l), 'v:val =~ " a20 "'))
960 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
961 \ filter(copy(l), 'v:val =~ " a21 "'))
962 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
963 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
964 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
965 \ filter(copy(l), 'v:val =~ " a24"'))
966
967 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
968 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
969 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
970 call delete('Xvimrc')
971
972 mapclear
973 nmapclear
974 vmapclear
975 xmapclear
976 smapclear
977 omapclear
978 imapclear
979 lmapclear
980 cmapclear
981 tmapclear
982endfunc
983
984" Test for recursive mapping ('maxmapdepth')
985func Test_map_recursive()
986 map x y
987 map y x
988 call assert_fails('normal x', 'E223:')
989 unmap x
990 unmap y
991endfunc
992
993" Test for removing an abbreviation using {rhs} and with space after {lhs}
994func Test_abbr_remove()
995 abbr foo bar
996 let d = maparg('foo', 'i', 1, 1)
997 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
998 unabbr bar
999 call assert_equal({}, maparg('foo', 'i', 1, 1))
1000
1001 abbr foo bar
1002 unabbr foo<space><tab>
1003 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001004endfunc
1005
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +01001006" Trigger an abbreviation using a special key
1007func Test_abbr_trigger_special()
1008 new
1009 iabbr teh the
1010 call feedkeys("iteh\<F2>\<Esc>", 'xt')
1011 call assert_equal('the<F2>', getline(1))
1012 iunab teh
1013 close!
1014endfunc
1015
1016" Test for '<' in 'cpoptions'
1017func Test_map_cpo_special_keycode()
1018 set cpo-=<
1019 imap x<Bslash>k Test
1020 let d = maparg('x<Bslash>k', 'i', 0, 1)
1021 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
1022 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
1023 call assert_equal('"imap x\k', @:)
1024 iunmap x<Bslash>k
1025 set cpo+=<
1026 imap x<Bslash>k Test
1027 let d = maparg('x<Bslash>k', 'i', 0, 1)
1028 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
1029 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
1030 call assert_equal('"imap x<Bslash>k', @:)
1031 iunmap x<Bslash>k
1032 set cpo-=<
1033 " Modifying 'cpo' above adds some default mappings, remove them
1034 mapclear
1035 mapclear!
1036endfunc
1037
Bram Moolenaar957cf672020-11-12 14:21:06 +01001038" Test for <Cmd> key in maps to execute commands
1039func Test_map_cmdkey()
1040 new
1041
1042 " Error cases
1043 let x = 0
1044 noremap <F3> <Cmd><Cmd>let x = 1<CR>
1045 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
1046 call assert_equal(0, x)
1047
Bram Moolenaar957cf672020-11-12 14:21:06 +01001048 noremap <F3> <Cmd>let x = 3
Bram Moolenaar806da512021-12-24 19:54:52 +00001049 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001050 call assert_equal(0, x)
1051
1052 " works in various modes and sees the correct mode()
1053 noremap <F3> <Cmd>let m = mode(1)<CR>
1054 noremap! <F3> <Cmd>let m = mode(1)<CR>
1055
1056 " normal mode
1057 call feedkeys("\<F3>", 'xt')
1058 call assert_equal('n', m)
1059
1060 " visual mode
1061 call feedkeys("v\<F3>", 'xt!')
1062 call assert_equal('v', m)
1063 " shouldn't leave the visual mode
1064 call assert_equal('v', mode(1))
1065 call feedkeys("\<Esc>", 'xt')
1066 call assert_equal('n', mode(1))
1067
1068 " visual mapping in select mode
1069 call feedkeys("gh\<F3>", 'xt!')
1070 call assert_equal('v', m)
1071 " shouldn't leave select mode
1072 call assert_equal('s', mode(1))
1073 call feedkeys("\<Esc>", 'xt')
1074 call assert_equal('n', mode(1))
1075
1076 " select mode mapping
1077 snoremap <F3> <Cmd>let m = mode(1)<cr>
1078 call feedkeys("gh\<F3>", 'xt!')
1079 call assert_equal('s', m)
1080 " shouldn't leave select mode
1081 call assert_equal('s', mode(1))
1082 call feedkeys("\<Esc>", 'xt')
1083 call assert_equal('n', mode(1))
1084
1085 " operator-pending mode
1086 call feedkeys("d\<F3>", 'xt!')
1087 call assert_equal('no', m)
1088 " leaves the operator-pending mode
1089 call assert_equal('n', mode(1))
1090
1091 " insert mode
1092 call feedkeys("i\<F3>abc", 'xt')
1093 call assert_equal('i', m)
1094 call assert_equal('abc', getline('.'))
1095
1096 " replace mode
1097 call feedkeys("0R\<F3>two", 'xt')
1098 call assert_equal('R', m)
1099 call assert_equal('two', getline('.'))
1100
1101 " virtual replace mode
1102 call setline('.', "one\ttwo")
1103 call feedkeys("4|gR\<F3>xxx", 'xt')
1104 call assert_equal('Rv', m)
1105 call assert_equal("onexxx\ttwo", getline('.'))
1106
1107 " cmdline mode
1108 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
1109 call assert_equal('c', m)
1110 call assert_equal('"xxx', @:)
1111
1112 " terminal mode
1113 if CanRunVimInTerminal()
1114 tnoremap <F3> <Cmd>let m = mode(1)<CR>
1115 let buf = Run_shell_in_terminal({})
1116 call feedkeys("\<F3>", 'xt')
1117 call assert_equal('t', m)
1118 call assert_equal('t', mode(1))
1119 call StopShellInTerminal(buf)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001120 close!
1121 tunmap <F3>
1122 endif
1123
1124 " invoke cmdline mode recursively
1125 noremap! <F2> <Cmd>norm! :foo<CR>
1126 %d
1127 call setline(1, ['some short lines', 'of test text'])
1128 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
1129 call assert_equal('"barx', @:)
1130 unmap! <F2>
1131
1132 " test for calling a <SID> function
1133 let lines =<< trim END
1134 map <F2> <Cmd>call <SID>do_it()<CR>
1135 func s:do_it()
1136 let g:x = 32
1137 endfunc
1138 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001139 call writefile(lines, 'Xscript', 'D')
Bram Moolenaar957cf672020-11-12 14:21:06 +01001140 source Xscript
1141 call feedkeys("\<F2>", 'xt')
1142 call assert_equal(32, g:x)
Bram Moolenaar957cf672020-11-12 14:21:06 +01001143
1144 unmap <F3>
1145 unmap! <F3>
1146 %bw!
1147endfunc
1148
1149" text object enters visual mode
1150func TextObj()
1151 if mode() !=# "v"
1152 normal! v
1153 end
1154 call cursor(1, 3)
1155 normal! o
1156 call cursor(2, 4)
1157endfunc
1158
1159func s:cmdmap(lhs, rhs)
1160 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1161 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1162endfunc
1163
1164func s:cmdunmap(lhs)
1165 exe 'unmap ' .. a:lhs
1166 exe 'unmap! ' .. a:lhs
1167endfunc
1168
1169" Map various <Fx> keys used by the <Cmd> key tests
1170func s:setupMaps()
1171 call s:cmdmap('<F3>', 'let m = mode(1)')
1172 call s:cmdmap('<F4>', 'normal! ww')
1173 call s:cmdmap('<F5>', 'normal! "ay')
1174 call s:cmdmap('<F6>', 'throw "very error"')
1175 call s:cmdmap('<F7>', 'call TextObj()')
1176 call s:cmdmap('<F8>', 'startinsert')
1177 call s:cmdmap('<F9>', 'stopinsert')
1178endfunc
1179
1180" Remove the mappings setup by setupMaps()
1181func s:cleanupMaps()
1182 call s:cmdunmap('<F3>')
1183 call s:cmdunmap('<F4>')
1184 call s:cmdunmap('<F5>')
1185 call s:cmdunmap('<F6>')
1186 call s:cmdunmap('<F7>')
1187 call s:cmdunmap('<F8>')
1188 call s:cmdunmap('<F9>')
1189endfunc
1190
1191" Test for <Cmd> mapping in normal mode
1192func Test_map_cmdkey_normal_mode()
1193 new
1194 call s:setupMaps()
1195
1196 " check v:count and v:register works
1197 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1198 call feedkeys("\<F2>", 'xt')
1199 call assert_equal(['n', 0, '"'], s)
1200 call feedkeys("7\<F2>", 'xt')
1201 call assert_equal(['n', 7, '"'], s)
1202 call feedkeys("\"e\<F2>", 'xt')
1203 call assert_equal(['n', 0, 'e'], s)
1204 call feedkeys("5\"k\<F2>", 'xt')
1205 call assert_equal(['n', 5, 'k'], s)
1206 call s:cmdunmap('<F2>')
1207
1208 call setline(1, ['some short lines', 'of test text'])
1209 call feedkeys("\<F7>y", 'xt')
1210 call assert_equal("me short lines\nof t", @")
1211 call assert_equal('v', getregtype('"'))
1212 call assert_equal([0, 1, 3, 0], getpos("'<"))
1213 call assert_equal([0, 2, 4, 0], getpos("'>"))
1214
1215 " startinsert
1216 %d
1217 call feedkeys("\<F8>abc", 'xt')
1218 call assert_equal('abc', getline(1))
1219
1220 " feedkeys are not executed immediately
1221 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1222 %d
1223 call setline(1, ['some short lines', 'of test text'])
1224 call cursor(2, 3)
1225 call feedkeys(",a\<F3>", 'xt')
1226 call assert_equal('of test text', g:a)
1227 call assert_equal('n', m)
1228 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1229 nunmap ,a
1230
1231 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1232 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1233 call feedkeys(",b\<F3>", 'xt')
1234 call assert_equal('n', m)
1235 call assert_equal('of alphabetatest text', g:b)
1236 nunmap ,b
1237
1238 call s:cleanupMaps()
1239 %bw!
1240endfunc
1241
1242" Test for <Cmd> mapping with the :normal command
1243func Test_map_cmdkey_normal_cmd()
1244 new
1245 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1246 noremap ,f <Cmd>nosuchcommand<CR>
1247 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1248 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1249 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1250
1251 call setline(1, ['some short lines', 'of test text'])
1252 exe "norm ,x\r"
1253 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1254
1255 call assert_fails('norm ,f', 'E492:')
1256 call assert_fails('norm ,e', 'very error')
1257 call assert_fails('norm ,m', 'The message.')
1258 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1259
1260 %d
1261 let caught_err = 0
1262 try
1263 exe "normal ,w"
1264 catch /Vim(echoerr):Err/
1265 let caught_err = 1
1266 endtry
1267 call assert_equal(1, caught_err)
1268 call assert_equal(['', '0'], getline(1, '$'))
1269
1270 %d
1271 call assert_fails('normal ,w', 'Err')
1272 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1273 call assert_equal(1, line('.'))
1274
1275 nunmap ,x
1276 nunmap ,f
1277 nunmap ,e
1278 nunmap ,m
1279 nunmap ,w
1280 %bw!
1281endfunc
1282
1283" Test for <Cmd> mapping in visual mode
1284func Test_map_cmdkey_visual_mode()
1285 new
1286 set showmode
1287 call s:setupMaps()
1288
1289 call setline(1, ['some short lines', 'of test text'])
1290 call feedkeys("v\<F4>", 'xt!')
1291 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1292
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +01001293 " can invoke an operator, ending the visual mode
Bram Moolenaar957cf672020-11-12 14:21:06 +01001294 let @a = ''
1295 call feedkeys("\<F5>", 'xt!')
1296 call assert_equal('n', mode(1))
1297 call assert_equal('some short l', @a)
1298
1299 " error doesn't interrupt visual mode
1300 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1301 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1302 call feedkeys("\<F7>", 'xt!')
1303 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1304
1305 " startinsert gives "-- (insert) VISUAL --" mode
1306 call feedkeys("\<F8>", 'xt!')
1307 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1308 redraw!
1309 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1310 call feedkeys("\<Esc>new ", 'x')
1311 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1312
1313 call s:cleanupMaps()
1314 set showmode&
1315 %bw!
1316endfunc
1317
1318" Test for <Cmd> mapping in select mode
1319func Test_map_cmdkey_select_mode()
1320 new
1321 set showmode
1322 call s:setupMaps()
1323
1324 snoremap <F1> <cmd>throw "very error"<CR>
1325 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1326 call setline(1, ['some short lines', 'of test text'])
1327
1328 call feedkeys("gh\<F4>", "xt!")
1329 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1330 redraw!
1331 call assert_match('^-- SELECT --', Screenline(&lines))
1332
1333 " visual mapping in select mode restarts select mode after operator
1334 let @a = ''
1335 call feedkeys("\<F5>", 'xt!')
1336 call assert_equal('s', mode(1))
1337 call assert_equal('some short l', @a)
1338
1339 " select mode mapping works, and does not restart select mode
1340 let @b = ''
1341 call feedkeys("\<F2>", 'xt!')
1342 call assert_equal('n', mode(1))
1343 call assert_equal('some short l', @b)
1344
1345 " error doesn't interrupt temporary visual mode
1346 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1347 redraw!
1348 call assert_match('^-- VISUAL --', Screenline(&lines))
1349 " quirk: restoration of select mode is not performed
1350 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1351
1352 " error doesn't interrupt select mode
1353 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1354 redraw!
1355 call assert_match('^-- SELECT --', Screenline(&lines))
1356 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1357
1358 call feedkeys("\<F7>", 'xt!')
1359 redraw!
1360 call assert_match('^-- SELECT --', Screenline(&lines))
1361 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1362
1363 " startinsert gives "-- SELECT (insert) --" mode
1364 call feedkeys("\<F8>", 'xt!')
1365 redraw!
1366 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1367 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1368 call feedkeys("\<Esc>new ", 'x')
1369 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1370
1371 sunmap <F1>
1372 sunmap <F2>
1373 call s:cleanupMaps()
1374 set showmode&
1375 %bw!
1376endfunc
1377
1378" Test for <Cmd> mapping in operator-pending mode
1379func Test_map_cmdkey_op_pending_mode()
1380 new
1381 call s:setupMaps()
1382
1383 call setline(1, ['some short lines', 'of test text'])
1384 call feedkeys("d\<F4>", 'xt')
1385 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1386 call assert_equal(['some short '], getreg('"', 1, 1))
1387 " create a new undo point
Christian Brabandt6efb1982023-08-10 05:44:25 +02001388 let &g:undolevels = &g:undolevels
Bram Moolenaar957cf672020-11-12 14:21:06 +01001389
1390 call feedkeys(".", 'xt')
1391 call assert_equal(['test text'], getline(1, '$'))
1392 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1393 " create a new undo point
Christian Brabandt6efb1982023-08-10 05:44:25 +02001394 let &g:undolevels = &g:undolevels
Bram Moolenaar957cf672020-11-12 14:21:06 +01001395
1396 call feedkeys("uu", 'xt')
1397 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1398
1399 " error aborts operator-pending, operator not performed
1400 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1401 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1402
1403 call feedkeys("\"bd\<F7>", 'xt')
1404 call assert_equal(['soest text'], getline(1, '$'))
1405 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1406
1407 " startinsert aborts operator
1408 call feedkeys("d\<F8>cc", 'xt')
1409 call assert_equal(['soccest text'], getline(1, '$'))
1410
1411 call s:cleanupMaps()
1412 %bw!
1413endfunc
1414
1415" Test for <Cmd> mapping in insert mode
1416func Test_map_cmdkey_insert_mode()
1417 new
1418 call s:setupMaps()
1419
1420 call setline(1, ['some short lines', 'of test text'])
1421 " works the same as <C-O>w<C-O>w
1422 call feedkeys("iindeed \<F4>little ", 'xt')
1423 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1424 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1425 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1426
1427 " Note when entering visual mode from InsertEnter autocmd, an async event,
1428 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1429 call feedkeys("i\<F7>stuff ", 'xt')
1430 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1431 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1432
1433 call feedkeys("\<F5>", 'xt')
1434 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1435
1436 " also works as part of abbreviation
1437 abbr foo <Cmd>let g:y = 17<CR>bar
1438 exe "normal i\<space>foo "
1439 call assert_equal(17, g:y)
1440 call assert_equal('in bar deed some short little 2 lines', getline(1))
1441 unabbr foo
1442
1443 " :startinsert does nothing
1444 call setline(1, 'foo bar')
1445 call feedkeys("ggi\<F8>vim", 'xt')
1446 call assert_equal('vimfoo bar', getline(1))
1447
1448 " :stopinsert works
1449 call feedkeys("ggi\<F9>Abc", 'xt')
1450 call assert_equal('vimfoo barbc', getline(1))
1451
1452 call s:cleanupMaps()
1453 %bw!
1454endfunc
1455
1456" Test for <Cmd> mapping in insert-completion mode
1457func Test_map_cmdkey_insert_complete_mode()
1458 new
1459 call s:setupMaps()
1460
1461 call setline(1, 'some short lines')
1462 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1463 call assert_equal('ic', m)
1464 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1465
1466 call s:cleanupMaps()
1467 %bw!
1468endfunc
1469
1470" Test for <Cmd> mapping in cmdline mode
1471func Test_map_cmdkey_cmdline_mode()
1472 new
1473 call s:setupMaps()
1474
1475 call setline(1, ['some short lines', 'of test text'])
1476 let x = 0
1477 call feedkeys(":let x\<F3>= 10\r", 'xt')
1478 call assert_equal('c', m)
1479 call assert_equal(10, x)
1480
1481 " exception doesn't leave cmdline mode
1482 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1483 call assert_equal(20, x)
1484
1485 " move cursor in the buffer from cmdline mode
1486 call feedkeys(":let x\<F4>= 30\r", 'xt')
1487 call assert_equal(30, x)
1488 call assert_equal(12, col('.'))
1489
1490 " :startinsert takes effect after leaving cmdline mode
1491 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1492 call assert_equal(40, x)
1493 call assert_equal('some short new lines', getline(1))
1494
1495 call s:cleanupMaps()
1496 %bw!
1497endfunc
1498
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001499func Test_map_cmdkey_redo()
1500 func SelectDash()
1501 call search('^---\n\zs', 'bcW')
1502 norm! V
1503 call search('\n\ze---$', 'W')
1504 endfunc
1505
1506 let text =<< trim END
1507 ---
1508 aaa
1509 ---
1510 bbb
1511 bbb
1512 ---
1513 ccc
1514 ccc
1515 ccc
1516 ---
1517 END
1518 new Xcmdtext
1519 call setline(1, text)
1520
1521 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1522 call feedkeys('2Gdi-', 'xt')
1523 call assert_equal(['---', '---'], getline(1, 2))
1524 call feedkeys('j.', 'xt')
1525 call assert_equal(['---', '---', '---'], getline(1, 3))
1526 call feedkeys('j.', 'xt')
1527 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1528
1529 bwipe!
1530 call delete('Xcmdtext')
1531 delfunc SelectDash
1532 ounmap i-
zeertzjq3ab3a862023-05-06 16:22:04 +01001533
1534 new
1535 call setline(1, 'aaa bbb ccc ddd')
1536
1537 " command can contain special keys
1538 onoremap ix <Cmd>let g:foo ..= '…'<Bar>normal! <C-Right><CR>
1539 let g:foo = ''
1540 call feedkeys('0dix.', 'xt')
1541 call assert_equal('……', g:foo)
1542 call assert_equal('ccc ddd', getline(1))
1543 unlet g:foo
1544
1545 " command line ending in "0" is handled without errors
1546 onoremap ix <Cmd>eval 0<CR>
1547 call feedkeys('dix.', 'xt')
1548
1549 ounmap ix
1550 bwipe!
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001551endfunc
1552
Bram Moolenaara9725222022-01-16 13:30:33 +00001553func Test_map_script_cmd_restore()
1554 let lines =<< trim END
1555 vim9script
1556 nnoremap <F3> <ScriptCmd>eval 1 + 2<CR>
1557 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001558 call v9.CheckScriptSuccess(lines)
Bram Moolenaara9725222022-01-16 13:30:33 +00001559 call feedkeys("\<F3>:let g:result = 3+4\<CR>", 'xtc')
1560 call assert_equal(7, g:result)
1561
1562 nunmap <F3>
1563 unlet g:result
1564endfunc
1565
Bram Moolenaardc987762022-01-16 15:52:35 +00001566func Test_map_script_cmd_finds_func()
1567 let lines =<< trim END
1568 vim9script
1569 onoremap <F3> <ScriptCmd>Func()<CR>
1570 def Func()
1571 g:func_called = 'yes'
1572 enddef
1573 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001574 call v9.CheckScriptSuccess(lines)
Bram Moolenaardc987762022-01-16 15:52:35 +00001575 call feedkeys("y\<F3>\<Esc>", 'xtc')
1576 call assert_equal('yes', g:func_called)
1577
1578 ounmap <F3>
1579 unlet g:func_called
1580endfunc
1581
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001582func Test_map_script_cmd_survives_unmap()
1583 let lines =<< trim END
1584 vim9script
1585 var n = 123
1586 nnoremap <F4> <ScriptCmd><CR>
1587 autocmd CmdlineEnter * silent! nunmap <F4>
1588 nnoremap <F3> :<ScriptCmd>eval setbufvar(bufnr(), "result", n)<CR>
1589 feedkeys("\<F3>\<CR>", 'xct')
1590 assert_equal(123, b:result)
1591 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00001592 call v9.CheckScriptSuccess(lines)
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001593
1594 nunmap <F3>
1595 unlet b:result
Bram Moolenaarca34db32022-01-20 11:17:18 +00001596 autocmd! CmdlineEnter
Bram Moolenaarf61c89d2022-01-19 22:51:48 +00001597endfunc
1598
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001599func Test_map_script_cmd_redo()
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001600 call mkdir('Xmapcmd', 'R')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001601 let lines =<< trim END
1602 vim9script
1603 import autoload './script.vim'
1604 onoremap <F3> <ScriptCmd>script.Func()<CR>
1605 END
1606 call writefile(lines, 'Xmapcmd/plugin.vim')
1607
1608 let lines =<< trim END
1609 vim9script
1610 export def Func()
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001611 normal! V
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001612 enddef
1613 END
1614 call writefile(lines, 'Xmapcmd/script.vim')
1615 new
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001616 call setline(1, ['one', 'two', 'three', 'four', 'five'])
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001617 nnoremap j j
1618 source Xmapcmd/plugin.vim
Bram Moolenaarceff9cd2023-04-16 17:17:37 +01001619 call feedkeys("d\<F3>j.j.", 'xt')
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001620 call assert_equal(['two', 'four'], getline(1, '$'))
1621
1622 ounmap <F3>
1623 nunmap j
Bram Moolenaarddf7dba2022-09-05 16:53:21 +01001624 bwipe!
1625endfunc
1626
Bram Moolenaar1f448d92021-03-22 19:37:06 +01001627" Test for using <script> with a map to remap characters in rhs
1628func Test_script_local_remap()
1629 new
1630 inoremap <buffer> <SID>xyz mno
1631 inoremap <buffer> <script> abc st<SID>xyzre
1632 normal iabc
1633 call assert_equal('stmnore', getline(1))
1634 bwipe!
1635endfunc
1636
Bram Moolenaar4934ed32021-04-30 19:43:11 +02001637func Test_abbreviate_multi_byte()
1638 new
1639 iabbrev foo bar
1640 call feedkeys("ifoo…\<Esc>", 'xt')
1641 call assert_equal("bar…", getline(1))
1642 iunabbrev foo
1643 bwipe!
1644endfunc
1645
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +02001646" Test for abbreviations with 'latin1' encoding
1647func Test_abbreviate_latin1_encoding()
1648 set encoding=latin1
1649 call assert_fails('abbr ab#$c ABC', 'E474:')
1650 new
1651 iabbr <buffer> #i #include
1652 iabbr <buffer> ## #enddef
1653 exe "normal i#i\<C-]>"
1654 call assert_equal('#include', getline(1))
1655 exe "normal 0Di##\<C-]>"
1656 call assert_equal('#enddef', getline(1))
1657 %bw!
1658 set encoding=utf-8
1659endfunc
1660
Bram Moolenaar1fc34222022-03-03 13:56:24 +00001661" Test for <Plug> always being mapped, even when used with "noremap".
1662func Test_plug_remap()
1663 let g:foo = 0
1664 nnoremap <Plug>(Increase_x) <Cmd>let g:foo += 1<CR>
1665 nmap <F2> <Plug>(Increase_x)
1666 nnoremap <F3> <Plug>(Increase_x)
1667 call feedkeys("\<F2>", 'xt')
1668 call assert_equal(1, g:foo)
1669 call feedkeys("\<F3>", 'xt')
1670 call assert_equal(2, g:foo)
1671 nnoremap x <Nop>
1672 nmap <F4> x<Plug>(Increase_x)x
1673 nnoremap <F5> x<Plug>(Increase_x)x
1674 call setline(1, 'Some text')
1675 normal! gg$
1676 call feedkeys("\<F4>", 'xt')
1677 call assert_equal(3, g:foo)
1678 call assert_equal('Some text', getline(1))
1679 call feedkeys("\<F5>", 'xt')
1680 call assert_equal(4, g:foo)
1681 call assert_equal('Some te', getline(1))
1682 nunmap <Plug>(Increase_x)
1683 nunmap <F2>
1684 nunmap <F3>
1685 nunmap <F4>
1686 nunmap <F5>
1687 unlet g:foo
1688 %bw!
1689endfunc
1690
zeertzjqac92ab72022-04-24 15:58:30 +01001691func Test_mouse_drag_mapped_start_select()
1692 set mouse=a
1693 set selectmode=key,mouse
1694 func ClickExpr()
1695 call test_setmouse(1, 1)
1696 return "\<LeftMouse>"
1697 endfunc
1698 func DragExpr()
1699 call test_setmouse(1, 2)
1700 return "\<LeftDrag>"
1701 endfunc
1702 nnoremap <expr> <F2> ClickExpr()
1703 nmap <expr> <F3> DragExpr()
1704
1705 nnoremap <LeftDrag> <LeftDrag><Cmd><CR>
1706 exe "normal \<F2>\<F3>"
1707 call assert_equal('s', mode())
1708 exe "normal! \<C-\>\<C-N>"
1709
1710 nunmap <LeftDrag>
1711 nunmap <F2>
1712 nunmap <F3>
1713 delfunc ClickExpr
1714 delfunc DragExpr
1715 set selectmode&
1716 set mouse&
1717endfunc
1718
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001719func Test_mouse_drag_statusline()
1720 set laststatus=2
1721 set mouse=a
1722 func ClickExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001723 call test_setmouse(&lines - 1, 1)
1724 return "\<LeftMouse>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001725 endfunc
1726 func DragExpr()
zeertzjq873f41a2022-11-01 11:44:43 +00001727 call test_setmouse(&lines - 2, 1)
1728 return "\<LeftDrag>"
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001729 endfunc
1730 nnoremap <expr> <F2> ClickExpr()
1731 nnoremap <expr> <F3> DragExpr()
1732
1733 " this was causing a crash in win_drag_status_line()
1734 call feedkeys("\<F2>:tabnew\<CR>\<F3>", 'tx')
zeertzjq873f41a2022-11-01 11:44:43 +00001735
1736 nunmap <F2>
1737 nunmap <F3>
1738 delfunc ClickExpr
1739 delfunc DragExpr
1740 set laststatus& mouse&
Bram Moolenaar8ab9ca92022-10-31 13:06:26 +00001741endfunc
1742
zeertzjq0f68e6c2022-04-05 13:17:01 +01001743" Test for mapping <LeftDrag> in Insert mode
1744func Test_mouse_drag_insert_map()
1745 set mouse=a
1746 func ClickExpr()
1747 call test_setmouse(1, 1)
1748 return "\<LeftMouse>"
1749 endfunc
1750 func DragExpr()
1751 call test_setmouse(1, 2)
1752 return "\<LeftDrag>"
1753 endfunc
1754 inoremap <expr> <F2> ClickExpr()
1755 imap <expr> <F3> DragExpr()
1756
1757 inoremap <LeftDrag> <LeftDrag><Cmd>let g:dragged = 1<CR>
1758 exe "normal i\<F2>\<F3>"
1759 call assert_equal(1, g:dragged)
1760 call assert_equal('v', mode())
1761 exe "normal! \<C-\>\<C-N>"
1762 unlet g:dragged
1763
1764 inoremap <LeftDrag> <LeftDrag><C-\><C-N>
1765 exe "normal i\<F2>\<F3>"
1766 call assert_equal('n', mode())
1767
1768 iunmap <LeftDrag>
1769 iunmap <F2>
1770 iunmap <F3>
1771 delfunc ClickExpr
1772 delfunc DragExpr
1773 set mouse&
1774endfunc
1775
zeertzjqabeb09b2022-04-26 12:29:43 +01001776func Test_unmap_simplifiable()
zeertzjqa4e33322022-04-24 17:07:53 +01001777 map <C-I> foo
1778 map <Tab> bar
1779 call assert_equal('foo', maparg('<C-I>'))
1780 call assert_equal('bar', maparg('<Tab>'))
1781 unmap <C-I>
1782 call assert_equal('', maparg('<C-I>'))
1783 call assert_equal('bar', maparg('<Tab>'))
1784 unmap <Tab>
zeertzjqabeb09b2022-04-26 12:29:43 +01001785
1786 map <C-I> foo
1787 unmap <Tab>
1788 " This should not error
1789 unmap <C-I>
zeertzjqa4e33322022-04-24 17:07:53 +01001790endfunc
1791
zeertzjq9d997ad2024-07-29 21:10:07 +02001792" Test that the first byte of rhs is not remapped if rhs starts with lhs.
1793func Test_map_rhs_starts_with_lhs()
1794 new
1795 func MapExpr()
1796 return "\<C-R>\<C-P>"
1797 endfunc
1798
1799 for expr in [v:false, v:true]
1800 if expr
1801 imap <buffer><expr> <C-R> MapExpr()
1802 else
1803 imap <buffer> <C-R> <C-R><C-P>
1804 endif
1805
1806 for restore in [v:false, v:true]
1807 if restore
1808 let saved = maparg('<C-R>', 'i', v:false, v:true)
1809 iunmap <buffer> <C-R>
1810 call mapset(saved)
1811 endif
1812
1813 let @a = 'foo'
zeertzjq74011dc2024-07-30 19:17:56 +02001814 call assert_nobeep('call feedkeys("S\<C-R>a", "tx")')
zeertzjq9d997ad2024-07-29 21:10:07 +02001815 call assert_equal('foo', getline('.'))
1816
1817 let @a = 'bar'
zeertzjq74011dc2024-07-30 19:17:56 +02001818 call assert_nobeep('call feedkeys("S\<*C-R>a", "tx")')
zeertzjq9d997ad2024-07-29 21:10:07 +02001819 call assert_equal('bar', getline('.'))
1820 endfor
1821 endfor
1822
1823 " When two mappings are used for <C-I> and <Tab>, remapping should work.
1824 imap <buffer> <C-I> <Tab>bar
1825 imap <buffer> <Tab> foo
1826 call feedkeys("S\<Tab>", 'xt')
1827 call assert_equal('foo', getline('.'))
1828 call feedkeys("S\<*C-I>", 'xt')
1829 call assert_equal('foobar', getline('.'))
1830
1831 delfunc MapExpr
1832 bwipe!
1833endfunc
1834
zeertzjqdb088872022-05-02 22:53:45 +01001835func Test_expr_map_escape_special()
1836 nnoremap <Cmd>let g:got_ellipsis += 1<CR>
1837 func Func()
1838 return '…'
1839 endfunc
1840 nmap <expr> <F2> Func()
1841 let g:got_ellipsis = 0
1842 call feedkeys("\<F2>", 'xt')
1843 call assert_equal(1, g:got_ellipsis)
1844 delfunc Func
1845 nunmap <F2>
1846 unlet g:got_ellipsis
1847 nunmap
1848endfunc
1849
zeertzjq3760bfd2022-06-06 16:22:46 +01001850" Testing for mapping after an <Nop> mapping is triggered on timeout.
1851" Test for what patch 8.1.0052 fixes.
1852func Test_map_after_timed_out_nop()
1853 CheckRunVimInTerminal
1854
1855 let lines =<< trim END
1856 set timeout timeoutlen=400
1857 inoremap ab TEST
1858 inoremap a <Nop>
1859 END
Bram Moolenaarb152b6a2022-09-29 21:37:33 +01001860 call writefile(lines, 'Xtest_map_after_timed_out_nop', 'D')
zeertzjq3760bfd2022-06-06 16:22:46 +01001861 let buf = RunVimInTerminal('-S Xtest_map_after_timed_out_nop', #{rows: 6})
1862
1863 " Enter Insert mode
1864 call term_sendkeys(buf, 'i')
1865 " Wait for the "a" mapping to timeout
1866 call term_sendkeys(buf, 'a')
1867 call term_wait(buf, 500)
1868 " Send "a" and wait for a period shorter than 'timeoutlen'
1869 call term_sendkeys(buf, 'a')
1870 call term_wait(buf, 100)
1871 " Send "b", should trigger the "ab" mapping
1872 call term_sendkeys(buf, 'b')
1873 call WaitForAssert({-> assert_equal("TEST", term_getline(buf, 1))})
1874
1875 " clean up
1876 call StopVimInTerminal(buf)
zeertzjq3760bfd2022-06-06 16:22:46 +01001877endfunc
1878
zeertzjqacdfb8a2024-04-17 21:28:54 +02001879" Test 'showcmd' behavior with a partial mapping
1880func Test_showcmd_part_map()
1881 CheckRunVimInTerminal
1882
zeertzjq094c4392024-04-18 22:09:37 +02001883 let lines =<< trim END
zeertzjqacdfb8a2024-04-17 21:28:54 +02001884 set notimeout showcmd
1885 nnoremap ,a <Ignore>
1886 nnoremap ;a <Ignore>
1887 nnoremap Àa <Ignore>
1888 nnoremap Ëa <Ignore>
1889 nnoremap βa <Ignore>
1890 nnoremap ωa <Ignore>
1891 nnoremap a <Ignore>
1892 nnoremap <C-W>a <Ignore>
1893 END
1894 call writefile(lines, 'Xtest_showcmd_part_map', 'D')
1895 let buf = RunVimInTerminal('-S Xtest_showcmd_part_map', #{rows: 6})
1896
1897 call term_sendkeys(buf, ":set noruler | echo\<CR>")
1898 call WaitForAssert({-> assert_equal('', term_getline(buf, 6))})
1899
1900 for c in [',', ';', 'À', 'Ë', 'β', 'ω', '…']
1901 call term_sendkeys(buf, c)
1902 call WaitForAssert({-> assert_equal(c, trim(term_getline(buf, 6)))})
zeertzjq094c4392024-04-18 22:09:37 +02001903 call term_sendkeys(buf, 'a')
1904 call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))})
zeertzjqacdfb8a2024-04-17 21:28:54 +02001905 endfor
1906
1907 call term_sendkeys(buf, "\<C-W>")
1908 call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))})
zeertzjq094c4392024-04-18 22:09:37 +02001909 call term_sendkeys(buf, 'a')
1910 call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))})
zeertzjqacdfb8a2024-04-17 21:28:54 +02001911
zeertzjq094c4392024-04-18 22:09:37 +02001912 " Use feedkeys() as terminal buffer cannot forward unsimplified Ctrl-W.
1913 " This is like typing Ctrl-W with modifyOtherKeys enabled.
zeertzjqacdfb8a2024-04-17 21:28:54 +02001914 call term_sendkeys(buf, ':call feedkeys("\<*C-W>", "m")' .. " | echo\<CR>")
1915 call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))})
zeertzjq094c4392024-04-18 22:09:37 +02001916 call term_sendkeys(buf, 'a')
1917 call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))})
zeertzjqacdfb8a2024-04-17 21:28:54 +02001918
1919 call StopVimInTerminal(buf)
1920endfunc
1921
Bram Moolenaar27efc622022-07-01 16:35:45 +01001922func Test_using_past_typeahead()
1923 nnoremap :00 0
1924 exe "norm :set \x80\xfb0=0\<CR>"
1925 exe "sil norm :0\x0f\<C-U>\<CR>"
1926
1927 exe "norm :set \x80\xfb0=\<CR>"
1928 nunmap :00
1929endfunc
1930
Bram Moolenaarbf533e42022-11-13 20:43:19 +00001931func Test_mapclear_while_listing()
1932 CheckRunVimInTerminal
1933
1934 let lines =<< trim END
1935 set nocompatible
1936 mapclear
1937 for i in range(1, 999)
1938 exe 'map ' .. 'foo' .. i .. ' bar'
1939 endfor
1940 au CmdlineLeave : call timer_start(0, {-> execute('mapclear')})
1941 END
1942 call writefile(lines, 'Xmapclear', 'D')
1943 let buf = RunVimInTerminal('-S Xmapclear', {'rows': 10})
1944
1945 " this was using freed memory
1946 call term_sendkeys(buf, ":map\<CR>")
1947 call TermWait(buf, 50)
1948 call term_sendkeys(buf, "G")
1949 call TermWait(buf, 50)
1950 call term_sendkeys(buf, "\<CR>")
1951
1952 call StopVimInTerminal(buf)
1953endfunc
1954
Bram Moolenaar27efc622022-07-01 16:35:45 +01001955
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001956" vim: shiftwidth=2 sts=2 expandtab