Class: Jinx::CLI::Command
- Inherits:
-
Application
- Object
- Logger::Application
- Application
- Jinx::CLI::Command
- Defined in:
- lib/jinx/cli/command.rb
Overview
Command-line parser and executor.
Constant Summary collapse
- DEF_OPTS =
The default options that apply to all commands.
[ [:help, "-h", "--help", "Display this help message"], [:file, "--file FILE", "Configuration file containing other options"], [:log, "--log FILE", "Log file"], [:debug, "--debug", "Display debug log messages"], [:quiet, "-q", "--quiet", "Suppress printing messages to stdout"], [:verbose, "-v", "--verbose", "Print additional messages to stdout"] ]
Instance Method Summary collapse
- #call_executor(opts) ⇒ Object private
-
#fail(message = nil) ⇒ Object
private
Prints the given error message and the program usage, then exits with status 1.
-
#get_args ⇒ {Symbol => Object}
private
Collects the non-option command line arguments.
-
#get_opts ⇒ {Symbol => Object}
private
Collects the command line options.
-
#halt(message = nil, status = 0) ⇒ Object
private
Prints the given message and program usage, then exits with the given status.
-
#handle_options(opts) ⇒ Object
private
Processes the built-in options as follows: *
:help
- print the usage message and exit *:file
FILE - load the options specified in the given file. -
#initialize(specs = Array::EMPTY_ARRAY) {|hash| ... } ⇒ Command
constructor
Command line application wrapper.
-
#parse(parser) ⇒ {Symbol => Object}
private
The option => value hash.
-
#run {|hash| ... } ⇒ Object
Runs this command by calling the block given to this method, if provided, otherwise the block given to #initialize option or argument symbol => value hash.
- #too_many_arguments ⇒ Object private
Methods inherited from Application
Constructor Details
#initialize(specs = Array::EMPTY_ARRAY) {|hash| ... } ⇒ Command
Command line application wrapper. The specs parameter is an array of command line option and argument specifications as follows:
The option specification has format:
- option, short, long, class, description
-
where:
-
option is the option symbol, e.g.
:output
-
short is the short option form, e.g. “-o”
-
long is the long option form, e.g. “–output FILE”
-
class is the option value class, e.g. Integer
-
description is the option usage, e.g. “Output file”
The option, long and description items are required; the short and class items can be omitted.
The argument specification is an array in the form:
- arg, text
-
where:
-
arg is the argument symbol, e.g.
:input
-
text is the usage message text, e.g. ‘input’, ‘[input]’ or ‘input …’
Both arg and text are required.
Built-in options include the following:
-
--help
: print the help message and exit -
--verbose
: print additional information to the console -
–log FILE : log file
-
--debug
: print debug messages to the log -
–file FILE: file containing other options
-
--quiet
: suppress printing messages to stdout
This class processes these built-in options. Subclasses are responsible for processing any remaining options.
-
-
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/jinx/cli/command.rb', line 59 def initialize(specs=Array::EMPTY_ARRAY, &executor) @executor = executor # Validate the specifications. unless Array === specs then raise ArgumentError.new("Command-line specification is not an array: #{specs.qp}") end invalid = specs.detect { |spec| spec.size < 2 } if invalid then raise ArgumentError.new("Command-line argument specification is missing text: #{invalid.qp}") end # Options start with a dash, arguments are whatever is left. @opt_specs, @arg_specs = specs.partition { |spec| spec[1][0, 1] == '-' } # Add the default option specifications. @opt_specs.concat(DEF_OPTS) # The application name is the command. super(File.basename($0, ".bat")) end |
Instance Method Details
#call_executor(opts) ⇒ Object (private)
107 108 109 110 |
# File 'lib/jinx/cli/command.rb', line 107 def call_executor(opts) if @executor.nil? then raise CommandError.new("Command #{self} does not have an execution block") end @executor.call(opts) end |
#fail(message = nil) ⇒ Object (private)
Prints the given error message and the program usage, then exits with status 1.
202 203 204 |
# File 'lib/jinx/cli/command.rb', line 202 def fail(=nil) halt(, 1) end |
#get_args ⇒ {Symbol => Object} (private)
Collects the non-option command line arguments.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/jinx/cli/command.rb', line 137 def get_args return Hash::EMPTY_HASH if ARGV.empty? if @arg_specs.empty? then too_many_arguments end # Collect the arguments from the command line. args = {} # The number of command line arguments or all but the last argument specifications, # whichever is less. The last argument can have more than one value, indicated by # the argument specification form '...', so it is processed separately below. n = [ARGV.size, @arg_specs.size - 1].min # the single-valued arguments n.times { |i| args[@arg_specs[i].first] = ARGV[i] } # Process the last argument. if n < ARGV.size then spec = @arg_specs.last arg, form = spec[0], spec[1] # A multi-valued last argument is the residual command argument array. # A single-valued last argument is the last value, if there is exactly one. # Otherwise, there are too many arguments. if form.index('...') then args[arg] = ARGV[n..-1] elsif @arg_specs.size == ARGV.size then args[arg] = ARGV[n] else too_many_arguments end end args end |
#get_opts ⇒ {Symbol => Object} (private)
Collects the command line options.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/jinx/cli/command.rb', line 115 def get_opts # the options hash opts = {} # the option parser OptionParser.new do |parser| # The help argument string is comprised of the argument specification labels. arg_s = @arg_specs.map { |spec| spec[1] }.join(' ') # Build the usage message. parser. = "Usage: #{parser.program_name} [options] #{arg_s}" parser.separator "" parser.separator "Options:" # parse the options opts = parse(parser) # grab the usage message @usage = parser.help end opts end |
#halt(message = nil, status = 0) ⇒ Object (private)
Prints the given message and program usage, then exits with the given status.
207 208 209 210 211 |
# File 'lib/jinx/cli/command.rb', line 207 def halt(=nil, status=0) puts() if puts(@usage) exit(status) end |
#handle_options(opts) ⇒ Object (private)
Processes the built-in options as follows:
-
:help
- print the usage message and exit -
:file
FILE - load the options specified in the given file
187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/jinx/cli/command.rb', line 187 def (opts) # if help, then print usage and exit if opts[:help] then halt end # If there is a file option, then load additional options from the file. file = opts.delete(:file) if file then fopts = File.open(file).map { |line| line.chomp }.split(' ').flatten ARGV.concat(fopts) OptionParser.new do |p| opts.merge!(parse(p)) { |ov, nv| ov ? ov : nv } end end end |
#parse(parser) ⇒ {Symbol => Object} (private)
Returns the option => value hash.
172 173 174 175 176 177 178 179 180 |
# File 'lib/jinx/cli/command.rb', line 172 def parse(parser) opts = {} @opt_specs.each do |opt, *spec| parser.on_tail(*spec) { |v| opts[opt] = v } end # build the option => value hash parser.parse! opts end |
#run {|hash| ... } ⇒ Object
Runs this command by calling the block given to this method, if provided, otherwise the block given to #initialize option or argument symbol => value hash.
82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/jinx/cli/command.rb', line 82 def run # the option => value hash opts = get_opts # this base class's options (opts) # add the argument => value hash opts.merge!(get_args) # call the block log(INFO, "Starting #{@appname}...") block_given? ? yield(opts) : call_executor(opts) end |
#too_many_arguments ⇒ Object (private)
166 167 168 |
# File 'lib/jinx/cli/command.rb', line 166 def too_many_arguments halt("Too many arguments - expected #{@arg_specs.size}, found: #{ARGV.join(' ')}.", 1) end |