Fast Rake Task Completion for Zsh
Posted by nicholas March 09, 2006 @ 02:50 AM
Those of you who love running Rake tasks but don’t like typing are in for a treat. Although there’s been task completion for Rake for a while now, most of the scripts for it are painfully slow, especially with Rails’ Rakefile.
Below is a small zsh completion script that uses a cache file (named .rake_tasks) to improve the performance of your tab keystrokes.
To use, throw it in your home folder somewhere and add source $HOME/.rake_completion.zsh to your .zshrc file.
A few disclaimers: Yes, it doesn’t work with lowercase named rakefile’s. Only barbarians use such names though, so hopefully you won’t have a problem there. And no, it doesn’t complete the other assorted arguments that the rake command can accept, frankly because I rarely use them.
Without further ado, here’s the bytes.
_rake_does_task_list_need_generating () {
if [ ! -f .rake_tasks ]; then return 0;
else
accurate=$(stat -f%m .rake_tasks)
changed=$(stat -f%m Rakefile)
return $(expr $accurate '>=' $changed)
fi
}
_rake () {
if [ -f Rakefile ]; then
if _rake_does_task_list_need_generating; then
echo "\nGenerating .rake_tasks..." > /dev/stderr
rake --silent --tasks | cut -d " " -f 2 > .rake_tasks
fi
compadd `cat .rake_tasks`
fi
}
compdef _rake rake
(Use at your own risk. Comments and improvements welcome.)

Sorry for the shameless selfpromoting but on the topic of shell-helpers for Rails I have written a transparent wrapper for subversion that runs tests before committing and remind you to run migrations if there are new migrations available when you run update.
Here, using Gentoo linux with coreutils 5.94 I had to replace ‘stat -f%m’ with ‘stat -c%Y’ to make this work.
/Users/yeah/.rake_completion.zsh:20: command not found: compdef
The default zsh on OS X 10.4 is slightly different, so you may need to do something like this:
function _rake_does_task_list_need_generating () { if [ ! -f .rake_tasks ]; then return 0; else accurate=$(stat -f%m .rake_tasks) changed=$(stat -f%m Rakefile) return $(expr $accurate '>=' $changed) fi } function _rake () { if [ -f Rakefile ]; then if _rake_does_task_list_need_generating; then echo "\nGenerating .rake_tasks..." > /dev/stderr rake --silent --tasks | cut -d " " -f 2 > .rake_tasks fi reply=( `cat .rake_tasks` ) fi } compctl -K _rake rakeVery nice, thanks
i think it could be a little faster using awk to extract tasks rather than using rake!
i think it could be a little faster using awk to extract tasks rather than using rake!
Check out Rails’ and you’ll see why awk won’t work: You can include files from other places, and that tasks in these files won’t be seen by awk. Using Rake to get the information is the most accurate method, and caching the task list makes it fast enough to be joyful.
here is the command line: cat Rakefile| awk ‘zsh~/^task / {print substr(,2,length())}’ Note: sorry for posting a couple of times.
For those of us on Linux (Ubuntu and Gentoo at least), change the -f%m to -c%Z in the two stats in the first bit.
Neato!
Any chance to get that script adapted to work with bash?
Any bash guru out there?
Layout of this page is buggy on IE. Check it out.
You can accomplish something similar in Bash w/ complete, ala (just type this on command line in same directory as your Rakefile or put in ~/.bashrc):
complete -W ”`rake—silent—tasks | cut -d ” ” -f 2`” rake
(You can substitute -W (wordlist) w/ the function -F (function) but Im not sure how much time you are really saving w/ the caching)