Is there any way to configure VIM to interactively search inside every file for an entire project?
By interactive, I mean updating each keystroke.
Something like Emacs counsel-git-grep, see: example demo.
Is there any way to configure VIM to interactively search inside every file for an entire project?
By interactive, I mean updating each keystroke.
Something like Emacs counsel-git-grep, see: example demo.
I'm not sure this is what you're looking for, but maybe you could try fzf and fzf.vim.
If you use vim-plug as a plugin manager, all you should have to do to install them, is to add these lines in your vimrc
:
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
Plug 'junegunn/fzf.vim'
... somewhere between the lines:
call plug#begin('~/.vim/plugged')
and:
call plug#end()
Then execute :PlugInstall
.
Among various commands and mappings provided by fzf.vim
(whose only purpose seems to be to install mappings and commands asking fzf
to fuzzy search through predefined sources), there is the command :Ag
.
To be able to use it, you need to install the shell command ag. On debian based distributions, it can be done with the following command:
apt-get install silversearcher-ag
The project on github explains how to install it on MacOS:
brew install the_silver_searcher
:Ag
is a wrapper around $ ag
, and allows you to fuzzy search a pattern in the files of the current directory (the one displayed when you type :pwd
). The matches are updated after every keystroke.
You can:
C-n
and C-p
Tab
/S-Tab
M-a
or M-d
If you select one or several matches, after hitting Enter, they will populate the quickfix list. From there you'll be able to navigate through them with default Vim commands / mappings, such as :cnext
and :cprevious
.
If you want to add a prefix to all the commands installed by fzf.vim
, and avoid overriding existing commands, you can add this in your vimrc
:
let g:fzf_command_prefix = 'your_prefix'
I use Fzf
as a prefix, that's why I didn't type :Ag
but :FzfAg
.
If you prefer to use git grep
instead of ag
, it seems you could install your own custom wrapper around it, :GGrep
, like this:
command! -bang -nargs=* GGrep
\ call fzf#vim#grep('git grep --line-number '.shellescape(<q-args>), 0, <bang>0)
It's explained in :h fzf-vim-customization
.
Also, if fzf
opens a pane in tmux, and you would prefer it takes the whole screen instead, you can append a bang to all the commands (:Ag!
, :GGrep!
, ...).
As you said in your last comment, by default fzf
changes the configuration of your shell. For example, if you use bash
, it will add the following line in your ~/.bashrc
:
[ -f ~/.fzf.bash ] && source ~/.fzf.bash
This will source the file ~/.fzf.bash
. The latter contains some code:
# Setup fzf
# ---------
if [[ ! "$PATH" == */home/user/.fzf/bin* ]]; then
export PATH="$PATH:/home/user/.fzf/bin"
fi
# Auto-completion
# ---------------
[[ $- == *i* ]] && source "/home/user/.fzf/shell/completion.bash" 2> /dev/null
# Key bindings
# ------------
source "/home/user/.fzf/shell/key-bindings.bash"
This code appends a path to the environment variable $PATH
: /home/user/.fzf/bin
; which is the folder containing the fzf
program.
It also sources 2 other files:
/home/user/.fzf/shell/completion.bash
/home/user/.fzf/shell/key-bindings.bash
The first one seems to define completion functions, while the second installs key bindings.
Unfortunately, the key bindings may override default readline
functions.
For example, fzf
binds the function fzf-file-widget
to C-t
. This key is usually used by readline to execute the transpose-chars
function.
If you don't want this, one possible solution would be to restore the key bindings inside your ~/.bashrc
, after fzf
has sourced its configuration. For example, if you wanted C-t
to keep its old behavior, that is transposing the 2 characters around the cursor, and bind fzf-file-widget
to another key, let's say C-x C-t
, you could add these lines at the end of ~/.bashrc
:
bind -x '"\C-x\C-t": fzf-file-widget'
bind '"\C-t": transpose-chars'
The same thing applies to the zsh
shell, but the syntax to install a key binding is a little different:
bindkey '^X^T' fzf-file-widget
bindkey '^T' transpose-chars
If one of the shell key binding you were used to has been overridden by fzf
, you want to restore it, but don't know what's the exact name of the function which was executed, you could try the following thing.
First, inside your ~/.bashrc
, temporarily comment out the line which sources the fzf
configuration. Then, reopen a terminal, and have a look at the output of the bind -P
command, which you can read in a Vim buffer:
bind -P | vim -R -
I'm not sure, but I think it should display most or all the readline
key bindings. If you're looking for the name of the readline function bound to the C-t
key, in the Vim buffer, you would search \\C-t
. And if you were looking for the one bound to M-c
(meta / alt key), you would search \\ec
(\e
stands for the escape key and it seems M-c
produces the same keycodes as escape + c
).
You can do the same thing in zsh
by looking at the output of the bindkey
command. But this time, ^[
stands for the meta/alt modifier key, while a single caret (^
) character stands for the control key.
Currently, I found 4 key bindings executing functions containing the fzf
keyword in their name. They use the key sequences C-i
(same as Tab
), C-r
, C-t
and M-c
. They are bound to the following functions:
C-i fzf-completion
C-r fzf-history-widget
C-t fzf-file-widget
M-c fzf-cd-widget
On my system, originally, readline
(the library used by bash
to edit the command line) bound those keys to these functions:
C-i complete
C-r reverse-search-history
C-t transpose-chars
M-c capitalize-word
And zle
(the line editor used by zsh
), bound them to:
C-i expand-or-complete
C-r history-incremental-search-backward
C-t transpose-chars
M-c capitalize-word
ag
a separate plugin/tool that needs to be installed?
Commented
Dec 21, 2016 at 12:41
ag
was also necessary. I updated the answer.
Commented
Dec 21, 2016 at 12:51
ctrl-p
or a similar plugin is what you are looking for. Note thatunite.vim
should also be able to do that but I wouldn't recommend it because in my opinion it is a pretty heavy and bug-creating plugin.ctrl-p
have a way to interactively search the file contents? I've only ever used it to interactively search for files based on their names.