From 1adf1fd93196e5406f0d5395a95355f0199b0efa Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Mon, 28 Sep 2026 21:55:14 +0900 Subject: [PATCH] Keep a tab inside a BTags pattern from cutting the address ctags leaves a tab as it found it, and :BTags splits the line on tabs, so a tab-indented definition arrived as '/^', which matched whatever line came next. Write the tab as '\t', which matches the same text and keeps the address one field. Only the ';"' terminator says where an address ends, so a line without one is left alone rather than guessed at. --- autoload/fzf/vim.vim | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/autoload/fzf/vim.vim b/autoload/fzf/vim.vim index a056e7a..e58fc77 100755 --- a/autoload/fzf/vim.vim +++ b/autoload/fzf/vim.vim @@ -1652,6 +1652,17 @@ endfunction " ------------------------------------------------------------------ " BTags " ------------------------------------------------------------------ +" ctags leaves a tab inside a pattern as it found it, and splitting the line on +" tabs would cut the address short, leaving a fragment that matches some other +" line. '\t' matches the same text and keeps the field the line's third. Only the +" ';"' terminator says where the address ends, so a line without one is left as +" it is rather than guessed at +function! s:tabs_in_address(line) + return substitute(a:line, '^\%([^\t]*\t\)\{2}\zs'.s:tag_address_part + \ .'\%(;'.s:tag_address_part.'\)*\ze;"\t', + \ '\=substitute(submatch(0), "\t", ''\\t'', "g")', '') +endfunction + function! s:btags_source(tag_cmds) if !filereadable(expand('%')) throw 'Save the file first' @@ -1668,7 +1679,8 @@ function! s:btags_source(tag_cmds) elseif empty(lines) throw 'No tags found' endif - return map(s:align_lists(map(lines, 'split(v:val, "\t")')), 'join(v:val, "\t")') + return map(s:align_lists(map(map(lines, 's:tabs_in_address(v:val)'), + \ 'split(v:val, "\t")')), 'join(v:val, "\t")') endfunction " Position to return to with CTRL-T. Captured before fzf opens, because the