summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2022-10-03 16:05:28 +0100
committerBram Moolenaar <Bram@vim.org>2022-10-03 16:05:28 +0100
commit0a016671b96ae7d27926e9d36dc11945c8f5749d (patch)
tree94ae165a23d4affb1f54e045d1a5201cbc73bb9d
parent13ece2ae1d09009d3fb8acf858c288e7848ecdac (diff)
downloadvim-git-0a016671b96ae7d27926e9d36dc11945c8f5749d.tar.gz
patch 9.0.0648: when using powershell input redirection does not workv9.0.0648
Problem: When using powershell input redirection does not work. Solution: Use a different shell command for powershell. (Yegappan Lakshmanan, closes #11257)
-rw-r--r--src/ex_cmds.c126
-rw-r--r--src/testdir/test_shell.vim12
-rw-r--r--src/version.c2
3 files changed, 91 insertions, 49 deletions
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 265927c4c..a5eae8d16 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -1531,56 +1531,68 @@ make_filter_cmd(
{
char_u *buf;
long_u len;
-
-#if defined(UNIX)
+ int is_powershell = FALSE;
+#ifdef UNIX
int is_fish_shell;
- char_u *shell_name = get_isolated_shell_name();
+#endif
+ char_u *shell_name = get_isolated_shell_name();
if (shell_name == NULL)
return NULL;
+#if defined(UNIX)
// Account for fish's different syntax for subshells
- is_fish_shell = (fnamecmp(shell_name, "fish") == 0);
- vim_free(shell_name);
+ is_fish_shell = fnamecmp(shell_name, "fish") == 0;
if (is_fish_shell)
len = (long_u)STRLEN(cmd) + 13; // "begin; " + "; end" + NUL
else
#endif
- len = (long_u)STRLEN(cmd) + 3; // "()" + NUL
+ {
+ is_powershell = (shell_name[0] == 'p')
+ && (fnamecmp(shell_name, "powershell") == 0
+ || fnamecmp(shell_name, "powershell.exe") == 0
+ || fnamecmp(shell_name, "pwsh") == 0
+ || fnamecmp(shell_name, "pwsh.exe") == 0);
+ len = (long_u)STRLEN(cmd) + 3; // "()" + NUL
+ }
+
if (itmp != NULL)
- len += (long_u)STRLEN(itmp) + 9; // " { < " + " } "
+ {
+ if (is_powershell)
+ // "& { Get-Content " + " | & " + " }"
+ len += (long_u)STRLEN(itmp) + 24;
+ else
+ len += (long_u)STRLEN(itmp) + 9; // " { < " + " } "
+ }
if (otmp != NULL)
len += (long_u)STRLEN(otmp) + (long_u)STRLEN(p_srr) + 2; // " "
+
+ vim_free(shell_name);
+
buf = alloc(len);
if (buf == NULL)
return NULL;
-#if defined(UNIX)
- /*
- * Put braces around the command (for concatenated commands) when
- * redirecting input and/or output.
- */
- if (itmp != NULL || otmp != NULL)
+ if (is_powershell)
{
- if (is_fish_shell)
- vim_snprintf((char *)buf, len, "begin; %s; end", (char *)cmd);
+ if (itmp != NULL)
+ vim_snprintf((char *)buf, len, "& { Get-Content %s | & %s }",
+ itmp, cmd);
else
- vim_snprintf((char *)buf, len, "(%s)", (char *)cmd);
+ vim_snprintf((char *)buf, len, "(%s)", cmd);
}
else
- STRCPY(buf, cmd);
- if (itmp != NULL)
- {
- STRCAT(buf, " < ");
- STRCAT(buf, itmp);
- }
-#else
- // For shells that don't understand braces around commands, at least allow
- // the use of commands in a pipe.
- if (*p_sxe != NUL && *p_sxq == '(')
{
+#if defined(UNIX)
+ // Put braces around the command (for concatenated commands) when
+ // redirecting input and/or output.
if (itmp != NULL || otmp != NULL)
- vim_snprintf((char *)buf, len, "(%s)", (char *)cmd);
+ {
+ if (is_fish_shell)
+ vim_snprintf((char *)buf, len, "begin; %s; end", (char *)cmd);
+ else
+ vim_snprintf((char *)buf, len, "(%s)", (char *)cmd);
+ }
else
STRCPY(buf, cmd);
if (itmp != NULL)
@@ -1588,37 +1600,53 @@ make_filter_cmd(
STRCAT(buf, " < ");
STRCAT(buf, itmp);
}
- }
- else
- {
- STRCPY(buf, cmd);
- if (itmp != NULL)
+#else
+ // For shells that don't understand braces around commands, at least
+ // allow the use of commands in a pipe.
+ if (*p_sxe != NUL && *p_sxq == '(')
{
- char_u *p;
-
- // 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
- // redirection would be inside the quotes.
- if (*p_shq == NUL)
+ if (itmp != NULL || otmp != NULL)
+ vim_snprintf((char *)buf, len, "(%s)", (char *)cmd);
+ else
+ STRCPY(buf, cmd);
+ if (itmp != NULL)
{
- p = find_pipe(buf);
- if (p != NULL)
- *p = NUL;
+ STRCAT(buf, " < ");
+ STRCAT(buf, itmp);
}
- STRCAT(buf, " <"); // " < " causes problems on Amiga
- STRCAT(buf, itmp);
- if (*p_shq == NUL)
+ }
+ else
+ {
+ STRCPY(buf, cmd);
+ if (itmp != NULL)
{
- p = find_pipe(cmd);
- if (p != NULL)
+ char_u *p;
+
+ // 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
+ // redirection would be inside the quotes.
+ if (*p_shq == NUL)
{
- STRCAT(buf, " "); // insert a space before the '|' for DOS
- STRCAT(buf, p);
+ p = find_pipe(buf);
+ if (p != NULL)
+ *p = NUL;
+ }
+ STRCAT(buf, " <"); // " < " causes problems on Amiga
+ STRCAT(buf, itmp);
+ if (*p_shq == NUL)
+ {
+ p = find_pipe(cmd);
+ if (p != NULL)
+ {
+ // insert a space before the '|' for DOS
+ STRCAT(buf, " ");
+ STRCAT(buf, p);
+ }
}
}
}
- }
#endif
+ }
if (otmp != NULL)
append_redir(buf, (int)len, p_srr, otmp);
diff --git a/src/testdir/test_shell.vim b/src/testdir/test_shell.vim
index 1ed4c5ec3..a194f3b68 100644
--- a/src/testdir/test_shell.vim
+++ b/src/testdir/test_shell.vim
@@ -97,6 +97,18 @@ func Test_shell_options()
finally
bwipe!
endtry
+
+ " filter buffer contents through an external command
+ new
+ call setline(1, ['tom', 'sam', 'andy'])
+ try
+ %!sort
+ call assert_equal(['andy', 'sam', 'tom'], getline(1, '$'), e[0])
+ catch
+ call assert_report($'Failed to filter buffer contents, shell: {e[0]}, caught {v:exception}')
+ finally
+ bwipe!
+ endtry
endif
endfor
set shell& shellcmdflag& shellpipe& shellquote&
diff --git a/src/version.c b/src/version.c
index 4c73092be..7a5d4955e 100644
--- a/src/version.c
+++ b/src/version.c
@@ -700,6 +700,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 648,
+/**/
647,
/**/
646,