mirror of
https://github.com/neovim/neovim.git
synced 2025-09-17 08:48:16 +00:00
vim-patch:8.2.3530: ":buf \{a}" fails while ":edit \{a}" works
Problem: ":buf \{a}" fails while ":edit \{a}" works.
Solution: Unescape "\{". (closes vim/vim#8917)
21c1a0c2f1
This commit is contained in:
@@ -2467,7 +2467,7 @@ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
/// "fnameescape({string})" function
|
/// "fnameescape({string})" function
|
||||||
static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
rettv->vval.v_string = vim_strsave_fnameescape(tv_get_string(&argvars[0]), false);
|
rettv->vval.v_string = vim_strsave_fnameescape(tv_get_string(&argvars[0]), VSE_NONE);
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4334,6 +4334,7 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
|
const int vse_what = xp->xp_context == EXPAND_BUFFERS ? VSE_BUFFER : VSE_NONE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* May change home directory back to "~"
|
* May change home directory back to "~"
|
||||||
@@ -4365,10 +4366,10 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef BACKSLASH_IN_FILENAME
|
#ifdef BACKSLASH_IN_FILENAME
|
||||||
p = (char_u *)vim_strsave_fnameescape((const char *)files[i], false);
|
p = (char_u *)vim_strsave_fnameescape((const char *)files[i], vse_what);
|
||||||
#else
|
#else
|
||||||
p = (char_u *)vim_strsave_fnameescape((const char *)files[i],
|
p = (char_u *)vim_strsave_fnameescape((const char *)files[i],
|
||||||
xp->xp_shell);
|
xp->xp_shell ? VSE_SHELL : vse_what);
|
||||||
#endif
|
#endif
|
||||||
xfree(files[i]);
|
xfree(files[i]);
|
||||||
files[i] = p;
|
files[i] = p;
|
||||||
@@ -4400,25 +4401,30 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Escape special characters in a file name for use as a command argument
|
/// Escape special characters in "fname", depending on "what":
|
||||||
///
|
///
|
||||||
/// @param[in] fname File name to escape.
|
/// @param[in] fname File name to escape.
|
||||||
/// @param[in] shell What to escape for: if false, escapes for VimL command,
|
/// @param[in] what What to escape for:
|
||||||
/// if true then it escapes for a shell command.
|
/// - 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.
|
||||||
///
|
///
|
||||||
/// @return [allocated] escaped file name.
|
/// @return [allocated] escaped file name.
|
||||||
char *vim_strsave_fnameescape(const char *const fname, const bool shell FUNC_ATTR_UNUSED)
|
char *vim_strsave_fnameescape(const char *const fname, const int what)
|
||||||
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
#ifdef BACKSLASH_IN_FILENAME
|
#ifdef BACKSLASH_IN_FILENAME
|
||||||
# define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<"
|
# define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<"
|
||||||
|
# define BUFFER_ESC_CHARS ((char_u *)" \t\n*?[`%#'\"|!<")
|
||||||
char_u buf[sizeof(PATH_ESC_CHARS)];
|
char_u buf[sizeof(PATH_ESC_CHARS)];
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
||||||
// Don't escape '[', '{' and '!' if they are in 'isfname'.
|
// Don't escape '[', '{' and '!' if they are in 'isfname' and for the
|
||||||
for (const char *s = PATH_ESC_CHARS; *s != NUL; s++) {
|
// ":buffer" command.
|
||||||
if ((*s != '[' && *s != '{' && *s != '!') || !vim_isfilec(*s)) {
|
for (const char *p = what == VSE_BUFFER ? BUFFER_ESC_CHARS : PATH_ESC_CHARS;
|
||||||
buf[j++] = *s;
|
*p != NUL; p++) {
|
||||||
|
if ((*p != '[' && *p != '{' && *p != '!') || !vim_isfilec(*p)) {
|
||||||
|
buf[j++] = *p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf[j] = NUL;
|
buf[j] = NUL;
|
||||||
@@ -4427,9 +4433,12 @@ char *vim_strsave_fnameescape(const char *const fname, const bool shell FUNC_ATT
|
|||||||
#else
|
#else
|
||||||
# define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<")
|
# define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<")
|
||||||
# define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&")
|
# define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&")
|
||||||
|
# define BUFFER_ESC_CHARS ((char_u *)" \t\n*?[`$\\%#'\"|!<")
|
||||||
char *p =
|
char *p =
|
||||||
(char *)vim_strsave_escaped((const char_u *)fname, (shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS));
|
(char *)vim_strsave_escaped((const char_u *)fname,
|
||||||
if (shell && csh_like_shell()) {
|
what == VSE_SHELL ? SHELL_ESC_CHARS
|
||||||
|
: what == VSE_BUFFER ? BUFFER_ESC_CHARS : PATH_ESC_CHARS);
|
||||||
|
if (what == VSE_SHELL && csh_like_shell()) {
|
||||||
// For csh and similar shells need to put two backslashes before '!'.
|
// For csh and similar shells need to put two backslashes before '!'.
|
||||||
// One is taken by Vim, one by the shell.
|
// One is taken by Vim, one by the shell.
|
||||||
char *s = (char *)vim_strsave_escaped((const char_u *)p,
|
char *s = (char *)vim_strsave_escaped((const char_u *)p,
|
||||||
|
@@ -34,6 +34,11 @@
|
|||||||
#define WILD_BUFLASTUSED 0x1000
|
#define WILD_BUFLASTUSED 0x1000
|
||||||
#define BUF_DIFF_FILTER 0x2000
|
#define BUF_DIFF_FILTER 0x2000
|
||||||
|
|
||||||
|
// flags used by vim_strsave_fnameescape()
|
||||||
|
#define VSE_NONE 0
|
||||||
|
#define VSE_SHELL 1 ///< escape for a shell command
|
||||||
|
#define VSE_BUFFER 2 ///< escape for a ":buffer" command
|
||||||
|
|
||||||
/// Present history tables
|
/// Present history tables
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HIST_DEFAULT = -2, ///< Default (current) history.
|
HIST_DEFAULT = -2, ///< Default (current) history.
|
||||||
|
@@ -285,7 +285,7 @@ static char *ses_escape_fname(char *name, unsigned *flagp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Escape special characters.
|
// Escape special characters.
|
||||||
p = vim_strsave_fnameescape(sname, false);
|
p = vim_strsave_fnameescape(sname, VSE_NONE);
|
||||||
xfree(sname);
|
xfree(sname);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@@ -4321,7 +4321,7 @@ static void nv_ident(cmdarg_T *cap)
|
|||||||
ptr = vim_strnsave(ptr, n);
|
ptr = vim_strnsave(ptr, n);
|
||||||
if (kp_ex) {
|
if (kp_ex) {
|
||||||
// Escape the argument properly for an Ex command
|
// Escape the argument properly for an Ex command
|
||||||
p = (char_u *)vim_strsave_fnameescape((const char *)ptr, false);
|
p = (char_u *)vim_strsave_fnameescape((const char *)ptr, VSE_NONE);
|
||||||
} else {
|
} else {
|
||||||
// Escape the argument properly for a shell command
|
// Escape the argument properly for a shell command
|
||||||
p = vim_strsave_shellescape(ptr, true, true);
|
p = vim_strsave_shellescape(ptr, true, true);
|
||||||
|
@@ -900,6 +900,12 @@ func Test_cmdline_complete_various()
|
|||||||
call feedkeys(":unlet one two\<C-A>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":unlet one two\<C-A>\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal("\"unlet one two", @:)
|
call assert_equal("\"unlet one two", @:)
|
||||||
|
|
||||||
|
" completion for the :buffer command with curlies
|
||||||
|
edit \{someFile}
|
||||||
|
call feedkeys(":buf someFile\<C-A>\<C-B>\"\<CR>", 'xt')
|
||||||
|
call assert_equal("\"buf {someFile}", @:)
|
||||||
|
bwipe {someFile}
|
||||||
|
|
||||||
" completion for the :bdelete command
|
" completion for the :bdelete command
|
||||||
call feedkeys(":bdel a b c\<C-A>\<C-B>\"\<CR>", 'xt')
|
call feedkeys(":bdel a b c\<C-A>\<C-B>\"\<CR>", 'xt')
|
||||||
call assert_equal("\"bdel a b c", @:)
|
call assert_equal("\"bdel a b c", @:)
|
||||||
|
Reference in New Issue
Block a user