Class: Cri::Command
- Inherits:
-
Object
- Object
- Cri::Command
- Defined in:
- lib/cri/command.rb
Overview
Cri::Command represents a command that can be executed on the command line. It is also used for the command-line tool itself.
Defined Under Namespace
Classes: CriExitException, ParserPartitioningDelegate
Instance Attribute Summary collapse
-
#aliases ⇒ Array<String>
A list of aliases for this command that can be used to invoke this command.
-
#all_opts_as_args ⇒ Boolean
(also: #all_opts_as_args?)
treat all options as arguments.
-
#block ⇒ Proc
The block that should be executed when invoking this command (ignored for commands with subcommands).
-
#commands ⇒ Set<Cri::Command>
(also: #subcommands)
This command’s subcommands.
-
#default_subcommand_name ⇒ Symbol
The name of the default subcommand.
-
#description ⇒ String
The long description (“description”).
-
#explicitly_no_params ⇒ Boolean
(also: #explicitly_no_params?)
Whether or not this command has parameters.
-
#hidden ⇒ Boolean
(also: #hidden?)
True if the command is hidden (e.g. because it is deprecated), false otherwise.
-
#name ⇒ String
The name.
-
#option_definitions ⇒ Array<Cri::OptionDefinition>
The list of option definitions.
-
#parameter_definitions ⇒ Array<Hash>
The list of parameter definitions.
-
#summary ⇒ String
The short description (“summary”).
-
#supercommand ⇒ Cri::Command?
This command’s supercommand, or nil if the command has no supercommand.
-
#usage ⇒ String
The usage, without the “usage:” prefix and without the supercommands’ names.
Class Method Summary collapse
-
.define(string = nil, filename = nil, &block) ⇒ Cri::Command
Creates a new command using the DSL.
-
.load_file(filename, infer_name: false) ⇒ Cri::Command
Creates a new command using a DSL, from code defined in the given filename.
-
.new_basic_help ⇒ Cri::Command
Returns a new command that implements showing help.
-
.new_basic_root ⇒ Cri::Command
Returns a new command that has support for the ‘-h`/`–help` option and also has a `help` subcommand.
Instance Method Summary collapse
-
#<=>(other) ⇒ -1, ...
Compares this command’s name to the other given command’s name.
-
#add_command(command) ⇒ void
Adds the given command as a subcommand to the current command.
- #all_opt_defns ⇒ Object
-
#command_named(name, hard_exit: true) ⇒ Cri::Command
Returns the command with the given name.
-
#commands_named(name) ⇒ Array<Cri::Command>
Returns the commands that could be referred to with the given name.
-
#define_command(name = nil, &block) ⇒ Cri::Command
Defines a new subcommand for the current command using the DSL.
-
#global_option_definitions ⇒ Enumerable<Cri::OptionDefinition>
The option definitions for the command itself and all its ancestors.
-
#help(**params) ⇒ String
The help text for this command.
-
#initialize ⇒ Command
constructor
A new instance of Command.
-
#modify(&block) ⇒ Cri::Command
Modifies the command using the DSL.
-
#run(opts_and_args, parent_opts = {}, hard_exit: true) ⇒ void
Runs the command with the given command-line arguments, possibly invoking subcommands and passing on the options and arguments.
-
#run_this(opts_and_args, parent_opts = {}) ⇒ void
Runs the actual command with the given command-line arguments, not invoking any subcommands.
Constructor Details
#initialize ⇒ Command
Returns a new instance of Command.
171 172 173 174 175 176 177 178 |
# File 'lib/cri/command.rb', line 171 def initialize @aliases = Set.new @commands = Set.new @option_definitions = Set.new @parameter_definitions = [] @explicitly_no_params = false @default_subcommand_name = nil end |
Instance Attribute Details
#aliases ⇒ Array<String>
Returns A list of aliases for this command that can be used to invoke this command.
75 76 77 |
# File 'lib/cri/command.rb', line 75 def aliases @aliases end |
#all_opts_as_args ⇒ Boolean Also known as: all_opts_as_args?
treat all options as arguments.
108 109 110 |
# File 'lib/cri/command.rb', line 108 def all_opts_as_args @all_opts_as_args end |
#block ⇒ Proc
Returns The block that should be executed when invoking this command (ignored for commands with subcommands).
104 105 106 |
# File 'lib/cri/command.rb', line 104 def block @block end |
#commands ⇒ Set<Cri::Command> Also known as: subcommands
Returns This command’s subcommands.
64 65 66 |
# File 'lib/cri/command.rb', line 64 def commands @commands end |
#default_subcommand_name ⇒ Symbol
Returns The name of the default subcommand.
68 69 70 |
# File 'lib/cri/command.rb', line 68 def default_subcommand_name @default_subcommand_name end |
#description ⇒ String
Returns The long description (“description”).
81 82 83 |
# File 'lib/cri/command.rb', line 81 def description @description end |
#explicitly_no_params ⇒ Boolean Also known as: explicitly_no_params?
Returns Whether or not this command has parameters.
99 100 101 |
# File 'lib/cri/command.rb', line 99 def explicitly_no_params @explicitly_no_params end |
#hidden ⇒ Boolean Also known as:
Returns true if the command is hidden (e.g. because it is deprecated), false otherwise.
89 90 91 |
# File 'lib/cri/command.rb', line 89 def hidden @hidden end |
#name ⇒ String
Returns The name.
71 72 73 |
# File 'lib/cri/command.rb', line 71 def name @name end |
#option_definitions ⇒ Array<Cri::OptionDefinition>
Returns The list of option definitions.
93 94 95 |
# File 'lib/cri/command.rb', line 93 def option_definitions @option_definitions end |
#parameter_definitions ⇒ Array<Hash>
Returns The list of parameter definitions.
96 97 98 |
# File 'lib/cri/command.rb', line 96 def parameter_definitions @parameter_definitions end |
#summary ⇒ String
Returns The short description (“summary”).
78 79 80 |
# File 'lib/cri/command.rb', line 78 def summary @summary end |
#supercommand ⇒ Cri::Command?
Returns This command’s supercommand, or nil if the command has no supercommand.
61 62 63 |
# File 'lib/cri/command.rb', line 61 def supercommand @supercommand end |
#usage ⇒ String
Returns The usage, without the “usage:” prefix and without the supercommands’ names.
85 86 87 |
# File 'lib/cri/command.rb', line 85 def usage @usage end |
Class Method Details
.define(string = nil, filename = nil, &block) ⇒ Cri::Command
Creates a new command using the DSL. If a string is given, the command will be defined using the string; if a block is given, the block will be used instead.
If the block has one parameter, the block will be executed in the same context with the command DSL as its parameter. If the block has no parameters, the block will be executed in the context of the DSL.
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/cri/command.rb', line 124 def self.define(string = nil, filename = nil, &block) dsl = Cri::CommandDSL.new if string args = filename ? [string, filename] : [string] dsl.instance_eval(*args) elsif [-1, 0].include? block.arity dsl.instance_eval(&block) else block.call(dsl) end dsl.command end |
.load_file(filename, infer_name: false) ⇒ Cri::Command
Creates a new command using a DSL, from code defined in the given filename.
143 144 145 146 147 148 149 150 151 |
# File 'lib/cri/command.rb', line 143 def self.load_file(filename, infer_name: false) code = File.read(filename, encoding: 'UTF-8') define(code, filename).tap do |cmd| if infer_name command_name = File.basename(filename, '.rb') cmd.modify { name command_name } end end end |
.new_basic_help ⇒ Cri::Command
Returns a new command that implements showing help.
166 167 168 169 |
# File 'lib/cri/command.rb', line 166 def self.new_basic_help filename = File.dirname(__FILE__) + '/commands/basic_help.rb' define(File.read(filename)) end |
.new_basic_root ⇒ Cri::Command
Returns a new command that has support for the ‘-h`/`–help` option and also has a `help` subcommand. It is intended to be modified (adding name, summary, description, other subcommands, …)
158 159 160 161 |
# File 'lib/cri/command.rb', line 158 def self.new_basic_root filename = File.dirname(__FILE__) + '/commands/basic_root.rb' define(File.read(filename)) end |
Instance Method Details
#<=>(other) ⇒ -1, ...
Compares this command’s name to the other given command’s name.
391 392 393 |
# File 'lib/cri/command.rb', line 391 def <=>(other) name <=> other.name end |
#add_command(command) ⇒ void
This method returns an undefined value.
Adds the given command as a subcommand to the current command.
211 212 213 214 |
# File 'lib/cri/command.rb', line 211 def add_command(command) @commands << command command.supercommand = self end |
#all_opt_defns ⇒ Object
365 366 367 368 369 370 371 |
# File 'lib/cri/command.rb', line 365 def all_opt_defns if supercommand supercommand.all_opt_defns | option_definitions else option_definitions end end |
#command_named(name, hard_exit: true) ⇒ Cri::Command
Returns the command with the given name. This method will display error messages and exit in case of an error (unknown or ambiguous command).
The name can be a full command name, a partial command name (e.g. “com” for “commit”) or an aliased command name (e.g. “ci” for “commit”).
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/cri/command.rb', line 266 def command_named(name, hard_exit: true) commands = commands_named(name) if commands.empty? warn "#{self.name}: unknown command '#{name}'\n" raise CriExitException.new(is_error: true) elsif commands.size > 1 warn "#{self.name}: '#{name}' is ambiguous:" warn " #{commands.map(&:name).sort.join(' ')}" raise CriExitException.new(is_error: true) else commands[0] end rescue CriExitException => e exit(e.error? ? 1 : 0) if hard_exit end |
#commands_named(name) ⇒ Array<Cri::Command>
Returns the commands that could be referred to with the given name. If the result contains more than one command, the name is ambiguous.
244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/cri/command.rb', line 244 def commands_named(name) # Find by exact name or alias @commands.each do |cmd| found = cmd.name == name || cmd.aliases.include?(name) return [cmd] if found end # Find by approximation @commands.select do |cmd| cmd.name[0, name.length] == name end end |
#define_command(name = nil, &block) ⇒ Cri::Command
Defines a new subcommand for the current command using the DSL.
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/cri/command.rb', line 222 def define_command(name = nil, &block) # Execute DSL dsl = Cri::CommandDSL.new dsl.name name unless name.nil? if [-1, 0].include? block.arity dsl.instance_eval(&block) else yield(dsl) end # Create command cmd = dsl.command add_command(cmd) cmd end |
#global_option_definitions ⇒ Enumerable<Cri::OptionDefinition>
Returns The option definitions for the command itself and all its ancestors.
199 200 201 202 203 204 |
# File 'lib/cri/command.rb', line 199 def global_option_definitions res = Set.new res.merge(option_definitions) res.merge(supercommand.global_option_definitions) if supercommand res end |
#help(**params) ⇒ String
Returns The help text for this command.
380 381 382 |
# File 'lib/cri/command.rb', line 380 def help(**params) HelpRenderer.new(self, **params).render end |
#modify(&block) ⇒ Cri::Command
Modifies the command using the DSL.
If the block has one parameter, the block will be executed in the same context with the command DSL as its parameter. If the block has no parameters, the block will be executed in the context of the DSL.
187 188 189 190 191 192 193 194 195 |
# File 'lib/cri/command.rb', line 187 def modify(&block) dsl = Cri::CommandDSL.new(self) if [-1, 0].include? block.arity dsl.instance_eval(&block) else yield(dsl) end self end |
#run(opts_and_args, parent_opts = {}, hard_exit: true) ⇒ void
This method returns an undefined value.
Runs the command with the given command-line arguments, possibly invoking subcommands and passing on the options and arguments.
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/cri/command.rb', line 292 def run(opts_and_args, parent_opts = {}, hard_exit: true) # Parse up to command name stuff = partition(opts_and_args) opts_before_subcmd, subcmd_name, opts_and_args_after_subcmd = *stuff if subcommands.empty? || (subcmd_name.nil? && !block.nil?) run_this(opts_and_args, parent_opts) else # Handle options (opts_before_subcmd) # Get command if subcmd_name.nil? if default_subcommand_name subcmd_name = default_subcommand_name else warn "#{name}: no command given" raise CriExitException.new(is_error: true) end end subcommand = command_named(subcmd_name, hard_exit: hard_exit) return if subcommand.nil? # Run subcommand.run(opts_and_args_after_subcmd, parent_opts.merge(opts_before_subcmd), hard_exit: hard_exit) end rescue CriExitException => e exit(e.error? ? 1 : 0) if hard_exit end |
#run_this(opts_and_args, parent_opts = {}) ⇒ void
This method returns an undefined value.
Runs the actual command with the given command-line arguments, not invoking any subcommands. If the command does not have an execution block, an error ir raised.
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/cri/command.rb', line 335 def run_this(opts_and_args, parent_opts = {}) if all_opts_as_args? args = opts_and_args global_opts = parent_opts else # Parse parser = Cri::Parser.new( opts_and_args, global_option_definitions, parameter_definitions, explicitly_no_params?, ) handle_errors_while { parser.run } local_opts = parser. global_opts = parent_opts.merge(parser.) global_opts = add_defaults(global_opts) # Handle options (local_opts) args = handle_errors_while { parser.gen_argument_list } end # Execute if block.nil? raise NotImplementedError, "No implementation available for '#{name}'" end block.call(global_opts, args, self) end |