blob: 2c6aa2497690ce6076b6ecaae934ac1169ec3605 [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
4
Bram Moolenaar2d1a2482016-08-14 15:32:11 +02005func Test_abbreviation()
6 " abbreviation with 0x80 should work
7 inoreab чкпр vim
8 call feedkeys("Goчкпр \<Esc>", "xt")
9 call assert_equal('vim ', getline('$'))
10 iunab чкпр
11 set nomodified
12endfunc
13
Bram Moolenaar8485be42019-04-23 16:36:05 +020014func Test_abclear()
15 abbrev foo foobar
16 iabbrev fooi foobari
17 cabbrev fooc foobarc
18 call assert_equal("\n\n"
19 \ .. "c fooc foobarc\n"
20 \ .. "i fooi foobari\n"
21 \ .. "! foo foobar", execute('abbrev'))
22
23 iabclear
24 call assert_equal("\n\n"
25 \ .. "c fooc foobarc\n"
26 \ .. "c foo foobar", execute('abbrev'))
27 abbrev foo foobar
28 iabbrev fooi foobari
29
30 cabclear
31 call assert_equal("\n\n"
32 \ .. "i fooi foobari\n"
33 \ .. "i foo foobar", execute('abbrev'))
34 abbrev foo foobar
35 cabbrev fooc foobarc
36
37 abclear
38 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
39endfunc
40
41func Test_abclear_buffer()
42 abbrev foo foobar
43 new X1
44 abbrev <buffer> foo1 foobar1
45 new X2
46 abbrev <buffer> foo2 foobar2
47
48 call assert_equal("\n\n"
49 \ .. "! foo2 @foobar2\n"
50 \ .. "! foo foobar", execute('abbrev'))
51
52 abclear <buffer>
53 call assert_equal("\n\n"
54 \ .. "! foo foobar", execute('abbrev'))
55
56 b X1
57 call assert_equal("\n\n"
58 \ .. "! foo1 @foobar1\n"
59 \ .. "! foo foobar", execute('abbrev'))
60 abclear <buffer>
61 call assert_equal("\n\n"
62 \ .. "! foo foobar", execute('abbrev'))
63
64 abclear
65 call assert_equal("\n\nNo abbreviation found", execute('abbrev'))
66
67 %bwipe
68endfunc
69
Bram Moolenaar2d1a2482016-08-14 15:32:11 +020070func Test_map_ctrl_c_insert()
71 " mapping of ctrl-c in Insert mode
72 set cpo-=< cpo-=k
73 inoremap <c-c> <ctrl-c>
74 cnoremap <c-c> dummy
75 cunmap <c-c>
76 call feedkeys("GoTEST2: CTRL-C |\<C-C>A|\<Esc>", "xt")
77 call assert_equal('TEST2: CTRL-C |<ctrl-c>A|', getline('$'))
78 unmap! <c-c>
79 set nomodified
80endfunc
81
82func Test_map_ctrl_c_visual()
83 " mapping of ctrl-c in Visual mode
84 vnoremap <c-c> :<C-u>$put ='vmap works'
85 call feedkeys("GV\<C-C>\<CR>", "xt")
86 call assert_equal('vmap works', getline('$'))
87 vunmap <c-c>
88 set nomodified
89endfunc
90
91func Test_map_langmap()
Bram Moolenaar920694c2016-08-21 17:45:02 +020092 if !has('langmap')
93 return
94 endif
95
96 " check langmap applies in normal mode
97 set langmap=+- nolangremap
98 new
99 call setline(1, ['a', 'b', 'c'])
100 2
101 call assert_equal('b', getline('.'))
102 call feedkeys("+", "xt")
103 call assert_equal('a', getline('.'))
104
105 " check no remapping
106 map x +
107 2
108 call feedkeys("x", "xt")
109 call assert_equal('c', getline('.'))
110
111 " check with remapping
112 set langremap
113 2
114 call feedkeys("x", "xt")
115 call assert_equal('a', getline('.'))
116
117 unmap x
118 bwipe!
119
120 " 'langnoremap' follows 'langremap' and vise versa
121 set langremap
122 set langnoremap
123 call assert_equal(0, &langremap)
124 set langremap
125 call assert_equal(0, &langnoremap)
126 set nolangremap
127 call assert_equal(1, &langnoremap)
128
Bram Moolenaarda9ce2c2016-09-02 19:34:10 +0200129 " check default values
130 set langnoremap&
131 call assert_equal(0, &langnoremap)
132 call assert_equal(1, &langremap)
133 set langremap&
134 call assert_equal(0, &langnoremap)
135 call assert_equal(1, &langremap)
136
Bram Moolenaar920694c2016-08-21 17:45:02 +0200137 " langmap should not apply in insert mode, 'langremap' doesn't matter
138 set langmap=+{ nolangremap
139 call feedkeys("Go+\<Esc>", "xt")
140 call assert_equal('+', getline('$'))
141 set langmap=+{ langremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200142 call feedkeys("Go+\<Esc>", "xt")
143 call assert_equal('+', getline('$'))
144
Bram Moolenaar920694c2016-08-21 17:45:02 +0200145 " langmap used for register name in insert mode.
146 call setreg('a', 'aaaa')
147 call setreg('b', 'bbbb')
148 call setreg('c', 'cccc')
149 set langmap=ab langremap
150 call feedkeys("Go\<C-R>a\<Esc>", "xt")
151 call assert_equal('bbbb', getline('$'))
152 call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt")
153 call assert_equal('bbbb', getline('$'))
154 " mapping does not apply
155 imap c a
156 call feedkeys("Go\<C-R>c\<Esc>", "xt")
157 call assert_equal('cccc', getline('$'))
158 imap a c
159 call feedkeys("Go\<C-R>a\<Esc>", "xt")
160 call assert_equal('bbbb', getline('$'))
161
162 " langmap should not apply in Command-line mode
163 set langmap=+{ nolangremap
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200164 call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
165 call assert_equal('+', getline('$'))
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200166
Bram Moolenaare90858d2017-02-01 17:24:34 +0100167 iunmap a
168 iunmap c
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200169 set nomodified
170endfunc
171
172func Test_map_feedkeys()
173 " issue #212 (feedkeys insert mapping at current position)
174 nnoremap . :call feedkeys(".", "in")<cr>
175 call setline('$', ['a b c d', 'a b c d'])
176 $-1
177 call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt")
178 call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$')))
Bram Moolenaare90858d2017-02-01 17:24:34 +0100179 nunmap .
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200180 set nomodified
181endfunc
182
183func Test_map_cursor()
184 " <c-g>U<cursor> works only within a single line
185 imapclear
186 imap ( ()<c-g>U<left>
187 call feedkeys("G2o\<Esc>ki\<CR>Test1: text with a (here some more text\<Esc>k.", "xt")
188 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 2))
189 call assert_equal('Test1: text with a (here some more text)', getline(line('$') - 1))
190
191 " test undo
192 call feedkeys("G2o\<Esc>ki\<CR>Test2: text wit a (here some more text [und undo]\<C-G>u\<Esc>k.u", "xt")
193 call assert_equal('', getline(line('$') - 2))
194 call assert_equal('Test2: text wit a (here some more text [und undo])', getline(line('$') - 1))
195 set nomodified
196 imapclear
197endfunc
198
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100199func Test_map_cursor_ctrl_gU()
200 " <c-g>U<cursor> works only within a single line
201 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left>
202 call setline(1, ['foo', 'foobar', '', 'foo'])
203 call cursor(1,2)
204 call feedkeys("c<*PREFIX\<esc>.", 'xt')
205 call assert_equal(['PREFIXfoo', 'foobar', '', 'PREFIXfoo'], getline(1,'$'))
206 " break undo manually
207 set ul=1000
208 exe ":norm! uu"
209 call assert_equal(['foo', 'foobar', '', 'foo'], getline(1,'$'))
210
211 " Test that it does not work if the cursor moves to the previous line
212 " 2 times <S-Left> move to the previous line
213 nnoremap c<* *Ncgn<C-r>"<C-G>U<S-Left><C-G>U<S-Left>
214 call setline(1, ['', ' foo', 'foobar', '', 'foo'])
215 call cursor(2,3)
216 call feedkeys("c<*PREFIX\<esc>.", 'xt')
217 call assert_equal(['PREFIXPREFIX', ' foo', 'foobar', '', 'foo'], getline(1,'$'))
218 nmapclear
219endfunc
220
221
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200222" This isn't actually testing a mapping, but similar use of CTRL-G U as above.
223func Test_break_undo()
Bram Moolenaar75bf3d22019-03-26 22:46:05 +0100224 set whichwrap=<,>,[,]
Bram Moolenaar2d1a2482016-08-14 15:32:11 +0200225 call feedkeys("G4o2k", "xt")
226 exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."
227 call assert_equal('new line here', getline(line('$') - 3))
228 call assert_equal('Test3: text with a (parenthesis here', getline(line('$') - 2))
229 call assert_equal('new line here', getline(line('$') - 1))
230 set nomodified
231endfunc
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +0200232
233func Test_map_meta_quotes()
234 imap <M-"> foo
235 call feedkeys("Go-\<M-\">-\<Esc>", "xt")
236 call assert_equal("-foo-", getline('$'))
237 set nomodified
238 iunmap <M-">
239endfunc
Bram Moolenaar878c2632017-04-01 15:15:52 +0200240
241func Test_abbr_after_line_join()
242 new
243 abbr foo bar
244 set backspace=indent,eol,start
245 exe "normal o\<BS>foo "
246 call assert_equal("bar ", getline(1))
247 bwipe!
248 unabbr foo
249 set backspace&
250endfunc
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200251
252func Test_map_timeout()
Bram Moolenaar26d98212019-01-27 22:32:55 +0100253 if !has('timers')
254 return
255 endif
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200256 nnoremap aaaa :let got_aaaa = 1<CR>
257 nnoremap bb :let got_bb = 1<CR>
258 nmap b aaa
259 new
260 func ExitInsert(timer)
261 let g:line = getline(1)
262 call feedkeys("\<Esc>", "t")
263 endfunc
264 set timeout timeoutlen=200
Bram Moolenaar26d98212019-01-27 22:32:55 +0100265 let timer = timer_start(300, 'ExitInsert')
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200266 " After the 'b' Vim waits for another character to see if it matches 'bb'.
267 " When it times out it is expanded to "aaa", but there is no wait for
268 " "aaaa". Can't check that reliably though.
269 call feedkeys("b", "xt!")
270 call assert_equal("aa", g:line)
271 call assert_false(exists('got_aaa'))
272 call assert_false(exists('got_bb'))
273
274 bwipe!
275 nunmap aaaa
276 nunmap bb
277 nunmap b
278 set timeoutlen&
279 delfunc ExitInsert
Bram Moolenaar26d98212019-01-27 22:32:55 +0100280 call timer_stop(timer)
281endfunc
282
283func Test_map_timeout_with_timer_interrupt()
284 if !has('job') || !has('timers')
285 return
286 endif
287
288 " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key
289 " sequence.
290 new
291 let g:val = 0
292 nnoremap \12 :let g:val = 1<CR>
293 nnoremap \123 :let g:val = 2<CR>
294 set timeout timeoutlen=1000
295
296 func ExitCb(job, status)
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100297 let g:timer = timer_start(1, {-> feedkeys("3\<Esc>", 't')})
Bram Moolenaar26d98212019-01-27 22:32:55 +0100298 endfunc
299
300 call job_start([&shell, &shellcmdflag, 'echo'], {'exit_cb': 'ExitCb'})
301 call feedkeys('\12', 'xt!')
302 call assert_equal(2, g:val)
303
304 bwipe!
305 nunmap \12
306 nunmap \123
307 set timeoutlen&
308 call WaitFor({-> exists('g:timer')})
309 call timer_stop(g:timer)
310 unlet g:timer
311 unlet g:val
312 delfunc ExitCb
Bram Moolenaarb7637c42017-04-23 18:49:36 +0200313endfunc
Bram Moolenaarc3c3e692018-04-26 22:30:33 +0200314
315func Test_abbreviation_CR()
316 new
317 func Eatchar(pat)
318 let c = nr2char(getchar(0))
319 return (c =~ a:pat) ? '' : c
320 endfunc
321 iabbrev <buffer><silent> ~~7 <c-r>=repeat('~', 7)<CR><c-r>=Eatchar('\s')<cr>
322 call feedkeys("GA~~7 \<esc>", 'xt')
323 call assert_equal('~~~~~~~', getline('$'))
324 %d
325 call feedkeys("GA~~7\<cr>\<esc>", 'xt')
326 call assert_equal(['~~~~~~~', ''], getline(1,'$'))
327 delfunc Eatchar
328 bw!
329endfunc
Bram Moolenaar5e3423d2018-05-13 18:36:27 +0200330
331func Test_cabbr_visual_mode()
332 cabbr s su
333 call feedkeys(":s \<c-B>\"\<CR>", 'itx')
334 call assert_equal('"su ', getreg(':'))
335 call feedkeys(":'<,'>s \<c-B>\"\<CR>", 'itx')
336 let expected = '"'. "'<,'>su "
337 call assert_equal(expected, getreg(':'))
338 call feedkeys(": '<,'>s \<c-B>\"\<CR>", 'itx')
339 let expected = '" '. "'<,'>su "
340 call assert_equal(expected, getreg(':'))
341 call feedkeys(":'a,'bs \<c-B>\"\<CR>", 'itx')
342 let expected = '"'. "'a,'bsu "
343 call assert_equal(expected, getreg(':'))
344 cunabbr s
345endfunc
Bram Moolenaar5976f8f2018-12-27 23:44:44 +0100346
347func Test_motionforce_omap()
348 func GetCommand()
349 let g:m=mode(1)
350 let [g:lnum1, g:col1] = searchpos('-', 'Wb')
351 if g:lnum1 == 0
352 return "\<Esc>"
353 endif
354 let [g:lnum2, g:col2] = searchpos('-', 'W')
355 if g:lnum2 == 0
356 return "\<Esc>"
357 endif
358 return ":call Select()\<CR>"
359 endfunc
360 func Select()
361 call cursor([g:lnum1, g:col1])
362 exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
363 call cursor([g:lnum2, g:col2])
364 execute "normal! \<BS>"
365 endfunc
366 new
367 onoremap <buffer><expr> i- GetCommand()
368 " 1) default omap mapping
369 %d_
370 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
371 call cursor(2, 1)
372 norm di-
373 call assert_equal('no', g:m)
374 call assert_equal(['aaa -- eee'], getline(1, '$'))
375 " 2) forced characterwise operation
376 %d_
377 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
378 call cursor(2, 1)
379 norm dvi-
380 call assert_equal('nov', g:m)
381 call assert_equal(['aaa -- eee'], getline(1, '$'))
382 " 3) forced linewise 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([''], getline(1, '$'))
389 " 4) forced blockwise operation
390 %d_
391 call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
392 call cursor(2, 1)
393 exe "norm d\<C-V>i-"
394 call assert_equal("no\<C-V>", g:m)
395 call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
396 bwipe!
397 delfunc Select
398 delfunc GetCommand
399endfunc
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200400
401func Test_error_in_map_expr()
Bram Moolenaar0d702022019-07-04 14:20:41 +0200402 if !has('terminal') || (has('win32') && has('gui_running'))
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200403 throw 'Skipped: cannot run Vim in a terminal window'
404 endif
405
406 let lines =<< trim [CODE]
407 func Func()
408 " fail to create list
409 let x = [
410 endfunc
411 nmap <expr> ! Func()
412 set updatetime=50
413 [CODE]
414 call writefile(lines, 'Xtest.vim')
415
Bram Moolenaar0d702022019-07-04 14:20:41 +0200416 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200417 let job = term_getjob(buf)
418 call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
419
420 " GC must not run during map-expr processing, which can make Vim crash.
421 call term_sendkeys(buf, '!')
422 call term_wait(buf, 100)
423 call term_sendkeys(buf, "\<CR>")
424 call term_wait(buf, 100)
425 call assert_equal('run', job_status(job))
426
427 call term_sendkeys(buf, ":qall!\<CR>")
428 call WaitFor({-> job_status(job) ==# 'dead'})
429 if has('unix')
430 call assert_equal('', job_info(job).termsig)
431 endif
432
433 call delete('Xtest.vim')
434 exe buf .. 'bwipe!'
435endfunc