neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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    nnoremapa <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