diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 4590b86f18..7a3cf52a1a 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4192,7 +4192,10 @@ char *vim_strsave_fnameescape(const char *const fname, const int what) { #ifdef BACKSLASH_IN_FILENAME # define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<" -# define BUFFER_ESC_CHARS (" \t\n*?[`%#'\"|!<") +// '%' and '#' are not escaped for ":buffer": it has no EX_XFILE, so they are +// not expanded, and escaping them as "\%"/"\#" breaks buffer name matching +// when '%'/'#' is in 'isfname' (backslash treated as a path separator). +# define BUFFER_ESC_CHARS (" \t\n*?[`'\"|!<") char buf[sizeof(PATH_ESC_CHARS)]; int j = 0; diff --git a/test/old/testdir/test_buffer.vim b/test/old/testdir/test_buffer.vim index e71907ff39..c025811b53 100644 --- a/test/old/testdir/test_buffer.vim +++ b/test/old/testdir/test_buffer.vim @@ -937,4 +937,19 @@ func Test_split_window_in_BufLeave_from_switching_buffer() bwipe! Xb endfunc +" Switch to a buffer whose name contains '%' via completion (#20529). +func Test_buffer_switch_to_name_with_percent() + CheckMSWindows + + let bufnr = bufadd('Xpercent%name') + call setbufvar(bufnr, '&buflisted', 1) + call bufload(bufnr) + enew + + call feedkeys(":b Xpercent\\", 'xt') + call assert_equal(bufnr, bufnr('%')) + + exe 'bwipe! ' .. bufnr +endfunc + " vim: shiftwidth=2 sts=2 expandtab