# HG changeset patch # User Bram Moolenaar # Date 1634488204 -7200 # Node ID e8873138ffbb585832dbb961cdc3e941acf19cb0 # Parent cbdbf71338a0d790f1c102beff7af275c82566b6 patch 8.2.3530: ":buf {a}" fails while ":edit {a}" works Commit: https://github.com/vim/vim/commit/21c1a0c2f10575dbb72fa873d33f0c1f6e170aa7 Author: Bram Moolenaar Date: Sun Oct 17 17:20:23 2021 +0100 patch 8.2.3530: ":buf \{a}" fails while ":edit \{a}" works Problem: ":buf \{a}" fails while ":edit \{a}" works. Solution: Unescape "\{". (closes https://github.com/vim/vim/issues/8917) diff --git a/src/cmdexpand.c b/src/cmdexpand.c --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -48,6 +48,8 @@ ExpandEscape( { int i; char_u *p; + int vse_what = xp->xp_context == EXPAND_BUFFERS + ? VSE_BUFFER : VSE_NONE; // May change home directory back to "~" if (options & WILD_HOME_REPLACE) @@ -84,9 +86,10 @@ ExpandEscape( } } #ifdef BACKSLASH_IN_FILENAME - p = vim_strsave_fnameescape(files[i], FALSE); + p = vim_strsave_fnameescape(files[i], vse_what); #else - p = vim_strsave_fnameescape(files[i], xp->xp_shell); + p = vim_strsave_fnameescape(files[i], + xp->xp_shell ? VSE_SHELL : vse_what); #endif if (p != NULL) { diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3886,7 +3886,7 @@ f_fnameescape(typval_T *argvars, typval_ return; rettv->vval.v_string = vim_strsave_fnameescape( - tv_get_string(&argvars[0]), FALSE); + tv_get_string(&argvars[0]), VSE_NONE); rettv->v_type = VAR_STRING; } diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -3894,27 +3894,32 @@ ccheck_abbr(int c) } /* - * Escape special characters in "fname" for when used as a file name argument - * after a Vim command, or, when "shell" is non-zero, a shell command. + * Escape special characters in "fname", depending on "what": + * VSE_NONE: for when used as a file name argument after a Vim command. + * VSE_SHELL: for a shell command. + * VSE_BUFFER: for the ":buffer" command. * Returns the result in allocated memory. */ char_u * -vim_strsave_fnameescape(char_u *fname, int shell UNUSED) +vim_strsave_fnameescape(char_u *fname, int what) { char_u *p; #ifdef BACKSLASH_IN_FILENAME char_u buf[20]; int j = 0; - // Don't escape '[', '{' and '!' if they are in 'isfname'. - for (p = PATH_ESC_CHARS; *p != NUL; ++p) + // Don't escape '[', '{' and '!' if they are in 'isfname' and for the + // ":buffer" command. + for (p = what == VSE_BUFFER ? BUFFER_ESC_CHARS : PATH_ESC_CHARS; + *p != NUL; ++p) if ((*p != '[' && *p != '{' && *p != '!') || !vim_isfilec(*p)) buf[j++] = *p; buf[j] = NUL; p = vim_strsave_escaped(fname, buf); #else - p = vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS); - if (shell && csh_like_shell() && p != NULL) + p = vim_strsave_escaped(fname, what == VSE_SHELL ? SHELL_ESC_CHARS + : what == VSE_BUFFER ? BUFFER_ESC_CHARS : PATH_ESC_CHARS); + if (what == VSE_SHELL && csh_like_shell() && p != NULL) { char_u *s; diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -3741,7 +3741,7 @@ nv_ident(cmdarg_T *cap) ptr = vim_strnsave(ptr, n); if (kp_ex) // Escape the argument properly for an Ex command - p = vim_strsave_fnameescape(ptr, FALSE); + p = vim_strsave_fnameescape(ptr, VSE_NONE); else // Escape the argument properly for a shell command p = vim_strsave_shellescape(ptr, TRUE, TRUE); diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro --- a/src/proto/ex_getln.pro +++ b/src/proto/ex_getln.pro @@ -26,7 +26,7 @@ void redrawcmd(void); void compute_cmdrow(void); void cursorcmd(void); void gotocmdline(int clr); -char_u *vim_strsave_fnameescape(char_u *fname, int shell); +char_u *vim_strsave_fnameescape(char_u *fname, int what); void escape_fname(char_u **pp); void tilde_replace(char_u *orig_pat, int num_files, char_u **files); cmdline_info_T *get_cmdline_info(void); diff --git a/src/session.c b/src/session.c --- a/src/session.c +++ b/src/session.c @@ -43,7 +43,7 @@ ses_put_fname(FILE *fd, char_u *name, un } // escape special characters - p = vim_strsave_fnameescape(sname, FALSE); + p = vim_strsave_fnameescape(sname, VSE_NONE); vim_free(sname); if (p == NULL) return FAIL; diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -667,7 +667,7 @@ term_start( if (s == NULL) break; - p = vim_strsave_fnameescape(s, FALSE); + p = vim_strsave_fnameescape(s, VSE_NONE); if (p == NULL) break; ga_concat(&ga, p); diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -900,6 +900,12 @@ func Test_cmdline_complete_various() call feedkeys(":unlet one two\\\"\", 'xt') call assert_equal("\"unlet one two", @:) + " completion for the :buffer command with curlies + edit \{someFile} + call feedkeys(":buf someFile\\\"\", 'xt') + call assert_equal("\"buf {someFile}", @:) + bwipe {someFile} + " completion for the :bdelete command call feedkeys(":bdel a b c\\\"\", 'xt') call assert_equal("\"bdel a b c", @:) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3530, +/**/ 3529, /**/ 3528, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -291,6 +291,7 @@ #endif #ifdef BACKSLASH_IN_FILENAME # define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<") +# define BUFFER_ESC_CHARS ((char_u *)" \t\n*?[`%#'\"|!<") #else # ifdef VMS // VMS allows a lot of characters in the file name @@ -300,6 +301,7 @@ # define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<") # define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&") # endif +# define BUFFER_ESC_CHARS ((char_u *)" \t\n*?[`$\\%#'\"|!<") #endif // length of a buffer to store a number in ASCII (64 bits binary + NUL) @@ -2766,5 +2768,9 @@ long elapsed(DWORD start_tick); #define UC_BUFFER 1 // -buffer: local to current buffer #define UC_VIM9 2 // {} argument: Vim9 syntax. +// flags used by vim_strsave_escaped() +#define VSE_NONE 0 +#define VSE_SHELL 1 // escape for a shell command +#define VSE_BUFFER 2 // escape for a ":buffer" command #endif // VIM__H diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1147,7 +1147,8 @@ do_2string(typval_T *tv, int is_2string_ while ((e = vim_strchr(s, '\n')) != NULL) { *e = NUL; - p = vim_strsave_fnameescape(s, FALSE); + p = vim_strsave_fnameescape(s, + VSE_NONE); if (p != NULL) { ga_concat(&ga, p);