From 0a016671b96ae7d27926e9d36dc11945c8f5749d Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Mon, 3 Oct 2022 16:05:28 +0100 Subject: patch 9.0.0648: when using powershell input redirection does not work Problem: When using powershell input redirection does not work. Solution: Use a different shell command for powershell. (Yegappan Lakshmanan, closes #11257) --- src/ex_cmds.c | 126 +++++++++++++++++++++++++++------------------ src/testdir/test_shell.vim | 12 +++++ src/version.c | 2 + 3 files changed, 91 insertions(+), 49 deletions(-) (limited to 'src') 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 @@ -699,6 +699,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 648, /**/ 647, /**/ -- cgit v1.2.1