diff options
-rw-r--r-- | runtime/doc/eval.txt | 4 | ||||
-rw-r--r-- | src/strings.c | 21 | ||||
-rw-r--r-- | src/testdir/test_shell.vim | 19 | ||||
-rw-r--r-- | src/version.c | 2 |
4 files changed, 38 insertions, 8 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index db74f9c10..93ff4169f 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -10111,6 +10111,10 @@ shellescape({string} [, {special}]) *shellescape()* 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 diff --git a/src/strings.c b/src/strings.c index ef0282a69..566f4dab4 100644 --- a/src/strings.c +++ b/src/strings.c @@ -125,6 +125,15 @@ csh_like_shell(void) } /* + * 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,6 +154,7 @@ vim_strsave_shellescape(char_u *string, int do_special, int do_newline) char_u *escaped_string; int l; int csh_like; + int fish_like; char_u *shname; int powershell; # ifdef MSWIN @@ -157,6 +167,10 @@ vim_strsave_shellescape(char_u *string, int do_special, int do_newline) // 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,6 +211,8 @@ vim_strsave_shellescape(char_u *string, int do_special, int do_newline) ++length; // insert backslash p += l - 1; } + if (*p == '\\' && fish_like) + ++length; // insert backslash } // Allocate memory for the result and fill it. @@ -261,6 +277,11 @@ vim_strsave_shellescape(char_u *string, int do_special, int do_newline) *d++ = *p++; continue; } + if (*p == '\\' && fish_like) + { + *d++ = '\\'; + *d++ = *p++; + } MB_COPY_CHAR(p, d); } diff --git a/src/testdir/test_shell.vim b/src/testdir/test_shell.vim index bdc663177..fa11f08d7 100644 --- a/src/testdir/test_shell.vim +++ b/src/testdir/test_shell.vim @@ -61,18 +61,21 @@ func Test_shell_options() 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'\\'' \\\\!\\%\\#'" + 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'' \\!\\%\\#'" + 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'\\'' \\!\\%\\#'" + 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]) + 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]) diff --git a/src/version.c b/src/version.c index d50d09829..5f427a877 100644 --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3385, +/**/ 3384, /**/ 3383, |