blob: d2b9f37d10ca36e769fed908b2c7834662151f13 [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 Moolenaar26d98212019-01-27 22:32:55 +01007
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02008func Test_abbreviation()
9 " abbreviation with 0x80 should work
10 inoreab чкпр vim
11 call feedkeys("Goчкпр \<Esc>", "xt")
12 call assert_equal('vim ', getline('$'))
13 iunab чкпр
14 set nomodified
15endfunc
16
Bram Moolenaar8485be42019-04-23 16:36:05 +020017func Test_abclear()
18 abbrev foo foobar
19 iabbrev fooi foobari
20 cabbrev fooc foobarc
21 call assert_equal("\n\n"
22 \ .. "c fooc foobarc\n"
23 \ .. "i fooi foobari\n"
24 \ .. "! foo foobar", execute('abbrev'))
25
26 iabclear
27 call assert_equal("\n\n"
28 \ .. "c fooc foobarc\n"
29 \ .. "c foo foobar", execute('abbrev'))
30 abbrev foo foobar
31 iabbrev fooi foobari
32
33 cabclear
34 call assert_equal("\n\n"
35 \ .. "i fooi foobari\n"
36 \ .. "i foo foobar", execute('abbrev'))
37 abbrev foo foobar
38 cabbrev fooc foobarc
39
40 abclear
41 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
Bram Moolenaarf0cee192020-02-16 13:33:56 +010042 call assert_fails('%abclear', 'E481:')
Bram Moolenaar8485be42019-04-23 16:36:05 +020043endfunc
44
45func Test_abclear_buffer()
46 abbrev foo foobar
47 new X1
48 abbrev <buffer> foo1 foobar1
49 new X2
50 abbrev <buffer> foo2 foobar2
51
52 call assert_equal("\n\n"
53 \ .. "! foo2 @foobar2\n"
54 \ .. "! foo foobar", execute('abbrev'))
55
56 abclear <buffer>
57 call assert_equal("\n\n"
58 \ .. "! foo foobar", execute('abbrev'))
59
60 b X1
61 call assert_equal("\n\n"
62 \ .. "! foo1 @foobar1\n"
63 \ .. "! foo foobar", execute('abbrev'))
64 abclear <buffer>
65 call assert_equal("\n\n"
66 \ .. "! foo foobar", execute('abbrev'))
67
68 abclear
69 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
70
71 %bwipe
72endfunc
73
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020074func Test_map_ctrl_c_insert()
75 " mapping of ctrl-c in Insert mode
76 set cpo-=< cpo-=k
77 inoremap <c-c> <ctrl-c>
78 cnoremap <c-c> dummy
79 cunmap <c-c>
Bram Moolenaarfccd93f2020-05-31 22:06:51 +020080 call feedkeys("GoTEST2: CTRL-C |\<*C-C>A|\<Esc>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020081 call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
82 unmap! <c-c>
83 set nomodified
84endfunc
85
86func Test_map_ctrl_c_visual()
87 " mapping of ctrl-c in Visual mode
88 vnoremap <c-c> :<C-u>$put ='vmap works'
Bram Moolenaarfccd93f2020-05-31 22:06:51 +020089 call feedkeys("GV\<*C-C>\<CR>", "xt")
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020090 call assert_equal('vmap works', getline('$'))
91 vunmap <c-c>
92 set nomodified
93endfunc
94
95func Test_map_langmap()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +020096 CheckFeature langmap
Bram Moolenaar920694c2016-08-21 17:45:02 +020097
98 " check langmap applies in normal mode
99 set langmap=+- nolangremap
100 new
101 call setline(1, ['a', 'b', 'c'])
102 2
103 call assert_equal('b', getline('.'))
104 call feedkeys("+", "xt")
105 call assert_equal('a', getline('.'))
106
107 " check no remapping
108 map x +
109 2
110 call feedkeys("x", "xt")
111 call assert_equal('c', getline('.'))
112
113 " check with remapping
114 set langremap
115 2
116 call feedkeys("x", "xt")
117 call assert_equal('a', getline('.'))
118
119 unmap x
120 bwipe!
121
122 " 'langnoremap' follows 'langremap' and vise versa
123 set langremap
124 set langnoremap
125 call assert_equal(0, &langremap)
126 set langremap
127 call assert_equal(0, &langnoremap)
128 set nolangremap
129 call assert_equal(1, &langnoremap)
130
Bram Moolenaarda9ce2c2016-09-02 19:34:10 +0200131 " check default values
132 set langnoremap&
133 call assert_equal(0, &langnoremap)
134 call assert_equal(1, &langremap)
135 set langremap&
136 call assert_equal(0, &langnoremap)
137 call assert_equal(1, &langremap)
138
Bram Moolenaar920694c2016-08-21 17:45:02 +0200139 " langmap should not apply in insert mode, 'langremap' doesn't matter
140 set langmap=+{ nolangremap
141 call feedkeys("Go+\<Esc>", "xt")
142 call assert_equal('+', getline('$'))
143 set langmap=+{ langremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200144 call feedkeys("Go+\<Esc>", "xt")
145 call assert_equal('+', getline('$'))
146
Bram Moolenaar920694c2016-08-21 17:45:02 +0200147 " langmap used for register name in insert mode.
148 call setreg('a', 'aaaa')
149 call setreg('b', 'bbbb')
150 call setreg('c', 'cccc')
151 set langmap=ab langremap
152 call feedkeys("Go\<C-R>a\<Esc>", "xt")
153 call assert_equal('bbbb', getline('$'))
154 call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt")
155 call assert_equal('bbbb', getline('$'))
156 " mapping does not apply
157 imap c a
158 call feedkeys("Go\<C-R>c\<Esc>", "xt")
159 call assert_equal('cccc', getline('$'))
160 imap a c
161 call feedkeys("Go\<C-R>a\<Esc>", "xt")
162 call assert_equal('bbbb', getline('$'))
163
164 " langmap should not apply in Command-line mode
165 set langmap=+{ nolangremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200166 call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
167 call assert_equal('+', getline('$'))
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200168
Bram Moolenaare90858d2017-02-01 17:24:34 +0100169 iunmap a
170 iunmap c
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200171 set nomodified
172endfunc
173
174func Test_map_feedkeys()
175 " issue #212 (feedkeys insert mapping at current position)
176 nnoremap . :call feedkeys(".", "in")<cr>
177 call setline('$', ['a b c d', 'a b c d'])
178 $-1
179 call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt")
180 call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$')))
Bram Moolenaare90858d2017-02-01 17:24:34 +0100181 nunmap .
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200182 set nomodified
183endfunc
184
185func Test_map_cursor()
186 " <c-g>U<cursor> works only within a single line
187 imapclear
188 imap ( ()<c-g>U<left>
189 call feedkeys("G2o\<Esc>ki\<CR>Test1: text with a (here some more text\<Esc>k.", "xt")
190 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 2))
191 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 1))
192
193 " test undo
194 call feedkeys("G2o\<Esc>ki\<CR>Test2: text wit a (here some more text [und undo]\<C-G>u\<Esc>k.u", "xt")
195 call assert_equal('', getline(line('$') - 2))
196 call assert_equal('Test2: text wit a (here some more text [und undo])', getline(line('$') - 1))
197 set nomodified
198 imapclear
199endfunc
200
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100201func Test_map_cursor_ctrl_gU()
202 " <c-g>U<cursor> works only within a single line
203 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left>
204 call setline(1, ['foo', 'foobar', '', 'foo'])
205 call cursor(1,2)
206 call feedkeys("c<*PREFIX\<esc>.", 'xt')
207 call assert_equal(['PREFIXfoo', 'foobar', '', 'PREFIXfoo'], getline(1,'$'))
208 " break undo manually
209 set ul=1000
210 exe ":norm! uu"
211 call assert_equal(['foo', 'foobar', '', 'foo'], getline(1,'$'))
212
213 " Test that it does not work if the cursor moves to the previous line
214 " 2 times <S-Left> move to the previous line
215 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left><C-G>U<S-Left>
216 call setline(1, ['', ' foo', 'foobar', '', 'foo'])
217 call cursor(2,3)
218 call feedkeys("c<*PREFIX\<esc>.", 'xt')
219 call assert_equal(['PREFIXPREFIX', ' foo', 'foobar', '', 'foo'], getline(1,'$'))
220 nmapclear
221endfunc
222
223
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200224" This isn't actually testing a mapping, but similar use of CTRL-G U as above.
225func Test_break_undo()
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100226 set whichwrap=<,>,[,]
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200227 call feedkeys("G4o2k", "xt")
228 exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."
229 call assert_equal('new line here', getline(line('$') - 3))
230 call assert_equal('Test3: text with a (parenthesis here', getline(line('$') - 2))
231 call assert_equal('new line here', getline(line('$') - 1))
232 set nomodified
233endfunc
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200234
235func Test_map_meta_quotes()
236 imap <M-"> foo
Bram Moolenaarfccd93f2020-05-31 22:06:51 +0200237 call feedkeys("Go-\<*M-\">-\<Esc>", "xt")
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200238 call assert_equal("-foo-", getline('$'))
239 set nomodified
240 iunmap <M-">
241endfunc
Bram Moolenaar878c2632017-04-01 15:15:52 +0200242
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200243func Test_map_meta_multibyte()
244 imap <M-á> foo
Bram Moolenaar2f710af2019-08-16 20:56:03 +0200245 call assert_match('i <M-á>\s*foo', execute('imap'))
Bram Moolenaarc8fd33d2019-08-16 20:33:05 +0200246 iunmap <M-á>
247endfunc
248
Bram Moolenaar878c2632017-04-01 15:15:52 +0200249func Test_abbr_after_line_join()
250 new
251 abbr foo bar
252 set backspace=indent,eol,start
253 exe "normal o\<BS>foo "
254 call assert_equal("bar ", getline(1))
255 bwipe!
256 unabbr foo
257 set backspace&
258endfunc
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200259
260func Test_map_timeout()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200261 CheckFeature timers
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200262 nnoremap aaaa :let got_aaaa = 1<CR>
263 nnoremap bb :let got_bb = 1<CR>
264 nmap b aaa
265 new
266 func ExitInsert(timer)
267 let g:line = getline(1)
268 call feedkeys("\<Esc>", "t")
269 endfunc
270 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100271 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200272 " After the 'b' Vim waits for another character to see if it matches 'bb'.
273 " When it times out it is expanded to "aaa", but there is no wait for
274 " "aaaa". Can't check that reliably though.
275 call feedkeys("b", "xt!")
276 call assert_equal("aa", g:line)
277 call assert_false(exists('got_aaa'))
278 call assert_false(exists('got_bb'))
279
280 bwipe!
281 nunmap aaaa
282 nunmap bb
283 nunmap b
284 set timeoutlen&
285 delfunc ExitInsert
Bram Moolenaar26d98212019-01-27 22:32:55 +0100286 call timer_stop(timer)
287endfunc
288
289func Test_map_timeout_with_timer_interrupt()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200290 CheckFeature job
291 CheckFeature timers
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +0100292 let g:test_is_flaky = 1
Bram Moolenaar26d98212019-01-27 22:32:55 +0100293
294 " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
295 " sequence.
296 new
297 let g:val = 0
298 nnoremap \12 :let g:val = 1<CR>
299 nnoremap \123 :let g:val = 2<CR>
Bram Moolenaarea94c852019-08-16 21:47:27 +0200300 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100301
302 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100303 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100304 endfunc
305
306 call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
307 call feedkeys('\12', 'xt!')
308 call assert_equal(2, g:val)
309
310 bwipe!
311 nunmap \12
312 nunmap \123
313 set timeoutlen&
314 call WaitFor({-> exists('g:timer')})
315 call timer_stop(g:timer)
316 unlet g:timer
317 unlet g:val
318 delfunc ExitCb
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200319endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200320
321func Test_abbreviation_CR()
322 new
323 func Eatchar(pat)
324 let c = nr2char(getchar(0))
325 return (c =~ a:pat) ? '' : c
326 endfunc
327 iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
328 call feedkeys("GA~~7 \<esc>", 'xt')
329 call assert_equal('~~~~~~~', getline('$'))
330 %d
331 call feedkeys("GA~~7\<cr>\<esc>", 'xt')
332 call assert_equal(['~~~~~~~', ''], getline(1,'$'))
333 delfunc Eatchar
334 bw!
335endfunc
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200336
337func Test_cabbr_visual_mode()
338 cabbr s su
339 call feedkeys(":s \<c-B>\"\<CR>", 'itx')
340 call assert_equal('"su ', getreg(':'))
341 call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
342 let expected = '"'. "'<,'>su "
343 call assert_equal(expected, getreg(':'))
344 call feedkeys(": '<,'>s \<c-B>\"\<CR>", 'itx')
345 let expected = '" '. "'<,'>su "
346 call assert_equal(expected, getreg(':'))
347 call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
348 let expected = '"'. "'a,'bsu "
349 call assert_equal(expected, getreg(':'))
350 cunabbr s
351endfunc
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100352
353func Test_motionforce_omap()
354 func GetCommand()
355 let g:m=mode(1)
356 let [g:lnum1, g:col1] = searchpos('-', 'Wb')
357 if g:lnum1 == 0
358 return "\<Esc>"
359 endif
360 let [g:lnum2, g:col2] = searchpos('-', 'W')
361 if g:lnum2 == 0
362 return "\<Esc>"
363 endif
364 return ":call Select()\<CR>"
365 endfunc
366 func Select()
367 call cursor([g:lnum1, g:col1])
368 exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
369 call cursor([g:lnum2, g:col2])
370 execute "normal! \<BS>"
371 endfunc
372 new
373 onoremap <buffer><expr> i- GetCommand()
374 " 1) default omap mapping
375 %d_
376 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
377 call cursor(2, 1)
378 norm di-
379 call assert_equal('no', g:m)
380 call assert_equal(['aaa -- eee'], getline(1, '$'))
381 " 2) forced characterwise operation
382 %d_
383 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
384 call cursor(2, 1)
385 norm dvi-
386 call assert_equal('nov', g:m)
387 call assert_equal(['aaa -- eee'], getline(1, '$'))
388 " 3) forced linewise operation
389 %d_
390 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
391 call cursor(2, 1)
392 norm dVi-
393 call assert_equal('noV', g:m)
394 call assert_equal([''], getline(1, '$'))
395 " 4) forced blockwise operation
396 %d_
397 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
398 call cursor(2, 1)
399 exe "norm d\<C-V>i-"
400 call assert_equal("no\<C-V>", g:m)
401 call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
402 bwipe!
403 delfunc Select
404 delfunc GetCommand
405endfunc
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200406
407func Test_error_in_map_expr()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200408 " Unlike CheckRunVimInTerminal this does work in a win32 console
409 CheckFeature terminal
410 if has('win32') && has('gui_running')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200411 throw 'Skipped: cannot run Vim in a terminal window'
412 endif
413
414 let lines =<< trim [CODE]
415 func Func()
416 " fail to create list
417 let x = [
418 endfunc
419 nmap <expr> ! Func()
420 set updatetime=50
421 [CODE]
422 call writefile(lines, 'Xtest.vim')
423
Bram Moolenaar0d702022019-07-04 14:20:41 +0200424 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200425 let job = term_getjob(buf)
426 call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
427
428 " GC must not run during map-expr processing, which can make Vim crash.
429 call term_sendkeys(buf, '!')
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200430 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200431 call term_sendkeys(buf, "\<CR>")
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200432 call TermWait(buf, 50)
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200433 call assert_equal('run', job_status(job))
434
435 call term_sendkeys(buf, ":qall!\<CR>")
436 call WaitFor({-> job_status(job) ==# 'dead'})
437 if has('unix')
438 call assert_equal('', job_info(job).termsig)
439 endif
440
441 call delete('Xtest.vim')
442 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
481 call assert_match("\tLast set from .*/test_mapping.vim line \\d\\+$",
482 \ execute('verbose map ,n')->trim()->split("\n")[1])
483
484 " map to CTRL-V
485 exe "nmap ,k \<C-V>"
486 call assert_equal(['n ,k <Nop>'],
487 \ execute('nmap ,k')->trim()->split("\n"))
488
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +0200489 " map with space at the beginning
490 exe "nmap \<C-V> w <Nop>"
491 call assert_equal(['n <Space>w <Nop>'],
492 \ execute("nmap \<C-V> w")->trim()->split("\n"))
493
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100494 nmapclear
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200495endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100496
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100497func Test_expr_map_gets_cursor()
498 new
499 call setline(1, ['one', 'some w!rd'])
500 func StoreColumn()
501 let g:exprLine = line('.')
502 let g:exprCol = col('.')
503 return 'x'
504 endfunc
505 nnoremap <expr> x StoreColumn()
506 2
507 nmap ! f!<Ignore>x
508 call feedkeys("!", 'xt')
509 call assert_equal('some wrd', getline(2))
510 call assert_equal(2, g:exprLine)
511 call assert_equal(7, g:exprCol)
512
513 bwipe!
514 unlet g:exprLine
515 unlet g:exprCol
Bram Moolenaar6ccfd992021-03-17 13:39:33 +0100516 delfunc StoreColumn
Bram Moolenaar18b7d862021-03-17 13:28:05 +0100517 nunmap x
518 nunmap !
519endfunc
520
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100521func Test_expr_map_restore_cursor()
522 CheckScreendump
523
524 let lines =<< trim END
525 call setline(1, ['one', 'two', 'three'])
526 2
527 set ls=2
528 hi! link StatusLine ErrorMsg
529 noremap <expr> <C-B> Func()
530 func Func()
531 let g:on = !get(g:, 'on', 0)
532 redraws
533 return ''
534 endfunc
535 func Status()
536 return get(g:, 'on', 0) ? '[on]' : ''
537 endfunc
538 set stl=%{Status()}
539 END
540 call writefile(lines, 'XtestExprMap')
541 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200542 call TermWait(buf)
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100543 call term_sendkeys(buf, "\<C-B>")
544 call VerifyScreenDump(buf, 'Test_map_expr_1', {})
545
546 " clean up
547 call StopVimInTerminal(buf)
548 call delete('XtestExprMap')
549endfunc
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100550
551" Test for mapping errors
552func Test_map_error()
553 call assert_fails('unmap', 'E474:')
554 call assert_fails("exe 'map ' .. repeat('a', 51) .. ' :ls'", 'E474:')
555 call assert_fails('unmap abc', 'E31:')
556 call assert_fails('unabbr abc', 'E24:')
557 call assert_equal('', maparg(''))
558 call assert_fails('echo maparg("abc", [])', 'E730:')
559
560 " unique map
561 map ,w /[#&!]<CR>
562 call assert_fails("map <unique> ,w /[#&!]<CR>", 'E227:')
563 " unique buffer-local map
564 call assert_fails("map <buffer> <unique> ,w /[.,;]<CR>", 'E225:')
565 unmap ,w
566
567 " unique abbreviation
568 abbr SP special
569 call assert_fails("abbr <unique> SP special", 'E226:')
570 " unique buffer-local map
571 call assert_fails("abbr <buffer> <unique> SP special", 'E224:')
572 unabbr SP
573
574 call assert_fails('mapclear abc', 'E474:')
575 call assert_fails('abclear abc', 'E474:')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100576 call assert_fails('abbr $xyz abc', 'E474:')
577
578 " space character in an abbreviation
579 call assert_fails('abbr ab<space> ABC', 'E474:')
580
581 " invalid <expr> map
582 map <expr> ,f abc
583 call assert_fails('normal ,f', 'E121:')
584 unmap <expr> ,f
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100585
586 " Recursive use of :normal in a map
587 set maxmapdepth=100
588 map gq :normal gq<CR>
589 call assert_fails('normal gq', 'E192:')
590 unmap gq
591 set maxmapdepth&
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100592endfunc
593
594" Test for <special> key mapping
595func Test_map_special()
596 new
597 let old_cpo = &cpo
598 set cpo+=<
599 imap <F12> Blue
600 call feedkeys("i\<F12>", "x")
601 call assert_equal("<F12>", getline(1))
602 call feedkeys("ddi<F12>", "x")
603 call assert_equal("Blue", getline(1))
604 iunmap <F12>
605 imap <special> <F12> Green
606 call feedkeys("ddi\<F12>", "x")
607 call assert_equal("Green", getline(1))
608 call feedkeys("ddi<F12>", "x")
609 call assert_equal("<F12>", getline(1))
610 iunmap <special> <F12>
611 let &cpo = old_cpo
612 %bwipe!
613endfunc
614
615" Test for hasmapto()
616func Test_hasmapto()
617 call assert_equal(0, hasmapto('/^\k\+ ('))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100618 map ,f /^\k\+ (<CR>
619 call assert_equal(1, hasmapto('/^\k\+ ('))
620 unmap ,f
621
622 " Insert mode mapping
623 call assert_equal(0, hasmapto('/^\k\+ (', 'i'))
624 imap ,f /^\k\+ (<CR>
625 call assert_equal(1, hasmapto('/^\k\+ (', 'i'))
626 iunmap ,f
627
628 " Normal mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100629 call assert_equal(0, hasmapto('/^\k\+ (', 'n'))
630 nmap ,f /^\k\+ (<CR>
631 call assert_equal(1, hasmapto('/^\k\+ ('))
632 call assert_equal(1, hasmapto('/^\k\+ (', 'n'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100633 nunmap ,f
634
635 " Visual and Select mode mapping
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100636 call assert_equal(0, hasmapto('/^\k\+ (', 'v'))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100637 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
638 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
639 vmap ,f /^\k\+ (<CR>
640 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
641 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
642 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
643 vunmap ,f
644
645 " Visual mode mapping
646 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
647 xmap ,f /^\k\+ (<CR>
648 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
649 call assert_equal(1, hasmapto('/^\k\+ (', 'x'))
650 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
651 xunmap ,f
652
653 " Select mode mapping
654 call assert_equal(0, hasmapto('/^\k\+ (', 's'))
655 smap ,f /^\k\+ (<CR>
656 call assert_equal(1, hasmapto('/^\k\+ (', 'v'))
657 call assert_equal(0, hasmapto('/^\k\+ (', 'x'))
658 call assert_equal(1, hasmapto('/^\k\+ (', 's'))
659 sunmap ,f
660
661 " Operator-pending mode mapping
662 call assert_equal(0, hasmapto('/^\k\+ (', 'o'))
663 omap ,f /^\k\+ (<CR>
664 call assert_equal(1, hasmapto('/^\k\+ (', 'o'))
665 ounmap ,f
666
667 " Language mapping
668 call assert_equal(0, hasmapto('/^\k\+ (', 'l'))
669 lmap ,f /^\k\+ (<CR>
670 call assert_equal(1, hasmapto('/^\k\+ (', 'l'))
671 lunmap ,f
672
673 " Cmdline mode mapping
674 call assert_equal(0, hasmapto('/^\k\+ (', 'c'))
675 cmap ,f /^\k\+ (<CR>
676 call assert_equal(1, hasmapto('/^\k\+ (', 'c'))
677 cunmap ,f
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100678
679 call assert_equal(0, hasmapto('/^\k\+ (', 'n', 1))
680endfunc
681
682" Test for command-line completion of maps
683func Test_mapcomplete()
684 call assert_equal(['<buffer>', '<expr>', '<nowait>', '<script>',
685 \ '<silent>', '<special>', '<unique>'],
686 \ getcompletion('', 'mapping'))
687 call assert_equal([], getcompletion(',d', 'mapping'))
688
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100689 call feedkeys(":unmap <buf\<C-A>\<C-B>\"\<CR>", 'tx')
690 call assert_equal('"unmap <buffer>', @:)
691
692 call feedkeys(":unabbr <buf\<C-A>\<C-B>\"\<CR>", 'tx')
693 call assert_equal('"unabbr <buffer>', @:)
694
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100695 call feedkeys(":abbr! \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100696 call assert_equal("\"abbr! \x01", @:)
697
698 " Multiple matches for a map
699 nmap ,f /H<CR>
700 omap ,f /H<CR>
701 call feedkeys(":map ,\<C-A>\<C-B>\"\<CR>", 'tx')
702 call assert_equal('"map ,f', @:)
703 mapclear
704endfunc
705
706" Test for <expr> in abbreviation
707func Test_expr_abbr()
708 new
709 iabbr <expr> teh "the"
710 call feedkeys("iteh ", "tx")
711 call assert_equal('the ', getline(1))
712 iabclear
713 call setline(1, '')
714
715 " invalid <expr> abbreviation
716 abbr <expr> hte GetAbbr()
717 call assert_fails('normal ihte ', 'E117:')
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100718 call assert_equal('', getline(1))
Bram Moolenaarc2a60ae2020-01-23 16:19:54 +0100719 unabbr <expr> hte
720
721 close!
722endfunc
723
724" Test for storing mappings in different modes in a vimrc file
725func Test_mkvimrc_mapmodes()
726 map a1 /a1
727 nmap a2 /a2
728 vmap a3 /a3
729 smap a4 /a4
730 xmap a5 /a5
731 omap a6 /a6
732 map! a7 /a7
733 imap a8 /a8
734 lmap a9 /a9
735 cmap a10 /a10
736 tmap a11 /a11
737 " Normal + Visual map
738 map a12 /a12
739 sunmap a12
740 ounmap a12
741 " Normal + Selectmode map
742 map a13 /a13
743 xunmap a13
744 ounmap a13
745 " Normal + OpPending map
746 map a14 /a14
747 vunmap a14
748 " Visual + Selectmode map
749 map a15 /a15
750 nunmap a15
751 ounmap a15
752 " Visual + OpPending map
753 map a16 /a16
754 nunmap a16
755 sunmap a16
756 " Selectmode + OpPending map
757 map a17 /a17
758 nunmap a17
759 xunmap a17
760 " Normal + Visual + Selectmode map
761 map a18 /a18
762 ounmap a18
763 " Normal + Visual + OpPending map
764 map a19 /a19
765 sunmap a19
766 " Normal + Selectmode + OpPending map
767 map a20 /a20
768 xunmap a20
769 " Visual + Selectmode + OpPending map
770 map a21 /a21
771 nunmap a21
772 " Mapping to Nop
773 map a22 <Nop>
774 " Script local mapping
775 map <script> a23 /a23
776
777 " Newline in {lhs} and {rhs} of a map
778 exe "map a24\<C-V>\<C-J> ia24\<C-V>\<C-J><Esc>"
779
780 " Abbreviation
781 abbr a25 A25
782 cabbr a26 A26
783 iabbr a27 A27
784
785 mkvimrc! Xvimrc
786 let l = readfile('Xvimrc')
787 call assert_equal(['map a1 /a1'], filter(copy(l), 'v:val =~ " a1 "'))
788 call assert_equal(['nmap a2 /a2'], filter(copy(l), 'v:val =~ " a2 "'))
789 call assert_equal(['vmap a3 /a3'], filter(copy(l), 'v:val =~ " a3 "'))
790 call assert_equal(['smap a4 /a4'], filter(copy(l), 'v:val =~ " a4 "'))
791 call assert_equal(['xmap a5 /a5'], filter(copy(l), 'v:val =~ " a5 "'))
792 call assert_equal(['omap a6 /a6'], filter(copy(l), 'v:val =~ " a6 "'))
793 call assert_equal(['map! a7 /a7'], filter(copy(l), 'v:val =~ " a7 "'))
794 call assert_equal(['imap a8 /a8'], filter(copy(l), 'v:val =~ " a8 "'))
795 call assert_equal(['lmap a9 /a9'], filter(copy(l), 'v:val =~ " a9 "'))
796 call assert_equal(['cmap a10 /a10'], filter(copy(l), 'v:val =~ " a10 "'))
797 call assert_equal(['tmap a11 /a11'], filter(copy(l), 'v:val =~ " a11 "'))
798 call assert_equal(['nmap a12 /a12', 'xmap a12 /a12'],
799 \ filter(copy(l), 'v:val =~ " a12 "'))
800 call assert_equal(['nmap a13 /a13', 'smap a13 /a13'],
801 \ filter(copy(l), 'v:val =~ " a13 "'))
802 call assert_equal(['nmap a14 /a14', 'omap a14 /a14'],
803 \ filter(copy(l), 'v:val =~ " a14 "'))
804 call assert_equal(['vmap a15 /a15'], filter(copy(l), 'v:val =~ " a15 "'))
805 call assert_equal(['xmap a16 /a16', 'omap a16 /a16'],
806 \ filter(copy(l), 'v:val =~ " a16 "'))
807 call assert_equal(['smap a17 /a17', 'omap a17 /a17'],
808 \ filter(copy(l), 'v:val =~ " a17 "'))
809 call assert_equal(['nmap a18 /a18', 'vmap a18 /a18'],
810 \ filter(copy(l), 'v:val =~ " a18 "'))
811 call assert_equal(['nmap a19 /a19', 'xmap a19 /a19', 'omap a19 /a19'],
812 \ filter(copy(l), 'v:val =~ " a19 "'))
813 call assert_equal(['nmap a20 /a20', 'smap a20 /a20', 'omap a20 /a20'],
814 \ filter(copy(l), 'v:val =~ " a20 "'))
815 call assert_equal(['vmap a21 /a21', 'omap a21 /a21'],
816 \ filter(copy(l), 'v:val =~ " a21 "'))
817 call assert_equal(['map a22 <Nop>'], filter(copy(l), 'v:val =~ " a22 "'))
818 call assert_equal([], filter(copy(l), 'v:val =~ " a23 "'))
819 call assert_equal(["map a24<NL> ia24<NL>\x16\e"],
820 \ filter(copy(l), 'v:val =~ " a24"'))
821
822 call assert_equal(['abbr a25 A25'], filter(copy(l), 'v:val =~ " a25 "'))
823 call assert_equal(['cabbr a26 A26'], filter(copy(l), 'v:val =~ " a26 "'))
824 call assert_equal(['iabbr a27 A27'], filter(copy(l), 'v:val =~ " a27 "'))
825 call delete('Xvimrc')
826
827 mapclear
828 nmapclear
829 vmapclear
830 xmapclear
831 smapclear
832 omapclear
833 imapclear
834 lmapclear
835 cmapclear
836 tmapclear
837endfunc
838
839" Test for recursive mapping ('maxmapdepth')
840func Test_map_recursive()
841 map x y
842 map y x
843 call assert_fails('normal x', 'E223:')
844 unmap x
845 unmap y
846endfunc
847
848" Test for removing an abbreviation using {rhs} and with space after {lhs}
849func Test_abbr_remove()
850 abbr foo bar
851 let d = maparg('foo', 'i', 1, 1)
852 call assert_equal(['foo', 'bar', '!'], [d.lhs, d.rhs, d.mode])
853 unabbr bar
854 call assert_equal({}, maparg('foo', 'i', 1, 1))
855
856 abbr foo bar
857 unabbr foo<space><tab>
858 call assert_equal({}, maparg('foo', 'i', 1, 1))
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +0100859endfunc
860
Bram Moolenaar7f51bbe2020-01-24 20:21:19 +0100861" Trigger an abbreviation using a special key
862func Test_abbr_trigger_special()
863 new
864 iabbr teh the
865 call feedkeys("iteh\<F2>\<Esc>", 'xt')
866 call assert_equal('the<F2>', getline(1))
867 iunab teh
868 close!
869endfunc
870
871" Test for '<' in 'cpoptions'
872func Test_map_cpo_special_keycode()
873 set cpo-=<
874 imap x<Bslash>k Test
875 let d = maparg('x<Bslash>k', 'i', 0, 1)
876 call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
877 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
878 call assert_equal('"imap x\k', @:)
879 iunmap x<Bslash>k
880 set cpo+=<
881 imap x<Bslash>k Test
882 let d = maparg('x<Bslash>k', 'i', 0, 1)
883 call assert_equal(['x<Bslash>k', 'Test', 'i'], [d.lhs, d.rhs, d.mode])
884 call feedkeys(":imap x\<C-A>\<C-B>\"\<CR>", 'tx')
885 call assert_equal('"imap x<Bslash>k', @:)
886 iunmap x<Bslash>k
887 set cpo-=<
888 " Modifying 'cpo' above adds some default mappings, remove them
889 mapclear
890 mapclear!
891endfunc
892
Bram Moolenaar957cf672020-11-12 14:21:06 +0100893" Test for <Cmd> key in maps to execute commands
894func Test_map_cmdkey()
895 new
896
897 " Error cases
898 let x = 0
899 noremap <F3> <Cmd><Cmd>let x = 1<CR>
900 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
901 call assert_equal(0, x)
902
903 noremap <F3> <Cmd><F3>let x = 2<CR>
904 call assert_fails('call feedkeys("\<F3>", "xt")', 'E1137:')
905 call assert_equal(0, x)
906
907 noremap <F3> <Cmd>let x = 3
908 call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1135:')
909 call assert_equal(0, x)
910
911 " works in various modes and sees the correct mode()
912 noremap <F3> <Cmd>let m = mode(1)<CR>
913 noremap! <F3> <Cmd>let m = mode(1)<CR>
914
915 " normal mode
916 call feedkeys("\<F3>", 'xt')
917 call assert_equal('n', m)
918
919 " visual mode
920 call feedkeys("v\<F3>", 'xt!')
921 call assert_equal('v', m)
922 " shouldn't leave the visual mode
923 call assert_equal('v', mode(1))
924 call feedkeys("\<Esc>", 'xt')
925 call assert_equal('n', mode(1))
926
927 " visual mapping in select mode
928 call feedkeys("gh\<F3>", 'xt!')
929 call assert_equal('v', m)
930 " shouldn't leave select mode
931 call assert_equal('s', mode(1))
932 call feedkeys("\<Esc>", 'xt')
933 call assert_equal('n', mode(1))
934
935 " select mode mapping
936 snoremap <F3> <Cmd>let m = mode(1)<cr>
937 call feedkeys("gh\<F3>", 'xt!')
938 call assert_equal('s', m)
939 " shouldn't leave select mode
940 call assert_equal('s', mode(1))
941 call feedkeys("\<Esc>", 'xt')
942 call assert_equal('n', mode(1))
943
944 " operator-pending mode
945 call feedkeys("d\<F3>", 'xt!')
946 call assert_equal('no', m)
947 " leaves the operator-pending mode
948 call assert_equal('n', mode(1))
949
950 " insert mode
951 call feedkeys("i\<F3>abc", 'xt')
952 call assert_equal('i', m)
953 call assert_equal('abc', getline('.'))
954
955 " replace mode
956 call feedkeys("0R\<F3>two", 'xt')
957 call assert_equal('R', m)
958 call assert_equal('two', getline('.'))
959
960 " virtual replace mode
961 call setline('.', "one\ttwo")
962 call feedkeys("4|gR\<F3>xxx", 'xt')
963 call assert_equal('Rv', m)
964 call assert_equal("onexxx\ttwo", getline('.'))
965
966 " cmdline mode
967 call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
968 call assert_equal('c', m)
969 call assert_equal('"xxx', @:)
970
971 " terminal mode
972 if CanRunVimInTerminal()
973 tnoremap <F3> <Cmd>let m = mode(1)<CR>
974 let buf = Run_shell_in_terminal({})
975 call feedkeys("\<F3>", 'xt')
976 call assert_equal('t', m)
977 call assert_equal('t', mode(1))
978 call StopShellInTerminal(buf)
979 call TermWait(buf)
980 close!
981 tunmap <F3>
982 endif
983
984 " invoke cmdline mode recursively
985 noremap! <F2> <Cmd>norm! :foo<CR>
986 %d
987 call setline(1, ['some short lines', 'of test text'])
988 call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
989 call assert_equal('"barx', @:)
990 unmap! <F2>
991
992 " test for calling a <SID> function
993 let lines =<< trim END
994 map <F2> <Cmd>call <SID>do_it()<CR>
995 func s:do_it()
996 let g:x = 32
997 endfunc
998 END
999 call writefile(lines, 'Xscript')
1000 source Xscript
1001 call feedkeys("\<F2>", 'xt')
1002 call assert_equal(32, g:x)
1003 call delete('Xscript')
1004
1005 unmap <F3>
1006 unmap! <F3>
1007 %bw!
Bram Moolenaar4a441202020-11-28 14:43:26 +01001008
1009 " command line ending in "0" is handled without errors
1010 onoremap ix <cmd>eval 0<cr>
1011 call feedkeys('dix.', 'xt')
1012 ounmap ix
Bram Moolenaar957cf672020-11-12 14:21:06 +01001013endfunc
1014
1015" text object enters visual mode
1016func TextObj()
1017 if mode() !=# "v"
1018 normal! v
1019 end
1020 call cursor(1, 3)
1021 normal! o
1022 call cursor(2, 4)
1023endfunc
1024
1025func s:cmdmap(lhs, rhs)
1026 exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1027 exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
1028endfunc
1029
1030func s:cmdunmap(lhs)
1031 exe 'unmap ' .. a:lhs
1032 exe 'unmap! ' .. a:lhs
1033endfunc
1034
1035" Map various <Fx> keys used by the <Cmd> key tests
1036func s:setupMaps()
1037 call s:cmdmap('<F3>', 'let m = mode(1)')
1038 call s:cmdmap('<F4>', 'normal! ww')
1039 call s:cmdmap('<F5>', 'normal! "ay')
1040 call s:cmdmap('<F6>', 'throw "very error"')
1041 call s:cmdmap('<F7>', 'call TextObj()')
1042 call s:cmdmap('<F8>', 'startinsert')
1043 call s:cmdmap('<F9>', 'stopinsert')
1044endfunc
1045
1046" Remove the mappings setup by setupMaps()
1047func s:cleanupMaps()
1048 call s:cmdunmap('<F3>')
1049 call s:cmdunmap('<F4>')
1050 call s:cmdunmap('<F5>')
1051 call s:cmdunmap('<F6>')
1052 call s:cmdunmap('<F7>')
1053 call s:cmdunmap('<F8>')
1054 call s:cmdunmap('<F9>')
1055endfunc
1056
1057" Test for <Cmd> mapping in normal mode
1058func Test_map_cmdkey_normal_mode()
1059 new
1060 call s:setupMaps()
1061
1062 " check v:count and v:register works
1063 call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
1064 call feedkeys("\<F2>", 'xt')
1065 call assert_equal(['n', 0, '"'], s)
1066 call feedkeys("7\<F2>", 'xt')
1067 call assert_equal(['n', 7, '"'], s)
1068 call feedkeys("\"e\<F2>", 'xt')
1069 call assert_equal(['n', 0, 'e'], s)
1070 call feedkeys("5\"k\<F2>", 'xt')
1071 call assert_equal(['n', 5, 'k'], s)
1072 call s:cmdunmap('<F2>')
1073
1074 call setline(1, ['some short lines', 'of test text'])
1075 call feedkeys("\<F7>y", 'xt')
1076 call assert_equal("me short lines\nof t", @")
1077 call assert_equal('v', getregtype('"'))
1078 call assert_equal([0, 1, 3, 0], getpos("'<"))
1079 call assert_equal([0, 2, 4, 0], getpos("'>"))
1080
1081 " startinsert
1082 %d
1083 call feedkeys("\<F8>abc", 'xt')
1084 call assert_equal('abc', getline(1))
1085
1086 " feedkeys are not executed immediately
1087 noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
1088 %d
1089 call setline(1, ['some short lines', 'of test text'])
1090 call cursor(2, 3)
1091 call feedkeys(",a\<F3>", 'xt')
1092 call assert_equal('of test text', g:a)
1093 call assert_equal('n', m)
1094 call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
1095 nunmap ,a
1096
1097 " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
1098 noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
1099 call feedkeys(",b\<F3>", 'xt')
1100 call assert_equal('n', m)
1101 call assert_equal('of alphabetatest text', g:b)
1102 nunmap ,b
1103
1104 call s:cleanupMaps()
1105 %bw!
1106endfunc
1107
1108" Test for <Cmd> mapping with the :normal command
1109func Test_map_cmdkey_normal_cmd()
1110 new
1111 noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
1112 noremap ,f <Cmd>nosuchcommand<CR>
1113 noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
1114 noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
1115 noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
1116
1117 call setline(1, ['some short lines', 'of test text'])
1118 exe "norm ,x\r"
1119 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1120
1121 call assert_fails('norm ,f', 'E492:')
1122 call assert_fails('norm ,e', 'very error')
1123 call assert_fails('norm ,m', 'The message.')
1124 call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
1125
1126 %d
1127 let caught_err = 0
1128 try
1129 exe "normal ,w"
1130 catch /Vim(echoerr):Err/
1131 let caught_err = 1
1132 endtry
1133 call assert_equal(1, caught_err)
1134 call assert_equal(['', '0'], getline(1, '$'))
1135
1136 %d
1137 call assert_fails('normal ,w', 'Err')
1138 call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
1139 call assert_equal(1, line('.'))
1140
1141 nunmap ,x
1142 nunmap ,f
1143 nunmap ,e
1144 nunmap ,m
1145 nunmap ,w
1146 %bw!
1147endfunc
1148
1149" Test for <Cmd> mapping in visual mode
1150func Test_map_cmdkey_visual_mode()
1151 new
1152 set showmode
1153 call s:setupMaps()
1154
1155 call setline(1, ['some short lines', 'of test text'])
1156 call feedkeys("v\<F4>", 'xt!')
1157 call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
1158
Bram Moolenaarf08b0eb2021-10-16 13:00:14 +01001159 " can invoke an operator, ending the visual mode
Bram Moolenaar957cf672020-11-12 14:21:06 +01001160 let @a = ''
1161 call feedkeys("\<F5>", 'xt!')
1162 call assert_equal('n', mode(1))
1163 call assert_equal('some short l', @a)
1164
1165 " error doesn't interrupt visual mode
1166 call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
1167 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1168 call feedkeys("\<F7>", 'xt!')
1169 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1170
1171 " startinsert gives "-- (insert) VISUAL --" mode
1172 call feedkeys("\<F8>", 'xt!')
1173 call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1174 redraw!
1175 call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
1176 call feedkeys("\<Esc>new ", 'x')
1177 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1178
1179 call s:cleanupMaps()
1180 set showmode&
1181 %bw!
1182endfunc
1183
1184" Test for <Cmd> mapping in select mode
1185func Test_map_cmdkey_select_mode()
1186 new
1187 set showmode
1188 call s:setupMaps()
1189
1190 snoremap <F1> <cmd>throw "very error"<CR>
1191 snoremap <F2> <cmd>normal! <c-g>"by<CR>
1192 call setline(1, ['some short lines', 'of test text'])
1193
1194 call feedkeys("gh\<F4>", "xt!")
1195 call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
1196 redraw!
1197 call assert_match('^-- SELECT --', Screenline(&lines))
1198
1199 " visual mapping in select mode restarts select mode after operator
1200 let @a = ''
1201 call feedkeys("\<F5>", 'xt!')
1202 call assert_equal('s', mode(1))
1203 call assert_equal('some short l', @a)
1204
1205 " select mode mapping works, and does not restart select mode
1206 let @b = ''
1207 call feedkeys("\<F2>", 'xt!')
1208 call assert_equal('n', mode(1))
1209 call assert_equal('some short l', @b)
1210
1211 " error doesn't interrupt temporary visual mode
1212 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
1213 redraw!
1214 call assert_match('^-- VISUAL --', Screenline(&lines))
1215 " quirk: restoration of select mode is not performed
1216 call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
1217
1218 " error doesn't interrupt select mode
1219 call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
1220 redraw!
1221 call assert_match('^-- SELECT --', Screenline(&lines))
1222 call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
1223
1224 call feedkeys("\<F7>", 'xt!')
1225 redraw!
1226 call assert_match('^-- SELECT --', Screenline(&lines))
1227 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1228
1229 " startinsert gives "-- SELECT (insert) --" mode
1230 call feedkeys("\<F8>", 'xt!')
1231 redraw!
1232 call assert_match('^-- (insert) SELECT --', Screenline(&lines))
1233 call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
1234 call feedkeys("\<Esc>new ", 'x')
1235 call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
1236
1237 sunmap <F1>
1238 sunmap <F2>
1239 call s:cleanupMaps()
1240 set showmode&
1241 %bw!
1242endfunc
1243
1244" Test for <Cmd> mapping in operator-pending mode
1245func Test_map_cmdkey_op_pending_mode()
1246 new
1247 call s:setupMaps()
1248
1249 call setline(1, ['some short lines', 'of test text'])
1250 call feedkeys("d\<F4>", 'xt')
1251 call assert_equal(['lines', 'of test text'], getline(1, '$'))
1252 call assert_equal(['some short '], getreg('"', 1, 1))
1253 " create a new undo point
1254 let &undolevels = &undolevels
1255
1256 call feedkeys(".", 'xt')
1257 call assert_equal(['test text'], getline(1, '$'))
1258 call assert_equal(['lines', 'of '], getreg('"', 1, 1))
1259 " create a new undo point
1260 let &undolevels = &undolevels
1261
1262 call feedkeys("uu", 'xt')
1263 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1264
1265 " error aborts operator-pending, operator not performed
1266 call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
1267 call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
1268
1269 call feedkeys("\"bd\<F7>", 'xt')
1270 call assert_equal(['soest text'], getline(1, '$'))
1271 call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
1272
1273 " startinsert aborts operator
1274 call feedkeys("d\<F8>cc", 'xt')
1275 call assert_equal(['soccest text'], getline(1, '$'))
1276
1277 call s:cleanupMaps()
1278 %bw!
1279endfunc
1280
1281" Test for <Cmd> mapping in insert mode
1282func Test_map_cmdkey_insert_mode()
1283 new
1284 call s:setupMaps()
1285
1286 call setline(1, ['some short lines', 'of test text'])
1287 " works the same as <C-O>w<C-O>w
1288 call feedkeys("iindeed \<F4>little ", 'xt')
1289 call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
1290 call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
1291 call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
1292
1293 " Note when entering visual mode from InsertEnter autocmd, an async event,
1294 " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
1295 call feedkeys("i\<F7>stuff ", 'xt')
1296 call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
1297 call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
1298
1299 call feedkeys("\<F5>", 'xt')
1300 call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
1301
1302 " also works as part of abbreviation
1303 abbr foo <Cmd>let g:y = 17<CR>bar
1304 exe "normal i\<space>foo "
1305 call assert_equal(17, g:y)
1306 call assert_equal('in bar deed some short little 2 lines', getline(1))
1307 unabbr foo
1308
1309 " :startinsert does nothing
1310 call setline(1, 'foo bar')
1311 call feedkeys("ggi\<F8>vim", 'xt')
1312 call assert_equal('vimfoo bar', getline(1))
1313
1314 " :stopinsert works
1315 call feedkeys("ggi\<F9>Abc", 'xt')
1316 call assert_equal('vimfoo barbc', getline(1))
1317
1318 call s:cleanupMaps()
1319 %bw!
1320endfunc
1321
1322" Test for <Cmd> mapping in insert-completion mode
1323func Test_map_cmdkey_insert_complete_mode()
1324 new
1325 call s:setupMaps()
1326
1327 call setline(1, 'some short lines')
1328 call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
1329 call assert_equal('ic', m)
1330 call assert_equal(['some short lines', 'short '], getline(1, '$'))
1331
1332 call s:cleanupMaps()
1333 %bw!
1334endfunc
1335
1336" Test for <Cmd> mapping in cmdline mode
1337func Test_map_cmdkey_cmdline_mode()
1338 new
1339 call s:setupMaps()
1340
1341 call setline(1, ['some short lines', 'of test text'])
1342 let x = 0
1343 call feedkeys(":let x\<F3>= 10\r", 'xt')
1344 call assert_equal('c', m)
1345 call assert_equal(10, x)
1346
1347 " exception doesn't leave cmdline mode
1348 call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
1349 call assert_equal(20, x)
1350
1351 " move cursor in the buffer from cmdline mode
1352 call feedkeys(":let x\<F4>= 30\r", 'xt')
1353 call assert_equal(30, x)
1354 call assert_equal(12, col('.'))
1355
1356 " :startinsert takes effect after leaving cmdline mode
1357 call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
1358 call assert_equal(40, x)
1359 call assert_equal('some short new lines', getline(1))
1360
1361 call s:cleanupMaps()
1362 %bw!
1363endfunc
1364
Bram Moolenaarc77534c2020-11-18 11:34:37 +01001365func Test_map_cmdkey_redo()
1366 func SelectDash()
1367 call search('^---\n\zs', 'bcW')
1368 norm! V
1369 call search('\n\ze---$', 'W')
1370 endfunc
1371
1372 let text =<< trim END
1373 ---
1374 aaa
1375 ---
1376 bbb
1377 bbb
1378 ---
1379 ccc
1380 ccc
1381 ccc
1382 ---
1383 END
1384 new Xcmdtext
1385 call setline(1, text)
1386
1387 onoremap <silent> i- <Cmd>call SelectDash()<CR>
1388 call feedkeys('2Gdi-', 'xt')
1389 call assert_equal(['---', '---'], getline(1, 2))
1390 call feedkeys('j.', 'xt')
1391 call assert_equal(['---', '---', '---'], getline(1, 3))
1392 call feedkeys('j.', 'xt')
1393 call assert_equal(['---', '---', '---', '---'], getline(1, 4))
1394
1395 bwipe!
1396 call delete('Xcmdtext')
1397 delfunc SelectDash
1398 ounmap i-
1399endfunc
1400
Bram Moolenaar1f448d92021-03-22 19:37:06 +01001401" Test for using <script> with a map to remap characters in rhs
1402func Test_script_local_remap()
1403 new
1404 inoremap <buffer> <SID>xyz mno
1405 inoremap <buffer> <script> abc st<SID>xyzre
1406 normal iabc
1407 call assert_equal('stmnore', getline(1))
1408 bwipe!
1409endfunc
1410
Bram Moolenaar4934ed32021-04-30 19:43:11 +02001411func Test_abbreviate_multi_byte()
1412 new
1413 iabbrev foo bar
1414 call feedkeys("ifoo\<Esc>", 'xt')
1415 call assert_equal("bar", getline(1))
1416 iunabbrev foo
1417 bwipe!
1418endfunc
1419
Yegappan Lakshmanan2d6d7182021-06-13 21:52:48 +02001420" Test for abbreviations with 'latin1' encoding
1421func Test_abbreviate_latin1_encoding()
1422 set encoding=latin1
1423 call assert_fails('abbr ab#$c ABC', 'E474:')
1424 new
1425 iabbr <buffer> #i #include
1426 iabbr <buffer> ## #enddef
1427 exe "normal i#i\<C-]>"
1428 call assert_equal('#include', getline(1))
1429 exe "normal 0Di##\<C-]>"
1430 call assert_equal('#enddef', getline(1))
1431 %bw!
1432 set encoding=utf-8
1433endfunc
1434
Bram Moolenaar8ba6bb72020-01-20 20:41:42 +01001435" vim: shiftwidth=2 sts=2 expandtab