[ditz-talk] [PATCH] Add support shell completion (zsh for now).

Nicolas Pouillard nicolas.pouillard at gmail.com
Wed Apr 9 19:55:17 EDT 2008


Note: patch pushed on my repo-clone as well.

---
 bin/ditz                     |   14 +++++++++++++-
 contrib/completion/_ditz.zsh |   29 +++++++++++++++++++++++++++++
 lib/operator.rb              |   15 ++++++++++++++-
 3 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 contrib/completion/_ditz.zsh

diff --git a/bin/ditz b/bin/ditz
index 0b042df..4b85d0a 100755
--- a/bin/ditz
+++ b/bin/ditz
@@ -1,5 +1,18 @@
 #!/usr/bin/env ruby
 
+# requires are splitted in two for efficiency reasons
+# ditz should be really fast when using it for
+# completion.
+require 'operator'
+
+op = Ditz::Operator.new
+
+# a secret option for shell completion
+if ARGV.include? '--commands'
+  puts op.class.operations.map { |name, _| name }
+  exit 0
+end
+
 require 'rubygems'
 require 'fileutils'
 require 'trollop'; include Trollop
@@ -17,7 +30,6 @@ $opts = options do
 end
 
 cmd = ARGV.shift or die "expecting a ditz command"
-op = Ditz::Operator.new
 dir = $opts[:issue_dir]
 
 case cmd # some special cases not handled by Ditz::Operator
diff --git a/contrib/completion/_ditz.zsh b/contrib/completion/_ditz.zsh
new file mode 100644
index 0000000..656860f
--- /dev/null
+++ b/contrib/completion/_ditz.zsh
@@ -0,0 +1,29 @@
+#compdef ditz
+
+ME=ditz
+COMMANDS=--commands
+OPTIONS='<options>'
+
+if (($CURRENT == 2)); then
+  # We're completing the first word after the tool: the command.
+  _wanted command expl "$ME command" \
+    compadd -- $( "$ME" "$COMMANDS" )
+else
+  # Find the options/files/URL/etc. for the current command by using the tool itself.
+      case "${words[$CURRENT]}"; in
+        -*)
+          _wanted args expl "Arguments for $ME ${words[2]}" \
+             compadd -- $( "$ME" "${words[2]}" "$OPTIONS" ; _files )
+            ;;
+        ht*|ft*)
+            _arguments '*:URL:_urls'
+            ;;
+        /*|./*|\~*|../*)
+            _arguments '*:file:_files'
+            ;;
+        *)
+          _wanted args expl "Arguments for $ME ${words[2]}" \
+             compadd -- $( "$ME" "${words[2]}" "$OPTIONS" )
+          ;;
+      esac
+fi
diff --git a/lib/operator.rb b/lib/operator.rb
index 74c9507..74ce0b0 100644
--- a/lib/operator.rb
+++ b/lib/operator.rb
@@ -59,10 +59,12 @@ class Operator
       command = "command '#{method_to_op method}'"
       built_args = @operations[method][:args_spec].map do |spec|
         val = args.shift
+        generate_choices(project, method, spec) if val == '<options>'
         case spec
         when :issue
           raise Error, "#{command} requires an issue name" unless val
-          project.issue_for(val) or raise Error, "no issue with name #{val}"
+          valr = val.sub(/\A(\w+-\d+)_.*$/,'\1')
+          project.issue_for(valr) or raise Error, "no issue with name #{val}"
         when :release
           raise Error, "#{command} requires a release name" unless val
           project.release_for(val) or raise Error, "no release with name #{val}"
@@ -75,9 +77,20 @@ class Operator
           val # no translation for other types
         end
       end
+      generate_choices(project, method, nil) if args.include? '<options>'
       raise Error, "too many arguments for #{command}" unless args.empty?
       built_args
     end
+
+    def generate_choices project, method, spec
+      case spec
+      when :issue
+        puts project.issues.map { |i| "#{i.name}_#{i.title.gsub(/\W+/, '-')}" }
+      when :release, :maybe_release
+        puts project.releases.map { |r| r.name }
+      end
+      exit 0
+    end
   end
 
   def do op, project, config, args
-- 
1.5.5.rc3



More information about the ditz-talk mailing list