Speeding up Selecta in Vim
2015-02-16I like using Selecta as a fuzzy file opener in Vim. It doesn’t do any caching, so I never have to remember to flush the cache after generating a migration in Rails.
The downside is that if you work on a larger project, it can get kinda pokey. Selecta’s Vim functionality relies on find
to populate the file list. If we tell find to ignore directories, it gets a lot faster. Here’s how many files the default find command returns.
><((°> find . -type f | wc -l
13213
That’s a lot! Let’s see if we can cut it down. I’m using a pretty typical Rails project as an example.
><((°> ls
Gemfile README.md coverage spec
Gemfile.lock Rakefile db tmp
Guardfile app lib vendor
Procfile bin log
Procfile.dev config public
Procfile.jobs.dev config.ru script
Logfiles are handy, but I never open them in Vim. If I need to see something, I’ll tail
it in the terminal. I also don’t care about tmp
. We’ll exclude hidden directories too, just for good measure. Let’s cut those out of the find command.
><((°>
find . \( -path ./log -o -path ./tmp -o -path './.*' \) -prune -o -type f -print | wc -l
2348
Woah! We just excluded 10,865 files! That oughta speed things up a bit. But first I’ll slow down and explain the command.
-o
stands for OR. It breaks the find arguments into two major parts:\( -path ./log -o -path ./tmp -o -path './.*' \) -prune
-type f -print
\( ... \)
is a group. We’re using it to OR several-path
arguments together.- If one of the paths in the group matched,
-prune
kicks in andfind
ignores that path. - Otherwise, the file name is printed.
Now we just have to put it in our config. Here’s what the old Vim mapping looked like:
nnoremap <leader>f :call SelectaCommand("find * -type f", "", ":e")<cr>
Here’s the new one:
let find_cmd = "find . \( -path ./log -o -path ./tmp -o -path './.*' \) "
\ . "-prune -o -type f -print"
nnoremap <leader>t :call SelectaCommand(find_cmd, "", ":e")<cr>
This is also an example of how to set a variable and concatinate a string in VimL.
Now, this isn’t totally optimal. I’d like to set up some directories that Selecta should ignore on a per-project basis. But it’ll do for now.
Also, Vim isn’t the only place that Selecta is useful! You can use it any place that you can pipe input into a command. This post has a bunch of other nifty examples.