Follow @learnvim for more Vim tips and tricks!
One of my Vim productivity bottleneck is navigating between files. While Vim provides cool ways to move around in a file, I feel like my file navigation in Vim is slower than when using popular editors like Atom, VSCode, Sublime, or IntelliJ.
This blog is an opinionated breakdown how I overcome that shortcoming.
Why most people are slow at navigating files using Vim
I think most people (myself included) that are coming from popular editors have the wrong approach. What I have been trying to do is making Vim do what I want, but never tried to learn how Vim does it.
Vim's way: Buffer
I believe buffer is Vim's way to navigate quickly between files. If you don't know what buffers are, think of it as a list of all your "opened" files.
Before we start, I recommend to have :set hidden
. This allows you to "hide" buffers when you are going in and out.
Below are some buffer tips I found very useful:
Buffer: Previous, Next, First, Last
You can go to next/previous and first/last buffers with bprev
, bnext
, bfirst
, and blast
. Here are my mappings:
nnoremap <Leader>h :bprevious<CR>
nnoremap <Leader>l :bnext<CR>
nnoremap <Leader>k :bfirst<CR>
nnoremap <Leader>j :blast<CR>
Buffer: Flying with buffer list
This - in my opinion - is the killer feature of Vim for fast navigation method: flying. It is done by using buffer list (:ls
or :buffers
) to display all opened files. From here, you can access any files within very few keystrokes.
I used this so much I have mine mapped to <Ctrl-b>
.
nnoremap <C-b> :ls<CR>:b<Space>
While you are on buffer list (:ls
/ :buffers
), there are multiple ways to go to a file after typing :b<space>
:
- You can type the buffer number.
- You can type the partial file name and auto-complete with tab.
- You can start pressing tabs to traverse buffer list until you find the file you want to go to.
- You can go to previous buffer with
#
. This lets you to toggle back and forth previous file. There is even a native vim shortcut for it:<Ctrl-^>
Stop for a moment and try to internalize this - when working on a task, there are usually Y amount of files needed. Once you have them "touched"/ "opened" (once you have them inside your buffer list), you generally don't need anything new (even if you do, you can use fzf - covered below). What you need now is a quick way to fly between those Y files. This is where the mapping comes - all your relevant files are accessible within 2-3 key presses.
How cool is that? 😎
I also wanted to add that <Ctrl-o>
and <Ctrl-i>
are indispensable shortcut to jump back to previous and next files.
Complementing Buffer flow with fzf
Although some vim purists might prefer :e
or :find
, I find fzf combined with ripgrep indispensable. Here are my mappings:
nnoremap <C-p> :Files<CR>
nnoremap <C-f> :Rg<CR>
With these two I can fuzzy-find filename with <Ctrl-p>
and fuzzy-find string in project with <Ctrl-f>
.
I usually use these to quickly open files I haven't opened yet. Once they are opened, I use flying technique to go around.
Using tags
There are times when I need to jump to an import/export file while editing a file. The easiest way is to jump to definition with C-]
. I use vim-gutentags for my tag usages.
NERDTree navigation
I still use NERDTree for navigation. I find it very helpful to visualize the project structure using a tree explorer. Some folks prefer netrw + vinegar. They all work similarly - I personally choose NERDTree because it is the first tree explorer I ever used with Vim, plus it looks pretty with devicons 😅.
My Vim flow
There are 6 scenarios during my normal workflow when I would need to navigate between files:
- Opening a file I have not opened before (search filename): fzf + rg
- Opening a file I have not opened before based on string keyword: fzf + rg
- Opening a file from an import/export link inside a file : ctags
- Opening a file from tree explorer: NERDTree
- Opening a file I've opened before: buffer
- Opening (toggle) previously opened file: buffer
When I am starting a task, I would open all starting files with fzf + rg. Then I would fly between buffers to edit files. This editing phase took up most of my coding time. Once I am done, I would clear up buffer list and start all over again.
There you have it folks, my current vim workflow navigating between files. Personally, how do you navigate files in Vim?
Please feel free to share below!! I would love to hear them.
Resources/ other readings
I am aware that some of my mapping coincides with Vim's native shortcuts. For example, Ctrl-f is scroll down full screen. I hardly ever used those features, plus it makes more sense mnemonically (f for find, b for buffer, and p for path)