Command-T is a vim plugin for rapid file navigation using fuzzy path matching. It is one of the few plugins I find truly essential. Although profoundly useful, I find that there are a few customizations that make it unbeatable.
In order to make Command-T a little more friendly, I do the following:
- Make all Command-T actions relative the current git repo root
- Use the
.gitignoreto filter the file list
- Setup a collection of maps for starting Command-T in subfolders
Command-T Relative the Git Root
The first thing I do in order to make working with Command-T more friendly is to make it work from the root of the current git repo. Reaching for Commend-T implies that I am in a project of some non trivial size, ie anything with one or more subfolders, then I can pretty safely assume I will have it in a git repo.
The following functions allow me to move the current working directory to the root of the git repo before starting up Command-T.
function! Git_Repo_Cdup() " Get the relative path to repo root "Ask git for the root of the git repo (as a relative '../../' path) let git_top = system('git rev-parse --show-cdup') let git_fail = 'fatal: Not a git repository' if strpart(git_top, 0, strlen(git_fail)) == git_fail " Above line says we are not in git repo. Ugly. Better version? return '' else " Return the cdup path to the root. If already in root, " path will be empty, so add './' return './' . git_top endif endfunction function! CD_Git_Root() execute 'cd '.Git_Repo_Cdup() let curdir = getcwd() echo 'CWD now set to: '.curdir endfunction nnoremap <LEADER>gr :call CD_Git_Root()<cr>
Using the .gitignore
By default, Command-T will use the vim
wildignore setting to filter files
from the Command-T list. This means that there will only be one global filter
used in every vim session to filter things out. This can be an issue when
working with things like an Octopress blog (like this one), a Rails 3.1 app, or
anything else that has build output or other numerous files that will be in the
I was able to track down a vim plugin create by Adam Bellaire that can parse a
gitignore and use it to define the vim
wildignore setting. His original
script can be found
here, but since it only
included a single function I just included that directly in my vimrc. What
follows is my version of Adam’s original script, wrapped up as a vim function:
" Define the wildignore from gitignore. Primarily for CommandT function! WildignoreFromGitignore() silent call CD_Git_Root() let gitignore = '.gitignore' if filereadable(gitignore) let igstring = '' for oline in readfile(gitignore) let line = substitute(oline, '\s|\n|\r', '', "g") if line =~ '^#' | con | endif if line == '' | con | endif if line =~ '^!' | con | endif if line =~ '/$' | let igstring .= "," . line . "*" | con | endif let igstring .= "," . line endfor let execstring = "set wildignore=".substitute(igstring,'^,','',"g") execute execstring echo 'Wildignore defined from gitignore in: '.getcwd() else echo 'Unable to find gitignore' endif endfunction nnoremap <LEADER>cti :call WildignoreFromGitignore()<cr> nnoremap <LEADER>cwi :set wildignore=''<cr>:echo 'Wildignore cleared'<cr>
Subfolder Focused Command-T Mappings
This last piece was inspired by a Destroy All Software screencast by Gary Bernhardt. I highly recommend anything by Gary Bernhardt.
All in all I am very happy with where I am at with file navigation. I barely have to think at this point to get to a file, and that’s the way I like it. You can checkout the full details of this and my other vim configs in my vimrc.
Room for Improvement
The one major issue I have with my current Command-t usage outlined above is
the need to explicitly fire the Command-t from gitignore function. I would like
to set this to fire based on an autocommand or by hooking into vims
trigger it automatically. I would imagine it would be necessary to cache the
current project in order to avoid doing this all the time. As of now I haven’t
felt a strong enough pull to figure this out, but I expect I will revisit it