1" Test for the shell related options ('shell', 'shellcmdflag', 'shellpipe', 2" 'shellquote', 'shellredir', 'shellxescape', and 'shellxquote') 3 4source check.vim 5source shared.vim 6 7func Test_shell_options() 8 " The expected value of 'shellcmdflag', 'shellpipe', 'shellquote', 9 " 'shellredir', 'shellxescape', 'shellxquote' for the supported shells. 10 let shells = [] 11 if has('unix') 12 let shells += [['sh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''], 13 \ ['ksh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''], 14 \ ['mksh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''], 15 \ ['zsh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''], 16 \ ['zsh-beta', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''], 17 \ ['bash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''], 18 \ ['fish', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''], 19 \ ['ash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''], 20 \ ['dash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''], 21 \ ['csh', '-c', '|& tee', '', '>&', '', ''], 22 \ ['tcsh', '-c', '|& tee', '', '>&', '', ''], 23 \ ['pwsh', '-c', '>%s 2>&1', '', '>%s 2>&1', '', '']] 24 endif 25 if has('win32') 26 let shells += [['cmd', '/c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', ''], 27 \ ['cmd.exe', '/c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '('], 28 \ ['powershell.exe', '-Command', '2>&1 | Out-File -Encoding default', 29 \ '', '2>&1 | Out-File -Encoding default', '"&|<>()@^', '"'], 30 \ ['powershell', '-Command', '2>&1 | Out-File -Encoding default', '', 31 \ '2>&1 | Out-File -Encoding default', '"&|<>()@^', '"'], 32 \ ['pwsh.exe', '-c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '"'], 33 \ ['pwsh', '-c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '"'], 34 \ ['sh.exe', '-c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '"'], 35 \ ['ksh.exe', '-c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '"'], 36 \ ['mksh.exe', '-c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '"'], 37 \ ['pdksh.exe', '-c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '"'], 38 \ ['zsh.exe', '-c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '"'], 39 \ ['zsh-beta.exe', '-c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '"'], 40 \ ['bash.exe', '-c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '"'], 41 \ ['dash.exe', '-c', '>%s 2>&1', '', '>%s 2>&1', '"&|<>()@^', '"'], 42 \ ['csh.exe', '-c', '>&', '', '>&', '"&|<>()@^', '"'], 43 \ ['tcsh.exe', '-c', '>&', '', '>&', '"&|<>()@^', '"']] 44 endif 45 46 " start a new Vim instance with 'shell' set to each of the supported shells 47 " and check the default shell option settings 48 let after =<< trim END 49 let l = [&shell, &shellcmdflag, &shellpipe, &shellquote] 50 let l += [&shellredir, &shellxescape, &shellxquote] 51 call writefile([json_encode(l)], 'Xtestout') 52 qall! 53 END 54 for e in shells 55 if RunVim([], after, '--cmd "set shell=' .. e[0] .. '"') 56 call assert_equal(e, json_decode(readfile('Xtestout')[0])) 57 endif 58 endfor 59 60 " Test shellescape() for each of the shells. 61 for e in shells 62 exe 'set shell=' .. e[0] 63 if e[0] =~# '.*csh$' || e[0] =~# '.*csh.exe$' 64 let str1 = "'cmd \"arg1\" '\\''arg2'\\'' \\!%#'" 65 let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\\\!\\%\\#'" 66 elseif e[0] =~# '.*powershell$' || e[0] =~# '.*powershell.exe$' 67 \ || e[0] =~# '.*pwsh$' || e[0] =~# '.*pwsh.exe$' 68 let str1 = "'cmd \"arg1\" ''arg2'' !%#'" 69 let str2 = "'cmd \"arg1\" ''arg2'' \\!\\%\\#'" 70 else 71 let str1 = "'cmd \"arg1\" '\\''arg2'\\'' !%#'" 72 let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\!\\%\\#'" 73 endif 74 call assert_equal(str1, shellescape("cmd \"arg1\" 'arg2' !%#"), e[0]) 75 call assert_equal(str2, shellescape("cmd \"arg1\" 'arg2' !%#", 1), e[0]) 76 77 " Try running an external command with the shell. 78 if executable(e[0]) 79 " set the shell options for the current 'shell' 80 let [&shellcmdflag, &shellpipe, &shellquote, &shellredir, 81 \ &shellxescape, &shellxquote] = e[1:6] 82 new 83 try 84 r !echo hello 85 call assert_equal('hello', substitute(getline(2), '\W', '', 'g'), e[0]) 86 catch 87 call assert_report('Failed to run shell command, shell: ' .. e[0]) 88 finally 89 bwipe! 90 endtry 91 endif 92 endfor 93 set shell& shellcmdflag& shellpipe& shellquote& 94 set shellredir& shellxescape& shellxquote& 95 call delete('Xtestout') 96endfunc 97 98" Test for the 'shell' option 99func Test_shell() 100 CheckUnix 101 let save_shell = &shell 102 set shell= 103 let caught_e91 = 0 104 try 105 shell 106 catch /E91:/ 107 let caught_e91 = 1 108 endtry 109 call assert_equal(1, caught_e91) 110 let &shell = save_shell 111endfunc 112 113" Test for the 'shellquote' option 114func Test_shellquote() 115 CheckUnix 116 set shellquote=# 117 set verbose=20 118 redir => v 119 silent! !echo Hello 120 redir END 121 set verbose& 122 set shellquote& 123 call assert_match(': "#echo Hello#"', v) 124endfunc 125 126" Test for the 'shellescape' option 127func Test_shellescape() 128 let save_shell = &shell 129 set shell=bash 130 call assert_equal("'text'", shellescape('text')) 131 call assert_equal("'te\"xt'", 'te"xt'->shellescape()) 132 call assert_equal("'te'\\''xt'", shellescape("te'xt")) 133 134 call assert_equal("'te%xt'", shellescape("te%xt")) 135 call assert_equal("'te\\%xt'", shellescape("te%xt", 1)) 136 call assert_equal("'te#xt'", shellescape("te#xt")) 137 call assert_equal("'te\\#xt'", shellescape("te#xt", 1)) 138 call assert_equal("'te!xt'", shellescape("te!xt")) 139 call assert_equal("'te\\!xt'", shellescape("te!xt", 1)) 140 141 call assert_equal("'te\nxt'", shellescape("te\nxt")) 142 call assert_equal("'te\\\nxt'", shellescape("te\nxt", 1)) 143 set shell=tcsh 144 call assert_equal("'te\\!xt'", shellescape("te!xt")) 145 call assert_equal("'te\\\\!xt'", shellescape("te!xt", 1)) 146 call assert_equal("'te\\\nxt'", shellescape("te\nxt")) 147 call assert_equal("'te\\\\\nxt'", shellescape("te\nxt", 1)) 148 149 let &shell = save_shell 150endfunc 151 152" Test for 'shellslash' 153func Test_shellslash() 154 CheckOption shellslash 155 let save_shellslash = &shellslash 156 " The shell and cmdflag, and expected slash in tempname with shellslash set or 157 " unset. The assert checks the file separator before the leafname. 158 " ".*\\\\[^\\\\]*$" 159 let shells = [['cmd', '/c', '\\', '/'], 160 \ ['powershell', '-Command', '\\', '/'], 161 \ ['pwsh', '-Command', '\\', '/'], 162 \ ['pwsh', '-c', '\\', '/'], 163 \ ['sh', '-c', '/', '/']] 164 for e in shells 165 exe 'set shell=' .. e[0] .. ' | set shellcmdflag=' .. e[1] 166 set noshellslash 167 let file = tempname() 168 call assert_match('^.\+' .. e[2] .. '[^' .. e[2] .. ']\+$', file, e[0] .. ' ' .. e[1] .. ' nossl') 169 set shellslash 170 let file = tempname() 171 call assert_match('^.\+' .. e[3] .. '[^' .. e[3] .. ']\+$', file, e[0] .. ' ' .. e[1] .. ' ssl') 172 endfor 173 let &shellslash = save_shellslash 174endfunc 175 176" Test for 'shellxquote' 177func Test_shellxquote() 178 CheckUnix 179 180 let save_shell = &shell 181 let save_sxq = &shellxquote 182 let save_sxe = &shellxescape 183 184 call writefile(['#!/bin/sh', 'echo "Cmd: [$*]" > Xlog'], 'Xtestshell') 185 call setfperm('Xtestshell', "r-x------") 186 set shell=./Xtestshell 187 188 set shellxquote=\\" 189 call feedkeys(":!pwd\<CR>\<CR>", 'xt') 190 call assert_equal(['Cmd: [-c "pwd"]'], readfile('Xlog')) 191 192 set shellxquote=( 193 call feedkeys(":!pwd\<CR>\<CR>", 'xt') 194 call assert_equal(['Cmd: [-c (pwd)]'], readfile('Xlog')) 195 196 set shellxquote=\\"( 197 call feedkeys(":!pwd\<CR>\<CR>", 'xt') 198 call assert_equal(['Cmd: [-c "(pwd)"]'], readfile('Xlog')) 199 200 set shellxescape=\"&<<()@^ 201 set shellxquote=( 202 call feedkeys(":!pwd\"&<<{}@^\<CR>\<CR>", 'xt') 203 call assert_equal(['Cmd: [-c (pwd^"^&^<^<{}^@^^)]'], readfile('Xlog')) 204 205 let &shell = save_shell 206 let &shellxquote = save_sxq 207 let &shellxescape = save_sxe 208 call delete('Xtestshell') 209 call delete('Xlog') 210endfunc 211 212" Test for using the shell set in the $SHELL environment variable 213func Test_set_shell() 214 let after =<< trim [CODE] 215 call writefile([&shell], "Xtestout") 216 quit! 217 [CODE] 218 219 if has('win32') 220 let $SHELL = 'C:\with space\cmd.exe' 221 let expected = '"C:\with space\cmd.exe"' 222 else 223 let $SHELL = '/bin/with space/sh' 224 let expected = '/bin/with\ space/sh' 225 endif 226 227 if RunVimPiped([], after, '', '') 228 let lines = readfile('Xtestout') 229 call assert_equal(expected, lines[0]) 230 endif 231 call delete('Xtestout') 232endfunc 233 234" vim: shiftwidth=2 sts=2 expandtab 235