class Como::Opt
Opt
includes all options spec information and parsed options and their values. Option instance is accessed with “Opt”. The option status (Opt
instance) can be queried with for example “given” and “value” methods.
Attributes
Opt
configuration.
Option documentation string.
Is option specified?
Long option string.
Option name.
Subcommand parent (i.e. host).
Opt
rules.
Short option string.
List of subcommands.
List of suboptions.
Option type as array of primitives (or :subcmd).
Option value.
Public Class Methods
Select option object by name. Main is searched first and then the flattened list of all options.
# File lib/como.rb, line 1062 def Opt.[](str) # Search Main first. ret = Opt.main.argByName( str ) unless ret ret = Opt.findOpt( str ) unless ret raise RuntimeError, "Option \"#{str}\" does not exist..." end end ret end
Add option to options list.
# File lib/como.rb, line 1026 def Opt.addOpt( opt ) @@opts.push opt end
Return default config for Como
options.
# File lib/como.rb, line 1144 def Opt.configGet @@config end
Overlay Opt
default configuration options.
# File lib/como.rb, line 1138 def Opt.configOverlay( config ) @@config.merge!( config ) end
Set default config for Como
options. User can manipulate the defaults with “preHook”.
# File lib/como.rb, line 1151 def Opt.configSet( config ) @@config = config end
Current subcmd processed.
# File lib/como.rb, line 1038 def Opt.current @@subcmd end
Return arguments (options) that have no switch.
# File lib/como.rb, line 1104 def Opt.default Opt.main.default end
Create default option spec, no switch.
# File lib/como.rb, line 1120 def Opt.defaultOpt( doc = "No doc." ) new( "<default>", "<default>", [ :default, :none, :one, :many, :opt ], doc, [] ) end
Options iterator for all options.
# File lib/como.rb, line 1126 def Opt.each( &blk ) Opt.main.each( &blk ) end
Options iterator for given options.
# File lib/como.rb, line 1132 def Opt.each_given( &blk ) Opt.main.each_given( &blk ) end
Issue non-fatal user error. See {#error}.
# File lib/como.rb, line 1157 def Opt.error( str, nl = false ) Opt.main.error( str, nl ) end
Return arguments (options) that are specified as command external (i.e. after '–').
# File lib/como.rb, line 1098 def Opt.external Opt.main.external end
Issue fatal user error. See {#fatal}.
# File lib/como.rb, line 1163 def Opt.fatal( str ) Opt.main.fatal( str ) end
Find option by name.
# File lib/como.rb, line 1044 def Opt.findOpt( name ) idx = @@opts.index do |i| i.name == name end if idx @@opts[ idx ] else nil end end
Create option spec.
# File lib/como.rb, line 1110 def Opt.full( name, opt, type, doc = "No doc." ) new( name, opt, type, doc ) end
Get main option.
# File lib/como.rb, line 1020 def Opt.main @@main end
Create Opt
object. @param name [String] Option name. @param opt [String] Switch. @param type [Array<Symbol>, Symbol] Option type in
primitives (or :subcmd).
@param doc [String] Option documentation. @param value [Object] Default value.
# File lib/como.rb, line 1223 def initialize( name, opt, type, doc, value = nil ) @parent = nil @name = name @shortOpt = opt @longOpt = "--#{name}" @type = type @value = value if @type != :subcmd if prim?( :many ) && value == nil @value = [] end end @doc = doc # Whether option was set or not. @given = false @subopt = [] @subcmd = [] @rules = nil @config = @@config.dup Opt.addOpt( self ) end
Return program name.
# File lib/como.rb, line 1079 def Opt.progname @@main.name end
Reset “dynamic” class members.
# File lib/como.rb, line 1055 def Opt.reset @@opts = [] end
Set main option.
# File lib/como.rb, line 1014 def Opt.setMain( main ) @@main = main Opt.setSubcmd( main ) end
Set current subcmd.
# File lib/como.rb, line 1032 def Opt.setSubcmd( opt ) @@subcmd = opt end
Create sub-command option spec.
# File lib/como.rb, line 1115 def Opt.subcmd( name, doc = "No doc." ) new( name, nil, :subcmd, doc, false ) end
Issue user warning. See {#warn}.
# File lib/como.rb, line 1169 def Opt.warn( str, nl = false ) Opt.main.warn( str, nl ) end
Return program year.
# File lib/como.rb, line 1085 def Opt.year @@main.year end
Public Instance Methods
Select option object by name operator.
# File lib/como.rb, line 1591 def []( str ) ret = argByName( str ) unless ret raise RuntimeError, "Subopt \"#{str}\" does not exist for \"#{@name}\"!" end ret end
Add subcommand option.
@param opt [Option] Option to add.
# File lib/como.rb, line 1268 def addOption( opt ) opt.parent = self @subopt.push opt end
Add subcommand subcmd.
@param cmd [Option] Subcmd to add.
# File lib/como.rb, line 1277 def addSubcmd( cmd ) cmd.parent = self @subcmd.push cmd end
Return option value if given otherwise the default. Example usage: fileName = Opt.apply( “no_name.txt” )
# File lib/como.rb, line 1646 def apply( default = nil ) if given if prim?( :none ) && !( prim?( :one ) || prim?( :many ) ) true else value end else default end end
Merge config to base config.
@param config [Hash] Configuration Hash to merge.
# File lib/como.rb, line 1286 def applyConfig( config ) @config.merge!( config ) end
Select option object by name/opt/longOpt.
# File lib/como.rb, line 1737 def argById( str ) if str == nil || str == :default @subopt.each do |o| if o.prim?( :default ) return o end end nil else suball.each do |o| if str == o.name || str == o.opt || str == o.longOpt return o end end nil end end
Select option object by name.
# File lib/como.rb, line 1717 def argByName( str ) if str == nil || str == :default @subopt.each do |o| if o.prim?( :default ) return o end end nil else suball.each do |o| if str == o.name return o end end nil end end
Check provided args.
# File lib/como.rb, line 1303 def check( argsState ) # Start at top. top = self parse = Proc.new do # Parse and check for invalid arguments. begin top = top.parse( argsState, top.config[ :check_invalid ] ) end while( top ) # Check for any missing valid arguments. checkMissing end error = Proc.new do |err| errornl( err.to_s ) # Display subcmd specific usage info. err.data.usage exit( 1 ) end begin parse.call rescue Opt::MissingArgument, Opt::InvalidOption => err error.call( err ) end # Revert back to top after hierarchy travelsal. usageIfHelp # Check rules. cur = self while cur cur.checkRule cur = cur.givenSubcmd end self end
Additional option check.
@param opt [String] Option name. @param error [String] Error string for false return values (from check). @param check [Proc] Checker proc run for the option. Either @return false or generate an exception when errors found.
# File lib/como.rb, line 1571 def checkAlso( opt, error, &check ) begin if self[opt].evalCheck( &check ) != true raise Opt::InvalidOption.new( error, self ) end rescue Opt::MissingArgument, Opt::InvalidOption => err @@io.puts errornl( err.to_s ) err.data.usage exit( 1 ) end end
Check for any non-given required arguments recursively through hierarchy of subcommands. MissingArgument
Exception is generated if argument is missing.
# File lib/como.rb, line 1491 def checkMissing return unless config[ :check_missing ] # Full cmd name. cmd = ( getParents.map do |i| i.name end ).join( ' ' ) # Check for any exclusive args first. @subopt.each do |o| if o.prim?( :mutex ) && o.given return end end # Check for required arguments for this level before # subcmds. @subopt.each do |o| if !o.prim?( :opt ) unless o.given raise MissingArgument.new( "Option \"#{o.opt}\" missing for \"#{cmd}\"...", self ) end end end if hasSubcmd if @config[ :subcheck ] # Compulsory Subcommand checking enabled. subcmdMissing = true else subcmdMissing = false end else subcmdMissing = false end # Check for any subcmd args. sub = givenSubcmd if sub subcmdMissing = false # Use recursion to examine the next level. return sub.checkMissing end # If no subcmds are given, issue error. raise MissingArgument.new( "Subcommand required for \"#{cmd}\"...", self ) if subcmdMissing end
Check option combination rules.
# File lib/como.rb, line 1547 def checkRule return unless @rules begin raise Opt::InvalidOption.new( "Option combination mismatch!", self ) unless RuleCheck.check( self, &@rules ) rescue Opt::MissingArgument, Opt::InvalidOption => err @@io.puts errornl( err.to_s ) usage( nil, true ) end end
Return cmdline usage strings for options in an Array.
# File lib/como.rb, line 1857 def cmdline opts = [] @subopt.each do |o| next if o.prim?( :hidden ) prural = nil if o.prim?( :none ) && o.prim?( :many ) prural = "*" elsif o.prim?( :one ) && !o.prim?( :many ) && o.prim?( :repeat ) prural = "#" elsif o.prim?( :one ) && o.prim?( :many ) prural = "+" else prural = "" end if !( o.hasSwitchStyleDoc ) name = " <#{o.name}>#{prural}" else name = "" end if o.shortOpt == nil opt = o.longOpt else opt = o.shortOpt end if !o.prim?( :opt ) opts.push "#{opt}#{name}" else opts.push "[#{opt}#{name}]" end end if hasSubcmd opts.push "<<subcommand>>" end opts end
Return default options.
# File lib/como.rb, line 1711 def default argByName( nil ) end
Options list iterator.
# File lib/como.rb, line 1613 def each( &blk ) suball.each do |o| yield o end end
Options iterator for given options.
# File lib/como.rb, line 1621 def each_given( &blk ) suball.each do |o| yield o if o.given end end
Como
error printout.
@param str [String] Error message. @param nl [Boolean] Prepend msg with newline.
# File lib/como.rb, line 1983 def error( str, nl = false ) nl = nl ? "\n" : "" STDERR.puts( "#{nl}#{Opt.progname} error: #{str}" ) end
Como
error printout with pre-newline.
# File lib/como.rb, line 1990 def errornl( str ) error( str, true ) end
Custom check for the option. User has to know some Como
internals.
# File lib/como.rb, line 2014 def evalCheck( &check ) instance_eval( &check ) end
Como
error printout with immediate exit.
# File lib/como.rb, line 1996 def fatal( str ) error( str ) exit( false ) end
Find option object by option str.
# File lib/como.rb, line 1930 def findOpt( str ) if str == nil subopt.detect { |i| i.prim?( :default ) } elsif str[0..1] == "--" subopt.detect { |i| i.longOpt == str } elsif str[0..0] == "-" subopt.detect { |i| i.opt == str } else suball.detect { |i| i.name == str } end end
Returns true if option is given, and block is not present. When block is present, the block is executed (with value as parameter) if option has been given.
@param optArg [Boolean] Pass Opt
to block instead of its
value.
# File lib/como.rb, line 1665 def given( optArg = false, &prog ) if block_given? if @given if optArg yield( self ) else yield( @value ) end else false end else @given end end
Number of given options.
# File lib/como.rb, line 1629 def givenCount cnt = 0 each_given do |i| cnt += 1 end cnt end
Return the selected subcommand.
# File lib/como.rb, line 1687 def givenSubcmd ( @subcmd.select do |o| o.given end )[0] end
Test if option is of switch type.
# File lib/como.rb, line 1763 def hasSwitchStyleDoc if ( prim?( :none ) && !prim?( :many ) ) || prim?( :default ) true else false end end
Option's opt id. Short if exists otherwise long.
# File lib/como.rb, line 1601 def opt @shortOpt ? @shortOpt : @longOpt end
Returns Hash of option value parameters. Example command line content:
-p rounds=10 length=5
Option value content in this case would be (Array of param settings):
[ "rounds=10", "length=5" ]
@return [Hash] Parameter settings included in the option.
# File lib/como.rb, line 1699 def params map = {} @value.each do |i| name, value = i.split('=') value = str_to_num( value ) map[ name ] = value end map end
Parse cmdline options from args.
# File lib/como.rb, line 1349 def parse( args, checkInvalids = true ) while args.get # puts "Opt.parse (#{@name}): #{args.get}" if args.isOptTerm # Rest of the args do not belong to this program. args.next Opt.main.external = args.rest break elsif args.isOpt o = findOpt( args.get ) if !o if checkInvalids raise \ InvalidOption.new( "Unknown option \"#{args.get}\"...", self ) else o = findOpt( nil ) if !o raise \ InvalidOption.new( "No default option specified to allow \"#{args.get}\"...", self ) else # Default option. o.value.push args.toValue args.next end end elsif o && ( o.prim?( :one ) || o.prim?( :many ) ) args.next if ( !args.get || args.isOpt ) && !o.prim?( :none ) raise MissingArgument.new( "No argument given for \"#{o.opt}\"...", self ) else if o.given && !o.prim?( :repeat ) raise \ InvalidOption.new( "Option specified too multiple times (\"#{o.name}\")...", self ) end if o.prim?( :many ) # Get all argument for multi-option. o.value = [] if !o.given while args.get && !args.isOpt o.value.push args.toValue args.next end else # Get one argument for single-option. if o.prim?( :repeat ) o.value = [] if !o.given o.value.push args.toValue else o.value = args.toValue end args.next end end o.given = true else if !o raise InvalidOption.new( "No valid options specified...", self ) else o.given = true args.next end end else # Subcmd or default. Check for Subcmd first. # Search for Subcmd. o = findOpt( args.get ) if !o # Search for default option. o = findOpt( nil ) if !o if @subcmd.any? raise \ InvalidOption.new( "Unknown subcmd: \"#{args.get}\"...", self ) else raise \ InvalidOption.new( "No default option specified to allow \"#{args.get}\"...", self ) end else # Default option. o.given = true o.value.push args.toValue args.next end else # Subcmd. o.given = true args.next return o end end end nil end
Check for primitive.
# File lib/como.rb, line 1757 def prim?( prim ) @type.index( prim ) end
Set command (subcommand) suboptions and subcmds.
@param opts [Array<Opt>]
# File lib/como.rb, line 1254 def setOptionSubcmd( opts, subs ) opts.each do |i| addOption( i ) end subs.each do |i| addSubcmd( i ) end end
Set rule checks for the option.
@param rule [Proc] Rule to check after command line parsing.
# File lib/como.rb, line 1294 def setRuleCheck( &rule ) @rules = rule end
Set optional header for “usage”.
# File lib/como.rb, line 1777 def setUsageHeader( str ) @config[ :header ] = str end
All subcommand options, options and subcommands.
# File lib/como.rb, line 1607 def suball @subopt + @subcmd end
Return document strings for options.
# File lib/como.rb, line 1905 def suboptDoc str = "" # format = Proc.new do |s,d| ( " %-#{@config[ :tab ]}s%s\n" % [ s, d ] ) end str += "\n" str += " Options:\n" if hasSubcmd && hasVisibleOptions @subopt.each do |o| next if o.prim?( :hidden ) str += suboptDocFormat( o.opt, o.doc ) end str += "\n" + suboptDocFormat( "Subcommands:", "" ) if hasSubcmd @subcmd.each do |o| str += suboptDocFormat( o.name, o.doc ) end str end
Convert to hash representation.
Keys are symbols: name, type, given, value, subopt, subcmd.
# File lib/como.rb, line 1946 def to_hash h = {} h[ :name ] = @name h[ :type ] = @type h[ :given ] = @given h[ :value ] = @value h[ :subopt ] = @subopt.map{|i| i.to_hash } h[ :subcmd ] = @subcmd.map{|i| i.to_hash } h end
Convert to hash representation with opt name keys.
Keys are symbols: name, type, given, value, subopt, subcmd.
# File lib/como.rb, line 1961 def to_hopt h = {} h[ :name ] = @name h[ :type ] = @type h[ :given ] = @given h[ :value ] = @value h[ :subopt ] = {} @subopt.each do |i| h[ :subopt ][ i.name ] = i.to_hopt end h[ :subcmd ] = {} @subcmd.each do |i| h[ :subcmd ][ i.name ] = i.to_hopt end h end
Display program usage (and optionally exit).
@param doExit [Boolean] Exit program after help
display. Default to help_exit config if nil.
@param ruleHelp [Boolean] Include rule help to help
display. Default to rulehelp config if nil.
# File lib/como.rb, line 1796 def usage( doExit = nil, ruleHelp = nil ) doExit = @config[ :help_exit ] if doExit == nil ruleHelp = @config[ :rulehelp ] if ruleHelp == nil @@io.puts usageNormal if ruleHelp @@io.puts "\n Option Combinations:" @@io.puts RuleDisplay.print( &@rules ) end exit( 1 ) if doExit end
Usage printout for command.
# File lib/como.rb, line 1823 def usageCommand str = "" str += "\ Subcommand \"#{@name}\" usage: #{fullCommand} #{cmdline.join(" ")} " str += suboptDoc str += "\n" end
Display program usage (and optionally exit).
# File lib/como.rb, line 1813 def usageIfHelp if self.argByName( 'help' ) && self['help'].given usage elsif hasSubcmd && givenSubcmd givenSubcmd.usageIfHelp end end
Usage info for Opt:s.
# File lib/como.rb, line 1835 def usageNormal str = "" if @config[ :header ] str += @config[ :header ] else str += "\n" end str += usageCommand if @config[ :footer ] str += @config[ :footer ] else str += "\n" end str end
Como
warning printout.
@param str [String] Warning message. @param nl [Boolean] Prepend msg with newline.
# File lib/como.rb, line 2006 def warn( str, nl = false ) nl = nl ? "\n" : "" STDERR.puts( "#{nl}#{Opt.progname} warning: #{str}" ) end
Short syntax for value reference. Example: “~Opt”.
# File lib/como.rb, line 1639 def ~() @value end
Private Instance Methods
Full command name.
# File lib/como.rb, line 2048 def fullCommand ( getParents.map do |i| i.name end ).join( ' ' ) end
Return list of parents.
# File lib/como.rb, line 2035 def getParents list = [] cur = self begin list.push cur cur = cur.parent end while cur list.reverse end
Test if option is of subcmd type.
# File lib/como.rb, line 2067 def hasSubcmd !@subcmd.empty? end
Test if option is of subcmd type.
# File lib/como.rb, line 2060 def hasVisibleOptions # Count non-silent options. ( @subopt.select do |i| !i.prim?( :hidden ) end ).length > 0 end
Test if option is of subcmd type.
# File lib/como.rb, line 2054 def isSubcmd @type == :subcmd end
Convert string to number if possible. The order of checks: integer, float, and no-conversion.
# File lib/como.rb, line 2027 def str_to_num( str ) begin return Integer( str ); rescue ; end begin return Float( str ); rescue ; end str end
Format option documentation. If newline is followed by tab, rest of the documentation is aligned with the description of previous line.
# File lib/como.rb, line 2075 def suboptDocFormat( switch, doc ) # Format doc nicely to multiple lines if newline is # followed by tab stop. parts = doc.split( "\n" ) lines = [ ( " %-#{@config[ :tab ]}s%s\n" % [ switch, parts[0] ] ) ] if parts[1] parts[1..-1].each do |p| if p[0] == "\t" lines.push ( " #{' '*@config[ :tab ]}%s\n" % [ p[1..-1] ] ) else lines.push p end end end lines.join end