带子命令的OptionParser

时间:2015-07-20 17:38:36

标签: ruby

我尝试使用OptionParser创建包含子命令的命令行程序。我跟随" ruby's OptionParser to get subcommands"。

问题在于它不允许这样的用例:

ruby main.rb --version 
#=> main.rb in `<main>': undefined method `order!' for nil:NilClass (NoMethodError)

但它确实允许这样做:

ruby main.rb foo --options
ruby main.rb --options foo
ruby main.rb --options foo --options

在没有给出子命令的情况下,如何正确处理命令行参数。

我的示例代码是:

global = OptionParser.new do |opts|
  opts.banner = "Usage: opt.rb [options] [subcommand [options]]"
  opts.on("-v", "--version", "Print the version") do |v|
    options[:version] = v
  end
  opts.separator ""
  opts.separator subtext
end

2 个答案:

答案 0 :(得分:1)

也许这会有所帮助:

require 'optparse'

VERSION = '1.0.0'

options = {}
OptionParser.new do |opt|
  opt.on('-f', '--foo', 'Foo it') { |o| options[:foo] = o }

  opt.on_tail('-v', '--version') do
    puts VERSION
    exit
  end

end.parse!

puts options

将其另存为&#34; test.rb&#34;并使用ruby test.rb运行它返回:

{}

使用ruby test.rb -f--foo运行它会返回:

{:foo=>true}

使用ruby test.rb -v--version运行它会返回:

1.0.0

为了获得更多乐趣,请运行ruby test.rb -h--help返回:

Usage: test [options]
    -f, --foo                        Foo it

即使我没有定义-h--help

如果我希望-v--version标记显示在列表中,那么我将它们从on_tail方法更改为普通on方法:

require 'optparse'

VERSION = '1.0.0'

options = {}
OptionParser.new do |opt|
  opt.on('-f', '--foo', 'Foo it') { |o| options[:foo] = o }

  opt.on('-v', '--version', 'Returns the version') do
    puts VERSION
    exit
  end

end.parse!

puts options

会返回:

Usage: test [options]
    -f, --foo                        Foo it
    -v, --version                    Returns the version

我可以补充一下:

puts ARGV

到脚本的末尾,看到OptionParser正确处理标志和参数:

>ruby test.rb bar --foo
{:foo=>true}
bar

>ruby test.rb --foo bar
{:foo=>true}
bar

参见&#34; Pass variables to Ruby script via command line&#34;了解更多信息。

您的示例代码无法使用--options处理您的示例输入。没有定义--options的处理程序。也不是subtext。您的代码返回:

undefined local variable or method `subtext' for main:Object (NameError)

将块剥离到:

global = OptionParser.new do |opts|
  opts.on("-v", "--version", "Print the version") do |v|
    options[:version] = v
  end
end

再次运行返回:

invalid option: --options (OptionParser::InvalidOption)

所以,再一次,你的例子并不符合你所说的结果。

答案 1 :(得分:1)

包含错误的行:

global.order!
command = ARGV.shift
subcommands[command].order!

如果global.order!使用全部ARGV,则命令为nil。所以......检查一下。

global.order!
command = ARGV.shift
unless command
  STDERR.puts "ERROR: no subcommand"
  STDERR.puts global # prints usage
  exit(-1)
end
subcommands[command].order!