| Class | OptionParser |
| In: |
lib/optparse.rb
|
| Parent: | Object |
+--------------+
| OptionParser |<>-----+
+--------------+ | +--------+
| ,-| Switch |
on_head -------->+---------------+ / +--------+
accept/reject -->| List |<|>-
| |<|>- +----------+
on ------------->+---------------+ `-| argument |
: : | class |
+---------------+ |==========|
on_tail -------->| | |pattern |
+---------------+ |----------|
OptionParser.accept ->| DefaultList | |converter |
reject |(shared between| +----------+
| all instances)|
+---------------+
OptionParser is a class for command-line option analysis. It is much more advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented solution.
All of these features are demonstrated in the examples below.
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
The following example is a complete Ruby program. You can run it and see the effect of specifying various options. This is probably the best way to learn the features of optparse.
require 'optparse'
require 'optparse/time'
require 'ostruct'
require 'pp'
class OptparseExample
CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
#
# Return a structure describing the options.
#
def self.parse(args)
# The options specified on the command line will be collected in *options*.
# We set default values here.
options = OpenStruct.new
options.library = []
options.inplace = false
options.encoding = "utf8"
options.transfer_type = :auto
options.verbose = false
opts = OptionParser.new do |opts|
opts.banner = "Usage: example.rb [options]"
opts.separator ""
opts.separator "Specific options:"
# Mandatory argument.
opts.on("-r", "--require LIBRARY",
"Require the LIBRARY before executing your script") do |lib|
options.library << lib
end
# Optional argument; multi-line description.
opts.on("-i", "--inplace [EXTENSION]",
"Edit ARGV files in place",
" (make backup if EXTENSION supplied)") do |ext|
options.inplace = true
options.extension = ext || ''
options.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension begins with dot.
end
# Cast 'delay' argument to a Float.
opts.on("--delay N", Float, "Delay N seconds before executing") do |n|
options.delay = n
end
# Cast 'time' argument to a Time object.
opts.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
options.time = time
end
# Cast to octal integer.
opts.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
"Specify record separator (default \\0)") do |rs|
options.record_separator = rs
end
# List of arguments.
opts.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
options.list = list
end
# 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(',')
opts.on("--code CODE", CODES, CODE_ALIASES, "Select encoding",
" (#{code_list})") do |encoding|
options.encoding = encoding
end
# Optional argument with keyword completion.
opts.on("--type [TYPE]", [:text, :binary, :auto],
"Select transfer type (text, binary, auto)") do |t|
options.transfer_type = t
end
# Boolean switch.
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
options.verbose = v
end
opts.separator ""
opts.separator "Common options:"
# No argument, shows at tail. This will print an options summary.
# Try it and see!
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
# Another typical switch to print the version.
opts.on_tail("--version", "Show version") do
puts OptionParser::Version.join('.')
exit
end
end
opts.parse!(args)
options
end # parse()
end # class OptparseExample
options = OptparseExample.parse(ARGV)
pp options
The above examples should be enough to learn how to use this class. If you have any questions, email me (gsinclair@soyabean.com.au) and I will update this document.
| DecimalInteger | = | /\A[-+]?#{decimal}/io | Decimal integer format, to be converted to Integer. | |
| OctalInteger | = | /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))/io | Ruby/C like octal/hexadecimal/binary integer format, to be converted to Integer. | |
| DecimalNumeric | = | floatpat # decimal integer is allowed as float also. | Decimal integer/float number format, to be converted to Integer for integer format, Float for float format. |
| banner= | -> | set_banner |
| for experimental cascading :-) | ||
| program_name= | -> | set_program_name |
| summary_width= | -> | set_summary_width |
| summary_indent= | -> | set_summary_indent |
| banner | [W] | Heading banner preceding summary. |
| default_argv | [RW] | Strings to be parsed in default. |
| program_name | [W] | Program name to be emitted in error message and default banner, defaults to $0. |
| release | [W] | Release code |
| summary_indent | [RW] | Indentation for summary. Must be String (or have + String method). |
| summary_width | [RW] | Width for option list portion of summary. Must be Numeric. |
| version | [W] | Version |
Returns an incremented value of default according to arg.
# File lib/optparse.rb, line 728
728: def self.inc(arg, default = nil)
729: case arg
730: when Integer
731: arg.nonzero?
732: when nil
733: default.to_i + 1
734: end
735: end
Initializes the instance and yields itself if called with a block.
| banner: | Banner message. |
| width: | Summary width. |
| indent: | Summary indent. |
# File lib/optparse.rb, line 747
747: def initialize(banner = nil, width = 32, indent = ' ' * 4)
748: @stack = [DefaultList, List.new, List.new]
749: @program_name = nil
750: @banner = banner
751: @summary_width = width
752: @summary_indent = indent
753: @default_argv = ARGV
754: add_officious
755: yield self if block_given?
756: end
# File lib/optparse.rb, line 772
772: def self.terminate(arg = nil)
773: throw :terminate, arg
774: end
Initializes a new instance and evaluates the optional block in context of the instance. Arguments args are passed to new, see there for description of parameters.
This method is deprecated, its behavior corresponds to the older new method.
# File lib/optparse.rb, line 719
719: def self.with(*args, &block)
720: opts = new(*args)
721: opts.instance_eval(&block)
722: opts
723: end
# File lib/optparse.rb, line 882
882: def abort(mesg = $!)
883: super("#{program_name}: #{mesg}")
884: end
Directs to accept specified class t. The argument string is passed to the block in which it should be converted to the desired class.
| t: | Argument class specifier, any object including Class. |
| pat: | Pattern for argument, defaults to t if it responds to match. |
accept(t, pat, &block)
# File lib/optparse.rb, line 788
788: def accept(*args, &blk) top.accept(*args, &blk) end
# File lib/optparse.rb, line 1138
1138: def define(*opts, &block)
1139: top.append(*(sw = make_switch(*opts, &block)))
1140: sw[0]
1141: end
# File lib/optparse.rb, line 1153
1153: def define_head(*opts, &block)
1154: top.prepend(*(sw = make_switch(*opts, &block)))
1155: sw[0]
1156: end
# File lib/optparse.rb, line 1167
1167: def define_tail(*opts, &block)
1168: base.append(*(sw = make_switch(*opts, &block)))
1169: sw[0]
1170: end
Parses environment variable env or its uppercase with splitting like a shell.
env defaults to the basename of the program.
# File lib/optparse.rb, line 1413
1413: def environment(env = File.basename($0, '.*'))
1414: env = ENV[env] || ENV[env.upcase] or return
1415: parse(*Shellwords.shellwords(env))
1416: end
Wrapper method for getopts.rb.
# File lib/optparse.rb, line 1307
1307: def getopts(argv, single_options, *long_options)
1308: result = {}
1309:
1310: single_options.scan(/(.)(:)?/) do |opt, val|
1311: if val
1312: result[opt] = nil
1313: define("-#{opt} VAL") {|val| result[opt] = val}
1314: else
1315: result[opt] = false
1316: define("-#{opt}") {result[opt] = true}
1317: end
1318: end if single_options
1319:
1320: long_options.each do |arg|
1321: opt, val = arg.split(':', 2)
1322: if val
1323: result[opt] = val.empty? ? nil : val
1324: define("--#{opt} VAL") {|val| result[opt] = val}
1325: else
1326: result[opt] = false
1327: define("--#{opt}") {result[opt] = true}
1328: end
1329: end
1330:
1331: order!(argv)
1332: result
1333: end
Returns option summary string.
# File lib/optparse.rb, line 936
936: def help; summarize(banner.to_s.sub(/\n?\z/, "\n")) end
Loads options from file names as filename. Does nothing when the file is not present. Returns whether successfully loaded.
filename defaults to basename of the program without suffix in a directory ~/.options.
# File lib/optparse.rb, line 1393
1393: def load(filename = nil)
1394: begin
1395: filename ||= File.expand_path(File.basename($0, '.*'), '~/.options')
1396: rescue
1397: return false
1398: end
1399: begin
1400: parse(*IO.readlines(filename).each {|s| s.chomp!})
1401: true
1402: rescue Errno::ENOENT, Errno::ENOTDIR
1403: false
1404: end
1405: end
Creates an OptionParser::Switch from the parameters. The parsed argument value is passed to the given block, where it can be processed.
See at the beginning of OptionParser for some full examples.
opts can include the following elements:
:NONE, :REQUIRED, :OPTIONAL
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"
There is also a special form which matches character range (not full set of regural expression):
"-[a-z]MANDATORY" "-[a-z][OPTIONAL]" "-[a-z]"
"=MANDATORY" "=[OPTIONAL]"
"Run verbosely"
# File lib/optparse.rb, line 1023
1023: def make_switch(*opts, &block)
1024: short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], []
1025: ldesc, sdesc, desc, arg = [], [], []
1026: default_style = Switch::NoArgument
1027: default_pattern = nil
1028: klass = nil
1029: o = nil
1030: n, q, a = nil
1031:
1032: opts.each do |o|
1033: # argument class
1034: next if search(:atype, o) do |pat, c|
1035: klass = notwice(o, klass, 'type')
1036: if not_style and not_style != Switch::NoArgument
1037: not_pattern, not_conv = pat, c
1038: else
1039: default_pattern, conv = pat, c
1040: end
1041: end
1042:
1043: # directly specified pattern(any object possible to match)
1044: if !(String === o) and o.respond_to?(:match)
1045: pattern = notwice(o, pattern, 'pattern')
1046: conv = (pattern.method(:convert).to_proc if pattern.respond_to?(:convert))
1047: next
1048: end
1049:
1050: # anything others
1051: case o
1052: when Proc, Method
1053: block = notwice(o, block, 'block')
1054: when Array, Hash
1055: case pattern
1056: when CompletingHash
1057: when nil
1058: pattern = CompletingHash.new
1059: conv = (pattern.method(:convert).to_proc if pattern.respond_to?(:convert))
1060: else
1061: raise ArgumentError, "argument pattern given twice"
1062: end
1063: o.each {|(o, *v)| pattern[o] = v.fetch(0) {o}}
1064: when Module
1065: raise ArgumentError, "unsupported argument type: #{o}"
1066: when *ArgumentStyle.keys
1067: style = notwice(ArgumentStyle[o], style, 'style')
1068: when /^--no-([^\[\]=\s]*)(.+)?/
1069: q, a = $1, $2
1070: o = notwice(a ? Object : TrueClass, klass, 'type')
1071: not_pattern, not_conv = search(:atype, o) unless not_style
1072: not_style = (not_style || default_style).guess(arg = a) if a
1073: default_style = Switch::NoArgument
1074: default_pattern, conv = search(:atype, FalseClass) unless default_pattern
1075: ldesc << "--no-#{q}"
1076: long << 'no-' + (q = q.downcase)
1077: nolong << q
1078: when /^--\[no-\]([^\[\]=\s]*)(.+)?/
1079: q, a = $1, $2
1080: o = notwice(a ? Object : TrueClass, klass, 'type')
1081: if a
1082: default_style = default_style.guess(arg = a)
1083: default_pattern, conv = search(:atype, o) unless default_pattern
1084: end
1085: ldesc << "--[no-]#{q}"
1086: long << (o = q.downcase)
1087: not_pattern, not_conv = search(:atype, FalseClass) unless not_style
1088: not_style = Switch::NoArgument
1089: nolong << 'no-' + o
1090: when /^--([^\[\]=\s]*)(.+)?/
1091: q, a = $1, $2
1092: if a
1093: o = notwice(NilClass, klass, 'type')
1094: default_style = default_style.guess(arg = a)
1095: default_pattern, conv = search(:atype, o) unless default_pattern
1096: end
1097: ldesc << "--#{q}"
1098: long << (o = q.downcase)
1099: when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
1100: q, a = $1, $2
1101: o = notwice(Object, klass, 'type')
1102: if a
1103: default_style = default_style.guess(arg = a)
1104: default_pattern, conv = search(:atype, o) unless default_pattern
1105: end
1106: sdesc << "-#{q}"
1107: short << Regexp.new(q)
1108: when /^-(.)(.+)?/
1109: q, a = $1, $2
1110: if a
1111: o = notwice(NilClass, klass, 'type')
1112: default_style = default_style.guess(arg = a)
1113: default_pattern, conv = search(:atype, o) unless default_pattern
1114: end
1115: sdesc << "-#{q}"
1116: short << q
1117: when /^=/
1118: style = notwice(default_style.guess(arg = o), style, 'style')
1119: default_pattern, conv = search(:atype, Object) unless default_pattern
1120: else
1121: desc.push(o)
1122: end
1123: end
1124:
1125: default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
1126: s = if short.empty? and long.empty?
1127: raise ArgumentError, "no switch given" if style or pattern or block
1128: desc
1129: else
1130: (style || default_style).new(pattern || default_pattern,
1131: conv, sdesc, ldesc, arg, desc, block)
1132: end
1133: return s, short, long,
1134: (not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
1135: nolong
1136: end
Add option switch and handler. See make_switch for an explanation of parameters.
# File lib/optparse.rb, line 1147
1147: def on(*opts, &block)
1148: define(*opts, &block)
1149: self
1150: end
Parses command line arguments argv in order. When a block is given, each non-option argument is yielded.
Returns the rest of argv left unparsed.
# File lib/optparse.rb, line 1194
1194: def order(*argv, &block)
1195: argv = argv[0].dup if argv.size == 1 and Array === argv[0]
1196: order!(argv, &block)
1197: end
Same as order, but removes switches destructively.
# File lib/optparse.rb, line 1202
1202: def order!(argv = default_argv, &nonopt)
1203: opt, arg, sw, val, rest = nil
1204: nonopt ||= proc {|arg| throw :terminate, arg}
1205: argv.unshift(arg) if arg = catch(:terminate) {
1206: while arg = argv.shift
1207: case arg
1208: # long option
1209: when /\A--([^=]*)(?:=(.*))?/nm
1210: opt, rest = $1, $2
1211: begin
1212: sw, = complete(:long, opt, true)
1213: rescue ParseError
1214: raise $!.set_option(arg, true)
1215: end
1216: begin
1217: opt, sw, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
1218: sw.call(val) if sw
1219: rescue ParseError
1220: raise $!.set_option(arg, rest)
1221: end
1222:
1223: # short option
1224: when /\A-(.)((=).*|.+)?/nm
1225: opt, has_arg, eq, val, rest = $1, $3, $3, $2, $2
1226: begin
1227: unless sw = search(:short, opt)
1228: begin
1229: sw, = complete(:short, opt)
1230: # short option matched.
1231: val = arg.sub(/\A-/, '')
1232: has_arg = true
1233: rescue InvalidOption
1234: # if no short options match, try completion with long
1235: # options.
1236: sw, = complete(:long, opt)
1237: eq ||= !rest
1238: end
1239: end
1240: rescue ParseError
1241: raise $!.set_option(arg, true)
1242: end
1243: begin
1244: opt, sw, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
1245: raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
1246: argv.unshift(opt) if opt and (opt = opt.sub(/\A-*/, '-')) != '-'
1247: sw.call(val) if sw
1248: rescue ParseError
1249: raise $!.set_option(arg, arg.length > 2)
1250: end
1251:
1252: # non-option argument
1253: else
1254: nonopt.call(arg)
1255: end
1256: end
1257:
1258: nil
1259: }
1260:
1261: argv
1262: end
Parses command line arguments argv in order when environment variable POSIXLY_CORRECT is set, and in permutation mode otherwise.
# File lib/optparse.rb, line 1288
1288: def parse(*argv)
1289: argv = argv[0].dup if argv.size == 1 and Array === argv[0]
1290: parse!(argv)
1291: end
Parses command line arguments argv in permutation mode and returns list of non-option arguments.
# File lib/optparse.rb, line 1268
1268: def permute(*argv)
1269: argv = argv[0].dup if argv.size == 1 and Array === argv[0]
1270: permute!(argv)
1271: end
Release code
# File lib/optparse.rb, line 863
863: def release
864: @release || (defined?(::Release) && ::Release) || (defined?(::RELEASE) && ::RELEASE)
865: end
Puts option summary into to and returns to. Yields each line if a block is given.
| to: | Output destination, which must have method <<. Defaults to []. |
| width: | Width of left side, defaults to @summary_width. |
| max: | Maximum length allowed for left side, defaults to width - 1. |
| indent: | Indentation, defaults to @summary_indent. |
# File lib/optparse.rb, line 928
928: def summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk)
929: visit(:summarize, {}, {}, width, max, indent, &(blk || proc {|l| to << l + $/}))
930: to
931: end
Terminates option parsing. Optional parameter arg is a string pushed back to be the first non-option argument.
# File lib/optparse.rb, line 769
769: def terminate(arg = nil)
770: self.class.terminate(arg)
771: end
Returns option summary list.
# File lib/optparse.rb, line 942
942: def to_a; summarize(banner.to_a.dup) end
Returns version string from program_name, version and release.
# File lib/optparse.rb, line 870
870: def ver
871: if v = version
872: str = "#{program_name} #{[v].join('.')}"
873: str << " (#{v})" if v = release
874: str
875: end
876: end
Version
# File lib/optparse.rb, line 856
856: def version
857: @version || (defined?(::Version) && ::Version)
858: end
# File lib/optparse.rb, line 878
878: def warn(mesg = $!)
879: super("#{program_name}: #{mesg}")
880: end
Completes shortened long style option switch and returns pair of canonical switch and switch descriptor OptionParser::Switch.
| id: | Searching table. |
| opt: | Searching key. |
| icase: | Search case insensitive if true. |
| pat: | Optional pattern for completion. |
# File lib/optparse.rb, line 1375
1375: def complete(typ, opt, icase = false, *pat)
1376: if pat.empty?
1377: search(typ, opt) {|sw| return [sw, opt]} # exact match or...
1378: end
1379: raise AmbiguousOption, catch(:ambiguous) {
1380: visit(:complete, typ, opt, icase, *pat) {|opt, *sw| return sw}
1381: raise InvalidOption, opt
1382: }
1383: end
Checks if an argument is given twice, in which case an ArgumentError is raised. Called from OptionParser#switch only.
| obj: | New argument. |
| prv: | Previously specified argument. |
| msg: | Exception message. |
# File lib/optparse.rb, line 952
952: def notwice(obj, prv, msg)
953: unless !prv or prv == obj
954: begin
955: raise ArgumentError, "argument #{msg} given twice: #{obj}"
956: rescue
957: $@[0, 2] = nil
958: raise
959: end
960: end
961: obj
962: end
Searches key k in @stack for id hash and returns or yields the result.
# File lib/optparse.rb, line 1358
1358: def search(id, k)
1359: visit(:search, id, k) do |k|
1360: return k unless block_given?
1361: return yield(k)
1362: end
1363: end