]> granicus.if.org Git - vim/commitdiff
patch 9.0.0648: when using powershell input redirection does not work v9.0.0648
authorYegappan Lakshmanan <yegappan@yahoo.com>
Mon, 3 Oct 2022 15:05:28 +0000 (16:05 +0100)
committerBram Moolenaar <Bram@vim.org>
Mon, 3 Oct 2022 15:05:28 +0000 (16:05 +0100)
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
src/testdir/test_shell.vim
src/version.c

index 265927c4cde75e7670aa0c6425bf580cebc314a3..a5eae8d166ef1af2241c95fb82003c1a9d3d63ac 100644 (file)
@@ -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);
 
index 1ed4c5ec3e67079527fda0c362b3a2bc36745076..a194f3b68c89df743403d09c897ecf2028fc93a8 100644 (file)
@@ -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&
index 4c73092bef2a0be1ee780fd3b9f71123f1ca07ce..7a5d4955efe159417968513cd7828b6c5ac3e7e8 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    648,
 /**/
     647,
 /**/