fix(powershell): filter ":!" commands with args #19268

Problem:
Since 0b9664f524 powershell filtered
:[range]! commands with args causes error:
"Start-Process: A positional parameter cannot be found that accepts argument ..."

Solution:
Pass args to Start-Process via `-ArgumentList`.
closes #19250
This commit is contained in:
Enan Ajmain
2022-07-19 02:26:09 +06:00
committed by GitHub
parent d73c31a41f
commit 3340728c72
2 changed files with 36 additions and 20 deletions

View File

@@ -1583,22 +1583,39 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
if (otmp != NULL) { if (otmp != NULL) {
len += STRLEN(otmp) + STRLEN(p_srr) + 2; // two extra spaces (" "), len += STRLEN(otmp) + STRLEN(p_srr) + 2; // two extra spaces (" "),
} }
const char *const cmd_args = strchr(cmd, ' ');
len += (is_pwsh && cmd_args)
? STRLEN(" -ArgumentList ") + 2 // two extra quotes
: 0;
char *const buf = xmalloc(len); char *const buf = xmalloc(len);
if (is_pwsh) {
xstrlcpy(buf, "Start-Process ", len);
if (cmd_args == NULL) {
xstrlcat(buf, cmd, len);
} else {
xstrlcpy(buf + STRLEN(buf), cmd, (size_t)(cmd_args - cmd + 1));
xstrlcat(buf, " -ArgumentList \"", len);
xstrlcat(buf, cmd_args + 1, len); // +1 to skip the leading space.
xstrlcat(buf, "\"", len);
}
#if defined(UNIX) #if defined(UNIX)
// Put delimiters around the command (for concatenated commands) when // Put delimiters around the command (for concatenated commands) when
// redirecting input and/or output. // redirecting input and/or output.
if (is_pwsh) {
xstrlcpy(buf, "Start-Process ", len);
xstrlcat(buf, cmd, len);
} else if (itmp != NULL || otmp != NULL) { } else if (itmp != NULL || otmp != NULL) {
char *fmt = is_fish_shell ? "begin; %s; end" char *fmt = is_fish_shell ? "begin; %s; end"
: "(%s)"; : "(%s)";
vim_snprintf(buf, len, fmt, cmd); vim_snprintf(buf, len, fmt, cmd);
#endif
// For shells that don't understand braces around commands, at least allow
// the use of commands in a pipe.
} else { } else {
xstrlcpy(buf, cmd, len); xstrlcpy(buf, cmd, len);
} }
#if defined(UNIX)
if (itmp != NULL) { if (itmp != NULL) {
if (is_pwsh) { if (is_pwsh) {
xstrlcat(buf, " -RedirectStandardInput ", len - 1); xstrlcat(buf, " -RedirectStandardInput ", len - 1);
@@ -1608,14 +1625,6 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
xstrlcat(buf, itmp, len - 1); xstrlcat(buf, itmp, len - 1);
} }
#else #else
// For shells that don't understand braces around commands, at least allow
// the use of commands in a pipe.
if (is_pwsh) {
xstrlcpy(buf, "Start-Process ", len);
xstrlcat(buf, cmd, len);
} else {
xstrlcpy(buf, cmd, len);
}
if (itmp != NULL) { if (itmp != NULL) {
// If there is a pipe, we have to put the '<' in front of it. // If there is a pipe, we have to put the '<' in front of it.
// Don't do this when 'shellquote' is not empty, otherwise the // Don't do this when 'shellquote' is not empty, otherwise the

View File

@@ -630,7 +630,7 @@ end)
describe('shell :!', function() describe('shell :!', function()
before_each(clear) before_each(clear)
it(':{range}! with powershell filter/redirect #16271', function() it(':{range}! with powershell filter/redirect #16271 #19250', function()
local screen = Screen.new(500, 8) local screen = Screen.new(500, 8)
screen:attach() screen:attach()
local found = helpers.set_shell_powershell(true) local found = helpers.set_shell_powershell(true)
@@ -639,18 +639,25 @@ describe('shell :!', function()
1 1
4 4
2]]) 2]])
feed(':4verbose %!sort<cr>') if iswin() then
feed(':4verbose %!sort /R<cr>')
screen:expect{ screen:expect{
any=[[Executing command: .?Start%-Process sort %-RedirectStandardInput .* %-RedirectStandardOutput .* %-NoNewWindow %-Wait]] any=[[Executing command: .?Start%-Process sort %-ArgumentList "/R" %-RedirectStandardInput .* %-RedirectStandardOutput .* %-NoNewWindow %-Wait]]
} }
else
feed(':4verbose %!sort -r<cr>')
screen:expect{
any=[[Executing command: .?Start%-Process sort %-ArgumentList "%-r" %-RedirectStandardInput .* %-RedirectStandardOutput .* %-NoNewWindow %-Wait]]
}
end
feed('<CR>') feed('<CR>')
if found then if found then
-- Not using fake powershell, so we can test the result. -- Not using fake powershell, so we can test the result.
expect([[ expect([[
1 4
2
3 3
4]]) 2
1]])
end end
end) end)
end) end)