blob: d3abaff9bfd19681d757d800cec74b97b074561a [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 Moolenaar26d98212019-01-27 22:32:55 +01006
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02007func Test_abbreviation()
8 " abbreviation with 0x80 should work
9 inoreab чкпр vim
10 call feedkeys("Goчкпр \<Esc>", "xt")
11 call assert_equal('vim ', getline('$'))
12 iunab чкпр
13 set nomodified
14endfunc
15
Bram Moolenaar8485be42019-04-23 16:36:05 +020016func Test_abclear()
17 abbrev foo foobar
18 iabbrev fooi foobari
19 cabbrev fooc foobarc
20 call assert_equal("\n\n"
21 \ .. "c fooc foobarc\n"
22 \ .. "i fooi foobari\n"
23 \ .. "! foo foobar", execute('abbrev'))
24
25 iabclear
26 call assert_equal("\n\n"
27 \ .. "c fooc foobarc\n"
28 \ .. "c foo foobar", execute('abbrev'))
29 abbrev foo foobar
30 iabbrev fooi foobari
31
32 cabclear
33 call assert_equal("\n\n"
34 \ .. "i fooi foobari\n"
35 \ .. "i foo foobar", execute('abbrev'))
36 abbrev foo foobar
37 cabbrev fooc foobarc
38
39 abclear
40 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
41endfunc
42
43func Test_abclear_buffer()
44 abbrev foo foobar
45 new X1
46 abbrev <buffer> foo1 foobar1
47 new X2
48 abbrev <buffer> foo2 foobar2
49
50 call assert_equal("\n\n"
51 \ .. "! foo2 @foobar2\n"
52 \ .. "! foo foobar", execute('abbrev'))
53
54 abclear <buffer>
55 call assert_equal("\n\n"
56 \ .. "! foo foobar", execute('abbrev'))
57
58 b X1
59 call assert_equal("\n\n"
60 \ .. "! foo1 @foobar1\n"
61 \ .. "! foo foobar", execute('abbrev'))
62 abclear <buffer>
63 call assert_equal("\n\n"
64 \ .. "! foo foobar", execute('abbrev'))
65
66 abclear
67 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
68
69 %bwipe
70endfunc
71
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020072func Test_map_ctrl_c_insert()
73 " mapping of ctrl-c in Insert mode
74 set cpo-=< cpo-=k
75 inoremap <c-c> <ctrl-c>
76 cnoremap <c-c> dummy
77 cunmap <c-c>
78 call feedkeys("GoTEST2: CTRL-C |\<C-C>A|\<Esc>", "xt")
79 call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
80 unmap! <c-c>
81 set nomodified
82endfunc
83
84func Test_map_ctrl_c_visual()
85 " mapping of ctrl-c in Visual mode
86 vnoremap <c-c> :<C-u>$put ='vmap works'
87 call feedkeys("GV\<C-C>\<CR>", "xt")
88 call assert_equal('vmap works', getline('$'))
89 vunmap <c-c>
90 set nomodified
91endfunc
92
93func Test_map_langmap()
Bram Moolenaar920694c2016-08-21 17:45:02 +020094 if !has('langmap')
95 return
96 endif
97
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
237 call feedkeys("Go-\<M-\">-\<Esc>", "xt")
238 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 Moolenaar26d98212019-01-27 22:32:55 +0100261 if !has('timers')
262 return
263 endif
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200264 nnoremap aaaa :let got_aaaa = 1<CR>
265 nnoremap bb :let got_bb = 1<CR>
266 nmap b aaa
267 new
268 func ExitInsert(timer)
269 let g:line = getline(1)
270 call feedkeys("\<Esc>", "t")
271 endfunc
272 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100273 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200274 " After the 'b' Vim waits for another character to see if it matches 'bb'.
275 " When it times out it is expanded to "aaa", but there is no wait for
276 " "aaaa". Can't check that reliably though.
277 call feedkeys("b", "xt!")
278 call assert_equal("aa", g:line)
279 call assert_false(exists('got_aaa'))
280 call assert_false(exists('got_bb'))
281
282 bwipe!
283 nunmap aaaa
284 nunmap bb
285 nunmap b
286 set timeoutlen&
287 delfunc ExitInsert
Bram Moolenaar26d98212019-01-27 22:32:55 +0100288 call timer_stop(timer)
289endfunc
290
291func Test_map_timeout_with_timer_interrupt()
292 if !has('job') || !has('timers')
293 return
294 endif
295
296 " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
297 " sequence.
298 new
299 let g:val = 0
300 nnoremap \12 :let g:val = 1<CR>
301 nnoremap \123 :let g:val = 2<CR>
Bram Moolenaarea94c852019-08-16 21:47:27 +0200302 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100303
304 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100305 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100306 endfunc
307
308 call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
309 call feedkeys('\12', 'xt!')
310 call assert_equal(2, g:val)
311
312 bwipe!
313 nunmap \12
314 nunmap \123
315 set timeoutlen&
316 call WaitFor({-> exists('g:timer')})
317 call timer_stop(g:timer)
318 unlet g:timer
319 unlet g:val
320 delfunc ExitCb
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200321endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200322
323func Test_abbreviation_CR()
324 new
325 func Eatchar(pat)
326 let c = nr2char(getchar(0))
327 return (c =~ a:pat) ? '' : c
328 endfunc
329 iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
330 call feedkeys("GA~~7 \<esc>", 'xt')
331 call assert_equal('~~~~~~~', getline('$'))
332 %d
333 call feedkeys("GA~~7\<cr>\<esc>", 'xt')
334 call assert_equal(['~~~~~~~', ''], getline(1,'$'))
335 delfunc Eatchar
336 bw!
337endfunc
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200338
339func Test_cabbr_visual_mode()
340 cabbr s su
341 call feedkeys(":s \<c-B>\"\<CR>", 'itx')
342 call assert_equal('"su ', getreg(':'))
343 call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
344 let expected = '"'. "'<,'>su "
345 call assert_equal(expected, getreg(':'))
346 call feedkeys(": '<,'>s \<c-B>\"\<CR>", 'itx')
347 let expected = '" '. "'<,'>su "
348 call assert_equal(expected, getreg(':'))
349 call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
350 let expected = '"'. "'a,'bsu "
351 call assert_equal(expected, getreg(':'))
352 cunabbr s
353endfunc
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100354
355func Test_motionforce_omap()
356 func GetCommand()
357 let g:m=mode(1)
358 let [g:lnum1, g:col1] = searchpos('-', 'Wb')
359 if g:lnum1 == 0
360 return "\<Esc>"
361 endif
362 let [g:lnum2, g:col2] = searchpos('-', 'W')
363 if g:lnum2 == 0
364 return "\<Esc>"
365 endif
366 return ":call Select()\<CR>"
367 endfunc
368 func Select()
369 call cursor([g:lnum1, g:col1])
370 exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
371 call cursor([g:lnum2, g:col2])
372 execute "normal! \<BS>"
373 endfunc
374 new
375 onoremap <buffer><expr> i- GetCommand()
376 " 1) default omap mapping
377 %d_
378 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
379 call cursor(2, 1)
380 norm di-
381 call assert_equal('no', g:m)
382 call assert_equal(['aaa -- eee'], getline(1, '$'))
383 " 2) forced characterwise operation
384 %d_
385 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
386 call cursor(2, 1)
387 norm dvi-
388 call assert_equal('nov', g:m)
389 call assert_equal(['aaa -- eee'], getline(1, '$'))
390 " 3) forced linewise operation
391 %d_
392 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
393 call cursor(2, 1)
394 norm dVi-
395 call assert_equal('noV', g:m)
396 call assert_equal([''], getline(1, '$'))
397 " 4) forced blockwise operation
398 %d_
399 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
400 call cursor(2, 1)
401 exe "norm d\<C-V>i-"
402 call assert_equal("no\<C-V>", g:m)
403 call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
404 bwipe!
405 delfunc Select
406 delfunc GetCommand
407endfunc
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200408
409func Test_error_in_map_expr()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200410 " Unlike CheckRunVimInTerminal this does work in a win32 console
411 CheckFeature terminal
412 if has('win32') && has('gui_running')
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200413 throw 'Skipped: cannot run Vim in a terminal window'
414 endif
415
416 let lines =<< trim [CODE]
417 func Func()
418 " fail to create list
419 let x = [
420 endfunc
421 nmap <expr> ! Func()
422 set updatetime=50
423 [CODE]
424 call writefile(lines, 'Xtest.vim')
425
Bram Moolenaar0d702022019-07-04 14:20:41 +0200426 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200427 let job = term_getjob(buf)
428 call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
429
430 " GC must not run during map-expr processing, which can make Vim crash.
431 call term_sendkeys(buf, '!')
432 call term_wait(buf, 100)
433 call term_sendkeys(buf, "\<CR>")
434 call term_wait(buf, 100)
435 call assert_equal('run', job_status(job))
436
437 call term_sendkeys(buf, ":qall!\<CR>")
438 call WaitFor({-> job_status(job) ==# 'dead'})
439 if has('unix')
440 call assert_equal('', job_info(job).termsig)
441 endif
442
443 call delete('Xtest.vim')
444 exe buf .. 'bwipe!'
445endfunc
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200446
447func Test_list_mappings()
Bram Moolenaar2559a472019-10-16 23:33:12 +0200448 " Remove default mappings
449 imapclear
Bram Moolenaar4f2f61a2019-10-16 22:27:49 +0200450
Bram Moolenaarfafb4b12019-10-16 18:34:57 +0200451 inoremap <C-M> CtrlM
452 inoremap <A-S> AltS
453 inoremap <S-/> ShiftSlash
454 call assert_equal([
455 \ 'i <S-/> * ShiftSlash',
456 \ 'i <M-S> * AltS',
457 \ 'i <C-M> * CtrlM',
458 \], execute('imap')->trim()->split("\n"))
459 iunmap <C-M>
460 iunmap <A-S>
461 call assert_equal(['i <S-/> * ShiftSlash'], execute('imap')->trim()->split("\n"))
462 iunmap <S-/>
463 call assert_equal(['No mapping found'], execute('imap')->trim()->split("\n"))
464endfunc
Bram Moolenaar4ebe0e62019-11-22 20:55:40 +0100465
466func Test_expr_map_restore_cursor()
467 CheckScreendump
468
469 let lines =<< trim END
470 call setline(1, ['one', 'two', 'three'])
471 2
472 set ls=2
473 hi! link StatusLine ErrorMsg
474 noremap <expr> <C-B> Func()
475 func Func()
476 let g:on = !get(g:, 'on', 0)
477 redraws
478 return ''
479 endfunc
480 func Status()
481 return get(g:, 'on', 0) ? '[on]' : ''
482 endfunc
483 set stl=%{Status()}
484 END
485 call writefile(lines, 'XtestExprMap')
486 let buf = RunVimInTerminal('-S XtestExprMap', #{rows: 10})
487 call term_wait(buf)
488 call term_sendkeys(buf, "\<C-B>")
489 call VerifyScreenDump(buf, 'Test_map_expr_1', {})
490
491 " clean up
492 call StopVimInTerminal(buf)
493 call delete('XtestExprMap')
494endfunc