класс OptionParser
OptionParser
Введение
OptionParser — это класс для анализа командно-строчных опций. Он значительно более продвинутый, но и проще в использовании, чем GetoptLong, и представляет более ориентированное на Ruby решение.
Особенности
-
Спецификация аргументов и код для их обработки записываются в одном месте.
-
Он может выводить сводку опций; вам не нужно хранить эту строку отдельно.
-
Необязательные и обязательные аргументы задаются очень удобно.
-
Аргументы могут быть автоматически преобразованы в указанный класс.
-
Аргументы могут быть ограничены определённым набором.
Все эти особенности продемонстрированы в примерах ниже. Полную документацию см. в make_switch.
Минимальный пример
require 'optparse'
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: example.rb [options]"
opts.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 |opts|
opts.banner = "Usage: example.rb [options]"
opts.on("-nNAME", "--name=NAME", "Name to say hello to") do |n|
args.name = n
end
opts.on("-h", "--help", "Prints this help") do
puts opts
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 поставляется с несколькими готовыми типами преобразований. Они следующие:
-
Date— Всё, что принимаетDate.parse -
DateTime— Всё, что принимаетDateTime.parse -
Time— Всё, что принимаетTime.httpdateилиTime.parse -
URI— Всё, что принимаетURI.parse -
Shellwords— Всё, что принимаетShellwords.shellwords -
String— Любая непустая строка -
Integer— Любое целое число. Преобразует восьмеричные числа. (например, 124, -3, 040) -
Float— Любое число с плавающей точкой. (например, 10, 3.14, -100E+13) -
Numeric— Любое целое число, число с плавающей точкой или рациональное число (1, 3.4, 1/3) -
DecimalInteger— КакInteger, но без восьмеричного формата. -
OctalInteger— КакInteger, но без десятичного формата. -
DecimalNumeric— Десятичное целое число или число с плавающей точкой. -
TrueClass— Принимает '+, да, true, -, нет, false' и по умолчанию какtrue -
FalseClass— То же, что иTrueClass, но по умолчаниюfalse -
Array— Строки, разделённые запятыми (например, 1,2,3) -
Regexp— Регулярные выражения. Также включает опции.
Мы также можем добавить свои преобразования, которые мы рассмотрим ниже.
Использование встроенных преобразований
В качестве примера используется встроенное преобразование 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 может использоваться для создания преобразователей. Он указывает, какой блок преобразования вызывать всякий раз, когда указывается класс. В примере ниже он используется для извлечения объекта User перед тем, как обработчик on его получит.
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
Опция into в методах order, parse и т. д. сохраняет командно-строчные опции в Hash.
require 'optparse'
params = {}
OptionParser.new do |opts|
opts.on('-a')
opts.on('-b NUM', Integer)
opts.on('-v', '--verbose')
end.parse!(into: params)
p params
Использование:
$ 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
Модуль оболочки Completion
Для современных оболочек (например, bash, zsh и т. д.) можно использовать автодополнение командных опций.
Дополнительная документация
Приведённых выше примеров должно быть достаточно, чтобы понять, как использовать этот класс. Если у вас есть вопросы, отправьте тикет на bugs.ruby-lang.org.
Константы
- DecimalInteger
-
Формат десятичного целого числа, который будет преобразован в
Integer. - DecimalNumeric
-
Формат десятичного целого/вещественного числа, который будет преобразован в
Integerдля целого формата иFloatдля формата с плавающей точкой. - OctalInteger
-
Формат восьмеричного/шестнадцатеричного/двоичного целого числа (подобно Ruby/C), который будет преобразован в
Integer.
Атрибуты
Заголовок-баннер, предшествующий описанию.
Строки, которые будут обработаны по умолчанию.
Имя программы, которое будет выведено в сообщении об ошибке и в баннере по умолчанию, по умолчанию равно $0.
Код выпуска
Заголовок-баннер, предшествующий описанию.
Имя программы, которое будет выведено в сообщении об ошибке и в баннере по умолчанию, по умолчанию равно $0.
Ширина части описания с перечислением опций. Должна быть Numeric.
Ширина части описания с перечислением опций. Должна быть Numeric.
Версия
Открытые методы класса
# File lib/optparse.rb, line 1130 def self.accept(*args, &blk) top.accept(*args, &blk) end
См. accept.
# 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 # File lib/optparse.rb, line 1740 def self.getopts(*args) new.getopts(*args) end
См. getopts.
# File lib/optparse.rb, line 1066
def self.inc(arg, default = nil)
case arg
when Integer
arg.nonzero?
when nil
default.to_i + 1
end
end Возвращает увеличенное значение default в соответствии с arg.
# File lib/optparse.rb, line 1085 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 add_officious yield self if block_given? end
Инициализирует экземпляр и вызывает переданный блок, если он указан.
-
banner -
Сообщение баннера.
-
width -
Ширина описания.
-
indent -
Отступ описания.
# File lib/optparse.rb, line 1143 def self.reject(*args, &blk) top.reject(*args, &blk) end
См. reject.
# 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 # 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 # File lib/optparse.rb, line 1110 def self.terminate(arg = nil) throw :terminate, arg end
# File lib/optparse.rb, line 1115 def self.top() DefaultList end
# File lib/optparse.rb, line 1057 def self.with(*args, &block) opts = new(*args) opts.instance_eval(&block) opts end
Инициализирует новый экземпляр и вычисляет указанный блок в контексте экземпляра. Аргументы args передаются в new, см. описание параметров там.
Этот метод устарел, его поведение соответствует более старому методу new.
Методы экземпляров общедоступного доступа
# File lib/optparse.rb, line 1224
def abort(mesg = $!)
super("#{program_name}: #{mesg}")
end Kernel#abort # File lib/optparse.rb, line 1126 def accept(*args, &blk) top.accept(*args, &blk) end
Направляет для приема указанного класса t. Строка аргумента передается в блок, в котором она должна быть преобразована в нужный класс.
-
t -
Указатель класса аргумента, любой объект, включая
Class. -
pat -
Шаблон для аргумента, по умолчанию
t, если он отвечает на match.
accept(t, pat, &block)
# File lib/optparse.rb, line 1791
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 Возвращает дополнительную информацию.
# File lib/optparse.rb, line 1168
def banner
unless @banner
@banner = +"Usage: #{program_name} [options]"
visit(:add_banner, @banner)
end
@banner
end Заголовок баннера, предваряющий сводку.
# File lib/optparse.rb, line 1238 def base @stack[1] end
Предмет on_tail.
# File lib/optparse.rb, line 1802
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 # File lib/optparse.rb, line 1499 def define(*opts, &block) top.append(*(sw = make_switch(opts, block))) sw[0] end
# File lib/optparse/kwargs.rb, line 5
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 # File lib/optparse.rb, line 1514 def define_head(*opts, &block) top.prepend(*(sw = make_switch(opts, block))) sw[0] end
# File lib/optparse.rb, line 1528 def define_tail(*opts, &block) base.append(*(sw = make_switch(opts, block))) sw[0] end
# File lib/optparse.rb, line 1872 def environment(env = File.basename($0, '.*')) env = ENV[env] || ENV[env.upcase] or return require 'shellwords' parse(*Shellwords.shellwords(env)) end
Парсит переменную окружения env или её верхний регистр с разбиением как в оболочке.
env по умолчанию — имя программы.
# File lib/optparse.rb, line 1705
def getopts(*args)
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(:[]=))
result
end Метод-обёртка для 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
# File lib/optparse.rb, line 1280
def help; summarize("#{banner}".sub(/\n?\z/, "\n")) end Возвращает строку сводки опций.
# File lib/optparse.rb, line 1074 def inc(*args) self.class.inc(*args) end
# File lib/optparse.rb, line 1840
def load(filename = nil)
unless filename
basename = File.basename($0, '.*')
return true if load(File.expand_path(basename, '~/.options')) 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)) rescue nil
}
end
begin
parse(*IO.readlines(filename).each {|s| s.chomp!})
true
rescue Errno::ENOENT, Errno::ENOTDIR
false
end
end Загружает опции из имён файлов как filename. Ничего не делает, когда файл отсутствует. Возвращает, загрузился ли успешно.
filename по умолчанию — имя программы без суффикса в каталоге ~/.options, затем имя программы с суффиксом '.options' в стандартных местах XDG и Haiku.
# File lib/optparse.rb, line 1366
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)
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 Создаёт OptionParser::Switch из параметров. Значение обработанного аргумента передаётся в указанный блок, где может быть обработано.
См. в начале OptionParser для некоторых полных примеров.
opts может содержать следующие элементы:
- Стиль аргумента:
-
Один из следующих:
:NONE, :REQUIRED, :OPTIONAL
- Шаблон аргумента:
-
Допустимый формат аргумента опции, должен быть предварительно определён с
OptionParser.acceptилиOptionParser#accept, илиRegexp. Это может появиться один раз или назначено какString, если отсутствует, в противном случае вызываетArgumentError. Примеры:Float, Time, Array
- Возможные значения аргументов:
-
[:text, :binary, :auto] %w[iso-2022-jp shift_jis euc-jp utf8 binary] { "jis" => "iso-2022-jp", "sjis" => "shift_jis" } - Переключатель длинной формы:
-
Указывает переключатель длинной формы, который принимает обязательный, необязательный или ни один аргумент. Это строка следующего вида:
"--switch=MANDATORY" or "--switch MANDATORY" "--switch[=OPTIONAL]" "--switch"
- Переключатель короткой формы:
-
Указывает переключатель короткой формы, который принимает обязательный, необязательный или ни один аргумент. Это строка следующего вида:
"-xMANDATORY" "-x[OPTIONAL]" "-x"
Также существует специальная форма, которая соответствует диапазону символов (не полный набор регулярных выражений):
"-[a-z]MANDATORY" "-[a-z][OPTIONAL]" "-[a-z]"
- Стиль аргумента и описание:
-
Вместо того, чтобы указывать обязательные или необязательные аргументы непосредственно в параметре переключателя, можно использовать этот отдельный параметр.
"=MANDATORY" "=[OPTIONAL]"
- Описание:
-
Строка описания опции.
"Run verbosely"
Если вы даёте несколько строк описания, каждая строка будет напечатана в отдельной строке.
- Обработчик:
-
Обработчик для значения обработанного аргумента. Либо укажите блок, либо передайте
ProcилиMethodкак аргумент.
# File lib/optparse.rb, line 1245
def new
@stack.push(List.new)
if block_given?
yield self
else
self
end
end Добавляет новый List.
# File lib/optparse.rb, line 1508 def on(*opts, &block) define(*opts, &block) self end
Добавляет переключатель опции и обработчик. Смотрите make_switch для объяснения параметров.
# File lib/optparse.rb, line 1522 def on_head(*opts, &block) define_head(*opts, &block) self end
Добавить переключатель опции, как с on, но в начале сводки.
# File lib/optparse.rb, line 1536 def on_tail(*opts, &block) define_tail(*opts, &block) self end
Добавить переключатель опции, как с on, но в конце сводки.
# File lib/optparse.rb, line 1558 def order(*argv, into: nil, &nonopt) argv = argv[0].dup if argv.size == 1 and Array === argv[0] order!(argv, into: into, &nonopt) end
Парсит аргументы командной строки argv в порядке. Когда задан блок, каждый не-опциональный аргумент передается в него. Если указан необязательный into ключевой аргумент, значения обработанных опций сохраняются там через []= метод (так что это может быть Hash, или OpenStruct, или другой аналогичный объект).
Возвращает остаток argv необработанных аргументов.
# File lib/optparse.rb, line 1567
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 То же, что и order, но удаляет переключатели деструктивно. Не-опциональные аргументы остаются в argv.
# File lib/optparse.rb, line 1678 def parse(*argv, into: nil) argv = argv[0].dup if argv.size == 1 and Array === argv[0] parse!(argv, into: into) end
Парсит аргументы командной строки argv в порядке, когда переменная окружения POSIXLY_CORRECT установлена, и в режиме перестановки в противном случае. Если указан необязательный into ключевой аргумент, значения обработанных опций сохраняются там через []= метод (так что это может быть Hash, или OpenStruct, или другой аналогичный объект).
# File lib/optparse.rb, line 1687
def parse!(argv = default_argv, into: nil)
if ENV.include?('POSIXLY_CORRECT')
order!(argv, into: into)
else
permute!(argv, into: into)
end
end То же, что и parse, но удаляет переключатели деструктивно. Не-опциональные аргументы остаются в argv.
# File lib/optparse.rb, line 1655 def permute(*argv, into: nil) argv = argv[0].dup if argv.size == 1 and Array === argv[0] permute!(argv, into: into) end
Парсит аргументы командной строки argv в режиме перестановки и возвращает список не-опциональных аргументов. Если указан необязательный into ключевой аргумент, значения обработанных опций сохраняются там через []= метод (так что это может быть Hash, или OpenStruct, или другой аналогичный объект).
# File lib/optparse.rb, line 1664 def permute!(argv = default_argv, into: nil) nonopts = [] order!(argv, into: into, &nonopts.method(:<<)) argv[0, 0] = nonopts argv end
То же, что и permute, но удаляет переключатели деструктивно. Не-опциональные аргументы остаются в argv.
# File lib/optparse.rb, line 1180 def program_name @program_name || File.basename($0, '.*') end
Имя программы, отображаемое в сообщении об ошибке и в баннере по умолчанию, по умолчанию равно $0.
# File lib/optparse.rb, line 1139 def reject(*args, &blk) top.reject(*args, &blk) end
Направляет для отклонения указанного аргумента класса.
-
t -
Указатель класса аргумента, любой объект, включая
Class.
reject(t)
# File lib/optparse.rb, line 1205 def release (defined?(@release) && @release) || (defined?(::Release) && ::Release) || (defined?(::RELEASE) && ::RELEASE) end
Код выпуска
# File lib/optparse.rb, line 1257 def remove @stack.pop end
Удаляет последнюю List.
# File lib/optparse.rb, line 1545 def separator(string) top.append(string, nil, nil) end
Добавляет разделитель в сводку.
# File lib/optparse.rb, line 1270
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 Добавляет сводку опций в to и возвращает to. Передает каждую строку, если задан блок.
-
to -
Место назначения вывода, которое должно иметь метод <<. По умолчанию [].
-
width -
Ширина левой стороны, по умолчанию @summary_width.
-
max -
Максимальная длина, разрешенная для левой стороны, по умолчанию
width- 1. -
indent -
Отступ, по умолчанию @summary_indent.
# File lib/optparse.rb, line 1107 def terminate(arg = nil) self.class.terminate(arg) end
Прерывает парсинг опций. Необязательный параметр arg — строка, возвращенная назад, чтобы быть первым не-опциональным аргументом.
# File lib/optparse.rb, line 1286
def to_a; summarize("#{banner}".split(/^/)) end Возвращает список сводки опций.
# File lib/optparse.rb, line 1212
def ver
if v = version
str = +"#{program_name} #{[v].join('.')}"
str << " (#{v})" if v = release
str
end
end Возвращает строку версии из program_name, версии и выпуска.
# File lib/optparse.rb, line 1198 def version (defined?(@version) && @version) || (defined?(::Version) && ::Version) end
Версия
# File lib/optparse.rb, line 1220
def warn(mesg = $!)
super("#{program_name}: #{mesg}")
end Kernel#warn Методы приватного экземпляра
# File lib/optparse.rb, line 1776
def complete(typ, opt, icase = false, *pat)
if pat.empty?
search(typ, opt) {|sw| return [sw, opt]} # exact match or...
end
ambiguous = catch(:ambiguous) {
visit(:complete, typ, opt, icase, *pat) {|o, *sw| return sw}
}
exc = ambiguous ? AmbiguousOption : InvalidOption
raise exc.new(opt, additional: self.method(:additional_message).curry[typ])
end Завершает сокращенную опцию длинного стиля и возвращает пару канонического переключателя и описателя переключателя OptionParser::Switch.
-
typ -
Таблица поиска.
-
opt -
Ключ поиска.
-
icase -
Поиск без учета регистра, если true.
-
pat -
Необязательный шаблон для завершения.
# File lib/optparse.rb, line 1296
def notwice(obj, prv, msg)
unless !prv or prv == obj
raise(ArgumentError, "argument #{msg} given twice: #{obj}",
ParseError.filter_backtrace(caller(2)))
end
obj
end Проверяет, задан ли аргумент дважды, в этом случае поднимается ArgumentError. Вызывается только из OptionParser#switch.
-
obj -
Новый аргумент.
-
prv -
Ранее указанный аргумент.
-
msg -
Сообщение
Exception.
# File lib/optparse.rb, line 1759
def search(id, key)
block_given = block_given?
visit(:search, id, key) do |k|
return block_given ? yield(k) : k
end
end Ищет key в @stack для хэша id и возвращает или передает результат.
# File lib/optparse.rb, line 1748
def visit(id, *args, &block)
@stack.reverse_each do |el|
el.send(id, *args, &block)
end
nil
end Обходит @stack, отправляя каждый элемент методу id с args и block.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.