Multiple fzf#run() with differentfzf_actions?
- [x] I have read through the manual page (
man fzf) - [x] I have the latest version of fzf
- [x] I have searched through the existing issues
Info
- OS
- [x] Linux
- [ ] Mac OS X
- [ ] Windows
- [ ] Etc.
- Shell
- [ ] bash
- [x] zsh
- [ ] fish
Problem / Steps to reproduce
Thanks for this fantastic tool! I'm trying to define multiple FZF commands in my .vimrc that each use a different g:fzf_action option. I understand from the docs that fzf#wrap injects g:fzf_action into the config before we pass it to fzf#run. However, restricts us to using the same action spec for all wrapped commands. I could not find a documented option for specifying the actions mapping directly for fzf#run. Is this possible?
I'm using the following FZF configuration in my vimrc:
Plug 'junegunn/fzf' # (not junegunn/fzf.vim)
let fzfcmd = "rg --files --hidden -g '!{.git,node_modules,__pycache__}'"
nnoremap <silent> <C-P> :call fzf#run(fzf#wrap({ 'source': fzfcmd }))<cr>
let g:fzf_history_dir = '/tmp/fzf_history'
let g:fzf_layout = {'window': 'new', 'down': '40%'}
let g:fzf_action = {
\ 'return': 'drop',
\ 'ctrl-t': 'tab drop',
\ 'ctrl-x': 'split',
\ 'ctrl-v': 'vsplit' }
Is this possible?
No, it's not. g:fzf_action only applies to the default sinklist (link) implementation which is for opening files. Is there any reason you want to use different key bindings for different commands for opening files? Wouldn't it be confusing?
fzf#wrap injects --expect option to find out which key was pressed, and the default sink function uses the information to select an option from g:fzf_actions. So you would take the same strategy in your commands to support different sets of keys.
let s:spec = { 'source': 'seq 100', 'options': '--multi --expect=ctrl-a,ctrl-b' }
function s:spec.sinklist(lines)
if len(a:lines) < 2
echom 'Cancelled'
endif
let [key; rest] = a:lines
let key = empty(key) ? 'enter' : key
echom printf('You pressed %s to select %s', key, join(rest, ', '))
endfunction
command! MyNumbers call fzf#run(fzf#wrap(s:spec))
Thanks, that's helpful! In my case, I would like one command to search for all filenames and another one to search inside all files. For both commands, I want drop), drop tab). However, for file content search, I want to not just open the file but also position the cursor at the match (I'm not quite sure how to do that yet). So even though the actions are the semantically same, they need to trigger different code.
I see. The problem is that the built-in sink function used for g:fzf_actions wasn't really designed to handle more than just file paths. You can write your own sink function as I suggested above, but it can be tricky if you're not well-versed in VimScripting.
Have you tried using fzf.vim? It provides :Ag, :Rg, and :RG commands, and the underlying fzf#vim#grep and fzf#vim#grep2 functions, which I think will suit your needs.
@danijar I have the same idea and need, as I am trying to implement a note taking system similar to Notational Velocity (i.e. both title and content of a text file note are meaningful).
This is working progress and it is incomplete, but I think I found a way to search both filenames and file content.
# Now we setup the two (key) commands used for nv(): fd and ripgrep
# Searching for filenames, ignoring certain files (.gitignore or .ignore) and searching in $SEARCHPATH only
FDCMD="fd -e exe -e md --ignore --type file {q} '$SEARCHPATH'"
# Searching inside the content of files, in $SEARCHPATH only and only for .md and .txt files
RGCMD="rg -tmd --column --color=always -I -p -C 1 --no-max-columns-preview --sortr=created --heading --line-buffered --no-line-number --no-messages --smart-case -- {q} '$SEARCHPATH'"
RELOAD="reload:($FDCMD & $RGCMD)|| :"
OPENER='echo $FZF_SELECT_COUNT
echo {1}
echo {2}'
# OPENER='if [[ $FZF_SELECT_COUNT -eq 0 ]]; then
# #vim {1} +{2} # No selection. Open the current line in Vim.
# vim "+normal G$" +startinsert {1}
#vi +"norm! go" {1} #
# else
# vim +cw -q {+f} # Build quickfix list for the selected items.
# fi'
fzf < /dev/null \
--disabled --ansi \
--bind "start:$RELOAD" --bind "change:$RELOAD" \
--bind "enter:become:$OPENER" \
--bind "ctrl-o:execute:$OPENER" \
--bind 'alt-a:select-all,alt-d:deselect-all,ctrl-/:toggle-preview' \
--delimiter : \
--preview 'bat --style=header-filename --color=always --highlight-line {2} {1}' \
--preview-window '~4,+{2}+4/3,<80(up)' \
--query "$*"
)
It is incomplete. I just had the idea of using tmux. But I am possibly searching for an overkill.