Follow @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
- Searching for files with
:find
- Searching for pattern within files with
:grep
- Browsing files with
netrw
I will also briefly list popular search plugins before concluding 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.
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 searchfile
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 shows you how to integrate with Ag
and Using ripgrep With Vim shows you how to use it with 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? or 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 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 is a good (lightweight) plugin to enhance netrw
if you decide to go with netrw
.
Plugins
Last but not least, Vim has many plugins to let you quickly search for/ within files. Here are some of them:
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:
:e
:find
:vim
and:grep
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
- Vim file navigation
- How to grep in Vim
- How do you use vim's quickfix feature?
- Move a File with Netrw
- Faster Grepping in Vim
- Practical Vim