'Vim file navigation

I'm trying really hard to learn vim after using TextMate for the last few years.

I've started to commit some of the in-file navigation to memory but I'm struggling with navigating between multiple files.

In my workflow it is pretty common that I'm flipping between a handful of files pretty regularly (enough files such that split-pane windows become too small).

I'm currently using NERDTree but find drilling down into directories cumbersome as well as constantly using CTRL+W h/CTRL+W l to hop back and forth.

I think I would do better with tabs I can easily toggle between but maybe I need to use a different workflow.

I'd also like a "Go to File..." shortcut like CMD+T in TextMate. I've found fuzzy_file_finder but it requires vim to be built with Ruby bindings which isn't the case the native installs I've worked on.

While I could rebuild the main reason I want to switch to vim is so I can have one editor environment that I know will easily work across any platform.



Solution 1:[1]

An easy way to browse the file system is the command:

:Sex

I'm not making this up :)

Solution 2:[2]

:Sex,:Vex, :Tex and :Ex are all useful commands for ex(ploring) the files on your system if you want to use something different from :e

(where S/V/T are short for Split/Vertical/Tab)

Solution 3:[3]

If you haven't found them already, you might want to check out:

  • the original fuzzy finder plugin -- which IIRC doesn't have the Ruby binding issues
  • the Project plugin -- similar to NERDTree
  • the buffer explorer plugin -- shows a list of open buffers

Also bear in mind that you can remap key shortcuts in your .vimrc to make them less cumbersome. I do use split windows a lot; I've found the following make dealing with them much easier:

" set your own personal modifier key to something handy
let mapleader = "," 

" use ,v to make a new vertical split, ,s for horiz, ,x to close a split
noremap <leader>v <c-w>v<c-w>l
noremap <leader>s <c-w>s<c-w>j
noremap <leader>x <c-w>c

" use ctrl-h/j/k/l to switch between splits
map <c-j> <c-w>j
map <c-k> <c-w>k
map <c-l> <c-w>l
map <c-h> <c-w>h

Solution 4:[4]

By far the best and fastest plugin I found for file navigation is fzf.vim. You can very quickly fuzzy search all your files, the open buffers and even the files contents.

Since we have a very large codebase at work I specified a couple of directories I use most as the directories fzf searches. Fzf even has a rich git integration. So you can search only tracked files.

This is how the file search looks: enter image description here

and his is how the content search looks:
enter image description here

Solution 5:[5]

It is surprising to see that :find command has not been mentioned in any of the answers. I usually work with rails projects where I need to drill down deep into the directory hierarchy. So for a file application.css, located in app/assets/stylesheets/ all I have to type is :find applica and then press tab to autocomplete and enter to open.

Solution 6:[6]

I think I would do better with tabs I can easily toggle between, but maybe I need to use a different workflow.

Are you aware of Vim's tabs? Not sure if you were referring to Vim's own tabs there, or pining for TextMate's. It's unclear what Vim version you're using but it's had tabs since at least 7.0 (which seems to be installed everywhere I look lately), and they're awesome.

:tabe opens a new one (short for "tab edit", so e.g. :tabe for empty or :tabe path/to/file for opening a file in a new tab,) you can move between adjacent tabs with gt/gT, and there's a bunch of other tab-related nav commands too, as you might expect from Vim (:help tabs)

My workflow for large projects tends to involve a bunch of tabs, each with between 1 and 3 windows depending on what sort of context I need. This works even better if I have a doublewide terminal window since I can vertically split with :vs, so then a single tab can easily show me 4 files at once with plenty of room for each.

Final tip: I sometimes use the "switch buffer" command (:sb <partial_buf_name>) which is sorta-kinda like TM's fuzzy finding, in that it works pretty well but only for already-open buffers. Still great for when I have a dozen or more files open at once. (N.B. I needed to :set switchbuf=usetab in my vimrc for this to work across tabs, but once that's set it's great.)

Solution 7:[7]

I find LustyExplorer the best so far.

You can open a file by typing only a part of its name.

You can open a file from the directory of the current file, or the current pwd, or from the buffer list.

If you open a file from the buffer list, you don't have to navigate through the directory tree, though unfortunately for the other two modes, you still have to navigate through the tree. The good thing is you don't have to start from the first character.

If you have:

dir_a/
    ...
dir_b/
    file.js
    file.html

and you want to open dir_b/file.html you can generally find it by typing b<Tab>h

Solution 8:[8]

Check out the plugin ctrlp as an alternative to the plugin Command-T. It's better than this in that it is a 'native' Vim script and doesnt need Vim to be compiled with ruby (or other support) while it runs very fast and unobtrusive.

Solution 9:[9]

If the file that you want is already loaded into a buffer (which is likely if you are flipping between a handful of files regularly) then you can quickly switch to the buffer with the :b[uffer] command.

:b can either take a buffer number as a parameter, or (more usefully) a string that matches part of the path/filename. If there are multiple matches you can use tab to cycle through them.

If you want to split the window and open the buffer in the new window then use :sb name

If you want to open the buffer in a new tab then use :tab b name

You can also use the :ls command to see a list of currently loaded buffers.

Solution 10:[10]

I use this function for finding files in subdirectories, I didn't write it though. It's from the vim wiki:

function! Find(name) 
    let l:list=system("find . -name '".a:name."' | grep -v \".svn/\" | perl -ne 'print \"$.\\t$_\"'") 
    let l:num=strlen(substitute(l:list, "[^\n]", "", "g")) 
    if l:num 0 
            echo "Not a number" 
            return 
        endif 
        if l:inputl:num 
            echo "Out of range" 
            return 
        endif 
        let l:line=matchstr("\n".l:list, "\n".l:input."\t[^\n]*") 
    else 
      let l:line=l:list 
    endif 
    let l:line=substitute(l:line, "^[^\t]*\t./", "", "") 
    execute ":e ".l:line 
endfunction 

command! -nargs=1 Find :call Find("") 

One thing I like is it has support for wildcards (*). It's also well behaved for multiple matches.

Solution 11:[11]

In addition to the wildmenu answers, I use BufExplorer plugin, and the following mappings to quickly jump buffers:

nmap <A-1> :b 1<CR>
nmap <A-2> :b 2<CR>
nmap <A-3> :b 3<CR>
...
nmap <A-0> :b 10<CR>
nmap <A-=> \bs

Or you can just replace the buffer explorer with the :ls command, which basically display the same thing.

The last one maps the Alt-= to show the buffer explorer.

I don't use Windows that much, as I generally have one or two windows only.

I also modified the statusline to include the buffer number %2n, so that the I always know which buffer is being edited. See :h statusline

Solution 12:[12]

do you know MacVim application? It is VIM polished for OS X, and one of its feature is support for tabs (CMD+T to open new tab), it have drawer, etc... (read this: http://zerokspot.com/weblog/2008/08/03/macvim-as-textmate-replacement/)

Try it!

Regards Michal

Solution 13:[13]

NerdTree is best for file navigation in vim.

The link below is a good introduction to nerdtree.

http://www.catonmat.net/blog/vim-plugins-nerdtree-vim/

Solution 14:[14]

Here's something fairly trivial that I stick in my .vimrc. It will load a file from any subdirectory.

" load from an unspecified subdirectory 
function! LoadFromSubdirectory(filespec) 
  let filename = glob("`find . -name '" . a:filespec . "' -print`") 
  exe ':e '.filename 
endfunction 
:command -nargs=1 Er :call LoadFromSubdirectory(<f-args>) 

So I can just say:

:Er Main.java

and it will search subdirectories, find Main.java and load it. It's not well behaved for multiple files of the same name, but it's quick and simple.

The other tool I use is VTreeExplorer, which provides a tree-based window of files/directories, and doesn't require any special build options from VIM (i.e. it's a vanilla plugin).

Solution 15:[15]

My workflow for finding files is the wildmenu, autocwd and :e.

Relevant parts in the .vimrc:

set wildmenu
set wildignore=*.dll,*.o,*.pyc,*.bak,*.exe,*.jpg,*.jpeg,*.png,*.gif
set wildmode=list:full
set autochdir
let g:netrw_list_hide='^\.,.\(pyc\|pyo\|o\)$'

And how to use it:

:e myf^D

That gives all the files in the current directory that start with myf. You can also <Tab> through them. Use return to open :)

^D will always give you all the matches. Because autocmd always goes to the folder of the current file it's easy to work with. If you are in foo/bar.py and you want to go to foo/baz.py you only do :e baz.py and you're there. That also works with buffers (:b foo^D lists all buffers starting with foo)