class Gem::OptionParser

Gem::OptionParser

Gem::OptionParser 新手?

请参阅 教程

简介

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

功能

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

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

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

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

  5. 参数可以限制为某个集合。

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

最小示例

require 'rubygems/vendor/optparse/lib/optparse'

options = {}
Gem::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

生成帮助

Gem::OptionParser 可用于自动为你编写的命令生成帮助

require 'rubygems/vendor/optparse/lib/optparse'

Options = Struct.new(:name)

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

    opt_parser = Gem::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 'rubygems/vendor/optparse/lib/optparse'

options = {}
Gem::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 (Gem::OptionParser::MissingArgument)
$ ruby optparse-test.rb -r my-library
You required my-library!

类型强制转换

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

Gem::OptionParser 附带了一些可以直接使用的类型强制转换。它们是

  • Date - 任何 Date.parse 接受的内容(需要 require optparse/date

  • DateTime - 任何 DateTime.parse 接受的内容(需要 require optparse/date

  • Time - 任何 Time.httpdateTime.parse 接受的内容(需要 require optparse/time

  • URI - 任何 Gem::URI.parse 接受的内容(需要 require optparse/uri

  • Shellwords - 任何 Shellwords.shellwords 接受的内容(需要 require optparse/shellwords

  • String - 任何非空字符串

  • Integer - 任何整数。将转换八进制。(例如 124, -3, 040)

  • Float - 任何浮点数。(例如 10, 3.14, -100E+13)

  • Numeric - 任何整数、浮点数或有理数(1, 3.4, 1/3)

  • DecimalInteger - 类似于 Integer,但没有八进制格式。

  • OctalInteger - 类似于 Integer,但没有十进制格式。

  • DecimalNumeric - 十进制整数或浮点数。

  • TrueClass - 接受 '+, yes, true, -, no, false',默认为 true

  • FalseClass - 与 TrueClass 相同,但默认为 false

  • Array - 用“,”分隔的字符串(例如 1,2,3)

  • Regexp - 正则表达式。还包括选项。

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

使用内置转换

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

require 'rubygems/vendor/optparse/lib/optparse'
require 'rubygems/vendor/optparse/lib/optparse/time'
Gem::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 (Gem::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

创建自定义转换

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

require 'rubygems/vendor/optparse/lib/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 = Gem::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)

将选项存储到哈希

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

require 'rubygems/vendor/optparse/lib/optparse'

options = {}
Gem::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 'rubygems/vendor/optparse/lib/optparse'
require 'rubygems/vendor/optparse/lib/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]", Gem::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 = Gem::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

十进制整数格式,要转换为整数。

DecimalNumeric

十进制整数/浮点数格式,对于整数格式转换为整数,对于浮点数格式转换为浮点数。

OctalInteger

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

Version

版本字符串

属性

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]

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

set_summary_width[RW]

摘要的选项列表部分的宽度。必须是数字。

summary_indent[RW]

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

summary_width[RW]

摘要的选项列表部分的宽度。必须是数字。

version[W]

公共类方法

accept(*args, &blk) 单击以切换源

请参阅 accept

# File rubygems/vendor/optparse/lib/optparse.rb, line 1233
def self.accept(*args, &blk) top.accept(*args, &blk) end
getopts(*args, symbolize_names: false) 单击以切换源

请参阅 getopts

# File rubygems/vendor/optparse/lib/optparse.rb, line 1913
def self.getopts(*args, symbolize_names: false)
  new.getopts(*args, symbolize_names: symbolize_names)
end
inc(arg, default = nil) 单击以切换源

根据 arg 返回 default 的递增值。

# File rubygems/vendor/optparse/lib/optparse.rb, line 1155
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 rubygems/vendor/optparse/lib/optparse.rb, line 1178
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 rubygems/vendor/optparse/lib/optparse.rb, line 1246
def self.reject(*args, &blk) top.reject(*args, &blk) end
show_version(*pkgs) 单击以切换源

如果定义了 Version,则显示包中的版本字符串。

pkgs

包列表

# File rubygems/vendor/optparse/lib/optparse/version.rb, line 10
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) 单击以切换源

请参阅 terminate

# File rubygems/vendor/optparse/lib/optparse.rb, line 1208
def self.terminate(arg = nil)
  throw :terminate, arg
end
top() 单击以切换源

返回全局顶级选项列表。

不要直接使用。

# File rubygems/vendor/optparse/lib/optparse.rb, line 1218
def self.top() DefaultList end
with(*args, &block) 单击以切换源

初始化新实例,并在实例的上下文中评估可选块。参数 args 传递给 new,请参阅那里以了解参数说明。

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

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

公共实例方法

abort(mesg = $!) 单击以切换源

显示带有程序名称的消息,然后中止。

mesg

消息,默认为 +$!+。

请参阅 Kernel#abort。

调用超类方法
# File rubygems/vendor/optparse/lib/optparse.rb, line 1348
def abort(mesg = $!)
  super("#{program_name}: #{mesg}")
end
accept(*args, &blk) 单击以切换源

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

t

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

pat

参数的模式,如果 t 响应 match,则默认为 t

accept(t, pat, &block)
# File rubygems/vendor/optparse/lib/optparse.rb, line 1229
def accept(*args, &blk) top.accept(*args, &blk) end
additional_message(typ, opt) 单击以切换源

返回附加信息。

# File rubygems/vendor/optparse/lib/optparse.rb, line 1964
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 rubygems/vendor/optparse/lib/optparse.rb, line 1362
def base
  @stack[1]
end
candidate(word) 单击以切换源

返回 word 的候选值。

# File rubygems/vendor/optparse/lib/optparse.rb, line 1978
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(*opts, &block)
别名:define_head
def_option(*opts, &block)
别名:define
def_tail_option(*opts, &block)
别名: define_tail
define(*params, &block) 点击切换源代码

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

如果给定了代码块,则该代码块是已创建选项的处理程序。当在命令行解析期间遇到该选项时,将调用该代码块,并传入为该选项提供的参数(如果有)。请参阅 选项处理程序

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

method 的关键字参数定义选项,这些选项将设置到 options 中。

每个关键字的参数作为 params 的元素给出。

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

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

如果给定了代码块,则该代码块是已创建选项的处理程序。当在命令行解析期间遇到该选项时,将调用该代码块,并传入为该选项提供的参数(如果有)。请参阅 选项处理程序

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

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

如果给定了代码块,则该代码块是已创建选项的处理程序。当在命令行解析期间遇到该选项时,将调用该代码块,并传入为该选项提供的参数(如果有)。请参阅 选项处理程序

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

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

env 默认为程序的基本名称。

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

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 键是否应该为 Symbol;默认为 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 rubygems/vendor/optparse/lib/optparse.rb, line 1878
def getopts(*args, symbolize_names: false, **keywords)
  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(:[]=), **keywords)
  symbolize_names ? result.transform_keys(&:to_sym) : result
end
help() 点击切换源代码

返回选项摘要字符串。

# File rubygems/vendor/optparse/lib/optparse.rb, line 1407
def help; summarize("#{banner}".sub(/\n?\z/, "\n")) end
也别名为: to_s
inc(*args) 点击切换源代码

请参阅 self.inc

# File rubygems/vendor/optparse/lib/optparse.rb, line 1167
def inc(*args)
  self.class.inc(*args)
end
load(filename = nil, **keywords) 点击切换源代码

从文件名为 filename 的文件中加载选项。当文件不存在时,不执行任何操作。返回是否成功加载。

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

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

# File rubygems/vendor/optparse/lib/optparse.rb, line 2019
def load(filename = nil, **keywords)
  unless filename
    basename = File.basename($0, '.*')
    return true if load(File.expand_path(basename, '~/.options'), **keywords) 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), **keywords) rescue nil
    }
  end
  begin
    parse(*File.readlines(filename, chomp: true), **keywords)
    true
  rescue Errno::ENOENT, Errno::ENOTDIR
    false
  end
end
make_switch(params, block = nil) 点击切换源代码

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

如果给定了代码块,则该代码块是已创建选项的处理程序。当在命令行解析期间遇到该选项时,将调用该代码块,并传入为该选项提供的参数(如果有)。请参阅 选项处理程序

# File rubygems/vendor/optparse/lib/optparse.rb, line 1462
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

如果给定了代码块,则会 yield self 并返回代码块的结果,否则返回 self

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

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

如果给定了代码块,则该代码块是已创建选项的处理程序。当在命令行解析期间遇到该选项时,将调用该代码块,并传入为该选项提供的参数(如果有)。请参阅 选项处理程序

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

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

如果给定了代码块,则该代码块是已创建选项的处理程序。当在命令行解析期间遇到该选项时,将调用该代码块,并传入为该选项提供的参数(如果有)。请参阅 选项处理程序

新选项添加到摘要的头部。

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

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

如果给定了代码块,则该代码块是已创建选项的处理程序。当在命令行解析期间遇到该选项时,将调用该代码块,并传入为该选项提供的参数(如果有)。请参阅 选项处理程序

新选项添加到摘要的尾部。

# File rubygems/vendor/optparse/lib/optparse.rb, line 1663
def on_tail(*opts, &block)
  define_tail(*opts, &block)
  self
end
order(*argv, **keywords, &nonopt) 点击切换源代码

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

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

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

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

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

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

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

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

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

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

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

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

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

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

# File rubygems/vendor/optparse/lib/optparse.rb, line 1290
def program_name
  @program_name || File.basename($0, '.*')
end
reject(*args, &blk) 单击以切换源

指示拒绝指定的类参数。

类型

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

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

发布代码

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

删除最后一个 List

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

在摘要中添加分隔符。

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

将选项摘要放入 to 并返回 to。如果给定了代码块,则 yield 每行。

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

width

左侧宽度,默认为 @summary_width。

最大值

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

indent

缩进,默认为 @summary_indent。

# File rubygems/vendor/optparse/lib/optparse.rb, line 1397
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 rubygems/vendor/optparse/lib/optparse.rb, line 1202
def terminate(arg = nil)
  self.class.terminate(arg)
end
to_a() 点击切换源代码

返回选项摘要列表。

# File rubygems/vendor/optparse/lib/optparse.rb, line 1436
def to_a; summarize("#{banner}".split(/^/)) end
to_s()
别名: help
top() 单击以切换源

on / on_headaccept / reject 的主题

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

program_name、版本和发布信息返回版本字符串。

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

Version

# File rubygems/vendor/optparse/lib/optparse.rb, line 1308
def version
  (defined?(@version) && @version) || (defined?(::Version) && ::Version)
end
warn(mesg = $!) 点击切换源代码

使用程序名称显示警告消息

mesg

消息,默认为 +$!+。

请参阅 Kernel#warn。

调用超类方法
# File rubygems/vendor/optparse/lib/optparse.rb, line 1337
def warn(mesg = $!)
  super("#{program_name}: #{mesg}")
end