neovim

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

test_shell.vim (10091B)


      1 " Test for the shell related options ('shell', 'shellcmdflag', 'shellpipe',
      2 " 'shellquote', 'shellredir', 'shellxescape', and 'shellxquote')
      3 
      4 source check.vim
      5 source shared.vim
      6 
      7 func Test_shell_options()
      8  if has('win32')
      9    " FIXME: This test is flaky on MS-Windows.
     10    let g:test_is_flaky = 1
     11  endif
     12 
     13  " The expected value of 'shellcmdflag', 'shellpipe', 'shellquote',
     14  " 'shellredir', 'shellxescape', 'shellxquote' for the supported shells.
     15  let shells = []
     16  if has('unix')
     17    let shells += [['sh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
     18          \ ['ksh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
     19          \ ['mksh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
     20          \ ['zsh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
     21          \ ['zsh-beta', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
     22          \ ['bash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
     23          \ ['fish', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
     24          \ ['ash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
     25          \ ['dash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
     26          \ ['csh', '-c', '|& tee', '', '>&', '', ''],
     27          \ ['tcsh', '-c', '|& tee', '', '>&', '', '']]
     28  endif
     29  if has('win32')
     30    let shells += [['cmd', '/s /c', '2>&1| tee', '', '>%s 2>&1', '', '"']]
     31  endif
     32 
     33  " start a new Vim instance with 'shell' set to each of the supported shells
     34  " and check the default shell option settings
     35  let after =<< trim END
     36    let l = [&shell, &shellcmdflag, &shellpipe, &shellquote]
     37    let l += [&shellredir, &shellxescape, &shellxquote]
     38    call writefile([json_encode(l)], 'Xtestout')
     39    qall!
     40  END
     41  for e in shells
     42    if RunVim([], after, '--cmd "set shell=' .. e[0] .. '"')
     43      call assert_equal(e, json_decode(readfile('Xtestout')[0]))
     44    endif
     45  endfor
     46 
     47  " Test shellescape() for each of the shells.
     48  for e in shells
     49    exe 'set shell=' .. e[0]
     50    if e[0] =~# '.*csh$' || e[0] =~# '.*csh.exe$'
     51      let str1 = "'cmd \"arg1\" '\\''arg2'\\'' \\!%#'"
     52      let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\\\!\\%\\#'"
     53    elseif e[0] =~# '.*powershell$' || e[0] =~# '.*powershell.exe$'
     54      let str1 = "'cmd \"arg1\" ''arg2'' !%#'"
     55      let str2 = "'cmd \"arg1\" ''arg2'' \\!\\%\\#'"
     56    else
     57      let str1 = "'cmd \"arg1\" '\\''arg2'\\'' !%#'"
     58      let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\!\\%\\#'"
     59    endif
     60    call assert_equal(str1, shellescape("cmd \"arg1\" 'arg2' !%#"), e[0])
     61    call assert_equal(str2, shellescape("cmd \"arg1\" 'arg2' !%#", 1), e[0])
     62 
     63    " Try running an external command with the shell.
     64    if executable(e[0])
     65      " set the shell options for the current 'shell'
     66      let [&shellcmdflag, &shellpipe, &shellquote, &shellredir,
     67            \ &shellxescape, &shellxquote] = e[1:6]
     68      new
     69      r !echo hello
     70      call assert_equal('hello', substitute(getline(2), '\W', '', 'g'), e[0])
     71      bwipe!
     72    endif
     73  endfor
     74  set shell& shellcmdflag& shellpipe& shellquote&
     75  set shellredir& shellxescape& shellxquote&
     76  call delete('Xtestout')
     77 endfunc
     78 
     79 " Test for the 'shell' option
     80 func Test_shell()
     81  throw 'Skipped: Nvim missing :shell currently'
     82  CheckUnix
     83  let save_shell = &shell
     84  set shell=
     85  let caught_e91 = 0
     86  try
     87    shell
     88  catch /E91:/
     89    let caught_e91 = 1
     90  endtry
     91  call assert_equal(1, caught_e91)
     92  let &shell = save_shell
     93 endfunc
     94 
     95 " Test for the 'shellquote' option
     96 func Test_shellquote()
     97  CheckUnix
     98  set shellquote=#
     99  set verbose=20
    100  redir => v
    101  silent! !echo Hello
    102  redir END
    103  set verbose&
    104  set shellquote&
    105  call assert_match(': "#echo Hello#"', v)
    106 endfunc
    107 
    108 " Test for the 'shellescape' option
    109 func Test_shellescape()
    110  let save_shell = &shell
    111  set shell=bash
    112  call assert_equal("'text'", shellescape('text'))
    113  call assert_equal("'te\"xt'", 'te"xt'->shellescape())
    114  call assert_equal("'te'\\''xt'", shellescape("te'xt"))
    115 
    116  call assert_equal("'te%xt'", shellescape("te%xt"))
    117  call assert_equal("'te\\%xt'", shellescape("te%xt", 1))
    118  call assert_equal("'te#xt'", shellescape("te#xt"))
    119  call assert_equal("'te\\#xt'", shellescape("te#xt", 1))
    120  call assert_equal("'te!xt'", shellescape("te!xt"))
    121  call assert_equal("'te\\!xt'", shellescape("te!xt", 1))
    122  call assert_equal("'te<cword>xt'", shellescape("te<cword>xt"))
    123  call assert_equal("'te\\<cword>xt'", shellescape("te<cword>xt", 1))
    124  call assert_equal("'te<cword>%xt'", shellescape("te<cword>%xt"))
    125  call assert_equal("'te\\<cword>\\%xt'", shellescape("te<cword>%xt", 1))
    126 
    127  call assert_equal("'te\nxt'", shellescape("te\nxt"))
    128  call assert_equal("'te\\\nxt'", shellescape("te\nxt", 1))
    129  set shell=tcsh
    130  call assert_equal("'te\\!xt'", shellescape("te!xt"))
    131  call assert_equal("'te\\\\!xt'", shellescape("te!xt", 1))
    132  call assert_equal("'te\\\nxt'", shellescape("te\nxt"))
    133  call assert_equal("'te\\\\\nxt'", shellescape("te\nxt", 1))
    134 
    135  set shell=fish
    136  call assert_equal("'text'", shellescape('text'))
    137  call assert_equal("'te\"xt'", shellescape('te"xt'))
    138  call assert_equal("'te'\\''xt'", shellescape("te'xt"))
    139 
    140  call assert_equal("'te%xt'", shellescape("te%xt"))
    141  call assert_equal("'te\\%xt'", shellescape("te%xt", 1))
    142  call assert_equal("'te#xt'", shellescape("te#xt"))
    143  call assert_equal("'te\\#xt'", shellescape("te#xt", 1))
    144  call assert_equal("'te!xt'", shellescape("te!xt"))
    145  call assert_equal("'te\\!xt'", shellescape("te!xt", 1))
    146 
    147  call assert_equal("'te\\\\xt'", shellescape("te\\xt"))
    148  call assert_equal("'te\\\\xt'", shellescape("te\\xt", 1))
    149  call assert_equal("'te\\\\'\\''xt'", shellescape("te\\'xt"))
    150  call assert_equal("'te\\\\'\\''xt'", shellescape("te\\'xt", 1))
    151  call assert_equal("'te\\\\!xt'", shellescape("te\\!xt"))
    152  call assert_equal("'te\\\\\\!xt'", shellescape("te\\!xt", 1))
    153  call assert_equal("'te\\\\%xt'", shellescape("te\\%xt"))
    154  call assert_equal("'te\\\\\\%xt'", shellescape("te\\%xt", 1))
    155  call assert_equal("'te\\\\#xt'", shellescape("te\\#xt"))
    156  call assert_equal("'te\\\\\\#xt'", shellescape("te\\#xt", 1))
    157 
    158  let &shell = save_shell
    159 endfunc
    160 
    161 " Test for 'shellslash'
    162 func Test_shellslash()
    163  CheckOption shellslash
    164  let save_shellslash = &shellslash
    165  " The shell and cmdflag, and expected slash in tempname with shellslash set or
    166  " unset.  The assert checks the file separator before the leafname.
    167  " ".*\\\\[^\\\\]*$"
    168  let shells = [['cmd', '/c', '/', '/'],
    169        \ ['powershell', '-Command', '/', '/'],
    170        \ ['sh', '-c', '/', '/']]
    171  for e in shells
    172    exe 'set shell=' .. e[0] .. ' | set shellcmdflag=' .. e[1]
    173    set noshellslash
    174    let file = tempname()
    175    call assert_match('^.\+' .. e[2] .. '[^' .. e[2] .. ']\+$', file, e[0] .. ' ' .. e[1] .. ' nossl')
    176    set shellslash
    177    let file = tempname()
    178    call assert_match('^.\+' .. e[3] .. '[^' .. e[3] .. ']\+$', file, e[0] .. ' ' .. e[1] .. ' ssl')
    179  endfor
    180  let &shellslash = save_shellslash
    181 endfunc
    182 
    183 " Test for 'shellxquote'
    184 func Test_shellxquote()
    185  CheckUnix
    186 
    187  let save_shell = &shell
    188  let save_sxq = &shellxquote
    189  let save_sxe = &shellxescape
    190 
    191  call writefile(['#!/bin/sh', 'echo "Cmd: [$*]" > Xlog'], 'Xtestshell', 'D')
    192  call setfperm('Xtestshell', "r-x------")
    193  set shell=./Xtestshell
    194 
    195  set shellxquote=\\"
    196  call feedkeys(":!pwd\<CR>\<CR>", 'xt')
    197  call assert_equal(['Cmd: [-c "pwd"]'], readfile('Xlog'))
    198 
    199  set shellxquote=(
    200  call feedkeys(":!pwd\<CR>\<CR>", 'xt')
    201  call assert_equal(['Cmd: [-c (pwd)]'], readfile('Xlog'))
    202 
    203  set shellxquote=\\"(
    204  call feedkeys(":!pwd\<CR>\<CR>", 'xt')
    205  call assert_equal(['Cmd: [-c "(pwd)"]'], readfile('Xlog'))
    206 
    207  set shellxescape=\"&<<()@^
    208  set shellxquote=(
    209  call feedkeys(":!pwd\"&<<{}@^\<CR>\<CR>", 'xt')
    210  call assert_equal(['Cmd: [-c (pwd^"^&^<^<{}^@^^)]'], readfile('Xlog'))
    211 
    212  let &shell = save_shell
    213  let &shellxquote = save_sxq
    214  let &shellxescape = save_sxe
    215  call delete('Xlog')
    216 endfunc
    217 
    218 " Test for using the shell set in the $SHELL environment variable
    219 func Test_set_shell()
    220  let after =<< trim [CODE]
    221    call writefile([&shell], "Xtestout")
    222    quit!
    223  [CODE]
    224 
    225  if has('win32')
    226    let $SHELL = 'C:\with space\cmd.exe'
    227    let expected = '"C:\with space\cmd.exe"'
    228  else
    229    let $SHELL = '/bin/with space/sh'
    230    let expected = '"/bin/with space/sh"'
    231  endif
    232 
    233  if RunVimPiped([], after, '', '')
    234    let lines = readfile('Xtestout')
    235    call assert_equal(expected, lines[0])
    236  endif
    237  call delete('Xtestout')
    238 endfunc
    239 
    240 func Test_shell_repeat()
    241  CheckUnix
    242 
    243  let save_shell = &shell
    244 
    245  call writefile(['#!/bin/sh', 'echo "Cmd: [$*]" > Xlog'], 'Xtestshell', 'D')
    246  call setfperm('Xtestshell', "r-x------")
    247  set shell=./Xtestshell
    248  defer delete('Xlog')
    249 
    250  call feedkeys(":!echo coconut\<CR>", 'xt')   " Run command
    251  call assert_equal(['Cmd: [-c echo coconut]'], readfile('Xlog'))
    252 
    253  call feedkeys(":!!\<CR>", 'xt')              " Re-run previous
    254  call assert_equal(['Cmd: [-c echo coconut]'], readfile('Xlog'))
    255 
    256  call writefile(['empty'], 'Xlog')
    257  call feedkeys(":!\<CR>", 'xt')               " :!
    258  call assert_equal(['Cmd: [-c ]'], readfile('Xlog'))
    259 
    260  call feedkeys(":!!\<CR>", 'xt')              " :! doesn't clear previous command
    261  call assert_equal(['Cmd: [-c echo coconut]'], readfile('Xlog'))
    262 
    263  call feedkeys(":!echo banana\<CR>", 'xt')    " Make sure setting previous command keeps working after a :! no-op
    264  call assert_equal(['Cmd: [-c echo banana]'], readfile('Xlog'))
    265  call feedkeys(":!!\<CR>", 'xt')
    266  call assert_equal(['Cmd: [-c echo banana]'], readfile('Xlog'))
    267 
    268  let &shell = save_shell
    269 endfunc
    270 
    271 func Test_shell_no_prevcmd()
    272  " this doesn't do anything, just check it doesn't crash
    273  let after =<< trim END
    274    exe "normal !!\<CR>"
    275    call writefile([v:errmsg, 'done'], 'Xtestdone')
    276    qall!
    277  END
    278  if RunVim([], after, '--clean')
    279    call assert_equal(['E34: No previous command', 'done'], readfile('Xtestdone'))
    280  endif
    281  call delete('Xtestdone')
    282 endfunc
    283 
    284 func Test_shell_filter_buffer_with_nul_bytes()
    285  CheckUnix
    286  new
    287  set noshelltemp
    288  " \n is a NUL byte
    289  let lines = ["aaa\nbbb\nccc\nddd\neee", "fff\nggg\nhhh\niii\njjj"]
    290  call setline(1, lines)
    291  %!cat
    292  call assert_equal(lines, getline(1, '$'))
    293 
    294  set shelltemp&
    295  bwipe!
    296 endfunc
    297 
    298 " vim: shiftwidth=2 sts=2 expandtab