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

Jeff Balogh its.jeff.balogh at gmail.com
Fri Apr 11 02:33:32 EDT 2008


Nicolas Pouillard wrote:
> 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

This is *very* useful.  Thanks!


More information about the ditz-talk mailing list