2015-07-20 79 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) 

所以,再一次,你的榜樣不匹配的結果,你說你正在得到。