Skip to content

Instantly share code, notes, and snippets.

@csswizardry
Last active June 16, 2024 13:44
Show Gist options
  • Save csswizardry/9a33342dace4786a9fee35c73fa5deeb to your computer and use it in GitHub Desktop.
Save csswizardry/9a33342dace4786a9fee35c73fa5deeb to your computer and use it in GitHub Desktop.
Vim without NERD tree or CtrlP

Vim without NERD tree or CtrlP

I used to use NERD tree for quite a while, then switched to CtrlP for something a little more lightweight. My setup now includes zero file browser or tree view, and instead uses native Vim fuzzy search and auto-directory switching.

Fuzzy Search

There is a super sweet feature in Vim whereby you can fuzzy find your files using **/*, e.g.:

:vs **/*<partial file name><Tab>

This will search the current directory and all directories below it for filenames containing your partial search. This can be used with :e, :sp, :vsp.

If there are multiple possible matches, you can see the options you have available by setting this in your .vimrc:

" Show file options above the command line
set wildmenu

For more information, run :h 'wildmenu'.

You’ll probably also want to exclude certain file types and directories from this fuzzy finding, so you can stick these in your .vimrc:

" Don't offer to open certain files/directories
set wildignore+=*.bmp,*.gif,*.ico,*.jpg,*.png,*.ico
set wildignore+=*.pdf,*.psd
set wildignore+=node_modules/*,bower_components/*

Now we’re at a point where I don’t need to look through any directories: if I know I want to open my _components.buttons.scss file I just need to do:

:vs **/*butto<Tab>

Vim will go off and find this for me, and if there are multiple possible matches it will also neatly display them all for me.

Auto-Change Directory

Vim runs from the context of wherever your ran $ vim from, so let’s say you have this simple project:

.
├── css
│   ├── components
│   │   ├── buttons.scss
│   │   ├── modal.scss
│   │   └── nav.scss
│   └── main.scss
├── index.html
└── js
    └── modules
        ├── buttons.js
        ├── modal.js
        └── nav.js

If we run $ vim index.html from here, we’d need to run the following within Vim in order to open the button’s Sass file in a new vertical split:

:vs css/components/buttons.scss

Them from there, to open the modal.scss, you’d need to run:

:vs css/components/modal.scss

This is kind of annoying, but we can get rid of if by telling Vim to track our current file’s directory! Drop this in your .vimrc:

" Set the working directory to wherever the open file lives
set autochdir

Now all of our file paths are relative to the current file, not absolute based on where we initialised Vim from! This means that we only need to do this in order to open our modal’s Sass file:

:vs modal.scss

…because Vim automatically moved us into the css/components/ directory.

You can toggle this by running:

:set autochdir!

…or you may prefer to make a mapping.

gf

Add this to your ~/.vimrc:

" `gf` opens file under cursor in a new vertical split
nnoremap gf :vertical wincmd f<CR>

When your cursor is over a path to a different file, hitting gf (go to file) will open it in a new split window. This helps you quickly explore the project based on its depedencies.

Without the above mapping, gf will still open the new file but in the same window.

Ack

If you’re not familiar with Ack, give it a quick read and then install Ack.vim. Now we can find things inside of files across our entire project by doing this:

:Ack --html 'button'

This will search all HTML files in the current directory (be mindful of your autochdir settings) and all directories below it for the string button. It will then populate your Quickfix list (:h quickfix) with all matching results (this is basically project-wide Find).

We can then take this one step further (if we need to) by running :cdo commands: a way of running a command over all of the results in our Quickfix list. Let’s say we found all instances of button by using the above, and now we want to change them all to btn. We can run this:

:cdo %s/btn/button/gc | update
  • :cdo tells Vim to do something across all items in our Quickfix list.
  • %s/button/btn/ tells Vim to look at every line (%) and substitite all instances of button for btn.
  • gc tells Vim to do this globally on each line and asks us, the developer, to manually confirm the change.
  • | update tells Vim to update the Quickfix list after making changes

All Together

So now we’re in a position where we can fuzzy search for file names, we can move Vim into our current directory to make things simpler to look for, we can do global finds using Ack, and global find and replace using the Quickfix list.

No more need for file explorer plugins!

@aliev
Copy link

aliev commented Jul 17, 2017

Ag is more faster than Ack. So you can also use it even without any plugins. My Configuration looks like:

if isdirectory('.git') && executable('git')
  set grepprg=git\ grep\ -nI
endif

if executable('ag') && !isdirectory('.git')
  " Silver searcher instead of grep
  set grepprg=ag\ --vimgrep
  set grepformat=%f:%l:%c%m
endif

:grep something

(and it will super faster in "git project" because of git grep).

My key map to find word under cursor:

map <LocalLeader>g :silent grep! <C-R>=expand("<cword>")<CR>

@idhamhafidz
Copy link

Excellent. Thanks

@vprasanth
Copy link

Great documentation, thank you!

@skyeplus
Copy link

There is a standard equivalent for remapped gf. Ctrl-W f or Ctrl-W F opens up a new horizontal window on the file location under cursor. f - is for a plain file name, F - jump to the line number if it's appended with colon after the filename (F variant for all "go file" commands is very handy when navigating grep -nr formatted search results opened in a temporary window). I don't know if there is a vertical split equivalent for this, but you can easily rearrange it with move window commands (Ctrl-W L or Ctrl-W H).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment