Best Way to Navigate Files in Vim
Tags: vim, neovim, navigation, files
Published: 2019-10-25 12:50:32

---
title: Best Way to Navigate Files in Vim
published: true
description: Once you get good at vim navigation, your life will change
tags: vim, neovim, navigation, files
canonical_url: https://irian.to/blogs/best-way-to-navigate-files-in-vim
---

*Follow [@learnvim](https://twitter.com/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](https://dev.to/iggredible/vim-cheatsheet-to-move-around-in-a-file-plus-tips-to-use-them-bme), 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](https://www.deviantart.com/bairuidahu/art/Flying-vs-Cycling-261641977). 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](https://github.com/junegunn/fzf.vim) combined with [ripgrep](https://github.com/BurntSushi/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](https://github.com/ludovicchabant/vim-gutentags) for my tag usages.

# NERDTree navigation

I still use [NERDTree](https://github.com/scrooloose/nerdtree) for navigation. I find it very helpful to visualize the project structure using a tree explorer. Some folks prefer netrw + [vinegar](https://github.com/tpope/vim-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](https://github.com/ryanoasis/vim-devicons) 😅.

# My Vim flow

There are 6 scenarios during my normal workflow when I would need to navigate between files:
1. Opening a file I have not opened before (search filename): fzf + rg
2. Opening a file I have not opened before based on string keyword: fzf + rg
3. Opening a file from an import/export link inside a file : ctags
4. Opening a file from tree explorer: NERDTree
5. Opening a file I've opened before: buffer
6. 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](https://stackoverflow.com/questions/4545275/vim-close-all-buffers-but-this-one) 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
- [Buffers in Vim](https://stackoverflow.com/questions/9962201/what-is-a-buffer-in-vim)
- [Buffer way](https://stackoverflow.com/questions/26708822/why-do-vim-experts-prefer-buffers-over-tabs)

*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)*