Class: CmdParse::Command
- Inherits:
-
Object
- Object
- CmdParse::Command
- Defined in:
- lib/cmdparse.rb
Overview
Base class for commands
This class implements all needed methods so that it can be used by the CommandParser class.
Commands can either be created by sub-classing or on the fly when using the #add_command method. The latter allows for a more terse specification of a command while the sub-class approach allows to customize all aspects of a command by overriding methods.
Basic example for sub-classing:
class TestCommand < CmdParse::Command
def initialize
super('test', takes_commands: false)
.on('-m', '--my-opt', 'My option') { 'Do something' }
end
end
parser = CmdParse::CommandParser.new
parser.add_command(TestCommand.new)
parser.parse
Basic example for on the fly creation:
parser = CmdParse::CommandParser.new
parser.add_command('test') do |cmd|
takes_commands(false)
.on('-m', '--my-opt', 'My option') { 'Do something' }
end
parser.parse
Basic Properties
The only thing that is mandatory to set for a Command is its #name. If the command does not take any sub-commands, then additionally an #action block needs to be specified or the #execute method overridden.
However, there are several other methods that can be used to configure the behavior of a command:
- #takes_commands
-
For specifying whether sub-commands are allowed.
- #options
-
For specifying command specific options.
- #add_command
-
For specifying sub-commands if the command takes them.
Help Related Methods
Many of this class’ methods are related to providing useful help output. While the most common methods can directly be invoked to set or retrieve information, many other methods compute the needed information dynamically and therefore need to be overridden to customize their return value.
- #short_desc
-
For a short description of the command (getter/setter).
- #long_desc
-
For a detailed description of the command (getter/setter).
- #argument_desc
-
For describing command arguments (setter).
- #help, #help_banner, #help_short_desc, #help_long_desc, #help_commands, #help_arguments, #help_options
-
For outputting the general command help or individual sections of the command help (getter).
- #usage, #usage_options, #usage_arguments, #usage_commands
-
For outputting the usage line or individual parts of it (getter).
Built-in Commands
cmdparse ships with two built-in commands:
-
HelpCommand (for showing help messages) and
-
VersionCommand (for showing version information).
Direct Known Subclasses
Instance Attribute Summary collapse
-
#commands ⇒ Object
readonly
Returns the mapping of command name to command for all sub-commands of this command.
-
#data ⇒ Object
A data store (initially an empty Hash) that can be used for storing anything.
-
#default_command ⇒ Object
readonly
Returns the name of the default sub-command or
nil
if there isn’t any. -
#name ⇒ Object
readonly
The name of the command.
-
#super_command ⇒ Object
Sets or returns the super-command of this command.
Instance Method Summary collapse
-
#<=>(other) ⇒ Object
For sorting commands by name.
-
#action(&block) ⇒ Object
Sets the given
block
as the action block that is used on when executing this command. -
#add_command(command, default: false) {|command| ... } ⇒ Object
:call-seq: command.add_command(other_command, default: false) {|cmd| … } -> command command.add_command(‘other’, default: false) {|cmd| …} -> command.
-
#argument_desc(hash) ⇒ Object
:call-seq: cmd.argument_desc(name => desc, …).
-
#arity ⇒ Object
Returns the number of arguments required for the execution of the command, i.e.
-
#command_chain ⇒ Object
:call-seq: command.command_chain -> [top_level_command, super_command, …, command].
-
#command_parser ⇒ Object
Returns the associated CommandParser instance for this command or
nil
if no command parser is associated. -
#execute(*args) ⇒ Object
Invokes the action block with the parsed arguments.
-
#help ⇒ Object
Returns a string containing the help message for the command.
-
#help_arguments ⇒ Object
Returns the formatted arguments of this command.
-
#help_banner ⇒ Object
Returns the banner (including the usage line) of the command.
-
#help_commands ⇒ Object
Returns the formatted sub-commands of this command.
-
#help_long_desc ⇒ Object
Returns the formatted detailed description.
-
#help_options(title, options) ⇒ Object
Returns the formatted option descriptions for the given OptionParser instance.
-
#help_short_desc ⇒ Object
Returns the formatted short description.
-
#initialize(name, takes_commands: true) ⇒ Command
constructor
Initializes the command called
name
. -
#long_desc(*val) ⇒ Object
(also: #long_desc=)
Sets the detailed description of the command if an argument is given.
-
#on_after_add ⇒ Object
This hook method is called when the command (or one of its super-commands) is added to another Command instance that has an associated command parser (#see command_parser).
-
#options {|@options| ... } ⇒ Object
:call-seq: command.options {|opts| …} -> opts command.options -> opts.
-
#short_desc(*val) ⇒ Object
(also: #short_desc=)
Sets the short description of the command if an argument is given.
-
#takes_arguments? ⇒ Boolean
Returns
true
if the command can take one or more arguments. -
#takes_commands(val) ⇒ Object
(also: #takes_commands=)
Sets whether this command can take sub-command.
-
#takes_commands? ⇒ Boolean
Return
true
if this command can take sub-commands. -
#usage ⇒ Object
Returns the usage line for the command.
-
#usage_arguments ⇒ Object
Returns a string describing the arguments for the command for use in the usage line.
-
#usage_commands ⇒ Object
Returns a string describing the sub-commands of the commands for use in the usage line.
-
#usage_options ⇒ Object
Returns a string describing the options of the command for use in the usage line.
Constructor Details
#initialize(name, takes_commands: true) ⇒ Command
Initializes the command called name
.
Options:
- takes_commands
-
Specifies whether this command can take sub-commands.
257 258 259 260 261 262 263 264 265 266 |
# File 'lib/cmdparse.rb', line 257 def initialize(name, takes_commands: true) @name = name.freeze @options = OptionParser.new @commands = CommandHash.new @default_command = nil @action = nil @argument_desc ||= {} @data = {} takes_commands(takes_commands) end |
Instance Attribute Details
#commands ⇒ Object (readonly)
Returns the mapping of command name to command for all sub-commands of this command.
246 247 248 |
# File 'lib/cmdparse.rb', line 246 def commands @commands end |
#data ⇒ Object
A data store (initially an empty Hash) that can be used for storing anything. For example, it can be used to store option values. cmdparse itself doesn’t do anything with it.
250 251 252 |
# File 'lib/cmdparse.rb', line 250 def data @data end |
#default_command ⇒ Object (readonly)
Returns the name of the default sub-command or nil
if there isn’t any.
238 239 240 |
# File 'lib/cmdparse.rb', line 238 def default_command @default_command end |
#name ⇒ Object (readonly)
The name of the command.
235 236 237 |
# File 'lib/cmdparse.rb', line 235 def name @name end |
#super_command ⇒ Object
Sets or returns the super-command of this command. The super-command is either a Command instance for normal commands or a CommandParser instance for the main command (ie. CommandParser#main_command).
243 244 245 |
# File 'lib/cmdparse.rb', line 243 def super_command @super_command end |
Instance Method Details
#<=>(other) ⇒ Object
For sorting commands by name.
567 568 569 |
# File 'lib/cmdparse.rb', line 567 def <=>(other) name <=> other.name end |
#action(&block) ⇒ Object
Sets the given block
as the action block that is used on when executing this command.
If a sub-class is created for specifying a command, then the #execute method should be overridden instead of setting an action block.
See also: #execute
351 352 353 |
# File 'lib/cmdparse.rb', line 351 def action(&block) @action = block end |
#add_command(command, default: false) {|command| ... } ⇒ Object
:call-seq:
command.add_command(other_command, default: false) {|cmd| ... } -> command
command.add_command('other', default: false) {|cmd| ...} -> command
Adds a command to the command list.
The argument command
can either be a Command object or a String in which case a new Command object is created. In both cases the Command object is yielded.
If the optional argument default
is true
, then the command is used when no other sub-command is specified on the command line.
If this command takes no other commands, an error is raised.
309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/cmdparse.rb', line 309 def add_command(command, default: false) # :yields: command_object raise TakesNoCommandError.new(name) unless takes_commands? command = Command.new(command) if command.kind_of?(String) command.super_command = self @commands[command.name] = command @default_command = command.name if default command.fire_hook_after_add yield(command) if block_given? self end |
#argument_desc(hash) ⇒ Object
:call-seq:
cmd.argument_desc(name => desc, ...)
Sets the descriptions for one or more arguments using name-description pairs.
The used names should correspond to the names used in #usage_arguments.
393 394 395 |
# File 'lib/cmdparse.rb', line 393 def argument_desc(hash) @argument_desc.update(hash) end |
#arity ⇒ Object
Returns the number of arguments required for the execution of the command, i.e. the number of arguments the #action block or the #execute method takes.
If the returned number is negative, it means that the minimum number of arguments is -n-1.
See: Method#arity, Proc#arity
403 404 405 |
# File 'lib/cmdparse.rb', line 403 def arity (@action || method(:execute)).arity end |
#command_chain ⇒ Object
:call-seq:
command.command_chain -> [top_level_command, super_command, ..., command]
Returns the command chain, i.e. a list containing this command and all of its super-commands, starting at the top level command.
327 328 329 330 331 332 333 334 335 |
# File 'lib/cmdparse.rb', line 327 def command_chain cmds = [] cmd = self while !cmd.nil? && !cmd.super_command.kind_of?(CommandParser) cmds.unshift(cmd) cmd = cmd.super_command end cmds end |
#command_parser ⇒ Object
Returns the associated CommandParser instance for this command or nil
if no command parser is associated.
339 340 341 342 343 |
# File 'lib/cmdparse.rb', line 339 def command_parser cmd = super_command cmd = cmd.super_command while !cmd.nil? && !cmd.kind_of?(CommandParser) cmd end |
#execute(*args) ⇒ Object
Invokes the action block with the parsed arguments.
This method is called by the CommandParser instance if this command was specified on the command line to be executed.
Sub-classes can either specify an action block or directly override this method (the latter is preferred).
362 363 364 |
# File 'lib/cmdparse.rb', line 362 def execute(*args) @action.call(*args) end |
#help ⇒ Object
Returns a string containing the help message for the command.
413 414 415 416 417 418 419 420 421 422 |
# File 'lib/cmdparse.rb', line 413 def help output = '' output << output << help_short_desc output << help_long_desc output << help_commands output << help_arguments output << ('Options (take precedence over global options)', ) output << ('Global Options', command_parser.) end |
#help_arguments ⇒ Object
Returns the formatted arguments of this command.
For the output format see #cond_format_help_section
539 540 541 542 |
# File 'lib/cmdparse.rb', line 539 def help_arguments desc = @argument_desc.map {|k, v| k.to_s.ljust(command_parser.help_desc_indent) << v.to_s} cond_format_help_section('Arguments', desc, condition: !@argument_desc.empty?) end |
#help_banner ⇒ Object
Returns the banner (including the usage line) of the command.
The usage line is command specific but the rest is the same for all commands and can be set via command_parser.main_options.banner
.
428 429 430 431 432 433 434 |
# File 'lib/cmdparse.rb', line 428 def output = '' if command_parser.. output << format(command_parser.., indent: 0) << "\n\n" end output << format(usage, indent: 7) << "\n\n" end |
#help_commands ⇒ Object
Returns the formatted sub-commands of this command.
For the output format see #cond_format_help_section
522 523 524 525 526 527 528 529 530 531 532 533 534 |
# File 'lib/cmdparse.rb', line 522 def help_commands describe_commands = lambda do |command, level = 0| command.commands.sort.collect do |name, cmd| str = " " * level << name << (name == command.default_command ? " (*)" : '') str = str.ljust(command_parser.help_desc_indent) << cmd.short_desc.to_s str = format(str, width: command_parser.help_line_width - command_parser.help_indent, indent: command_parser.help_desc_indent) str << "\n" << (cmd.takes_commands? ? describe_commands.call(cmd, level + 1) : "") end.join('') end cond_format_help_section("Available commands", describe_commands.call(self), condition: takes_commands?, preformatted: true) end |
#help_long_desc ⇒ Object
Returns the formatted detailed description.
For the output format see #cond_format_help_section
514 515 516 517 |
# File 'lib/cmdparse.rb', line 514 def help_long_desc cond_format_help_section("Description", [long_desc].flatten, condition: long_desc && !long_desc.empty?) end |
#help_options(title, options) ⇒ Object
Returns the formatted option descriptions for the given OptionParser instance.
The section title needs to be specified with the title
argument.
For the output format see #cond_format_help_section
549 550 551 552 553 554 555 556 557 |
# File 'lib/cmdparse.rb', line 549 def (title, ) summary = '' summary_width = command_parser..summary_width .summarize([], summary_width, summary_width - 1, '') do |line| summary << format(line, width: command_parser.help_line_width - command_parser.help_indent, indent: summary_width + 1, indent_first_line: false) << "\n" end cond_format_help_section(title, summary, condition: !summary.empty?, preformatted: true) end |
#help_short_desc ⇒ Object
Returns the formatted short description.
For the output format see #cond_format_help_section
506 507 508 509 |
# File 'lib/cmdparse.rb', line 506 def help_short_desc cond_format_help_section("Summary", "#{name} - #{short_desc}", condition: short_desc && !short_desc.empty?) end |
#long_desc(*val) ⇒ Object Also known as: long_desc=
Sets the detailed description of the command if an argument is given. Always returns the detailed description.
This may be a single string or an array of strings for multiline description. Each string is ideally shorter than 76 characters.
381 382 383 384 |
# File 'lib/cmdparse.rb', line 381 def long_desc(*val) @long_desc = val.flatten unless val.empty? @long_desc end |
#on_after_add ⇒ Object
This hook method is called when the command (or one of its super-commands) is added to another Command instance that has an associated command parser (#see command_parser).
It can be used, for example, to add global options.
563 564 |
# File 'lib/cmdparse.rb', line 563 def on_after_add end |
#options {|@options| ... } ⇒ Object
:call-seq:
command.options {|opts| ...} -> opts
command.options -> opts
Yields the OptionParser instance that is used for parsing the options of this command (if a block is given) and returns it.
291 292 293 294 |
# File 'lib/cmdparse.rb', line 291 def #:yields: options yield(@options) if block_given? @options end |
#short_desc(*val) ⇒ Object Also known as: short_desc=
Sets the short description of the command if an argument is given. Always returns the short description.
The short description is ideally shorter than 60 characters.
370 371 372 373 |
# File 'lib/cmdparse.rb', line 370 def short_desc(*val) @short_desc = val[0] unless val.empty? @short_desc end |
#takes_arguments? ⇒ Boolean
Returns true
if the command can take one or more arguments.
408 409 410 |
# File 'lib/cmdparse.rb', line 408 def takes_arguments? arity.abs > 0 end |
#takes_commands(val) ⇒ Object Also known as: takes_commands=
Sets whether this command can take sub-command.
The argument val
needs to be true
or false
.
271 272 273 274 275 276 277 |
# File 'lib/cmdparse.rb', line 271 def takes_commands(val) if !val && !commands.empty? raise Error, "Can't change takes_commands to false because there are already sub-commands" else @takes_commands = val end end |
#takes_commands? ⇒ Boolean
Return true
if this command can take sub-commands.
281 282 283 |
# File 'lib/cmdparse.rb', line 281 def takes_commands? @takes_commands end |
#usage ⇒ Object
Returns the usage line for the command.
The usage line is automatically generated from the available information. If this is not suitable, override this method to provide a command specific usage line.
Typical usage lines looks like the following:
Usage: program [options] command [options] {sub_command1 | sub_command2}
Usage: program [options] command [options] ARG1 [ARG2] [REST...]
See: #usage_options, #usage_arguments, #usage_commands
447 448 449 450 451 452 453 454 455 456 457 |
# File 'lib/cmdparse.rb', line 447 def usage tmp = "Usage: #{command_parser..program_name}" tmp << command_parser.main_command. tmp << command_chain.map {|cmd| " #{cmd.name}#{cmd.}"}.join('') if takes_commands? tmp << " #{usage_commands}" elsif takes_arguments? tmp << " #{usage_arguments}" end tmp end |
#usage_arguments ⇒ Object
Returns a string describing the arguments for the command for use in the usage line.
By default the names of the action block or #execute method arguments are used (done via Ruby’s reflection API). If this is not wanted, override this method.
A typical return value would look like the following:
ARG1 [ARG2] [REST...]
See: #usage, #argument_desc
482 483 484 485 486 487 488 489 490 |
# File 'lib/cmdparse.rb', line 482 def usage_arguments (@action || method(:execute)).parameters.map do |type, name| case type when :req then name.to_s when :opt then "[#{name}]" when :rest then "[#{name}...]" end end.join(" ").upcase end |
#usage_commands ⇒ Object
Returns a string describing the sub-commands of the commands for use in the usage line.
Override this method for providing a command specific specialization.
A typical return value would look like the following:
{command | other_command | another_command }
499 500 501 |
# File 'lib/cmdparse.rb', line 499 def usage_commands (commands.empty? ? '' : "{#{commands.keys.sort.join(" | ")}}") end |
#usage_options ⇒ Object
Returns a string describing the options of the command for use in the usage line.
If there are any options, the resulting string also includes a leading space!
A typical return value would look like the following:
[]
See: #usage
468 469 470 |
# File 'lib/cmdparse.rb', line 468 def (. ? ' [options]' : '') end |