See devel branch for the progress.
Add bindable reload action that can start an arbitrary program and dynamically replace the input list of fzf with its result without restarting fzf.
fzf was designed to be a Unix filter that consumes input only once. However, due to the interactive nature of it, some users want to update the input without restarting fzf altogether (using esoteric --no-clear option).
For example,
CTRL-R (R for refresh or reload).CTRL-F for a list of files, and CTRL-D for a list of directories.--phony option (#1723).Instead of introducing a separate mode of execution as suggested in #751 and #1736. I'd like to add a special action called reload that can be bound to a key or change event using the good old --bind.
ps -ef | fzf --bind 'ctrl-r:reload(ps -ef)' --header 'Press CTRL-R to reload' \
--header-lines=1 --layout=reverse
find . -type f |
fzf --bind 'ctrl-d:reload(find . -type d),ctrl-f:reload(find . -type f)'
There are two problems here:
find . -type f command twicefind process may take a long time to finish. Since fzf cannot kill the process behind the standard input, the process will keep running even after we hit CTRL-D.To work around the issues, we set $FZF_DEFAULT_COMMAND to the initial find command, so fzf can start the process and kill it when it has to.
FZF_DEFAULT_COMMAND='find . -type f' fzf \
--bind 'ctrl-d:reload(find . -type d),ctrl-f:reload($FZF_DEFAULT_COMMAND)'
The following example uses fzf as the selector interface for ripgrep. We bound reload action to change event, so every time you type on fzf, ripgrep process will restart with the updated query string denoted by the placeholder expression {q}. Also, note that we used --phony option so that fzf doesn't perform any secondary filtering.
RG_PREFIX="rg --column --line-number --no-heading --color=always --smart-case "
INITIAL_QUERY=""
FZF_DEFAULT_COMMAND="$RG_PREFIX '$INITIAL_QUERY'" \
fzf --bind "change:reload:$RG_PREFIX {q} || true" \
--ansi --phony --query "$INITIAL_QUERY"
If ripgrep doesn't find any matches, it will exit with a non-zero exit status, and fzf will warn you about it. To suppress the warning message, we added || true to the command, so that it always exits with 0.
function! RipgrepFzf(query, fullscreen)
let command_fmt = 'rg --column --line-number --no-heading --color=always --smart-case %s || true'
let initial_command = printf(command_fmt, shellescape(a:query))
let reload_command = printf(command_fmt, '{q}')
let spec = {'options': ['--phony', '--query', a:query, '--bind', 'change:reload:'.reload_command]}
call fzf#vim#grep(initial_command, 1, fzf#vim#with_preview(spec), a:fullscreen)
endfunction
command! -nargs=* -bang Rg call RipgrepFzf(<q-args>, <bang>0)
0.19.0 released.
Hey @junegunn I am trying to bind the Ripgrep Integration to Ctrl-f (in zsh), and I don't want to change FZF_DEFAULT_COMMAND so my other settings are affected, I have come up with the following...
RG_PREFIX='rg --column --line-number --no-heading --color=always --smart-case '
INITIAL_QUERY=''
bindkey -s '^f' "$RG_PREFIX '$INITIAL_QUERY' | fzf --bind \"change:reload:$RG_PREFIX {q} || true\" --ansi --phony --query \"$INITIAL_QUERY\"^M"
...which works, but a couple things...
FZF_DEFAULT_COMMAND in the above example. By doing so, fzf launches the process and it can kill it when it exits.Thanks for the tips @junegunn! I solved it by adding the following to my .zshrc, in case others are interested...
# Ctrl-F (Find in Files)
RG_PREFIX='rg --column --line-number --no-heading --color=always --smart-case '
INITIAL_QUERY=''
FZF_DEFAULT_COMMAND="$RG_PREFIX '$INITIAL_QUERY' $HOME"
__fif() {
fzf --bind "change:reload:$RG_PREFIX {q} $HOME || true" --ansi --phony --query "$INITIAL_QUERY" | cut -d ':' -f1
}
find-in-files() {
LBUFFER="${LBUFFER}$(__fif)"
local ret=$?
zle reset-prompt
return $ret
}
zle -N find-in-files
bindkey '^f' find-in-files
...note that I added $HOME in a couple places as I usually want to search beyond just the current directory (and use ~/.ignore or alternatives to maintain speed).
Is it possible to get this working with -1, so once a selection is narrowed down to 1, it's picked?
Most helpful comment
0.19.0 released.