aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/eval/funcs.c2
-rw-r--r--src/nvim/ex_getln.c33
-rw-r--r--src/nvim/ex_getln.h5
-rw-r--r--src/nvim/ex_session.c2
-rw-r--r--src/nvim/normal.c2
-rw-r--r--src/nvim/testdir/test_cmdline.vim6
6 files changed, 35 insertions, 15 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 2775fd4778..6466e06010 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -2467,7 +2467,7 @@ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "fnameescape({string})" function
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;
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 32977569c3..a5783f4ced 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -4334,6 +4334,7 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
{
int i;
char_u *p;
+ const int vse_what = xp->xp_context == EXPAND_BUFFERS ? VSE_BUFFER : VSE_NONE;
/*
* 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
}
#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
p = (char_u *)vim_strsave_fnameescape((const char *)files[i],
- xp->xp_shell);
+ xp->xp_shell ? VSE_SHELL : vse_what);
#endif
xfree(files[i]);
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] shell What to escape for: if false, escapes for VimL command,
-/// if true then it escapes for a shell command.
+/// @param[in] what What to escape for:
+/// - 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.
-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
{
#ifdef BACKSLASH_IN_FILENAME
# define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<"
+# define BUFFER_ESC_CHARS ((char_u *)" \t\n*?[`%#'\"|!<")
char_u buf[sizeof(PATH_ESC_CHARS)];
int j = 0;
- // Don't escape '[', '{' and '!' if they are in 'isfname'.
- for (const char *s = PATH_ESC_CHARS; *s != NUL; s++) {
- if ((*s != '[' && *s != '{' && *s != '!') || !vim_isfilec(*s)) {
- buf[j++] = *s;
+ // Don't escape '[', '{' and '!' if they are in 'isfname' and for the
+ // ":buffer" command.
+ for (const char *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;
@@ -4427,9 +4433,12 @@ char *vim_strsave_fnameescape(const char *const fname, const bool shell FUNC_ATT
#else
# define PATH_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 *)vim_strsave_escaped((const char_u *)fname, (shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS));
- if (shell && csh_like_shell()) {
+ (char *)vim_strsave_escaped((const char_u *)fname,
+ 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 '!'.
// One is taken by Vim, one by the shell.
char *s = (char *)vim_strsave_escaped((const char_u *)p,
diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h
index 5da9febe71..1cc6faf87c 100644
--- a/src/nvim/ex_getln.h
+++ b/src/nvim/ex_getln.h
@@ -34,6 +34,11 @@
#define WILD_BUFLASTUSED 0x1000
#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
typedef enum {
HIST_DEFAULT = -2, ///< Default (current) history.
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index d18ef3a188..a7f4080b22 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -285,7 +285,7 @@ static char *ses_escape_fname(char *name, unsigned *flagp)
}
// Escape special characters.
- p = vim_strsave_fnameescape(sname, false);
+ p = vim_strsave_fnameescape(sname, VSE_NONE);
xfree(sname);
return p;
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 9696130070..0eb8a8f59b 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -4321,7 +4321,7 @@ static void nv_ident(cmdarg_T *cap)
ptr = vim_strnsave(ptr, n);
if (kp_ex) {
// 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 {
// Escape the argument properly for a shell command
p = vim_strsave_shellescape(ptr, true, true);
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 93b5e4d1cf..e42510c17f 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -900,6 +900,12 @@ func Test_cmdline_complete_various()
call feedkeys(":unlet one two\<C-A>\<C-B>\"\<CR>", 'xt')
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
call feedkeys(":bdel a b c\<C-A>\<C-B>\"\<CR>", 'xt')
call assert_equal("\"bdel a b c", @:)