How to search and open files in Vim without plugins
Tags: vim, files, management, productivity
Published: 2020-04-23 19:42:40

---
title: How to search and open files in Vim without plugins
published: true
description: How to open and search for files in Vim without plugins
tags: vim, files, management, productivity
---

*Follow [@learnvim](https://twitter.com/learnvim) for more Vim tips and tricks!*

You may find yourself in situation where you need to use Vim without plugins (inside a docker container or connecting to remote server for example). In that case, what will you do to search and open files quickly? You have to rely on Vim's built-in search methods. Luckily, Vim provides different ways to search and open files without plugins. 

In this article, I will show different ways you can search and open files without plugins. Here are subjects I will cover:

- [Opening files with `:edit`](#edit)
- [Searching for files with `:find`](#find)
- [Searching for pattern within files with `:grep`](#grep)
- [Browsing files with `netrw`](#netrw)

I will also briefly list [popular search plugins](#plugins) before [concluding](#conclusion) the article. 

# Opening files with `:edit`
`:edit` is the simplest way to open a file in Vim. 

```
:e[dit] file
```

- If `file` exists, it opens that file in current buffer. 
- If `file` doesn't exist, it creates a new file in current buffer.

Autocomplete (`<tab>`) works with `:e`. For example, if your file is `./app/controllers/users_controllers.rb`, you can do:
```
:e a<tab>c<tab>u<tab>
```

`edit` accepts wildcards. If you are only looking for `.yml` files in root directory:

```
:e *.yml<tab>
```
Post tab, Vim will list you all `.yml` files in current directory to choose from.

You can also use `**` to search recursively. Let's say you want to look for all `*.png` files in your project:
```
:e **/*.png<tab>
```
*You may get warning that there are too many file names, depending on your project size.*

`:e` integrates well with `netrw`, Vim's built-in text editor. If you pass it a directory instead of file, it will open a `netrw` explorer (which I will cover later):
```
:e .
:e test/unit/
```

By the way, when you opening a file with `:e`, you can also pass an Ex command.

```
:e +EX_COMMAND /your/file
```

To go to line 5:
```
:e +5 /test/unit/helper.spec.js
```

To go to the first line containing `"const"`:
```
:e +/const /test/unit/helper.spec.js
```

To delete all empty lines:
```
:e +g/^$/d test/unit/helper.spec.js
```

# Searching for files with `:find`
Vim has a `:find` method to find a file in our project. It finds a file in `path`, then `edit` it. 

```
:find package.json
:find app/controllers/users_controller.rb
```

Autocomplete works with `:find`.

```
:find p<tab>              " to find package.json
:find a<tab>c<tab>u<tab>  " to find app/controllers/users_controller.rb
```

So far `:find` looks a lot like `:edit`. You may wonder, "Why should I use find at all? Can't I just use edit?"

The difference is that `:find` *finds file in `path`*. Edit doesn't.

Let's learn a little about path. Once we learn how to modify our paths, `:find` can become a powerful tool to search files.

To check what your paths are, do

```
:set path?
```

By default, yours probably look like this:

```
path=.,/usr/include,,
```

Here is what they mean:
- `.` means current directory
- `,,` means anything relative to current directory
- `/usr/include` is a [directory](https://askubuntu.com/questions/191611/what-is-the-use-of-usr-include-directory).

Let's assume this is our project structure:
```
▾ app/
  ▸ assets/
  ▾ controllers/
      application_controller.rb
      comments_controller.rb
      users_controller.rb
  ...
```

You want to go to `users_controller` without going through each directory (and doing a lot of `<tab>` presses on the way). Path can shorten the journey.

Add `controllers` to your own path with:

```
:set path+=app/controllers/
```

What we just did is adding `app/controllers/` to our current path (run `:set path?` again to see updated path). Now everything inside `app/controllers/` path, Vim will look when we tab.

Before we added `app/controllers/` to our path, if we type `:find u<tab>`, nothing happens. That's because Vim only sees everything inside current directory `.`. After adding new path, when we do:

```
:find u<tab> -> :find users_controller.rb
```

Vim finds and autocompletes it (assuming there is no other controller starting with `u`)

If you have nested directories inside `app/controllers`, you might want to add  `:set path+=app/controllers/**` so autocomplete will find those files. The larger your directories, the slower finding each file may be.

If you're familiar with Rails, you might want to add paths for `models` (`:set path+=app/models`)and `views` (`:set path+=app/views`). You can also add the entire app directory into your path (`:set path+=app/**`).

You may be tempted to do something like:
```
:set path+=$PWD/**
```

To add everything in your project to your path so you can tab to any file quickly. While this may work for small project, I suggest you don't do it on large projects. On gargantuan projects, when I typed `:find a<tab>`, Vim tried to find everything starting with "a" and froze momentarily. I don't think this is how path is supposed to be used.

Adding paths for your frequently visited directories takes only a few seconds and it lets you find files quickly, saving you a lot of time. You can even make it permanent by adding it to your vimrc (ex: `set path+=app/controllers`).

# Searching within files with `:grep`
If you need to find a phrase within files, you can use grep. 

Vim has two different greps:
- Internal (`:vim[grep]`. Yes, this command is spelled `:vim`)
- External (`:grep`)

Let's go through **Internal* grep* first. `:vim` has the following syntax:
```
:vim /pattern/ file
```

- `/pattern/` is a regex pattern of what we want to search
- `file` is the file(s) we pass. It accepts `*` and `**` wildcards.

For example, to look for all occurrences of  `"before_action"` inside all  ruby files within `app/controllers` directory:

```
:vim /before_action/ app/controllers/**/*.rb
```
 
You'll notice that once Vim is done, you don't immediately see all results. This is because the search result is inside quickfix (`:h quickfix`). To see the search result, type `:copen`.

I won't go over quickfix here. But here are some useful shortcuts to get started:

```
:cope[n]     " Open the quickfix window
:ccl[ose]    " Close the quickfix window
:cn[ext]     " Go to the next error
:cp[revious] " Go to the previous error
:col[der]    " Go to older error list
:cnew[er]    " Go to newer error list
```

You may notice that running internal grep (`:vim`) can get slow if there are many matches. This is because internal grep (`:vim`) reads all matches into memory. Vim loads each matching files as if they are being edited.

**External grep**, by default, uses shell `grep`. 

To search for `"require"` inside a ruby file inside my controllers, I can do:
```
:grep require app/controllers/**/*.rb
```

Just like `:vim`, `:grep` accepts `*` and `**`. It also displays via quickfix.

Vim uses `grepprg` variable to determine which external program to run when running `:grep`, so you don't have to always use shell `grep`. I will not discuss how to do it here because the point is this article is to use default Vim config, but if you're interested, this article [Faster Grepping in Vim](https://thoughtbot.com/blog/faster-grepping-in-vim) shows you how to integrate with [`Ag`](https://github.com/ggreer/the_silver_searcher) and  [Using ripgrep With Vim](https://www.wezm.net/technical/2016/09/ripgrep-with-vim/) shows you how to use it with [ripgrep](https://github.com/BurntSushi/ripgrep).

# Browsing files with `netrw`

`netrw` is Vim's built-in file explorer. In order to get started, you need two minimum settings in your `.vimrc`:

```
set nocp
filetype plugin on
```

I will only cover the very basic of `netrw`, but it should be enough to get started.

You can start `netrw` when you launch Vim and passing it a directory instead of a file:

```
vim .
vim src/client/
vim app/controllers/
```

To start `netrw` from inside Vim while editing a file, you can use `:e`:

```
:e .
:e src/client/
:e app/controllers/
```

Alternatively, `netrw` has its own set of commands to launch the explorer. Some of them are:

```
:Ex      " Explore directory of current file (head)
:Sex     " Not kidding. It splits horizontally and start netrw on top screen
:Vex     " Split vertically
```

You can navigate with Vim motions. `hjkl` and searches like `/?`, work well. To go up one directory, use `-`.

While inside `netrw` explorer, sometimes you need to create, delete, rename file/directory.

```
%    " create new file
d    " create new directory
R    " rename file/directory
D    " delete file/directory
```

To move file/directory requires more steps, but you can check [How do I copy a file in netrw?](https://vi.stackexchange.com/questions/6254/how-do-i-copy-a-file-in-netrw) or [Move a File with Netrw](https://til.hashrocket.com/posts/31d2f81172-move-a-file-with-netrw).

These should be enough to get you going. `:h netrw` is very comprehensive. If you have time, I highly suggest checking it out.

Some of you may ask, "Do I need to use `netrw`? [Nerdtree](https://github.com/preservim/nerdtree) looks much better."

It's up to you. I've used nerdtree for several years and I loved it. However, if you must use Vim without plugins and you're not used to `netrw` basic navigations, you may lose some speed.

By the way, [vim-vinegar](https://github.com/tpope/vim-vinegar) is a good (lightweight) plugin to enhance `netrw` if you decide to go with `netrw`.

<a name="plugins">
# Plugins
Last but not least, Vim has many plugins to let you quickly search for/ within files. Here are some of them:
- [fzf.vim](https://github.com/junegunn/fzf.vim)
- [CtrlP](https://github.com/kien/ctrlp.vim)
- [FuzzyFinder](https://github.com/vim-scripts/FuzzyFinder)
- [Command-T](https://github.com/wincent/command-t)

Plugins are awesome. I personally use `fzf.vim` with `ripgrep` for searching. I would recommend to learn what Vim can do without plugins before you use one. Only use the plugins you need.

# Conclusion
I think this is a good place to stop. I've shown you different ways to search and open files in Vim with:

1. `:e`
2. `:find`
3. `:vim` and `:grep`
4. `netrw`

You don't know when you'll have to use Vim without any. Be the Vim expert in your team.

Thanks for reading. Happy coding!

# Resources
- `:h :grep`/`:h netrw`/`:h :edit`/`:h :find`
- [Vim netrw](https://shapeshed.com/vim-netrw/)
- [Vim file navigation](https://stackoverflow.com/questions/1445992/vim-file-navigation)
- [How to grep in Vim](https://codeyarns.github.io/tech/2017-09-14-how-to-grep-in-vim.html)
- [How do you use vim's quickfix feature?](https://stackoverflow.com/questions/1747091/how-do-you-use-vims-quickfix-feature)
- [Move a File with Netrw](https://til.hashrocket.com/posts/31d2f81172-move-a-file-with-netrw)
- [Faster Grepping in Vim](https://thoughtbot.com/blog/faster-grepping-in-vim)
- [Practical Vim](https://pragprog.com/book/dnvim/practical-vim)