vim - Plugin fzf
How to search faster in Vim with FZF.vim
### FZF syntax
Let’s go over syntax so we can search more efficiently. Fortunately for us, there aren’t many to learn.
command | description |
---|---|
——- | ———– |
^ | prefix exact match. To search for phrase starting with “welcome”, we do ^welcome. |
$ | suffix exact match. To search for phrase ending with “my friends”, we do friends$. |
' | n exact match. To search for phrase “welcome my friends”, we do ‘welcome my friends. |
(pipe) | n “or” match. To search for either “friends” or “foes”, we can use friends (pipe) foes. |
! | n inverse match. To search for phrase containing “welcome” and not “friends”, we can use welcome !friends |
We can mix and match the above. For example, `^hello | ^welcome friends$` searches for phrase starting with either “welcome” or “hello” and ending with “friends”.
Side note: FZF.vim :Rg option also searches for file name in addition to the phrase. If you think this is an issue, check out this comment. I added this in my .vimrc:
``` command! -bang -nargs=* Rg call fzf#vim#grep(“rg –column –line-number –no-heading –color=always –smart-case “.shellescape(<q-args>), 1, {‘options’: ‘–delimiter : –nth 4..’}, <bang>0)
```
With the above, every time we invoke Rg, FZF + ripgrep will not consider filename as a match in Vim.
### Replacing grep with rg or ag
Internally, Vim has two ways to search in files: :vimgrep and :grep.
:vimgrep uses vim’s built-in grep and :grep uses external tool which you can reassign using ‘grepprg’.
For example, if we want to search for “iggy” with :grep, we can run :grep “iggy” . -R
You may notice that Vim’s :grep syntax is similar to terminal grep command; this is because :grep by default runs grep -n $* /dev/null on unix-based machine.
The command above will search for the string “iggy” recursively (-R) from current location (.).
Vim allows us to change the program used by :grep.
We can tell Vim to use ripgrep instead of grep by adding this inside our vimrc: ``` set grepprg=rg\ –vimgrep\ –smart-case\ –follow ``` ripgrep works great. But, in certain corporate environments, it may be difficult to install ripgrep.
We can tell Vim to use silver searcher instead of grep by adding this inside our vimrc: ``` set grepprg=ag\ –vimgrep\ –smart-case\ –follow ``` I’ve noticed that installing silver searcher is relatively easier than installing ripgrep.
If we configure Vim to use ripgrep: (and the scenarios are exactly the same for silver searcher as well.)
Now when we run :grep inside Vim, it will run rg –vimgrep –smart-case –follow instead.
For more information about what the options above mean, check out man rg.
I can now run a more succinct command ``` :grep “iggy” ``` instead of ``` :grep “iggy” . -R. ```
FZF.vim :Rg option also searches for file name in addition to the phrase. If you think this is an issue, use the command below to change the behavior: With this command, every time we invoke Rg, FZF + ripgrep will not consider filename as a match in Vim. ``` command! -bang -nargs=* Rg call fzf#vim#grep(“rg –column –line-number –no-heading –color=always –smart-case “.shellescape(<q-args>), 1, {‘options’: ‘–delimiter : –nth 4..’}, <bang>0) ```
Vim :grep command uses quickfix list to display results. We can use :copen to display quickfix window and :cclose to close quickfix window. Try it!
If you want to look at the quickfix list in a separate tab, just move them to a separate tab like you would move any other buffer - with Ctrl w T.
You might wonder, “Well, this is nice but I never used :grep in Vim, plus can’t we just use :Rg to find string in files? When will I ever need to use :grep?”
That is a very good question. The answer to “why do we need to use grep in Vim?” is that it will let us do what I’ll going to cover next: search and replace in multiple files.
NOTE: The part about using ripgrep instead of grep is complete optional. You do not have to switch to using ripgrep instead of grep. In some corporate environments, installing ripgrep on computers can be a real struggle. In cases like that, just go with using grep. The part that explains about using quickfix list after the search command completes is the same - whether you use ripgrep or grep or silver search or any one of the many ways you can search for something.
### Searching with grep If you just want to use grep instead of replacing it with ripgrep or silver searcher, here is a command that will help.
In case you do not have ripgrep or silver_searcher (ag) installed in your computer and you need to use “grep” to search for something in the project: search for a word using grep: ``` nnoremap <leader>f :grep . -R –exclude-dir={node_modules,dir1,dir2,dir3}<c-b><right><right><right><right><right> ``` The mapping will first go into command mode: : Then write s//nextposition/g in the command lines Go to the beginning of the command <c-b> And move to the desired position: <right> Some interesting command line mappings can be found here: :h cmdline-editing
### Search and replace in multiple files
Modern text editors like VSCode makes it very easy to search and replace string across multiple files. If I may confess, in the beginning when I had to search/replace string in multiple files, I used VSCode because doing it in Vim, although possible, takes too long… until now.
I will show you two different tricks to easily do search and replace phrases across multiple files in Vim.
The first method is to replace ALL matching phrases in our project. We will need to use :grep. Let’s say you want to replace all instance of “pizza” with “donut”. Here’s what you do:
``` :grep “pizza” :cfdo %s/pizza/donut/g | update ```
That’s it? Yup! That’s it. Let me break down the steps:
- :grep pizza uses ripgrep to succinctly search for all instances of “pizza”. By the way, this would still work even if we didn’t reassign ripgrep to replace default grep. The difference is, with default grep, we would have to do :grep “pizza” . -R instead of :grep “pizza”.
- We run :cfdo because :grep uses quickfix and :cfdo executes any command we pass (in this case, our command is %s/pizza/donut/g) on all entries in our quickfix list. To run multiple commands, we can chain it with pipe (|). The first command we are executing is pizza-donut substitution: %s/pizza/donut/g. The second command, update, saves each file after the first is finished.
Let’s discuss the second way.
The second method is to search and replace in select multiple files instead of all files using buffers. Here we can choose which files we want to perform select and replace.
- Clear our buffers (:Buffers) first. Our buffers list should contain only the needed files. We can clear it with %bd | e# | bd# (or restart Vim).
- Run :Files.
- Select all files you want to perform search and replace on. To select multiple files, use Tab / Shift+Tab. This is only possible if we have -m in FZF_DEFAULT_OPTS.
- Run :bufdo %s/pizza/donut/g | update.
Our command :bufdo %s/pizza/donut/g | update looks similar to :cfdo %s/pizza/donut/g | update. That’s because they are. Instead of performing substitution on all quickfix (cfdo) entries, we perform our substitution on all buffer (bufdo) entries.
### Learn how to do the following in Vim/Find out the answers to the following questions
- How to tell if “ripgrep” is installed in the computer?
- What other alternatives can we use with fzf instead of “ripgrep”?
- How to search for all occurances of a function name or a variable name in a project - and then view quicklist for all of them.