Withhold the show key from a key the command binds

Setting show_key to a key a command binds for its own hint, ctrl-alt-x on
Buffers or alt-a on Rg, advertised both in the footer while the command's
binding won by coming later in the options. '_hint' entries now carry the
fzf key names behind the label, which is what the check compares, since a
label like 'A-a/d' cannot be.
This commit is contained in:
Junegunn Choi
2026-08-26 20:52:47 +09:00
parent a246483a09
commit 091f9c92f9
+22 -11
View File
@@ -371,8 +371,8 @@ function! s:build_hint(entries, defaults, ...)
endif
endfor
endif
for [key, action] in entries
call add(keys, s:magenta(key, 'Special').' '.action)
for entry in entries
call add(keys, s:magenta(entry[0], 'Special').' '.entry[1])
endfor
return join(keys, ' ')
endfunction
@@ -801,7 +801,7 @@ endfunction
" Whether the show key can be offered for this run. Decided from the merged
" spec, since the layout can arrive with the per-call spec, and a bang puts
" fzf on its own tabpage where the window we would open in is not visible.
function! s:can_show(spec, bang, key) abort
function! s:can_show(spec, bang, key, claimed) abort
" Older fzf blocks Vim in popup and fullscreen modes, so the callback would
" only run after fzf exits, overriding whatever was selected. fzf#run is
" only asynchronous when it has a terminal to put fzf in, and win32unix
@@ -816,12 +816,13 @@ function! s:can_show(spec, bang, key) abort
return 0
endif
" fzf matches --expect before the key bindings, so an action or the paste
" key would win over ours. Any key of the list losing disables all of them,
" so that the footer cannot advertise a key that does nothing
" key would win over ours, and a key the command binds itself would win by
" coming later in the options. Any key of the list losing disables all of
" them, so that the footer cannot advertise a key that does nothing
let actions = get(g:, 'fzf_action', s:default_action)
let paste = s:split_keys(s:paste_key())
for key in s:split_keys(a:key)
if has_key(actions, key) || index(paste, key) >= 0
if has_key(actions, key) || index(paste, key) >= 0 || index(a:claimed, key) >= 0
return 0
endif
endfor
@@ -844,7 +845,9 @@ function! s:can_show(spec, bang, key) abort
endfunction
" Installs the show key binding and the key hint footer. '_show' names the entry
" kind, '_hint' opts in to the footer and carries the command's own keys.
" kind, '_hint' opts in to the footer and carries the command's own keys as
" [label, description] or [label, description, keys]. The fzf key names in
" 'keys' are what the show key is checked against, since the label cannot be.
" Returns the fifo of the ipc channel it started, so the caller can stop it if
" the run never reaches 'exit'
function! s:add_hints(spec, bang) abort
@@ -852,8 +855,16 @@ function! s:add_hints(spec, bang) abort
let taken = []
let kind = s:pluck(a:spec, '_show', '')
let entries = s:pluck(a:spec, '_hint', 0)
let claimed = []
if type(entries) == s:TYPE.list
for entry in entries
for name in get(entry, 2, [])
call extend(claimed, s:split_keys(name))
endfor
endfor
endif
let key = s:show_key()
if !empty(kind) && !empty(key) && s:can_show(a:spec, a:bang, key)
if !empty(kind) && !empty(key) && s:can_show(a:spec, a:bang, key, claimed)
let dir = get(a:spec, 'dir', '')
let fifo = fzf#vim#ipc#start(function('s:show_entry',
\ [win_getid(), empty(dir) ? getcwd() : dir, kind]))
@@ -1347,7 +1358,7 @@ function! fzf#vim#buffers(...)
\ '_paste': 1
\}
let spec._show = 'buffer'
let spec._hint = [['C-A-X', 'Unload']]
let spec._hint = [['C-A-X', 'Unload', ['ctrl-alt-x']]]
let options = ['+m', '-x', '--tiebreak=index', '--ansi', '-d', '\t', '--with-nth', '3..', '-n', '2,1..2', '--prompt', 'Buf> ', '--query', query, '--preview-window', '+{2}/2', '--tabstop', tabstop, '--bind', 'ctrl-alt-x:execute-silent(echo {} >> '.fzf#shellescape(delete_file).')+exclude']
if bufnr('') == first
call extend(options, ['--sync', '--bind', 'start:pos:2'])
@@ -1473,7 +1484,7 @@ function! fzf#vim#grep(grep_command, ...)
let opts._paste = 1
let opts._show = 'grep'
let opts._hint = [['A-a/d', 'Select/deselect all']]
let opts._hint = [['A-a/d', 'Select/deselect all', ['alt-a', 'alt-d']]]
function! opts.sink(lines) closure
return s:ag_handler(get(opts, 'name', name), a:lines)
endfunction
@@ -1521,7 +1532,7 @@ function! fzf#vim#grep2(command_prefix, query, ...)
endif
let opts._paste = 1
let opts._show = 'grep'
let opts._hint = [['A-a/d', 'Select/deselect all']]
let opts._hint = [['A-a/d', 'Select/deselect all', ['alt-a', 'alt-d']]]
function! opts.sink(lines) closure
return s:ag_handler(name, a:lines)
endfunction