win: defaults: 'shellcmdflag', 'shellxquote' #7343
closes #7698 Wrapping a command in double-quotes allows cmd.exe to safely dequote the entire command as if the user entered the entire command in an interactive prompt. This reduces the need to escape nested and uneven double quotes. The `/s` flag of cmd.exe makes the behaviour more reliable: :set shellcmdflag=/s\ /c Before this patch, cmd.exe cannot use cygwin echo.exe (as opposed to cmd.exe `echo` builtin) even if it is wrapped in double quotes. Example: :: internal echo > cmd /s /c " echo foo\:bar" " foo\:bar" :: cygwin echo.exe > cmd /s /c " "echo" foo\:bar" " foo:bar
This commit is contained in:
parent
be67d926c5
commit
131aad953c
|
@ -5160,10 +5160,10 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
security reasons.
|
||||
|
||||
*'shellcmdflag'* *'shcf'*
|
||||
'shellcmdflag' 'shcf' string (default: "-c"; Windows: "/c")
|
||||
'shellcmdflag' 'shcf' string (default: "-c"; Windows: "/s /c")
|
||||
global
|
||||
Flag passed to the shell to execute "!" and ":!" commands; e.g.,
|
||||
"bash.exe -c ls" or "cmd.exe /c dir". For Windows
|
||||
`bash.exe -c ls` or `cmd.exe /s /c "dir"`. For Windows
|
||||
systems, the default is set according to the value of 'shell', to
|
||||
reduce the need to set this option by the user.
|
||||
On Unix it can have more than one flag. Each white space separated
|
||||
|
@ -5284,7 +5284,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
to execute most external commands with cmd.exe.
|
||||
|
||||
*'shellxquote'* *'sxq'*
|
||||
'shellxquote' 'sxq' string (default: "")
|
||||
'shellxquote' 'sxq' string (default: "", Windows: "\"")
|
||||
global
|
||||
Quoting character(s), put around the command passed to the shell, for
|
||||
the "!" and ":!" commands. Includes the redirection. See
|
||||
|
|
|
@ -2048,7 +2048,7 @@ return {
|
|||
varname='p_shcf',
|
||||
defaults={
|
||||
condition='WIN32',
|
||||
if_true={vi="/c"},
|
||||
if_true={vi="/s /c"},
|
||||
if_false={vi="-c"}
|
||||
}
|
||||
},
|
||||
|
@ -2104,7 +2104,11 @@ return {
|
|||
secure=true,
|
||||
vi_def=true,
|
||||
varname='p_sxq',
|
||||
defaults={if_true={vi=""}}
|
||||
defaults={
|
||||
condition='WIN32',
|
||||
if_true={vi="\""},
|
||||
if_false={vi=""},
|
||||
}
|
||||
},
|
||||
{
|
||||
full_name='shellxescape', abbreviation='sxe',
|
||||
|
|
|
@ -120,33 +120,47 @@ describe('system()', function()
|
|||
end
|
||||
end)
|
||||
|
||||
describe('executes shell function if passed a string', function()
|
||||
describe('executes shell function', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = Screen.new()
|
||||
screen:attach()
|
||||
clear()
|
||||
screen = Screen.new()
|
||||
screen:attach()
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
screen:detach()
|
||||
screen:detach()
|
||||
end)
|
||||
|
||||
if iswin() then
|
||||
local function test_more()
|
||||
eq('root = true', eval([[get(split(system('"more" ".editorconfig"'), "\n"), 0, '')]]))
|
||||
end
|
||||
local function test_shell_unquoting()
|
||||
eval([[system('"ping" "-n" "1" "127.0.0.1"')]])
|
||||
eq(0, eval('v:shell_error'))
|
||||
eq('"a b"\n', eval([[system('cmd /s/c "cmd /s/c "cmd /s/c "echo "a b""""')]]))
|
||||
eq('"a b"\n', eval([[system('powershell -NoProfile -NoLogo -ExecutionPolicy RemoteSigned -Command echo ''\^"a b\^"''')]]))
|
||||
end
|
||||
|
||||
it('with shell=cmd.exe', function()
|
||||
command('set shell=cmd.exe')
|
||||
eq('""\n', eval([[system('echo ""')]]))
|
||||
eq('"a b"\n', eval([[system('echo "a b"')]]))
|
||||
eq('a \nb\n', eval([[system('echo a & echo b')]]))
|
||||
eq('a \n', eval([[system('echo a 2>&1')]]))
|
||||
test_more()
|
||||
eval([[system('cd "C:\Program Files"')]])
|
||||
eq(0, eval('v:shell_error'))
|
||||
test_shell_unquoting()
|
||||
end)
|
||||
|
||||
it('with shell=cmd', function()
|
||||
command('set shell=cmd')
|
||||
eq('"a b"\n', eval([[system('echo "a b"')]]))
|
||||
test_more()
|
||||
test_shell_unquoting()
|
||||
end)
|
||||
|
||||
it('with shell=$COMSPEC', function()
|
||||
|
@ -154,6 +168,8 @@ describe('system()', function()
|
|||
if comspecshell == 'cmd.exe' then
|
||||
command('set shell=$COMSPEC')
|
||||
eq('"a b"\n', eval([[system('echo "a b"')]]))
|
||||
test_more()
|
||||
test_shell_unquoting()
|
||||
else
|
||||
pending('$COMSPEC is not cmd.exe: ' .. comspecshell)
|
||||
end
|
||||
|
@ -187,7 +203,7 @@ describe('system()', function()
|
|||
]])
|
||||
end)
|
||||
|
||||
it('`yes` and is interrupted with CTRL-C', function()
|
||||
it('`yes` interrupted with CTRL-C', function()
|
||||
feed(':call system("' .. (iswin()
|
||||
and 'for /L %I in (1,0,2) do @echo y'
|
||||
or 'yes') .. '")<cr>')
|
||||
|
@ -239,6 +255,8 @@ describe('system()', function()
|
|||
end
|
||||
end)
|
||||
it('to backgrounded command does not crash', function()
|
||||
-- cmd.exe doesn't background a command with &
|
||||
if iswin() then return end
|
||||
-- This is indeterminate, just exercise the codepath. May get E5677.
|
||||
feed_command('call system("echo -n echoed &")')
|
||||
local v_errnum = string.match(eval("v:errmsg"), "^E%d*:")
|
||||
|
@ -254,6 +272,8 @@ describe('system()', function()
|
|||
eq("input", eval('system("cat -", "input")'))
|
||||
end)
|
||||
it('to backgrounded command does not crash', function()
|
||||
-- cmd.exe doesn't background a command with &
|
||||
if iswin() then return end
|
||||
-- This is indeterminate, just exercise the codepath. May get E5677.
|
||||
feed_command('call system("cat - &", "input")')
|
||||
local v_errnum = string.match(eval("v:errmsg"), "^E%d*:")
|
||||
|
@ -299,7 +319,7 @@ describe('system()', function()
|
|||
after_each(delete_file(fname))
|
||||
|
||||
it('replaces NULs by SOH characters', function()
|
||||
eq('part1\001part2\001part3\n', eval('system("cat '..fname..'")'))
|
||||
eq('part1\001part2\001part3\n', eval([[system('"cat" "]]..fname..[["')]]))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
@ -366,7 +386,7 @@ describe('systemlist()', function()
|
|||
end
|
||||
end)
|
||||
|
||||
describe('exectues shell function', function()
|
||||
describe('executes shell function', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
|
@ -399,7 +419,7 @@ describe('systemlist()', function()
|
|||
]])
|
||||
end)
|
||||
|
||||
it('`yes` and is interrupted with CTRL-C', function()
|
||||
it('`yes` interrupted with CTRL-C', function()
|
||||
feed(':call systemlist("yes | xargs")<cr>')
|
||||
screen:expect([[
|
||||
|
|
||||
|
@ -464,7 +484,7 @@ describe('systemlist()', function()
|
|||
after_each(delete_file(fname))
|
||||
|
||||
it('replaces NULs by newline characters', function()
|
||||
eq({'part1\npart2\npart3'}, eval('systemlist("cat '..fname..'")'))
|
||||
eq({'part1\npart2\npart3'}, eval([[systemlist('"cat" "]]..fname..[["')]]))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ describe(':edit term://*', function()
|
|||
local scr = get_screen(columns, lines)
|
||||
local rep = 'a'
|
||||
meths.set_option('shellcmdflag', 'REP ' .. rep)
|
||||
command('set shellxquote=') -- win: avoid extra quotes
|
||||
local rep_size = rep:byte() -- 'a' => 97
|
||||
local sb = 10
|
||||
command('autocmd TermOpen * :setlocal scrollback='..tostring(sb)
|
||||
|
|
|
@ -8,6 +8,7 @@ local funcs = helpers.funcs
|
|||
local retry = helpers.retry
|
||||
local ok = helpers.ok
|
||||
local iswin = helpers.iswin
|
||||
local command = helpers.command
|
||||
|
||||
describe(':terminal', function()
|
||||
local screen
|
||||
|
@ -143,6 +144,7 @@ describe(':terminal (with fake shell)', function()
|
|||
end)
|
||||
|
||||
it('executes a given command through the shell', function()
|
||||
command('set shellxquote=') -- win: avoid extra quotes
|
||||
terminal_with_fake_shell('echo hi')
|
||||
screen:expect([[
|
||||
^ready $ echo hi |
|
||||
|
@ -154,6 +156,7 @@ describe(':terminal (with fake shell)', function()
|
|||
|
||||
it("executes a given command through the shell, when 'shell' has arguments", function()
|
||||
nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff')
|
||||
command('set shellxquote=') -- win: avoid extra quotes
|
||||
terminal_with_fake_shell('echo hi')
|
||||
screen:expect([[
|
||||
^jeff $ echo hi |
|
||||
|
@ -164,6 +167,7 @@ describe(':terminal (with fake shell)', function()
|
|||
end)
|
||||
|
||||
it('allows quotes and slashes', function()
|
||||
command('set shellxquote=') -- win: avoid extra quotes
|
||||
terminal_with_fake_shell([[echo 'hello' \ "world"]])
|
||||
screen:expect([[
|
||||
^ready $ echo 'hello' \ "world" |
|
||||
|
@ -217,6 +221,7 @@ describe(':terminal (with fake shell)', function()
|
|||
end)
|
||||
|
||||
it('works with gf', function()
|
||||
command('set shellxquote=') -- win: avoid extra quotes
|
||||
terminal_with_fake_shell([[echo "scripts/shadacat.py"]])
|
||||
screen:expect([[
|
||||
^ready $ echo "scripts/shadacat.py" |
|
||||
|
|
Loading…
Reference in New Issue