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