1

我正在学习使用 Ruby 的 OptionParser 类。如何提高解析器错误消息的质量?下面是一个带有强制选项的标志示例,该选项必须是hourdayweek或之一month

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

4

3 回答 3

2

我通过以下方式做到这一点:

begin
    parser.parse! ARGV
rescue OptionParser::InvalidArgument => e
#    puts e.instance_variables
#    puts e.args
#    puts e.reason
    if e.args.include? '-t'
        STDERR.puts "Invalid value of parameter -t. Availible options: #{t_options}"
        puts parser.help
        exit 1
    end
    STDERR.puts e
end

如果参数 -t 缺少以下打印输出。否则打印默认错误信息。留下一些注释掉的“puts”行,我可以帮助您在异常数据中找到其他有用的东西。

于 2018-05-01T13:03:46.177 回答
1

OptionParser 在这方面并没有真正帮助您,但是您可以自己实现它而不会遇到太多麻烦并且仍然是 DRY。只需自己检查正确性并在需要时抛出错误。

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
于 2014-08-22T15:42:58.350 回答
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
于 2014-01-30T20:21:04.413 回答