类 OptionParser

OptionParser

OptionParser 新手?

查看 教程.

简介

OptionParser 是一个用于命令行选项分析的类。它比 GetoptLong 更高级,也更容易使用,并且是一个更面向 Ruby 的解决方案。

特性

  1. 参数规范和处理它的代码在同一个地方编写。

  2. 它可以输出选项摘要;您不需要单独维护此字符串。

  3. 可选参数和必填参数的指定非常优雅。

  4. 参数可以自动转换为指定的类。

  5. 参数可以限制为特定集合。

所有这些功能都在下面的示例中演示。有关完整文档,请参见 make_switch

最小示例

require 'optparse'

options = {}
OptionParser.new do |parser|
  parser.banner = "Usage: example.rb [options]"

  parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
    options[:verbose] = v
  end
end.parse!

p options
p ARGV

生成帮助

OptionParser 可用于自动生成您编写的命令的帮助信息

require 'optparse'

Options = Struct.new(:name)

class Parser
  def self.parse(options)
    args = Options.new("world")

    opt_parser = OptionParser.new do |parser|
      parser.banner = "Usage: example.rb [options]"

      parser.on("-nNAME", "--name=NAME", "Name to say hello to") do |n|
        args.name = n
      end

      parser.on("-h", "--help", "Prints this help") do
        puts parser
        exit
      end
    end

    opt_parser.parse!(options)
    return args
  end
end
options = Parser.parse %w[--help]

#=>
   # Usage: example.rb [options]
   #     -n, --name=NAME                  Name to say hello to
   #     -h, --help                       Prints this help

必填参数

对于需要参数的选项,选项规范字符串可能包含一个全大写的选项名称。如果选项在没有必需参数的情况下使用,则会引发异常。

require 'optparse'

options = {}
OptionParser.new do |parser|
  parser.on("-r", "--require LIBRARY",
            "Require the LIBRARY before executing your script") do |lib|
    puts "You required #{lib}!"
  end
end.parse!

使用

$ ruby optparse-test.rb -r
optparse-test.rb:9:in `<main>': missing argument: -r (OptionParser::MissingArgument)
$ ruby optparse-test.rb -r my-library
You required my-library!

类型强制转换

OptionParser 支持将命令行参数强制转换为对象的能力。

OptionParser 附带了一些现成的类型强制转换。它们是

我们也可以添加自己的强制转换,我们将在下面介绍。

使用内置转换

例如,使用内置的 Time 转换。其他内置转换的行为方式相同。 OptionParser 将尝试将参数解析为 Time。如果成功,该时间将传递给处理程序块。否则,将引发异常。

require 'optparse'
require 'optparse/time'
OptionParser.new do |parser|
  parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
    p time
  end
end.parse!

使用

$ ruby optparse-test.rb  -t nonsense
... invalid argument: -t nonsense (OptionParser::InvalidArgument)
$ ruby optparse-test.rb  -t 10-11-12
2010-11-12 00:00:00 -0500
$ ruby optparse-test.rb  -t 9:30
2014-08-13 09:30:00 -0400

创建自定义转换

accept 方法在 OptionParser 上可用于创建转换器。它指定在指定类时要调用哪个转换块。下面的示例使用它在 on 处理程序接收它之前获取 User 对象。

require 'optparse'

User = Struct.new(:id, :name)

def find_user id
  not_found = ->{ raise "No User Found for id #{id}" }
  [ User.new(1, "Sam"),
    User.new(2, "Gandalf") ].find(not_found) do |u|
    u.id == id
  end
end

op = OptionParser.new
op.accept(User) do |user_id|
  find_user user_id.to_i
end

op.on("--user ID", User) do |user|
  puts user
end

op.parse!

使用

$ ruby optparse-test.rb --user 1
#<struct User id=1, name="Sam">
$ ruby optparse-test.rb --user 2
#<struct User id=2, name="Gandalf">
$ ruby optparse-test.rb --user 3
optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError)

将选项存储到 Hash

orderparse 等方法的 into 选项将命令行选项存储到 Hash 中。

require 'optparse'

options = {}
OptionParser.new do |parser|
  parser.on('-a')
  parser.on('-b NUM', Integer)
  parser.on('-v', '--verbose')
end.parse!(into: options)

p options

使用

$ ruby optparse-test.rb -a
{:a=>true}
$ ruby optparse-test.rb -a -v
{:a=>true, :verbose=>true}
$ ruby optparse-test.rb -a -b 100
{:a=>true, :b=>100}

完整示例

以下示例是一个完整的 Ruby 程序。您可以运行它并查看指定各种选项的效果。这可能是学习 optparse 功能的最佳方法。

require 'optparse'
require 'optparse/time'
require 'ostruct'
require 'pp'

class OptparseExample
  Version = '1.0.0'

  CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
  CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }

  class ScriptOptions
    attr_accessor :library, :inplace, :encoding, :transfer_type,
                  :verbose, :extension, :delay, :time, :record_separator,
                  :list

    def initialize
      self.library = []
      self.inplace = false
      self.encoding = "utf8"
      self.transfer_type = :auto
      self.verbose = false
    end

    def define_options(parser)
      parser.banner = "Usage: example.rb [options]"
      parser.separator ""
      parser.separator "Specific options:"

      # add additional options
      perform_inplace_option(parser)
      delay_execution_option(parser)
      execute_at_time_option(parser)
      specify_record_separator_option(parser)
      list_example_option(parser)
      specify_encoding_option(parser)
      optional_option_argument_with_keyword_completion_option(parser)
      boolean_verbose_option(parser)

      parser.separator ""
      parser.separator "Common options:"
      # No argument, shows at tail.  This will print an options summary.
      # Try it and see!
      parser.on_tail("-h", "--help", "Show this message") do
        puts parser
        exit
      end
      # Another typical switch to print the version.
      parser.on_tail("--version", "Show version") do
        puts Version
        exit
      end
    end

    def perform_inplace_option(parser)
      # Specifies an optional option argument
      parser.on("-i", "--inplace [EXTENSION]",
                "Edit ARGV files in place",
                "(make backup if EXTENSION supplied)") do |ext|
        self.inplace = true
        self.extension = ext || ''
        self.extension.sub!(/\A\.?(?=.)/, ".")  # Ensure extension begins with dot.
      end
    end

    def delay_execution_option(parser)
      # Cast 'delay' argument to a Float.
      parser.on("--delay N", Float, "Delay N seconds before executing") do |n|
        self.delay = n
      end
    end

    def execute_at_time_option(parser)
      # Cast 'time' argument to a Time object.
      parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
        self.time = time
      end
    end

    def specify_record_separator_option(parser)
      # Cast to octal integer.
      parser.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
                "Specify record separator (default \\0)") do |rs|
        self.record_separator = rs
      end
    end

    def list_example_option(parser)
      # List of arguments.
      parser.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
        self.list = list
      end
    end

    def specify_encoding_option(parser)
      # Keyword completion.  We are specifying a specific set of arguments (CODES
      # and CODE_ALIASES - notice the latter is a Hash), and the user may provide
      # the shortest unambiguous text.
      code_list = (CODE_ALIASES.keys + CODES).join(', ')
      parser.on("--code CODE", CODES, CODE_ALIASES, "Select encoding",
                "(#{code_list})") do |encoding|
        self.encoding = encoding
      end
    end

    def optional_option_argument_with_keyword_completion_option(parser)
      # Optional '--type' option argument with keyword completion.
      parser.on("--type [TYPE]", [:text, :binary, :auto],
                "Select transfer type (text, binary, auto)") do |t|
        self.transfer_type = t
      end
    end

    def boolean_verbose_option(parser)
      # Boolean switch.
      parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
        self.verbose = v
      end
    end
  end

  #
  # Return a structure describing the options.
  #
  def parse(args)
    # The options specified on the command line will be collected in
    # *options*.

    @options = ScriptOptions.new
    @args = OptionParser.new do |parser|
      @options.define_options(parser)
      parser.parse!(args)
    end
    @options
  end

  attr_reader :parser, :options
end  # class OptparseExample

example = OptparseExample.new
options = example.parse(ARGV)
pp options # example.options
pp ARGV

Shell Completion

对于现代 shell(例如 bash、zsh 等),您可以使用 shell 完成来完成命令行选项。

进一步的文档

上面的示例以及附带的 教程 应该足以学习如何使用此类。如果您有任何问题,请在 bugs.ruby-lang.org 上提交工单。

常量

DecimalInteger

十进制整数格式,将转换为 Integer

DecimalNumeric

十进制整数/浮点数格式,将转换为 Integer(对于整数格式)或 Float(对于浮点数格式)。

OctalInteger

类似 Ruby/C 的八进制/十六进制/二进制整数格式,将转换为 Integer

版本

属性

banner[W]

摘要前的标题横幅。

default_argv[RW]

在默认情况下要解析的字符串。

program_name[W]

在错误消息和默认横幅中要发出的程序名称,默认为 $0。

raise_unknown[RW]

是否在未知选项时引发异常。

release[W]

发布代码

require_exact[RW]

是否要求选项完全匹配(不允许将缩写的长选项作为短选项提供)。

set_banner[W]

摘要前的标题横幅。

set_program_name[W]

在错误消息和默认横幅中要发出的程序名称,默认为 $0。

set_summary_indent[RW]

摘要的缩进。必须是 String(或具有 + String 方法)。

set_summary_width[RW]

摘要中选项列表部分的宽度。必须是 Numeric

summary_indent[RW]

摘要的缩进。必须是 String(或具有 + String 方法)。

summary_width[RW]

摘要中选项列表部分的宽度。必须是 Numeric

version[W]

公共类方法

accept(*args, &blk) 点击切换源代码

参见 accept

# File lib/optparse.rb, line 1190
def self.accept(*args, &blk) top.accept(*args, &blk) end
each_const(path, base = ::Object) 点击切换源代码
# File lib/optparse/version.rb, line 50
def each_const(path, base = ::Object)
  path.split(/::|\//).inject(base) do |klass, name|
    raise NameError, path unless Module === klass
    klass.constants.grep(/#{name}/i) do |c|
      klass.const_defined?(c) or next
      klass.const_get(c)
    end
  end
end
getopts(*args, symbolize_names: false) 点击切换源代码

参见 getopts

# File lib/optparse.rb, line 1822
def self.getopts(*args, symbolize_names: false)
  new.getopts(*args, symbolize_names: symbolize_names)
end
inc(arg, default = nil) 点击切换源代码

根据 arg 返回 default 的递增值。

# File lib/optparse.rb, line 1124
def self.inc(arg, default = nil)
  case arg
  when Integer
    arg.nonzero?
  when nil
    default.to_i + 1
  end
end
new(banner = nil, width = 32, indent = ' ' * 4) { |self| ... } 点击切换源代码

初始化实例,如果用块调用,则会生成自身。

banner

横幅消息。

width

摘要宽度。

indent

摘要缩进。

# File lib/optparse.rb, line 1143
def initialize(banner = nil, width = 32, indent = ' ' * 4)
  @stack = [DefaultList, List.new, List.new]
  @program_name = nil
  @banner = banner
  @summary_width = width
  @summary_indent = indent
  @default_argv = ARGV
  @require_exact = false
  @raise_unknown = true
  add_officious
  yield self if block_given?
end
reject(*args, &blk) 点击切换源代码

参见 reject.

# File lib/optparse.rb, line 1203
def self.reject(*args, &blk) top.reject(*args, &blk) end
search_const(klass, name) { |klass, cname, const| ... } 点击切换源代码
# File lib/optparse/version.rb, line 60
def search_const(klass, name)
  klasses = [klass]
  while klass = klasses.shift
    klass.constants.each do |cname|
      klass.const_defined?(cname) or next
      const = klass.const_get(cname)
      yield klass, cname, const if name === cname
      klasses << const if Module === const and const != ::Object
    end
  end
end
show_version(*pkgs) 点击切换源代码
# File lib/optparse/version.rb, line 5
def show_version(*pkgs)
  progname = ARGV.options.program_name
  result = false
  show = proc do |klass, cname, version|
    str = "#{progname}"
    unless klass == ::Object and cname == :VERSION
      version = version.join(".") if Array === version
      str << ": #{klass}" unless klass == Object
      str << " version #{version}"
    end
    [:Release, :RELEASE].find do |rel|
      if klass.const_defined?(rel)
        str << " (#{klass.const_get(rel)})"
      end
    end
    puts str
    result = true
  end
  if pkgs.size == 1 and pkgs[0] == "all"
    self.search_const(::Object, /\AV(?:ERSION|ersion)\z/) do |klass, cname, version|
      unless cname[1] == ?e and klass.const_defined?(:Version)
        show.call(klass, cname.intern, version)
      end
    end
  else
    pkgs.each do |pkg|
      begin
        pkg = pkg.split(/::|\//).inject(::Object) {|m, c| m.const_get(c)}
        v = case
            when pkg.const_defined?(:Version)
              pkg.const_get(n = :Version)
            when pkg.const_defined?(:VERSION)
              pkg.const_get(n = :VERSION)
            else
              n = nil
              "unknown"
            end
        show.call(pkg, n, v)
      rescue NameError
      end
    end
  end
  result
end
terminate(arg = nil) 点击切换源代码
# File lib/optparse.rb, line 1170
def self.terminate(arg = nil)
  throw :terminate, arg
end
top() 点击切换源代码
# File lib/optparse.rb, line 1175
def self.top() DefaultList end
with(*args, &block) 点击切换源代码

初始化一个新实例,并在实例的上下文中执行可选的代码块。参数 args 传递给 new,有关参数的描述,请参见那里。

此方法已弃用,其行为对应于旧的 new 方法。

# File lib/optparse.rb, line 1115
def self.with(*args, &block)
  opts = new(*args)
  opts.instance_eval(&block)
  opts
end

公共实例方法

abort(mesg = $!) 点击切换源代码
调用超类方法 Kernel#abort
# File lib/optparse.rb, line 1291
def abort(mesg = $!)
  super("#{program_name}: #{mesg}")
end
accept(*args, &blk) 点击切换源代码

指示接受指定的类 t。参数字符串传递给代码块,在代码块中应将其转换为所需的类。

t

参数类说明符,任何对象,包括 Class.

pat

参数模式,如果它响应匹配,则默认为 t

accept(t, pat, &block)
# File lib/optparse.rb, line 1186
def accept(*args, &blk) top.accept(*args, &blk) end
additional_message(typ, opt) 点击切换源代码

返回附加信息。

# File lib/optparse.rb, line 1873
def additional_message(typ, opt)
  return unless typ and opt and defined?(DidYouMean::SpellChecker)
  all_candidates = []
  visit(:get_candidates, typ) do |candidates|
    all_candidates.concat(candidates)
  end
  all_candidates.select! {|cand| cand.is_a?(String) }
  checker = DidYouMean::SpellChecker.new(dictionary: all_candidates)
  DidYouMean.formatter.message_for(all_candidates & checker.correct(opt))
end
banner() 点击切换源代码

摘要前的标题横幅。

base() 点击切换源代码

on_tail 的主题。

# File lib/optparse.rb, line 1305
def base
  @stack[1]
end
candidate(word) 点击切换源代码
# File lib/optparse.rb, line 1884
def candidate(word)
  list = []
  case word
  when '-'
    long = short = true
  when /\A--/
    word, arg = word.split(/=/, 2)
    argpat = Completion.regexp(arg, false) if arg and !arg.empty?
    long = true
  when /\A-/
    short = true
  end
  pat = Completion.regexp(word, long)
  visit(:each_option) do |opt|
    next unless Switch === opt
    opts = (long ? opt.long : []) + (short ? opt.short : [])
    opts = Completion.candidate(word, true, pat, &opts.method(:each)).map(&:first) if pat
    if /\A=/ =~ opt.arg
      opts.map! {|sw| sw + "="}
      if arg and CompletingHash === opt.pattern
        if opts = opt.pattern.candidate(arg, false, argpat)
          opts.map!(&:last)
        end
      end
    end
    list.concat(opts)
  end
  list
end
def_head_option
别名:define_head
def_option
别名:define
def_tail_option
别名:define_tail
define(*params, &block) 点击切换源代码

根据给定的参数 params 创建一个选项。参见 新选项的参数.

如果给定代码块,则它是为创建的选项创建的处理程序。当在命令行解析期间遇到该选项时,将使用为该选项给定的参数(如果有)调用该代码块。参见 选项处理程序.

# File lib/optparse.rb, line 1540
def define(*opts, &block)
  top.append(*(sw = make_switch(opts, block)))
  sw[0]
end
也称为:def_option
define_by_keywords(options, method, **params) 点击切换源代码

根据给定的参数 params 创建一个选项。参见 新选项的参数.

如果给定代码块,则它是为创建的选项创建的处理程序。当在命令行解析期间遇到该选项时,将使用为该选项给定的参数(如果有)调用该代码块。参见 选项处理程序.

# File lib/optparse/kwargs.rb, line 10
def define_by_keywords(options, meth, **opts)
  meth.parameters.each do |type, name|
    case type
    when :key, :keyreq
      op, cl = *(type == :key ? %w"[ ]" : ["", ""])
      define("--#{name}=#{op}#{name.upcase}#{cl}", *opts[name]) do |o|
        options[name] = o
      end
    end
  end
  options
end
define_head(*params, &block) 点击切换源代码

根据给定的参数 params 创建一个选项。参见 新选项的参数.

如果给定代码块,则它是为创建的选项创建的处理程序。当在命令行解析期间遇到该选项时,将使用为该选项给定的参数(如果有)调用该代码块。参见 选项处理程序.

# File lib/optparse.rb, line 1561
def define_head(*opts, &block)
  top.prepend(*(sw = make_switch(opts, block)))
  sw[0]
end
也称为:def_head_option
define_tail(*params, &block) 点击切换源代码

根据给定的参数 params 创建一个选项。参见 新选项的参数.

如果给定代码块,则它是为创建的选项创建的处理程序。当在命令行解析期间遇到该选项时,将使用为该选项给定的参数(如果有)调用该代码块。参见 选项处理程序.

# File lib/optparse.rb, line 1584
def define_tail(*opts, &block)
  base.append(*(sw = make_switch(opts, block)))
  sw[0]
end
也称为:def_tail_option
environment(env = File.basename($0, '.*')) 点击切换源代码

解析环境变量 env 或其大写形式,并像 shell 一样进行分割。

env 默认值为程序的基名。

# File lib/optparse.rb, line 1957
def environment(env = File.basename($0, '.*'))
  env = ENV[env] || ENV[env.upcase] or return
  require 'shellwords'
  parse(*Shellwords.shellwords(env))
end
getopts(*args, symbolize_names: false) 点击切换源代码

getopts.rb 的包装方法。

params = ARGV.getopts("ab:", "foo", "bar:", "zot:Z;zot option")
# params["a"] = true   # -a
# params["b"] = "1"    # -b1
# params["foo"] = "1"  # --foo
# params["bar"] = "x"  # --bar x
# params["zot"] = "z"  # --zot Z

选项 symbolize_names(布尔值)指定返回的 Hash 键是否应该为符号;默认值为 false(使用字符串)。

params = ARGV.getopts("ab:", "foo", "bar:", "zot:Z;zot option", symbolize_names: true)
# params[:a] = true   # -a
# params[:b] = "1"    # -b1
# params[:foo] = "1"  # --foo
# params[:bar] = "x"  # --bar x
# params[:zot] = "z"  # --zot Z
# File lib/optparse.rb, line 1787
def getopts(*args, symbolize_names: false)
  argv = Array === args.first ? args.shift : default_argv
  single_options, *long_options = *args

  result = {}

  single_options.scan(/(.)(:)?/) do |opt, val|
    if val
      result[opt] = nil
      define("-#{opt} VAL")
    else
      result[opt] = false
      define("-#{opt}")
    end
  end if single_options

  long_options.each do |arg|
    arg, desc = arg.split(';', 2)
    opt, val = arg.split(':', 2)
    if val
      result[opt] = val.empty? ? nil : val
      define("--#{opt}=#{result[opt] || "VAL"}", *[desc].compact)
    else
      result[opt] = false
      define("--#{opt}", *[desc].compact)
    end
  end

  parse_in_order(argv, result.method(:[]=))
  symbolize_names ? result.transform_keys(&:to_sym) : result
end
help() 点击切换源代码

返回选项摘要字符串。

# File lib/optparse.rb, line 1347
def help; summarize("#{banner}".sub(/\n?\z/, "\n")) end
也称为:to_s
inc(*args) 点击切换源代码
# File lib/optparse.rb, line 1132
def inc(*args)
  self.class.inc(*args)
end
load(filename = nil, into: nil) 点击切换源代码

filename 指定的文件名加载选项。如果文件不存在,则不执行任何操作。返回是否成功加载。

filename 默认值为程序的基名(不带后缀),位于 ~/.options 目录下,然后是 XDG 和 Haiku 标准位置下的基名(带 '.options' 后缀)。

可选的 into 关键字参数的工作方式与方法 parse 中接受的完全相同。

# File lib/optparse.rb, line 1925
def load(filename = nil, into: nil)
  unless filename
    basename = File.basename($0, '.*')
    return true if load(File.expand_path(basename, '~/.options'), into: into) rescue nil
    basename << ".options"
    return [
      # XDG
      ENV['XDG_CONFIG_HOME'],
      '~/.config',
      *ENV['XDG_CONFIG_DIRS']&.split(File::PATH_SEPARATOR),

      # Haiku
      '~/config/settings',
    ].any? {|dir|
      next if !dir or dir.empty?
      load(File.expand_path(basename, dir), into: into) rescue nil
    }
  end
  begin
    parse(*File.readlines(filename, chomp: true), into: into)
    true
  rescue Errno::ENOENT, Errno::ENOTDIR
    false
  end
end
make_switch(params, block = nil) 点击切换源代码

根据给定的参数 params 创建一个选项。参见 新选项的参数.

如果给定代码块,则它是为创建的选项创建的处理程序。当在命令行解析期间遇到该选项时,将使用为该选项给定的参数(如果有)调用该代码块。参见 选项处理程序.

# File lib/optparse.rb, line 1402
def make_switch(opts, block = nil)
  short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], []
  ldesc, sdesc, desc, arg = [], [], []
  default_style = Switch::NoArgument
  default_pattern = nil
  klass = nil
  q, a = nil
  has_arg = false

  opts.each do |o|
    # argument class
    next if search(:atype, o) do |pat, c|
      klass = notwice(o, klass, 'type')
      if not_style and not_style != Switch::NoArgument
        not_pattern, not_conv = pat, c
      else
        default_pattern, conv = pat, c
      end
    end

    # directly specified pattern(any object possible to match)
    if (!(String === o || Symbol === o)) and o.respond_to?(:match)
      pattern = notwice(o, pattern, 'pattern')
      if pattern.respond_to?(:convert)
        conv = pattern.method(:convert).to_proc
      else
        conv = SPLAT_PROC
      end
      next
    end

    # anything others
    case o
    when Proc, Method
      block = notwice(o, block, 'block')
    when Array, Hash
      case pattern
      when CompletingHash
      when nil
        pattern = CompletingHash.new
        conv = pattern.method(:convert).to_proc if pattern.respond_to?(:convert)
      else
        raise ArgumentError, "argument pattern given twice"
      end
      o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}}
    when Module
      raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4))
    when *ArgumentStyle.keys
      style = notwice(ArgumentStyle[o], style, 'style')
    when /^--no-([^\[\]=\s]*)(.+)?/
      q, a = $1, $2
      o = notwice(a ? Object : TrueClass, klass, 'type')
      not_pattern, not_conv = search(:atype, o) unless not_style
      not_style = (not_style || default_style).guess(arg = a) if a
      default_style = Switch::NoArgument
      default_pattern, conv = search(:atype, FalseClass) unless default_pattern
      ldesc << "--no-#{q}"
      (q = q.downcase).tr!('_', '-')
      long << "no-#{q}"
      nolong << q
    when /^--\[no-\]([^\[\]=\s]*)(.+)?/
      q, a = $1, $2
      o = notwice(a ? Object : TrueClass, klass, 'type')
      if a
        default_style = default_style.guess(arg = a)
        default_pattern, conv = search(:atype, o) unless default_pattern
      end
      ldesc << "--[no-]#{q}"
      (o = q.downcase).tr!('_', '-')
      long << o
      not_pattern, not_conv = search(:atype, FalseClass) unless not_style
      not_style = Switch::NoArgument
      nolong << "no-#{o}"
    when /^--([^\[\]=\s]*)(.+)?/
      q, a = $1, $2
      if a
        o = notwice(NilClass, klass, 'type')
        default_style = default_style.guess(arg = a)
        default_pattern, conv = search(:atype, o) unless default_pattern
      end
      ldesc << "--#{q}"
      (o = q.downcase).tr!('_', '-')
      long << o
    when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
      q, a = $1, $2
      o = notwice(Object, klass, 'type')
      if a
        default_style = default_style.guess(arg = a)
        default_pattern, conv = search(:atype, o) unless default_pattern
      else
        has_arg = true
      end
      sdesc << "-#{q}"
      short << Regexp.new(q)
    when /^-(.)(.+)?/
      q, a = $1, $2
      if a
        o = notwice(NilClass, klass, 'type')
        default_style = default_style.guess(arg = a)
        default_pattern, conv = search(:atype, o) unless default_pattern
      end
      sdesc << "-#{q}"
      short << q
    when /^=/
      style = notwice(default_style.guess(arg = o), style, 'style')
      default_pattern, conv = search(:atype, Object) unless default_pattern
    else
      desc.push(o) if o && !o.empty?
    end
  end

  default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
  if !(short.empty? and long.empty?)
    if has_arg and default_style == Switch::NoArgument
      default_style = Switch::RequiredArgument
    end
    s = (style || default_style).new(pattern || default_pattern,
                                     conv, sdesc, ldesc, arg, desc, block)
  elsif !block
    if style or pattern
      raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller)
    end
    s = desc
  else
    short << pattern
    s = (style || default_style).new(pattern,
                                     conv, nil, nil, arg, desc, block)
  end
  return s, short, long,
    (not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
    nolong
end
new() { |self| ... } 点击切换源代码

推送一个新的 List

# File lib/optparse.rb, line 1312
def new
  @stack.push(List.new)
  if block_given?
    yield self
  else
    self
  end
end
on(*params, &block) 点击切换源代码

根据给定的参数 params 创建一个选项。参见 新选项的参数.

如果给定代码块,则它是为创建的选项创建的处理程序。当在命令行解析期间遇到该选项时,将使用为该选项给定的参数(如果有)调用该代码块。参见 选项处理程序.

# File lib/optparse.rb, line 1550
def on(*opts, &block)
  define(*opts, &block)
  self
end
on_head(*params, &block) 点击切换源代码

根据给定的参数 params 创建一个选项。参见 新选项的参数.

如果给定代码块,则它是为创建的选项创建的处理程序。当在命令行解析期间遇到该选项时,将使用为该选项给定的参数(如果有)调用该代码块。参见 选项处理程序.

新选项将添加到摘要的开头。

# File lib/optparse.rb, line 1573
def on_head(*opts, &block)
  define_head(*opts, &block)
  self
end
on_tail(*params, &block) 点击切换源代码

根据给定的参数 params 创建一个选项。参见 新选项的参数.

如果给定代码块,则它是为创建的选项创建的处理程序。当在命令行解析期间遇到该选项时,将使用为该选项给定的参数(如果有)调用该代码块。参见 选项处理程序.

新选项将添加到摘要的结尾。

# File lib/optparse.rb, line 1597
def on_tail(*opts, &block)
  define_tail(*opts, &block)
  self
end
order(*argv, into: nil, &nonopt) 点击切换源代码

按顺序解析命令行参数 argv。 当给出代码块时,每个非选项参数都会被 yield。 当提供可选的 into 关键字参数时,解析后的选项值将通过 []= 方法存储在那里(因此它可以是 Hash,或 OpenStruct,或其他类似对象)。

返回未解析的 argv 的剩余部分。

# File lib/optparse.rb, line 1619
def order(*argv, into: nil, &nonopt)
  argv = argv[0].dup if argv.size == 1 and Array === argv[0]
  order!(argv, into: into, &nonopt)
end
order!(argv = default_argv, into: nil, &nonopt) 点击切换源代码

order 相同,但会破坏性地删除开关。 非选项参数保留在 argv 中。

# File lib/optparse.rb, line 1628
def order!(argv = default_argv, into: nil, &nonopt)
  setter = ->(name, val) {into[name.to_sym] = val} if into
  parse_in_order(argv, setter, &nonopt)
end
parse(*argv, into: nil) 点击切换源代码

当环境变量 POSIXLY_CORRECT 设置时,按顺序解析命令行参数 argv,否则以排列模式解析。 当提供可选的 into 关键字参数时,解析后的选项值将通过 []= 方法存储在那里(因此它可以是 Hash,或 OpenStruct,或其他类似对象)。

# File lib/optparse.rb, line 1751
def parse(*argv, into: nil)
  argv = argv[0].dup if argv.size == 1 and Array === argv[0]
  parse!(argv, into: into)
end
parse!(argv = default_argv, into: nil) 点击切换源代码

parse 相同,但会破坏性地删除开关。 非选项参数保留在 argv 中。

# File lib/optparse.rb, line 1760
def parse!(argv = default_argv, into: nil)
  if ENV.include?('POSIXLY_CORRECT')
    order!(argv, into: into)
  else
    permute!(argv, into: into)
  end
end
permute(*argv, into: nil) 点击切换源代码

以排列模式解析命令行参数 argv 并返回非选项参数列表。 当提供可选的 into 关键字参数时,解析后的选项值将通过 []= 方法存储在那里(因此它可以是 Hash,或 OpenStruct,或其他类似对象)。

# File lib/optparse.rb, line 1728
def permute(*argv, into: nil)
  argv = argv[0].dup if argv.size == 1 and Array === argv[0]
  permute!(argv, into: into)
end
permute!(argv = default_argv, into: nil) 点击切换源代码

permute 相同,但会破坏性地移除开关。非选项参数将保留在 argv 中。

# File lib/optparse.rb, line 1737
def permute!(argv = default_argv, into: nil)
  nonopts = []
  order!(argv, into: into, &nonopts.method(:<<))
  argv[0, 0] = nonopts
  argv
end
program_name() 点击切换源代码

在错误消息和默认横幅中要发出的程序名称,默认为 $0。

# File lib/optparse.rb, line 1247
def program_name
  @program_name || File.basename($0, '.*')
end
reject(*args, &blk) 点击切换源代码

指示拒绝指定的类参数。

t

参数类说明符,任何对象,包括 Class.

reject(t)
# File lib/optparse.rb, line 1199
def reject(*args, &blk) top.reject(*args, &blk) end
release() 点击切换源代码

发布代码

# File lib/optparse.rb, line 1272
def release
  (defined?(@release) && @release) || (defined?(::Release) && ::Release) || (defined?(::RELEASE) && ::RELEASE)
end
remove() 点击切换源代码

移除最后一个 List

# File lib/optparse.rb, line 1324
def remove
  @stack.pop
end
separator(string) 点击切换源代码

在摘要中添加分隔符。

# File lib/optparse.rb, line 1606
def separator(string)
  top.append(string, nil, nil)
end
summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk) 点击切换源代码

将选项摘要放入 to 并返回 to。如果给定块,则对每一行进行 yield。

to

输出目标,必须具有方法 <<。默认为 []。

width

左侧的宽度,默认为 @summary_width。

max

左侧允许的最大长度,默认为 width - 1。

indent

缩进,默认为 @summary_indent。

# File lib/optparse.rb, line 1337
def summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk)
  nl = "\n"
  blk ||= proc {|l| to << (l.index(nl, -1) ? l : l + nl)}
  visit(:summarize, {}, {}, width, max, indent, &blk)
  to
end
terminate(arg = nil) 点击切换源代码

终止选项解析。可选参数 arg 是一个字符串,被推回作为第一个非选项参数。

# File lib/optparse.rb, line 1167
def terminate(arg = nil)
  self.class.terminate(arg)
end
to_a() 点击切换源代码

返回选项摘要列表。

# File lib/optparse.rb, line 1376
def to_a; summarize("#{banner}".split(/^/)) end
to_s()
别名:help
top() 点击切换源代码

on / on_headaccept / reject 的主题

# File lib/optparse.rb, line 1298
def top
  @stack[-1]
end
ver() 点击切换源代码

program_name、版本和发行版返回版本字符串。

# File lib/optparse.rb, line 1279
def ver
  if v = version
    str = +"#{program_name} #{[v].join('.')}"
    str << " (#{v})" if v = release
    str
  end
end
version() 点击切换源代码

版本

# File lib/optparse.rb, line 1265
def version
  (defined?(@version) && @version) || (defined?(::Version) && ::Version)
end
warn(mesg = $!) 点击切换源代码
调用超类方法 Kernel#warn
# File lib/optparse.rb, line 1287
def warn(mesg = $!)
  super("#{program_name}: #{mesg}")
end