Module: GLI
- Extended by:
- GLI
- Includes:
- CopyOptionsToAliases
- Included in:
- GLI
- Defined in:
- lib/gli.rb,
lib/gli/flag.rb,
lib/gli/switch.rb,
lib/gli/command.rb,
lib/gli/options.rb,
lib/gli_version.rb,
lib/gli/terminal.rb,
lib/support/help.rb,
lib/support/rdoc.rb,
lib/gli/exceptions.rb,
lib/support/scaffold.rb,
lib/support/initconfig.rb,
lib/gli/command_line_token.rb,
lib/gli/copy_options_to_aliases.rb
Overview
A means to define and parse a command line interface that works as Git’s does, in that you specify global options, a command name, command specific options, and then command arguments.
Defined Under Namespace
Modules: CopyOptionsToAliases Classes: BadCommandLine, Command, CommandLineToken, CustomExit, DefaultHelpCommand, Flag, InitConfig, Options, RDocCommand, Scaffold, Switch, Terminal, UnknownCommand, UnknownCommandArgument, UnknownGlobalArgument
Constant Summary collapse
- VERSION =
'1.6.0'
- @@program_name =
$0.split(/\//)[-1]
- @@post_block =
nil
- @@pre_block =
nil
- @@error_block =
nil
- @@config_file =
nil
- @@use_openstruct =
false
- @@version =
nil
- @@stderr =
$stderr
- @@program_desc =
nil
- @@skips_pre =
false
- @@skips_post =
false
- @@default_command =
:help
Instance Method Summary collapse
-
#arg_name(name) ⇒ Object
Describe the argument name of the next flag.
-
#clear_nexts ⇒ Object
:nodoc:.
-
#command(*names) {|command| ... } ⇒ Object
(also: #c)
Define a new command.
-
#commands ⇒ Object
:nodoc:.
-
#config_file(filename) ⇒ Object
Sets that this app uses a config file as well as the name of the config file.
-
#convert_to_openstruct?(options) ⇒ Boolean
Possibly returns a copy of the passed-in Hash as an instance of GLI::Option.
-
#copy_options_to_aliased_versions(global_options, command, options) ⇒ Object
Copies all options in both global_options and options to keys for the aliases of those flags.
-
#default_command(command) ⇒ Object
Sets a default command to run when none is specified on the command line.
-
#default_value(val) ⇒ Object
set the default value of the next flag.
-
#desc(description) ⇒ Object
(also: #d)
Describe the next switch, flag, or command.
-
#error_device=(e) ⇒ Object
Override the device of stderr; exposed only for testing.
-
#error_message(ex) ⇒ Object
- Returns a String of the error message to show the user
ex
-
The exception we caught that launched the error handling routines.
- Returns a String of the error message to show the user
-
#exit_now!(message, exit_code) ⇒ Object
Simpler means of exiting with a custom exit code.
-
#find_command(name) ⇒ Object
:nodoc:.
-
#find_non_flag_index(args) ⇒ Object
Finds the index of the first non-flag argument or -1 if there wasn’t one.
-
#flag(*names) ⇒ Object
(also: #f)
Create a flag, which is a switch that takes an argument.
- #flag_switch_index(args) ⇒ Object
-
#flags ⇒ Object
:nodoc:.
-
#long_desc(long_desc) ⇒ Object
Provide a longer, more detailed description.
-
#on_error(&a_proc) ⇒ Object
Define a block to run if an error occurs.
-
#parse_config ⇒ Object
:nodoc:.
-
#parse_options(args) ⇒ Object
Returns an array of four values: * global options (as a Hash) * Command * command options (as a Hash) * arguments (as an Array).
-
#parse_options_helper(args, global_options, command, command_options, arguments) ⇒ Object
- Recursive helper for parsing command line options
args
- the arguments that have yet to be processed
global_options
- the global options hash
command
- the Command that has been identified (or nil if not identified yet)
command_options
- options for Command
arguments
-
the arguments for Command.
- options for Command
- the Command that has been identified (or nil if not identified yet)
- the global options hash
- the arguments that have yet to be processed
- Recursive helper for parsing command line options
-
#post(&a_proc) ⇒ Object
Define a block to run after the command was executed, only if there was not an error.
-
#pre(&a_proc) ⇒ Object
Define a block to run after command line arguments are parsed but before any command is run.
-
#proceed?(global_options, command, options, arguments) ⇒ Boolean
True if we should proceed with executing the command; this calls the pre block if it’s defined.
-
#program_desc(description = nil) ⇒ Object
Describe the overall application/programm.
-
#program_name(override = nil) ⇒ Object
Set or get the name of the program, if you don’t want the default (which is the name of the command line program).
-
#regular_error_handling?(ex) ⇒ Boolean
Returns true if we should proceed with GLI’s basic error handling.
-
#reset ⇒ Object
Reset the GLI module internal data structures; mostly useful for testing.
-
#run(args) ⇒ Object
Runs whatever command is needed based on the arguments.
-
#skips_post ⇒ Object
Use this if the following command should not have the post block executed.
-
#skips_pre ⇒ Object
Use this if the following command should not have the pre block executed.
-
#switch(*names) ⇒ Object
(also: #s)
Create a switch, which is a command line flag that takes no arguments (thus, it switches something on).
-
#switches ⇒ Object
:nodoc:.
-
#use_openstruct(use_openstruct) ⇒ Object
Call this with
true
will cause theglobal_options
andoptions
passed to your code to be wrapped in Options, which is a subclass ofOpenStruct
that adds[]
and[]=
methods. -
#verify_unused(names, flags, switches, context) ⇒ Object
Checks that the names passed in have not been used in another flag or option.
-
#version(version) ⇒ Object
Indicate the version of your application.
Methods included from CopyOptionsToAliases
Instance Method Details
#arg_name(name) ⇒ Object
Describe the argument name of the next flag. It’s important to keep this VERY short and, ideally, without any spaces (see Example).
name
-
A String that briefly describes the argument given to the following command or flag.
Example:
desc 'Set the filename'
arg_name 'file_name'
flag [:f,:filename]
Produces:
-f, --filename=file_name Set the filename
115 |
# File 'lib/gli.rb', line 115 def arg_name(name); @@next_arg_name = name; end |
#clear_nexts ⇒ Object
:nodoc:
386 387 388 389 390 391 392 393 |
# File 'lib/gli.rb', line 386 def clear_nexts # :nodoc: @@next_desc = nil @@next_arg_name = nil @@next_default_value = nil @@next_long_desc = nil @@skips_pre = false @@skips_post = false end |
#command(*names) {|command| ... } ⇒ Object Also known as: c
Define a new command. This takes a block that will be given an instance of the Command that was created. You then may call methods on this object to define aspects of that Command.
names
-
a String or Symbol, or an Array of String or Symbol that represent all the different names and aliases for this command.
176 177 178 179 180 181 |
# File 'lib/gli.rb', line 176 def command(*names) command = Command.new([names].flatten,@@next_desc,@@next_arg_name,@@next_long_desc,@@skips_pre,@@skips_post) commands[command.name] = command yield command clear_nexts end |
#commands ⇒ Object
:nodoc:
403 404 405 |
# File 'lib/gli.rb', line 403 def commands # :nodoc: @@commands ||= {} end |
#config_file(filename) ⇒ Object
Sets that this app uses a config file as well as the name of the config file.
filename
-
A String representing the path to the file to use for the config file. If it’s an absolute path, this is treated as the path to the file. If it’s not, it’s treated as relative to the user’s home directory as produced by
File.expand_path('~')
.
161 162 163 164 165 166 167 168 169 |
# File 'lib/gli.rb', line 161 def config_file(filename) if filename =~ /^\// @@config_file = filename else @@config_file = File.join(File.('~'),filename) end commands[:initconfig] = InitConfig.new(@@config_file) @@config_file end |
#convert_to_openstruct?(options) ⇒ Boolean
Possibly returns a copy of the passed-in Hash as an instance of GLI::Option. By default, it will not. However by putting use_openstruct true
in your CLI definition, it will
335 336 337 |
# File 'lib/gli.rb', line 335 def convert_to_openstruct?() # :nodoc: @@use_openstruct ? Options.new() : end |
#copy_options_to_aliased_versions(global_options, command, options) ⇒ Object
Copies all options in both global_options and options to keys for the aliases of those flags. For example, if a flag works with either -f or –flag, this will copy the value from [:f] to [:flag] to allow the user to access the options by any alias
342 343 344 345 |
# File 'lib/gli.rb', line 342 def (,command,) # :nodoc: () command.() end |
#default_command(command) ⇒ Object
Sets a default command to run when none is specified on the command line. Note that if you use this, you won’t be able to pass arguments, flags, or switches to the command when run in default mode. All flags and switches are treated as global, and any argument will be interpretted as the command name and likely fail.
command
-
Command to run as default
62 63 64 |
# File 'lib/gli.rb', line 62 def default_command(command) @@default_command = command.to_sym end |
#default_value(val) ⇒ Object
set the default value of the next flag
val
-
A String reprensenting the default value to be used for the following flag if the user doesn’t specify one and, when using a config file, the config also doesn’t specify one
121 |
# File 'lib/gli.rb', line 121 def default_value(val); @@next_default_value = val; end |
#desc(description) ⇒ Object Also known as: d
Describe the next switch, flag, or command. This should be a short, one-line description
description
-
A String of the short descripiton of the switch, flag, or command following
70 |
# File 'lib/gli.rb', line 70 def desc(description); @@next_desc = description; end |
#error_device=(e) ⇒ Object
Override the device of stderr; exposed only for testing
35 36 37 |
# File 'lib/gli.rb', line 35 def error_device=(e) #:nodoc: @@stderr = e end |
#error_message(ex) ⇒ Object
Returns a String of the error message to show the user
ex
-
The exception we caught that launched the error handling routines
293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/gli.rb', line 293 def (ex) #:nodoc: msg = "error: #{ex.}" case ex when UnknownCommand msg += ". Use '#{program_name} help' for a list of commands" when UnknownCommandArgument msg += ". Use '#{program_name} help #{ex.command.name}' for a list of command options" when UnknownGlobalArgument msg += ". Use '#{program_name} help' for a list of global options" end msg end |
#exit_now!(message, exit_code) ⇒ Object
Simpler means of exiting with a custom exit code. This will raise a CustomExit with the given message and exit code, which will ultimatley cause your application to exit with the given exit_code as its exit status
309 310 311 |
# File 'lib/gli.rb', line 309 def exit_now!(,exit_code) raise CustomExit.new(,exit_code) end |
#find_command(name) ⇒ Object
:nodoc:
527 528 529 530 531 532 533 534 |
# File 'lib/gli.rb', line 527 def find_command(name) # :nodoc: sym = name.to_sym return commands[name.to_sym] if commands[sym] commands.each do |command_name,command| return command if (command.aliases && command.aliases.include?(sym)) end nil end |
#find_non_flag_index(args) ⇒ Object
Finds the index of the first non-flag argument or -1 if there wasn’t one.
371 372 373 374 375 376 377 |
# File 'lib/gli.rb', line 371 def find_non_flag_index(args) # :nodoc: args.each_with_index do |item,index| return index if item =~ /^[^\-]/ return index-1 if item =~ /^\-\-$/ end -1 end |
#flag(*names) ⇒ Object Also known as: f
Create a flag, which is a switch that takes an argument
names
-
a String or Symbol, or an Array of String or Symbol that represent all the different names and aliases for this flag.
Example:
desc 'Set the filename'
flag [:f,:filename,'file-name']
Produces:
-f, --filename, --file-name=arg Set the filename
136 137 138 139 140 141 142 |
# File 'lib/gli.rb', line 136 def flag(*names) names = [names].flatten verify_unused(names,flags,switches,"in global options") flag = Flag.new(names,@@next_desc,@@next_arg_name,@@next_default_value,@@next_long_desc) flags[flag.name] = flag clear_nexts end |
#flag_switch_index(args) ⇒ Object
379 380 381 382 383 384 |
# File 'lib/gli.rb', line 379 def flag_switch_index(args) args.each_with_index do |item,index| return index if item =~ /^[\-]/ end -1 end |
#flags ⇒ Object
:nodoc:
397 398 399 |
# File 'lib/gli.rb', line 397 def flags # :nodoc: @@flags ||= {} end |
#long_desc(long_desc) ⇒ Object
Provide a longer, more detailed description. This will be reformatted and wrapped to fit in the terminal’s columns
long_desc
-
A String that is s longer description of the switch, flag, or command following.
101 |
# File 'lib/gli.rb', line 101 def long_desc(long_desc); @@next_long_desc = long_desc; end |
#on_error(&a_proc) ⇒ Object
Define a block to run if an error occurs. The block will receive any Exception that was caught. It should evaluate to false to avoid the built-in error handling (which basically just prints out a message). GLI uses a variety of exceptions that you can use to find out what errors might’ve occurred during command-line parsing:
-
GLI::CustomExit
-
GLI::UnknownCommandArgument
-
GLI::UnknownGlobalArgument
-
GLI::UnknownCommand
-
GLI::BadCommandLine
210 211 212 |
# File 'lib/gli.rb', line 210 def on_error(&a_proc) @@error_block = a_proc end |
#parse_config ⇒ Object
:nodoc:
347 348 349 350 351 352 353 354 355 |
# File 'lib/gli.rb', line 347 def parse_config # :nodoc: return nil if @@config_file.nil? require 'yaml' if File.exist?(@@config_file) File.open(@@config_file) { |file| YAML::load(file) } else {} end end |
#parse_options(args) ⇒ Object
Returns an array of four values:
* global options (as a Hash)
* Command
* command options (as a Hash)
* arguments (as an Array)
362 363 364 365 366 367 |
# File 'lib/gli.rb', line 362 def (args) # :nodoc: ,command,,arguments = (args.clone,Hash.new,nil,Hash.new,Array.new) flags.each { |name,flag| [name] = flag.default_value if ![name] } command.flags.each { |name,flag| [name] = flag.default_value if ![name] } return [,command,,arguments] end |
#parse_options_helper(args, global_options, command, command_options, arguments) ⇒ Object
Recursive helper for parsing command line options
args
-
the arguments that have yet to be processed
global_options
-
the global options hash
command
-
the Command that has been identified (or nil if not identified yet)
command_options
-
options for Command
arguments
-
the arguments for Command
This works by finding the first non-switch/flag argument, and taking that sublist and trying to pick out flags and switches. After this is done, one of the following is true:
* the sublist is empty - in this case, go again, as there might be more flags to parse
* the sublist has a flag left in it - unknown flag; we bail
* the sublist has a non-flag left in it - this is the command (or the start of the arguments list)
This sort of does the same thing in two phases; in the first phase, the command hasn’t been identified, so we are looking for global switches and flags, ending when we get the command.
Once the command has been found, we start looking for command-specific flags and switches. When those have been found, we know the rest of the argument list is arguments for the command
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
# File 'lib/gli.rb', line 425 def (args,,command,,arguments) # :nodoc: non_flag_i = find_non_flag_index(args) all_flags = false if non_flag_i == 0 # no flags if !command command_name = args.shift command = find_command(command_name) raise UnknownCommand.new("Unknown command '#{command_name}'") if !command return (args, , command, Hash.new, arguments) elsif((index = flag_switch_index(args)) >= 0) try_me = args[0..index-1] rest = args[index..args.length] new_args = rest + try_me return (new_args, , command, Hash.new, arguments) else return ,command,,arguments + args end elsif non_flag_i == -1 all_flags = true end try_me = args[0..non_flag_i] rest = args[(non_flag_i+1)..args.length] if all_flags try_me = args rest = [] end # Suck up whatever options we can switch_hash = switches flag_hash = flags = if command switch_hash = command.switches flag_hash = command.flags = end switch_hash.each do |name,switch| value = switch.get_value!(try_me) [name] = value if ![name] end flag_hash.each do |name,flag| value = flag.get_value!(try_me) # So, there's a case where the first time we request the value for a flag, # we get the default and not the user-provided value. The next time we request # it, we want to override it with the real value. # HOWEVER, sometimes this happens in reverse, so we want to err on taking the # user-provided, non-default value where possible. if value if [name] [name] = value if [name] == flag.default_value else [name] = value end end end if try_me.empty? return [,command,,arguments] if rest.empty? # If we have no more options we've parsed them all # and rest may have more return (rest,,command,,arguments) else if command check = rest check = rest + try_me if all_flags check.each() do |arg| if arg =~ /^\-\-$/ try_me.delete arg break end raise UnknownCommandArgument.new("Unknown option #{arg}",command) if arg =~ /^\-/ end return [,command,,try_me + rest] else # Now we have our command name command_name = try_me.shift raise UnknownGlobalArgument.new("Unknown option #{command_name}") if command_name =~ /^\-/ command = find_command(command_name) raise UnknownCommand.new("Unknown command '#{command_name}'") if !command return (rest, , command, Hash.new, arguments) end end end |
#post(&a_proc) ⇒ Object
Define a block to run after the command was executed, only if there was not an error. The block will receive the global-options,command,options, and arguments
196 197 198 |
# File 'lib/gli.rb', line 196 def post(&a_proc) @@post_block = a_proc end |
#pre(&a_proc) ⇒ Object
Define a block to run after command line arguments are parsed but before any command is run. If this block raises an exception the command specified will not be executed. The block will receive the global-options,command,options, and arguments If this block evaluates to true, the program will proceed; otherwise the program will end immediately
189 190 191 |
# File 'lib/gli.rb', line 189 def pre(&a_proc) @@pre_block = a_proc end |
#proceed?(global_options, command, options, arguments) ⇒ Boolean
True if we should proceed with executing the command; this calls the pre block if it’s defined
271 272 273 274 275 276 277 278 279 |
# File 'lib/gli.rb', line 271 def proceed?(,command,,arguments) #:nodoc: if command && command.skips_pre true elsif @@pre_block @@pre_block.call(,command,,arguments) else true end end |
#program_desc(description = nil) ⇒ Object
Describe the overall application/programm. This should be a one-sentence summary of what your program does that will appear in the help output.
description
-
A String of the short description of your program’s purpose
76 77 78 79 80 81 |
# File 'lib/gli.rb', line 76 def program_desc(description=nil) if description @@program_desc = description end @@program_desc end |
#program_name(override = nil) ⇒ Object
Set or get the name of the program, if you don’t want the default (which is the name of the command line program). This is only used currently in the help and rdoc commands.
override
-
A String that represents the name of the program to use, other than the default.
Returns the current program name, as a String
320 321 322 323 324 325 |
# File 'lib/gli.rb', line 320 def program_name(override=nil) if override @@program_name = override end @@program_name end |
#regular_error_handling?(ex) ⇒ Boolean
Returns true if we should proceed with GLI’s basic error handling. This calls the error block if the user provided one
283 284 285 286 287 288 289 |
# File 'lib/gli.rb', line 283 def regular_error_handling?(ex) #:nodoc: if @@error_block @@error_block.call(ex) else true end end |
#reset ⇒ Object
Reset the GLI module internal data structures; mostly useful for testing
40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/gli.rb', line 40 def reset # :nodoc: switches.clear flags.clear commands.clear @@version = nil @@config_file = nil @@use_openstruct = false @@prog_desc = nil @@default_command = :help clear_nexts desc 'Show this message' switch :help end |
#run(args) ⇒ Object
Runs whatever command is needed based on the arguments.
args
-
the command line ARGV array
Returns a number that would be a reasonable exit code
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/gli.rb', line 236 def run(args) #:nodoc: rdoc = RDocCommand.new commands[:rdoc] = rdoc if !commands[:rdoc] commands[:help] = DefaultHelpCommand.new(@@version,rdoc) if !commands[:help] exit_code = 0 begin config = parse_config override_defaults_based_on_config(config) ,command,,arguments = (args) (,command,) = convert_to_openstruct?() = convert_to_openstruct?() if proceed?(,command,,arguments) command = commands[@@default_command] if !command command.execute(,,arguments) if !command.skips_post && @@post_block @@post_block.call(,command,,arguments) end end rescue Exception => ex @@stderr.puts (ex) if regular_error_handling?(ex) exit_code = if ex.respond_to? :exit_code ex.exit_code else -2 end raise ex if ENV['GLI_DEBUG'] == 'true' end exit_code end |
#skips_post ⇒ Object
Use this if the following command should not have the post block executed. By default, the post block is executed after each command. Using this will avoid that behavior for the following command
93 94 95 |
# File 'lib/gli.rb', line 93 def skips_post @@skips_post = true end |
#skips_pre ⇒ Object
Use this if the following command should not have the pre block executed. By default, the pre block is executed before each command and can result in aborting the call. Using this will avoid that behavior for the following command
86 87 88 |
# File 'lib/gli.rb', line 86 def skips_pre @@skips_pre = true end |
#switch(*names) ⇒ Object Also known as: s
Create a switch, which is a command line flag that takes no arguments (thus, it switches something on)
names
-
a String or Symbol, or an Array of String or Symbol that represent all the different names and aliases for this switch.
148 149 150 151 152 153 154 |
# File 'lib/gli.rb', line 148 def switch(*names) names = [names].flatten verify_unused(names,flags,switches,"in global options") switch = Switch.new(names,@@next_desc,@@next_long_desc) switches[switch.name] = switch clear_nexts end |
#switches ⇒ Object
:nodoc:
400 401 402 |
# File 'lib/gli.rb', line 400 def switches # :nodoc: @@switches ||= {} end |
#use_openstruct(use_openstruct) ⇒ Object
Call this with true
will cause the global_options
and options
passed to your code to be wrapped in Options, which is a subclass of OpenStruct
that adds []
and []=
methods.
use_openstruct
-
a Boolean indicating if we should use OpenStruct instead of Hashes
227 228 229 |
# File 'lib/gli.rb', line 227 def use_openstruct(use_openstruct) @@use_openstruct = use_openstruct end |
#verify_unused(names, flags, switches, context) ⇒ Object
Checks that the names passed in have not been used in another flag or option
537 538 539 540 541 542 |
# File 'lib/gli.rb', line 537 def verify_unused(names,flags,switches,context) # :nodoc: names.each do |name| verify_unused_in_option(name,flags,"flag",context) verify_unused_in_option(name,switches,"switch",context) end end |
#version(version) ⇒ Object
Indicate the version of your application
version
-
String containing the version of your application.
217 218 219 |
# File 'lib/gli.rb', line 217 def version(version) @@version = version end |