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 \ .. ', caught ' .. v:exception) 89 finally 90 bwipe! 91 endtry 92 endif 93 endfor 94 set shell& shellcmdflag& shellpipe& shellquote& 95 set shellredir& shellxescape& shellxquote& 96 call delete('Xtestout') 97endfunc 98 99" Test for the 'shell' option 100func Test_shell() 101 CheckUnix 102 let save_shell = &shell 103 set shell= 104 let caught_e91 = 0 105 try 106 shell 107 catch /E91:/ 108 let caught_e91 = 1 109 endtry 110 call assert_equal(1, caught_e91) 111 let &shell = save_shell 112endfunc 113 114" Test for the 'shellquote' option 115func Test_shellquote() 116 CheckUnix 117 set shellquote=# 118 set verbose=20 119 redir => v 120 silent! !echo Hello 121 redir END 122 set verbose& 123 set shellquote& 124 call assert_match(': "#echo Hello#"', v) 125endfunc 126 127" Test for the 'shellescape' option 128func Test_shellescape() 129 let save_shell = &shell 130 set shell=bash 131 call assert_equal("'text'", shellescape('text')) 132 call assert_equal("'te\"xt'", 'te"xt'->shellescape()) 133 call assert_equal("'te'\\''xt'", shellescape("te'xt")) 134 135 call assert_equal("'te%xt'", shellescape("te%xt")) 136 call assert_equal("'te\\%xt'", shellescape("te%xt", 1)) 137 call assert_equal("'te#xt'", shellescape("te#xt")) 138 call assert_equal("'te\\#xt'", shellescape("te#xt", 1)) 139 call assert_equal("'te!xt'", shellescape("te!xt")) 140 call assert_equal("'te\\!xt'", shellescape("te!xt", 1)) 141 142 call assert_equal("'te\nxt'", shellescape("te\nxt")) 143 call assert_equal("'te\\\nxt'", shellescape("te\nxt", 1)) 144 set shell=tcsh 145 call assert_equal("'te\\!xt'", shellescape("te!xt")) 146 call assert_equal("'te\\\\!xt'", shellescape("te!xt", 1)) 147 call assert_equal("'te\\\nxt'", shellescape("te\nxt")) 148 call assert_equal("'te\\\\\nxt'", shellescape("te\nxt", 1)) 149 150 let &shell = save_shell 151endfunc 152 153" Test for 'shellslash' 154func Test_shellslash() 155 CheckOption shellslash 156 let save_shellslash = &shellslash 157 " The shell and cmdflag, and expected slash in tempname with shellslash set or 158 " unset. The assert checks the file separator before the leafname. 159 " ".*\\\\[^\\\\]*$" 160 let shells = [['cmd', '/c', '\\', '/'], 161 \ ['powershell', '-Command', '\\', '/'], 162 \ ['pwsh', '-Command', '\\', '/'], 163 \ ['pwsh', '-c', '\\', '/'], 164 \ ['sh', '-c', '/', '/']] 165 for e in shells 166 exe 'set shell=' .. e[0] .. ' | set shellcmdflag=' .. e[1] 167 set noshellslash 168 let file = tempname() 169 call assert_match('^.\+' .. e[2] .. '[^' .. e[2] .. ']\+$', file, e[0] .. ' ' .. e[1] .. ' nossl') 170 set shellslash 171 let file = tempname() 172 call assert_match('^.\+' .. e[3] .. '[^' .. e[3] .. ']\+$', file, e[0] .. ' ' .. e[1] .. ' ssl') 173 endfor 174 let &shellslash = save_shellslash 175endfunc 176 177" Test for 'shellxquote' 178func Test_shellxquote() 179 CheckUnix 180 181 let save_shell = &shell 182 let save_sxq = &shellxquote 183 let save_sxe = &shellxescape 184 185 call writefile(['#!/bin/sh', 'echo "Cmd: [$*]" > Xlog'], 'Xtestshell') 186 call setfperm('Xtestshell', "r-x------") 187 set shell=./Xtestshell 188 189 set shellxquote=\\" 190 call feedkeys(":!pwd\<CR>\<CR>", 'xt') 191 call assert_equal(['Cmd: [-c "pwd"]'], readfile('Xlog')) 192 193 set shellxquote=( 194 call feedkeys(":!pwd\<CR>\<CR>", 'xt') 195 call assert_equal(['Cmd: [-c (pwd)]'], readfile('Xlog')) 196 197 set shellxquote=\\"( 198 call feedkeys(":!pwd\<CR>\<CR>", 'xt') 199 call assert_equal(['Cmd: [-c "(pwd)"]'], readfile('Xlog')) 200 201 set shellxescape=\"&<<()@^ 202 set shellxquote=( 203 call feedkeys(":!pwd\"&<<{}@^\<CR>\<CR>", 'xt') 204 call assert_equal(['Cmd: [-c (pwd^"^&^<^<{}^@^^)]'], readfile('Xlog')) 205 206 let &shell = save_shell 207 let &shellxquote = save_sxq 208 let &shellxescape = save_sxe 209 call delete('Xtestshell') 210 call delete('Xlog') 211endfunc 212 213" Test for using the shell set in the $SHELL environment variable 214func Test_set_shell() 215 let after =<< trim [CODE] 216 call writefile([&shell], "Xtestout") 217 quit! 218 [CODE] 219 220 if has('win32') 221 let $SHELL = 'C:\with space\cmd.exe' 222 let expected = '"C:\with space\cmd.exe"' 223 else 224 let $SHELL = '/bin/with space/sh' 225 let expected = '/bin/with\ space/sh' 226 endif 227 228 if RunVimPiped([], after, '', '') 229 let lines = readfile('Xtestout') 230 call assert_equal(expected, lines[0]) 231 endif 232 call delete('Xtestout') 233endfunc 234 235" vim: shiftwidth=2 sts=2 expandtab 236