# HG changeset patch # User Bram Moolenaar # Date 1664810103 -7200 # Node ID 5bc844667d4629a890a0d8ca264dc35089bd34bc # Parent 33ed996584e52ab3afbca8c39442609be0514c24 patch 9.0.0648: when using powershell input redirection does not work Commit: https://github.com/vim/vim/commit/0a016671b96ae7d27926e9d36dc11945c8f5749d Author: Yegappan Lakshmanan Date: Mon Oct 3 16:05:28 2022 +0100 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) diff --git a/src/ex_cmds.c b/src/ex_cmds.c --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -1531,56 +1531,68 @@ make_filter_cmd( { char_u *buf; long_u len; + int is_powershell = FALSE; +#ifdef UNIX + int is_fish_shell; +#endif + + char_u *shell_name = get_isolated_shell_name(); + if (shell_name == NULL) + return NULL; #if defined(UNIX) - int is_fish_shell; - char_u *shell_name = get_isolated_shell_name(); - - if (shell_name == NULL) - return NULL; - // 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) + { + STRCAT(buf, " < "); + STRCAT(buf, itmp); + } + } + else + { + STRCPY(buf, cmd); + if (itmp != NULL) { - 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) + 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 } -#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 --- 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 --- 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,