Class: Commander::Runner
Defined Under Namespace
Classes: CommandError, InvalidCommandError
Instance Attribute Summary collapse
-
#commands ⇒ Object
readonly
Array of commands.
-
#help_formatter_aliases ⇒ Object
readonly
Hash of help formatter aliases.
-
#options ⇒ Object
readonly
Global options.
Class Method Summary collapse
-
.instance ⇒ Object
Return singleton Runner instance.
-
.separate_switches_from_description(*args) ⇒ Object
Return switches and description separated from the args passed.
-
.switch_to_sym(switch) ⇒ Object
Attempts to generate a method name symbol from
switch
.
Instance Method Summary collapse
-
#active_command ⇒ Object
Get active command within arguments passed to this runner.
-
#add_command(command) ⇒ Object
Add a command object to this runner.
-
#alias?(name) ⇒ Boolean
Check if command name is an alias.
-
#alias_command(alias_name, name, *args) ⇒ Object
Alias command name with alias_name.
-
#args_without_command_name ⇒ Object
Return arguments without the command name.
-
#command(name) {|add_command(Commander::Command.new(name))| ... } ⇒ Object
Creates and yields a command instance when a block is passed.
-
#command_exists?(name) ⇒ Boolean
Check if a command name exists.
-
#command_name_from_args ⇒ Object
Attempts to locate a command name from within the arguments.
-
#create_default_commands ⇒ Object
Creates default commands such as ‘help’ which is essentially the same as using the –help switch.
-
#default_command(name) ⇒ Object
Default command name to be used when no other command is found in the arguments.
-
#global_option(*args, &block) ⇒ Object
Add a global option; follows the same syntax as Command#option This would be used for switches such as –version, –trace, etc.
-
#global_option_proc(switches, &block) ⇒ Object
Returns a proc allowing for commands to inherit global options.
-
#help_formatter ⇒ Object
Help formatter instance.
-
#help_formatter_alias_defaults ⇒ Object
Returns hash of help formatter alias defaults.
-
#initialize(args = ARGV) ⇒ Runner
constructor
Initialize a new command runner.
-
#parse_global_options ⇒ Object
Parse global command options.
-
#program(key, *args, &block) ⇒ Object
Assign program information.
-
#program_defaults ⇒ Object
Returns hash of program defaults.
-
#remove_global_options(options, args) ⇒ Object
Removes global options from args.
-
#require_program(*keys) ⇒ Object
Raises a CommandError when the program any of the keys are not present, or empty.
-
#require_valid_command(command = active_command) ⇒ Object
Raises InvalidCommandError when a command is not found.
-
#run! ⇒ Object
Run command parsing and execution process.
-
#run_active_command ⇒ Object
Run the active command.
-
#say(*args) ⇒ Object
:nodoc:.
-
#valid_command_names_from(*args) ⇒ Object
Returns array of valid command names found within args.
-
#version ⇒ Object
Return program version.
Constructor Details
#initialize(args = ARGV) ⇒ Runner
Initialize a new command runner. Optionally supplying args for mocking, or arbitrary usage.
33 34 35 36 37 38 |
# File 'lib/commander/runner.rb', line 33 def initialize args = ARGV @args, @commands, @aliases, @options = args, {}, {}, [] @help_formatter_aliases = help_formatter_alias_defaults @program = program_defaults create_default_commands end |
Instance Attribute Details
#commands ⇒ Object (readonly)
Array of commands.
17 18 19 |
# File 'lib/commander/runner.rb', line 17 def commands @commands end |
#help_formatter_aliases ⇒ Object (readonly)
Hash of help formatter aliases.
27 28 29 |
# File 'lib/commander/runner.rb', line 27 def help_formatter_aliases @help_formatter_aliases end |
#options ⇒ Object (readonly)
Global options.
22 23 24 |
# File 'lib/commander/runner.rb', line 22 def @options end |
Class Method Details
.instance ⇒ Object
Return singleton Runner instance.
43 44 45 |
# File 'lib/commander/runner.rb', line 43 def self.instance @singleton ||= new end |
.separate_switches_from_description(*args) ⇒ Object
Return switches and description separated from the args passed.
357 358 359 360 361 |
# File 'lib/commander/runner.rb', line 357 def self.separate_switches_from_description *args switches = args.find_all { |arg| arg.to_s =~ /^-/ } description = args.last unless !args.last.is_a? String or args.last.match(/^-/) return switches, description end |
.switch_to_sym(switch) ⇒ Object
Attempts to generate a method name symbol from switch
. For example:
-h # => :h
--trace # => :trace
--some-switch # => :some_switch
--[no-]feature # => :feature
--file FILE # => :file
--list of,things # => :list
375 376 377 |
# File 'lib/commander/runner.rb', line 375 def self.switch_to_sym switch switch.scan(/[\-\]](\w+)/).join('_').to_sym rescue nil end |
Instance Method Details
#active_command ⇒ Object
Get active command within arguments passed to this runner.
205 206 207 |
# File 'lib/commander/runner.rb', line 205 def active_command @__active_command ||= command(command_name_from_args) end |
#add_command(command) ⇒ Object
Add a command object to this runner.
182 183 184 |
# File 'lib/commander/runner.rb', line 182 def add_command command @commands[command.name] = command end |
#alias?(name) ⇒ Boolean
Check if command name is an alias.
189 190 191 |
# File 'lib/commander/runner.rb', line 189 def alias? name @aliases.include? name.to_s end |
#alias_command(alias_name, name, *args) ⇒ Object
Alias command name with alias_name. Optionally args may be passed as if they were being passed straight to the original command via the command-line.
166 167 168 169 |
# File 'lib/commander/runner.rb', line 166 def alias_command alias_name, name, *args @commands[alias_name.to_s] = command name @aliases[alias_name.to_s] = args end |
#args_without_command_name ⇒ Object
Return arguments without the command name.
235 236 237 238 239 240 241 |
# File 'lib/commander/runner.rb', line 235 def args_without_command_name removed = [] parts = command_name_from_args.split rescue [] @args.dup.delete_if do |arg| removed << arg if parts.include?(arg) and not removed.include?(arg) end end |
#command(name) {|add_command(Commander::Command.new(name))| ... } ⇒ Object
Creates and yields a command instance when a block is passed. Otherwise attempts to return the command, raising InvalidCommandError when it does not exist.
Examples
command :my_command do |c|
c.when_called do |args|
# Code
end
end
143 144 145 146 |
# File 'lib/commander/runner.rb', line 143 def command name, &block yield add_command(Commander::Command.new(name)) if block @commands[name.to_s] end |
#command_exists?(name) ⇒ Boolean
Check if a command name exists.
196 197 198 |
# File 'lib/commander/runner.rb', line 196 def command_exists? name @commands[name.to_s] end |
#command_name_from_args ⇒ Object
Attempts to locate a command name from within the arguments. Supports multi-word commands, using the largest possible match.
213 214 215 |
# File 'lib/commander/runner.rb', line 213 def command_name_from_args @__command_name_from_args ||= (valid_command_names_from(*@args.dup).sort.last || @default_command) end |
#create_default_commands ⇒ Object
Creates default commands such as ‘help’ which is essentially the same as using the –help switch.
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/commander/runner.rb', line 262 def create_default_commands command :help do |c| c.syntax = 'commander help [command]' c.description = 'Display global or [command] help documentation.' c.example 'Display global help', 'command help' c.example "Display help for 'foo'", 'command help foo' c.when_called do |args, | enable_paging if args.empty? say help_formatter.render else command = command args.join(' ') require_valid_command command say help_formatter.render_command(command) end end end end |
#default_command(name) ⇒ Object
Default command name to be used when no other command is found in the arguments.
175 176 177 |
# File 'lib/commander/runner.rb', line 175 def default_command name @default_command = name end |
#global_option(*args, &block) ⇒ Object
Add a global option; follows the same syntax as Command#option This would be used for switches such as –version, –trace, etc.
152 153 154 155 156 157 158 159 160 |
# File 'lib/commander/runner.rb', line 152 def global_option *args, &block switches, description = Runner.separate_switches_from_description *args @options << { :args => args, :proc => block, :switches => switches, :description => description, } end |
#global_option_proc(switches, &block) ⇒ Object
Returns a proc allowing for commands to inherit global options. This functionality works whether a block is present for the global option or not, so simple switches such as –verbose can be used without a block, and used throughout all commands.
336 337 338 339 340 341 342 343 |
# File 'lib/commander/runner.rb', line 336 def global_option_proc switches, &block lambda do |value| unless active_command.nil? active_command. << [Runner.switch_to_sym(switches.last), value] end yield value if block and !value.nil? end end |
#help_formatter ⇒ Object
Help formatter instance.
228 229 230 |
# File 'lib/commander/runner.rb', line 228 def help_formatter @__help_formatter ||= program(:help_formatter).new self end |
#help_formatter_alias_defaults ⇒ Object
Returns hash of help formatter alias defaults.
246 247 248 |
# File 'lib/commander/runner.rb', line 246 def help_formatter_alias_defaults return :compact => HelpFormatter::TerminalCompact end |
#parse_global_options ⇒ Object
Parse global command options.
321 322 323 324 325 326 327 328 |
# File 'lib/commander/runner.rb', line 321 def .inject OptionParser.new do |, option| .on *option[:args], &global_option_proc(option[:switches], &option[:proc]) end.parse! @args.dup rescue OptionParser::InvalidOption # Ignore invalid options since options will be further # parsed by our sub commands. end |
#program(key, *args, &block) ⇒ Object
Assign program information.
Examples
# Set data
program :name, 'Commander'
program :version, Commander::VERSION
program :description, 'Commander utility program.'
program :help, 'Copyright', '2008 TJ Holowaychuk'
program :help, 'Anything', 'You want'
program :int_message 'Bye bye!'
program :help_formatter, :compact
program :help_formatter, Commander::HelpFormatter::TerminalCompact
# Get data
program :name # => 'Commander'
Keys
:version (required) Program version triple, ex: '0.0.1'
:description (required) Program description
:name Program name, defaults to basename of executable
:help_formatter Defaults to Commander::HelpFormatter::Terminal
:help Allows addition of arbitrary global help blocks
:int_message Message to display when interrupted (CTRL + C)
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/commander/runner.rb', line 113 def program key, *args, &block if key == :help and !args.empty? @program[:help] ||= {} @program[:help][args.first] = args.at(1) elsif key == :help_formatter && !args.empty? @program[key] = (@help_formatter_aliases[args.first] || args.first) elsif block @program[key] = block else unless args.empty? @program[key] = (args.count == 1 && args[0]) || args end @program[key] end end |
#program_defaults ⇒ Object
Returns hash of program defaults.
253 254 255 256 |
# File 'lib/commander/runner.rb', line 253 def program_defaults return :help_formatter => HelpFormatter::Terminal, :name => File.basename($0) end |
#remove_global_options(options, args) ⇒ Object
Removes global options from args. This prevents an invalid option error from occurring when options are parsed again for the command.
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/commander/runner.rb', line 293 def , args # TODO: refactor with flipflop, please TJ ! have time to refactor me ! .each do |option| switches = option[:switches].dup next if switches.empty? if switchHasArg = switches.any? { |s| s =~ /[ =]/ } switches.map! { |s| s[0, s.index('=') || s.index(' ') || s.length] } end past_switch, arg_removed = false, false args.delete_if do |arg| if switches.any? { |s| arg[0, s.length] == s } arg_removed = !switchHasArg past_switch = true elsif past_switch && !arg_removed && arg !~ /^-/ arg_removed = true else arg_removed = true false end end end end |
#require_program(*keys) ⇒ Object
Raises a CommandError when the program any of the keys are not present, or empty.
348 349 350 351 352 |
# File 'lib/commander/runner.rb', line 348 def require_program *keys keys.each do |key| raise CommandError, "program #{key} required" if program(key).nil? or program(key).empty? end end |
#require_valid_command(command = active_command) ⇒ Object
Raises InvalidCommandError when a command is not found.
284 285 286 |
# File 'lib/commander/runner.rb', line 284 def require_valid_command command = active_command raise InvalidCommandError, 'invalid command', caller if command.nil? end |
#run! ⇒ Object
Run command parsing and execution process.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/commander/runner.rb', line 50 def run! trace = false require_program :version, :description trap('INT') { abort program(:int_message) } if program(:int_message) trap('INT') { program(:int_block).call } if program(:int_block) global_option('-h', '--help', 'Display help documentation') { command(:help).run *@args[1..-1]; return } global_option('-v', '--version', 'Display version information') { say version; return } global_option('-t', '--trace', 'Display backtrace when an error occurs') { trace = true } , @args unless trace begin run_active_command rescue InvalidCommandError => e abort "#{e}. Use --help for more information" rescue \ OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument => e abort e rescue => e abort "error: #{e}. Use --trace to view backtrace" end else run_active_command end end |
#run_active_command ⇒ Object
Run the active command.
382 383 384 385 386 387 388 389 |
# File 'lib/commander/runner.rb', line 382 def run_active_command require_valid_command if alias? command_name_from_args active_command.run *(@aliases[command_name_from_args.to_s] + args_without_command_name) else active_command.run *args_without_command_name end end |
#say(*args) ⇒ Object
:nodoc:
391 392 393 |
# File 'lib/commander/runner.rb', line 391 def say *args #:nodoc: $terminal.say *args end |
#valid_command_names_from(*args) ⇒ Object
Returns array of valid command names found within args.
220 221 222 223 |
# File 'lib/commander/runner.rb', line 220 def valid_command_names_from *args arg_string = args.delete_if { |value| value =~ /^-/ }.join ' ' commands.keys.find_all { |name| name if /^#{name}/.match arg_string } end |
#version ⇒ Object
Return program version.
81 82 83 |
# File 'lib/commander/runner.rb', line 81 def version '%s %s' % [program(:name), program(:version)] end |