Keep a newline in an entry from splitting the fifo payload

The fifo is read a line at a time, but ':GFiles' reads NUL separated names
from 'git ls-files -z', so an entry can hold a newline. It arrived as two
callbacks, and a fragment that named another tracked file opened that one
instead.

The binding swaps the newline for \1 and s:show_entry puts it back, so a
multi-line entry stays one payload.
This commit is contained in:
Junegunn Choi
2026-08-26 23:28:07 +09:00
parent cb6ea5e06f
commit e541ce6037
+9 -4
View File
@@ -655,7 +655,9 @@ endfunction
" Scopes the options s:goto_entry needs, which every early return has to
" restore, hence the split.
function! s:show_entry(winid, bufnr, dir, kind, entry) abort
if empty(a:entry)
" Undo the newline escaping the binding applies
let entry = substitute(a:entry, nr2char(1), "\n", 'g')
if empty(entry)
return
endif
" 'acd' would move the cwd on the first open, and s:ag_to_qf resolves a
@@ -667,7 +669,7 @@ function! s:show_entry(winid, bufnr, dir, kind, entry) abort
let [&magic, &wrapscan] = [0, 1]
endif
try
call s:goto_entry(a:winid, a:bufnr, a:dir, a:kind, a:entry)
call s:goto_entry(a:winid, a:bufnr, a:dir, a:kind, entry)
finally
let [&magic, &wrapscan, &acd] = [magic, wrapscan, acd]
endtry
@@ -746,7 +748,7 @@ function! s:goto_entry(winid, bufnr, dir, kind, entry) abort
\ printf('keepjumps call cursor(%d, %d)', str2nr(parts[2]), str2nr(parts[3])),
\ 'normal! zvzz']
elseif a:kind ==# 'grep'
" Vim sends one line per callback, so multi-line entries arrive in pieces
" A multi-line match arrives whole, and s:ag_to_qf reads the first line
try
let entry = s:ag_to_qf(entry)
catch
@@ -885,7 +887,10 @@ function! s:add_hints(spec, bang) abort
let Exit = get(a:spec, 'exit', 0)
let a:spec.exit = { code -> [fzf#vim#ipc#stop(fifo),
\ type(Exit) == s:TYPE.funcref ? call(Exit, [code]) : 0] }
call s:prepend_opts(a:spec, ['--bind', key.':execute-silent:printf ''%s\n'' {} > '.fzf#shellescape(fifo)])
" The fifo is read a line at a time, but an entry can contain a newline
" where the source is NUL separated, as ':GFiles' is. Swap it for a
" byte no path is going to hold and put it back in s:show_entry
call s:prepend_opts(a:spec, ['--bind', key.':execute-silent:{ printf ''%s'' {} | tr ''\n'' ''\1''; echo; } > '.fzf#shellescape(fifo)])
let entries = [[s:key_label(key), 'Show']] + (type(entries) == s:TYPE.list ? entries : [])
let started = fifo
let taken = s:split_keys(key)