onrails.org home

Namespaces and Rake Command Completion

Update: Now using rake and caching

I got some basic rake command line completion working today using Jon Baer’s comment. Very simple, very easy:

complete -W '`rake—silent—tasks | cut -d ” ” -f 2`' -o default rake

However this didn’t work for the namespaced tasks in a rails app like rake test:units. Searching a little further I found a reference to some code Nicholas Seckar wrote on project.ioni.st. This used ruby to find the possible tasks for command completion. This looked promising, but it still didn’t work for namespaced tasks. A little more googling led me to what looked like the perfect link: Rake-completion script that handles namespaces. Alas, it only handled one level of namespacing. It worked nicely for rake test:units, but rake tmp:ses<TAB> would complete to rake tmp:clear instead of rake tmp:sessions:clear. Also, rake test:units <TAB> would complete to rake test:units units instead of giving me all the tasks again, just in case you want to run multiple tasks form the command line.

So, now what? Stand on the shoulders of others, naturally. Here is what I’m using now that handles multiple namespaces and multiple tasks per command line:

#!/usr/bin/env ruby # Complete rake tasks script for bash # Save it somewhere and then add # complete -C path/to/script -o default rake # to your ~/.bashrc # Nicholas Seckar # Saimon Moore # http://www.webtypes.com/2006/03/31/rake-completion-script-that-handles-namespaces exit 0 unless File.file?(File.join(Dir.pwd, 'Rakefile')) exit 0 unless /^rake\b/ =~ ENV["COMP_LINE"] after_match = $' task_match = (after_match.empty? || after_match =~ /\s$/) ? nil : after_match.split.last tasks = `rake --silent --tasks`.split("\n")[1..-1].collect {|line| line.split[1]} tasks = tasks.select {|t| /^#{Regexp.escape task_match}/ =~ t} if task_match # handle namespaces if task_match =~ /^([-\w:]+:)/ upto_last_colon = $1 after_match = $' tasks = tasks.collect { |t| (t =~ /^#{Regexp.escape upto_last_colon}([-\w:]+)$/) ? "#{$1}" : t } end puts tasks exit 0

Enjoy

Fork me on GitHub