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