aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-11-19 12:07:09 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-11-19 12:07:09 +0000
commit91c0ff4f7d28856645b72d09f58dbabfa5e862ad (patch)
tree3df4b21c3dd67b8969019c7dd190bddc142cb11a
parent67f3280cfe75391f97bb342da10186fa190373b2 (diff)
downloadruby-91c0ff4f7d28856645b72d09f58dbabfa5e862ad.tar.gz
* 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--ChangeLog5
-rw-r--r--lib/optparse.rb49
-rw-r--r--misc/rb_optparse.zsh30
-rw-r--r--test/optparse/test_zsh_completion.rb22
4 files changed, 105 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index c47d6c5101..fe550356da 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,7 @@
-Fri Nov 19 20:26:51 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Fri Nov 19 21:07:06 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * 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