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.)

Posted in Tools, Tricks | 13 comments

Comments

  1. Tuxie on 09 Mar 05:37:

    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.

  2. Tarmo on 09 Mar 11:48:

    Here, using Gentoo linux with coreutils 5.94 I had to replace ‘stat -f%m’ with ‘stat -c%Y’ to make this work.

  3. Yeah on 09 Mar 17:56:

    /Users/yeah/.rake_completion.zsh:20: command not found: compdef

  4. Faisal N. Jawdat on 09 Mar 18:19:

    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 rake
    
  5. gogo on 09 Mar 18:31:

    Very nice, thanks

  6. alaa on 09 Mar 19:30:

    i think it could be a little faster using awk to extract tasks rather than using rake!

  7. alaa on 09 Mar 19:30:

    i think it could be a little faster using awk to extract tasks rather than using rake!

  8. Ulysses on 09 Mar 19:48:

    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.

  9. alaa on 09 Mar 19:49:

    here is the command line: cat Rakefile| awk ‘zsh~/^task / {print substr(,2,length())}’ Note: sorry for posting a couple of times.

  10. Jamie Macey on 10 Mar 20:00:

    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.

  11. Lord of the Chunky Bacon on 11 Mar 13:34:

    Neato!

    Any chance to get that script adapted to work with bash?

    Any bash guru out there?

  12. Michael on 13 Mar 12:36:

    Layout of this page is buggy on IE. Check it out.

  13. Jon Baer on 15 Mar 08:28:

    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)