Patch 8.2.3385
Problem: Escaping for fish shell does not work properly.
Solution: Insert a backslash before a backslash. (Jason Cox, closes #8810)
Files: runtime/doc/eval.txt, src/strings.c, src/testdir/test_shell.vim
*** ../vim-8.2.3384/runtime/doc/eval.txt 2021-08-16 21:38:38.127122597 +0200
--- runtime/doc/eval.txt 2021-08-29 12:29:23.666462297 +0200
***************
*** 10016,10021 ****
--- 10111,10120 ----
escaped. When 'shell' containing "csh" in the tail it's
escaped a second time.
+ The "\" character will be escaped when 'shell' contains "fish"
+ in the tail. That is because for fish "\" is used as an escape
+ character inside single quotes.
+
Example of use with a |:!| command: >
:exe '!dir ' . shellescape(expand('<cfile>'), 1)
< This results in a directory listing for the file under the
*** ../vim-8.2.3384/src/strings.c 2021-08-09 19:59:01.446811234 +0200
--- src/strings.c 2021-08-29 12:33:09.886138250 +0200
***************
*** 125,130 ****
--- 125,139 ----
}
/*
+ * Return TRUE when 'shell' has "fish" in the tail.
+ */
+ int
+ fish_like_shell(void)
+ {
+ return (strstr((char *)gettail(p_sh), "fish") != NULL);
+ }
+
+ /*
* Escape "string" for use as a shell argument with system().
* This uses single quotes, except when we know we need to use double quotes
* (MS-DOS and MS-Windows not using PowerShell and without 'shellslash' set).
***************
*** 145,150 ****
--- 154,160 ----
char_u *escaped_string;
int l;
int csh_like;
+ int fish_like;
char_u *shname;
int powershell;
# ifdef MSWIN
***************
*** 157,162 ****
--- 167,176 ----
// Csh also needs to have "\n" escaped twice when do_special is set.
csh_like = csh_like_shell();
+ // Fish shell uses '\' as an escape character within single quotes, so '\'
+ // itself must be escaped to get a literal '\'.
+ fish_like = fish_like_shell();
+
// PowerShell uses it's own version for quoting single quotes
shname = gettail(p_sh);
powershell = strstr((char *)shname, "pwsh") != NULL;
***************
*** 197,202 ****
--- 211,218 ----
++length; // insert backslash
p += l - 1;
}
+ if (*p == '\\' && fish_like)
+ ++length; // insert backslash
}
// Allocate memory for the result and fill it.
***************
*** 261,266 ****
--- 277,287 ----
*d++ = *p++;
continue;
}
+ if (*p == '\\' && fish_like)
+ {
+ *d++ = '\\';
+ *d++ = *p++;
+ }
MB_COPY_CHAR(p, d);
}
*** ../vim-8.2.3384/src/testdir/test_shell.vim 2021-08-06 21:34:34.626972208 +0200
--- src/testdir/test_shell.vim 2021-08-29 12:29:23.666462297 +0200
***************
*** 61,78 ****
for e in shells
exe 'set shell=' .. e[0]
if e[0] =~# '.*csh$' || e[0] =~# '.*csh.exe$'
! let str1 = "'cmd \"arg1\" '\\''arg2'\\'' \\!%#'"
! let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\\\!\\%\\#'"
elseif e[0] =~# '.*powershell$' || e[0] =~# '.*powershell.exe$'
\ || e[0] =~# '.*pwsh$' || e[0] =~# '.*pwsh.exe$'
! let str1 = "'cmd \"arg1\" ''arg2'' !%#'"
! let str2 = "'cmd \"arg1\" ''arg2'' \\!\\%\\#'"
else
! let str1 = "'cmd \"arg1\" '\\''arg2'\\'' !%#'"
! let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\!\\%\\#'"
endif
! call assert_equal(str1, shellescape("cmd \"arg1\" 'arg2' !%#"), e[0])
! call assert_equal(str2, shellescape("cmd \"arg1\" 'arg2' !%#", 1), e[0])
" Try running an external command with the shell.
if executable(e[0])
--- 61,81 ----
for e in shells
exe 'set shell=' .. e[0]
if e[0] =~# '.*csh$' || e[0] =~# '.*csh.exe$'
! let str1 = "'cmd \"arg1\" '\\''arg2'\\'' \\!%# \\'"
! let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\\\!\\%\\# \\'"
elseif e[0] =~# '.*powershell$' || e[0] =~# '.*powershell.exe$'
\ || e[0] =~# '.*pwsh$' || e[0] =~# '.*pwsh.exe$'
! let str1 = "'cmd \"arg1\" ''arg2'' !%# \\'"
! let str2 = "'cmd \"arg1\" ''arg2'' \\!\\%\\# \\'"
! elseif e[0] =~# '.*fish$' || e[0] =~# '.*fish.exe$'
! let str1 = "'cmd \"arg1\" '\\''arg2'\\'' !%# \\\\'"
! let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\!\\%\\# \\\\'"
else
! let str1 = "'cmd \"arg1\" '\\''arg2'\\'' !%# \\'"
! let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\!\\%\\# \\'"
endif
! call assert_equal(str1, shellescape("cmd \"arg1\" 'arg2' !%# \\"), e[0])
! call assert_equal(str2, shellescape("cmd \"arg1\" 'arg2' !%# \\", 1), e[0])
" Try running an external command with the shell.
if executable(e[0])
*** ../vim-8.2.3384/src/version.c 2021-08-28 20:42:43.636422753 +0200
--- src/version.c 2021-08-29 12:36:20.149901341 +0200
***************
*** 757,758 ****
--- 757,760 ----
{ /* Add new patch number below this line */
+ /**/
+ 3385,
/**/
--
Hanson's Treatment of Time:
There are never enough hours in a day, but always too
many days before Saturday.
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///