Speeding up Selecta in Vim2015-02-16
I 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.
-ostands 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
- If one of the paths in the group matched,
-prunekicks in and
findignores 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.