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, OptionParserPartitioningDelegate
Instance Attribute Summary collapse
-
#aliases ⇒ Array<String>
A list of aliases for this command that can be used to invoke this command.
-
#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”).
-
#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<Hash>
The list of option 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.
-
.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 ahelp
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.
-
#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 ⇒ Hash
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
139 140 141 142 143 144 |
# File 'lib/cri/command.rb', line 139 def initialize @aliases = Set.new @commands = Set.new @option_definitions = Set.new @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
71 72 73 |
# File 'lib/cri/command.rb', line 71 def aliases @aliases end |
#block ⇒ Proc
Returns The block that should be executed when invoking this command (ignored for commands with subcommands)
93 94 95 |
# File 'lib/cri/command.rb', line 93 def block @block end |
#commands ⇒ Set<Cri::Command> Also known as: subcommands
Returns This command’s subcommands
60 61 62 |
# File 'lib/cri/command.rb', line 60 def commands @commands end |
#default_subcommand_name ⇒ Symbol
Returns The name of the default subcommand
64 65 66 |
# File 'lib/cri/command.rb', line 64 def default_subcommand_name @default_subcommand_name end |
#description ⇒ String
Returns The long description (“description”)
77 78 79 |
# File 'lib/cri/command.rb', line 77 def description @description end |
#hidden ⇒ Boolean Also known as:
Returns true if the command is hidden (e.g. because it is deprecated), false otherwise
85 86 87 |
# File 'lib/cri/command.rb', line 85 def hidden @hidden end |
#option_definitions ⇒ Array<Hash>
Returns The list of option definitions
89 90 91 |
# File 'lib/cri/command.rb', line 89 def option_definitions @option_definitions end |
#summary ⇒ String
Returns The short description (“summary”)
74 75 76 |
# File 'lib/cri/command.rb', line 74 def summary @summary end |
#supercommand ⇒ Cri::Command?
Returns This command’s supercommand, or nil if the command has no supercommand
57 58 59 |
# File 'lib/cri/command.rb', line 57 def supercommand @supercommand end |
#usage ⇒ String
Returns The usage, without the “usage:” prefix and without the supercommands’ names.
81 82 83 |
# File 'lib/cri/command.rb', line 81 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.
108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/cri/command.rb', line 108 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 |
.new_basic_help ⇒ Cri::Command
Returns a new command that implements showing help.
134 135 136 137 |
# File 'lib/cri/command.rb', line 134 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, …)
126 127 128 129 |
# File 'lib/cri/command.rb', line 126 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.
340 341 342 |
# File 'lib/cri/command.rb', line 340 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.
177 178 179 180 |
# File 'lib/cri/command.rb', line 177 def add_command(command) @commands << command command.supercommand = self 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”).
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/cri/command.rb', line 232 def command_named(name, hard_exit: true) commands = commands_named(name) if commands.empty? $stderr.puts "#{self.name}: unknown command '#{name}'\n" raise CriExitException.new(is_error: true) elsif commands.size > 1 $stderr.puts "#{self.name}: '#{name}' is ambiguous:" $stderr.puts " #{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.
210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/cri/command.rb', line 210 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.
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/cri/command.rb', line 188 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 ⇒ Hash
Returns The option definitions for the command itself and all its ancestors
165 166 167 168 169 170 |
# File 'lib/cri/command.rb', line 165 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
329 330 331 |
# File 'lib/cri/command.rb', line 329 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.
153 154 155 156 157 158 159 160 161 |
# File 'lib/cri/command.rb', line 153 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.
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/cri/command.rb', line 258 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 $stderr.puts "#{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, 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.
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 301 def run_this(opts_and_args, parent_opts = {}) # Parse parser = Cri::OptionParser.new( opts_and_args, global_option_definitions ) handle_parser_errors_while { parser.run } local_opts = parser. global_opts = parent_opts.merge(parser.) args = parser.arguments # Handle options (local_opts) # Execute if block.nil? raise NotImplementedError, "No implementation available for '#{name}'" end block.call(global_opts, args, self) end |