May 03, 2007
Tab completion for Capistrano tasks in bash
I love tab completion for rake tasks, and tonight I got annoyed that I didn’t have the same thing for Capistrano tasks. Here’s what I came up with:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#!/usr/bin/env ruby # Save this somewhere, chmod 755 it, then add # complete -C path/to/this/script -o default cap # to your ~/.bashrc or ~/.bash_login # # If you update your tasks, just $ rm ~/.captabs* # # Originally adapted from # http://onrails.org/articles/2006/08/30/namespaces-and-rake-command-completion exit 0 unless File.file?(File.join(Dir.pwd, 'config', 'deploy.rb')) exit 0 unless /^cap\b/ =~ ENV["COMP_LINE"] def cap_tasks if File.exists?(dotcache = File.join(File.expand_path('~'), ".captabs-#{Dir.pwd.hash}")) File.read(dotcache) else tasks = `cap show_tasks 2>/dev/null|tail +3|cut -c 1-30|grep "[a-z]"|grep -v "^after_"|sort` File.open(dotcache, 'w') { |f| f.puts tasks } tasks end end after_match = $' task_match = (after_match.empty? || after_match =~ /\s$/) ? nil : after_match.split.last tasks = cap_tasks.split("\n").map { |t| t.gsub(/\s/, '') } tasks = tasks.select { |t| /^#{Regexp.escape task_match}/ =~ t } if task_match puts tasks exit 0 |
Enjoy.
Update: I switched to Capistrano 2.0. Here’s the new tab completion code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#!/usr/bin/env ruby # Save this somewhere, chmod 755 it, then add # complete -C path/to/this/script -o default cap # to your ~/.bashrc # # If you update your tasks, just $ rm ~/.captabs* # # Adapted from # http://onrails.org/articles/2006/08/30/namespaces-and-rake-command-completion exit 0 unless File.file?(File.join(Dir.pwd, 'config', 'deploy.rb')) exit 0 unless /^cap\b/ =~ ENV["COMP_LINE"] def cap_tasks if File.exists?(dotcache = File.join(File.expand_path('~'), ".captabs-#{Dir.pwd.hash}")) File.read(dotcache) else tasks = `cap -T|grep "^cap"|cut -d " " -f 2` File.open(dotcache, 'w') { |f| f.puts tasks } tasks end end after_match = $' task_match = (after_match.empty? || after_match =~ /\s$/) ? nil : after_match.split.last tasks = cap_tasks.split("\n").map { |t| t.gsub(/\s/, '') } 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.map { |t| (t =~ /^#{Regexp.escape upto_last_colon}([-\w:]+)$/) ? "#{$1}" : t } end puts tasks exit 0 |