2015-07-20 81 views
1

我想创建一个命令行程序与子命令使用OptionParser。我正在关注“ruby's OptionParser to get subcommands”。OptionParser与子命令

的问题是,它不允许使用案例是这样的:

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 
+3

你可以添加你的实际代码吗?你链接到的例子确实允许你的'ruby main.rb --version'的情况,所以没有看到你的代码,我们不能调试这个问题。 – jkeuhlen

+0

@jkeuhlen该代码与我发布的URL完全相同,除了“--verbose”替换为“--version”,代码原本就是抛出一个“nil:NilClass(NoMethodError)如果它不遵循'program [[options] [subcommand] [options]]'格式 – user2840647

回答

0

与错误的行:

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! 
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 

将其保存为 “test.rb” 并运行它与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 

请参阅“Pass variables to Ruby script via command line”的详细信息。


您的示例代码无法使用--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) 

所以,再一次,你的榜样不匹配的结果,你说你正在得到。