diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-11-19 12:07:09 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-11-19 12:07:09 +0000 |
commit | 91c0ff4f7d28856645b72d09f58dbabfa5e862ad (patch) | |
tree | 3df4b21c3dd67b8969019c7dd190bddc142cb11a | |
parent | 67f3280cfe75391f97bb342da10186fa190373b2 (diff) |
* lib/optparse.rb: shell completion support for zsh. based on
<http://d.hatena.ne.jp/rubikitch/20071002/zshcomplete>
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29834 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | lib/optparse.rb | 49 | ||||
-rw-r--r-- | misc/rb_optparse.zsh | 30 | ||||
-rw-r--r-- | test/optparse/test_zsh_completion.rb | 22 |
4 files changed, 105 insertions, 1 deletions
@@ -1,4 +1,7 @@ -Fri Nov 19 20:26:51 2010 Nobuyoshi Nakada <[email protected]> +Fri Nov 19 21:07:06 2010 Nobuyoshi Nakada <[email protected]> + + * lib/optparse.rb: shell completion support for zsh. based on + <http://d.hatena.ne.jp/rubikitch/20071002/zshcomplete> * lib/optparse.rb: shell completion support for bash. diff --git a/lib/optparse.rb b/lib/optparse.rb index e36b52f7ec..b21bd935c7 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -441,6 +441,24 @@ class OptionParser (long.first || short.first).sub(/\A-+(?:\[no-\])?/, '') end + def compsys(sdone, ldone) # :nodoc: + sopts, lopts, s = [], [], nil + @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short + @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long + return if sopts.empty? and lopts.empty? # completely hidden + + (sopts+lopts).each do |opt| + # "(-x -c -r)-l[left justify]" \ + if opt =~ /^--\[no-\](.+)$/ + o = $1 + yield("--#{o}", desc.join("")) + yield("--no-#{o}", desc.join("")) + else + yield("#{opt}", desc.join("")) + end + end + end + # # Switch that takes no arguments. # @@ -679,6 +697,14 @@ class OptionParser end to end + + def compsys(*args, &block) # :nodoc: + list.each do |opt| + if opt.respond_to?(:compsys) + opt.compsys(*args, &block) + end + end + end end # @@ -725,6 +751,24 @@ class OptionParser DefaultList.short['-'] = Switch::NoArgument.new {} DefaultList.long[''] = Switch::NoArgument.new {throw :terminate} + + COMPSYS_HEADER = <<'XXX' # :nodoc: + +typeset -A opt_args +local context state line + +_arguments -s -S \ +XXX + + def compsys(to, name = File.basename($0)) # :nodoc: + to << "#compdef #{name}\n" + to << COMPSYS_HEADER + visit(:compsys, {}, {}) {|o, d| + to << %Q[ "#{o}[#{d.gsub(/\"/, '\"')}]" \\\n] + } + to << " '*:file:_files' && return 0\n" + end + # # Default options for ARGV, which never appear in option summary. # @@ -737,11 +781,16 @@ class OptionParser # --help=complete=WORD # Shows candidates for command line completion. # + # --help=zshcomplete[=NAME:FILE] + # Creates zsh completion file. + # Officious['help'] = proc do |parser| Switch::OptionalArgument.new do |arg| case arg when /\Acomplete=(.*)/ puts parser.candidate($1) + when /\Azshcomplete(?:=(.+))?/ + parser.compsys(STDOUT, $1) else puts parser.help end diff --git a/misc/rb_optparse.zsh b/misc/rb_optparse.zsh new file mode 100644 index 0000000000..2aff063744 --- /dev/null +++ b/misc/rb_optparse.zsh @@ -0,0 +1,30 @@ +#!/bin/zsh +# Completion for zsh: +# (based on <http://d.hatena.ne.jp/rubikitch/20071002/zshcomplete>) +# +# (1) install this file, +# +# (2) load the script, and +# . ~/.zsh.d/rb_optparse.zsh +# +# (3) geneate completion files once. +# generate-complete-function/ruby/optparse COMMAND1 +# generate-complete-function/ruby/optparse COMMAND2 +# + +generate-complete-function/ruby/optparse () +{ + local cmpl="_${1:t}" + mkdir -p "${ZSH_COMPLETION_DIR-$HOME/.zsh.d/Completion}" + $1 --help=zshcomplete="${1:t}" > "${ZSH_COMPLETION_DIR-$HOME/.zsh.d/Completion}/$comp" + if [[ $(type -w "$cmpl") == "${cmpl}: function" ]]; then + unfunction "$cmpl" + autoload -U "$cmpl}" + else + compinit "$cmpl" + fi +} + +for cmd in "$@"; do + generate-complete-function/ruby/optparse "$cmd" +done diff --git a/test/optparse/test_zsh_completion.rb b/test/optparse/test_zsh_completion.rb new file mode 100644 index 0000000000..7e5ba71384 --- /dev/null +++ b/test/optparse/test_zsh_completion.rb @@ -0,0 +1,22 @@ +require 'test/unit' +require 'optparse' + +class TestOptionParser < Test::Unit::TestCase +end +class TestOptionParser::BashCompletion < Test::Unit::TestCase + def setup + @opt = OptionParser.new + @opt.define("-z", "zzz") {} + @opt.define("--foo") {} + @opt.define("--bar=BAR") {} + @opt.define("--for=TYPE", [:hello, :help, :zot]) {} + end + + def test_compsys + compsys = @opt.compsys("", "zshcompsys") + assert_match(/\"-z\[zzz\]\"/, compsys) + assert_match(/\"--foo\[\]\"/, compsys) + assert_match(/\"--bar\[\]\"/, compsys) + assert_match(/\"--for\[\]\"/, compsys) + end +end |