2014-01-30 60 views
1

我正在學習使用Ruby的OptionParser類。如何提高解析器錯誤消息的質量?以下是帶有強制選項的標誌示例,該選項必須是hour,day,weekmonth之一。修改Ruby OptionParser錯誤消息

opt_parser = OptionParser.new do |opts| 
    opts.banner = "Usage: #{$0} [options] username" 

    times = [:hour, :day, :week, :month] 
    opts.on('-t', '--time=TIME', times, 
      'Show messages from the last TIME (defaults to weeks)', "Avaliable options are (#{times.join(', ')})") do |time| 
    o.time = time 
    end 
end 

以下是一些示例輸出。

$ ./script -t 
./scraper.rb:195:in `main': missing argument: -t (OptionParser::MissingArgument) 
from ./scraper.rb:210:in `<main>' 

$ ./script -t not_a_value 
./scraper.rb:195:in `main': invalid argument: -t not_a_value (OptionParser::InvalidArgument) 
from ./scraper.rb:210:in `<main>' 

我想錯誤提可接受值,像invalid option for -t 'not_a_value', valid options are hour, day, week, month

回答

0

當然這很簡單,只要:

opt_parser = OptionParser.new do |opts| 
    opts.banner = "Usage: #{$0} [options] username" 

    times = [:hour, :day, :week, :month] 
    begin 
    opts.on('-t', '--time=TIME', times, 
     'Show messages from the last TIME (defaults to weeks)', "Avaliable options are (# {times.join(', ')})") do |time| 
    o.time = time 
    rescue OptionParser::MissingArgument, OptionParser::InvalidArgument 
     $stderr.print "Usage: -t <argument> where argument in [:hour, :day, :week, :month]" 
    end 
    end 
end 
+0

我試過了。異常不會拋出,直到opt_parser.parse!被稱爲,以便開始......救援塊沒有幫助。 – everett1992

+0

@ everett1992所以解救周圍!呼叫。 – mcfinnigan

+1

然後,你將不得不字符串搜索異常消息,以找到哪個標誌是無效的(我的實際代碼有多個標誌,這個例子只是爲了簡潔)。這是一個選項,但似乎kludgey。我希望錯誤消息在選項解析器中是常用的,我很驚訝他們不被支持。 – everett1992

0

OptionParser並不能真正幫助你多少與此,但你可以自己實現而不會有太多麻煩,並且仍然是乾的。只需檢查自己的正確性,並在需要時發出錯誤。

times = [:hour, :day, :week, :month] 
opts.on('-t', '--time=TIME', 
    'Show messages from the last TIME (defaults to weeks)', 
    "Available options are <#{times.join ', '}>") do |time| 
    times.include?(time.to_sym) or 
    raise OptionParser::ParseError.new("time must be one of <#{times.join ', '}>") 
    o.time = time 
end 

這也是很好的使輸出乾淨了一點:

begin 
    p.parse!(ARGV) 
    rescue OptionParser::ParseError => e 
    puts e 
    exit 1 
    end