lib/gli.rb in gli-1.2.6 vs lib/gli.rb in gli-1.3.0
- old
+ new
@@ -1,11 +1,12 @@
-require 'gli/command_line_token.rb'
require 'gli/command.rb'
-require 'gli/switch.rb'
+require 'gli/command_line_token.rb'
+require 'gli/copy_options_to_aliases.rb'
+require 'gli/exceptions.rb'
require 'gli/flag.rb'
require 'gli/options.rb'
-require 'gli/exceptions.rb'
+require 'gli/switch.rb'
require 'gli_version.rb'
require 'support/help.rb'
require 'support/rdoc.rb'
require 'support/initconfig.rb'
require 'etc'
@@ -13,19 +14,23 @@
# 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.
module GLI
extend self
+ include CopyOptionsToAliases
@@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
# Override the device of stderr; exposed only for testing
def error_device=(e) #:nodoc:
@@stderr = e
end
@@ -36,19 +41,45 @@
flags.clear
commands.clear
@@version = nil
@@config_file = nil
@@use_openstruct = false
+ @@prog_desc = nil
clear_nexts
end
# 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
def desc(description); @@next_desc = description; end
+ # 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
+ def program_desc(description=nil)
+ if description
+ @@program_desc = description
+ end
+ @@program_desc
+ end
+
+ # 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
+ def skips_pre
+ @@skips_pre = true
+ end
+
+ # 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
+ def skips_post
+ @@skips_post = true
+ end
+
# 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.
def long_desc(long_desc); @@next_long_desc = long_desc; end
@@ -125,11 +156,11 @@
# 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.
#
def command(*names)
- command = Command.new([names].flatten,@@next_desc,@@next_arg_name,@@next_long_desc)
+ 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
@@ -191,38 +222,42 @@
commands[:rdoc] = rdoc if !commands[:rdoc]
commands[:help] = DefaultHelpCommand.new(@@version,rdoc) if !commands[:help]
exit_code = 0
begin
config = parse_config
- global_options,command,options,arguments = parse_options(args,config)
+ override_defaults_based_on_config(config)
+ global_options,command,options,arguments = parse_options(args)
copy_options_to_aliased_versions(global_options,command,options)
global_options = convert_to_openstruct?(global_options)
options = convert_to_openstruct?(options)
if proceed?(global_options,command,options,arguments)
command = commands[:help] if !command
command.execute(global_options,options,arguments)
- @@post_block.call(global_options,command,options,arguments) if @@post_block
+ if !command.skips_post && @@post_block
+ @@post_block.call(global_options,command,options,arguments)
+ end
end
rescue Exception => ex
@@stderr.puts error_message(ex) if regular_error_handling?(ex)
- raise ex if ENV['GLI_DEBUG'] == 'true'
-
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
# True if we should proceed with executing the command; this calls
# the pre block if it's defined
def proceed?(global_options,command,options,arguments) #:nodoc:
- if @@pre_block
+ if command && command.skips_pre
+ true
+ elsif @@pre_block
@@pre_block.call(global_options,command,options,arguments)
else
true
end
end
@@ -286,78 +321,53 @@
# 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
def copy_options_to_aliased_versions(global_options,command,options) # :nodoc:
- copy_options_to_aliases(global_options,self)
- copy_options_to_aliases(options,command)
+ copy_options_to_aliases(global_options)
+ command.copy_options_to_aliases(options)
end
- # For each option in options, copies its value to keys for the aliases of the flags or
- # switches in gli_like
- #
- # options - Hash of options parsed from command line; this is an I/O param
- # gli_like - Object resonding to flags and switches in the same way that GLI or a Command instance do
- def copy_options_to_aliases(options,gli_like) # :nodoc:
- new_options = {}
- options.each do |key,value|
- if gli_like.flags[key] && gli_like.flags[key].aliases
- gli_like.flags[key].aliases.each do |alias_name|
- new_options[alias_name] = value
- end
- elsif gli_like.switches[key] && gli_like.switches[key].aliases
- gli_like.switches[key].aliases.each do |alias_name|
- new_options[alias_name] = value
- end
- end
- end
- options.merge!(new_options)
- end
-
def parse_config # :nodoc:
return nil if @@config_file.nil?
require 'yaml'
if File.exist?(@@config_file)
- File.open(@@config_file) { |f| YAML::load(f) }
+ File.open(@@config_file) { |file| YAML::load(file) }
else
{}
end
end
# Returns an array of four values:
# * global options (as a Hash)
# * Command
# * command options (as a Hash)
# * arguments (as an Array)
- def parse_options(args,config=nil) # :nodoc:
- command_configs = {}
- if config.nil?
- config = {}
- else
- command_configs = config.delete(GLI::InitConfig::COMMANDS_KEY) if !config.nil?
- end
- global_options,command,options,arguments = parse_options_helper(args.clone,config,nil,Hash.new,Array.new,command_configs)
+ def parse_options(args) # :nodoc:
+ global_options,command,options,arguments = parse_options_helper(args.clone,Hash.new,nil,Hash.new,Array.new)
flags.each { |name,flag| global_options[name] = flag.default_value if !global_options[name] }
command.flags.each { |name,flag| options[name] = flag.default_value if !options[name] }
return [global_options,command,options,arguments]
end
# Finds the index of the first non-flag
# argument or -1 if there wasn't one.
def find_non_flag_index(args) # :nodoc:
- args.each_index do |i|
- return i if args[i] =~ /^[^\-]/;
- return i-1 if args[i] =~ /^\-\-$/;
+ args.each_with_index do |item,index|
+ return index if item =~ /^[^\-]/
+ return index-1 if item =~ /^\-\-$/
end
- -1;
+ -1
end
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
clear_nexts
def flags # :nodoc:
@@ -374,11 +384,10 @@
# <code>args</code>:: the arguments that have yet to be processed
# <code>global_options</code>:: the global options hash
# <code>command</code>:: the Command that has been identified (or nil if not identified yet)
# <code>command_options</code>:: options for Command
# <code>arguments</code>:: the arguments for Command
- # <code>command_configs</code>:: the configuration file for all commands, used as defaults
#
# 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
@@ -387,11 +396,11 @@
# 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
- def parse_options_helper(args,global_options,command,command_options,arguments,command_configs) # :nodoc:
+ def parse_options_helper(args,global_options,command,command_options,arguments) # :nodoc:
non_flag_i = find_non_flag_index(args)
all_flags = false
if non_flag_i == 0
# no flags
if !command
@@ -399,13 +408,12 @@
command = find_command(command_name)
raise UnknownCommand.new("Unknown command '#{command_name}'") if !command
return parse_options_helper(args,
global_options,
command,
- default_command_options(command,command_configs),
- arguments,
- command_configs)
+ Hash.new,
+ arguments)
else
return global_options,command,command_options,arguments + args
end
elsif non_flag_i == -1
all_flags = true
@@ -451,11 +459,11 @@
if try_me.empty?
return [global_options,command,command_options,arguments] if rest.empty?
# If we have no more options we've parsed them all
# and rest may have more
- return parse_options_helper(rest,global_options,command,command_options,arguments,command_configs)
+ return parse_options_helper(rest,global_options,command,command_options,arguments)
else
if command
check = rest
check = rest + try_me if all_flags
check.each() do |arg|
@@ -475,27 +483,21 @@
raise UnknownCommand.new("Unknown command '#{command_name}'") if !command
return parse_options_helper(rest,
global_options,
command,
- default_command_options(command,command_configs),
- arguments,
- command_configs)
+ Hash.new,
+ arguments)
end
end
end
- def default_command_options(command,command_configs) # :nodoc:
- options = (command_configs && command_configs[command.name.to_sym]) || {}
- end
-
def find_command(name) # :nodoc:
sym = name.to_sym
return commands[name.to_sym] if commands[sym]
- commands.keys.each do |command_name|
- command = commands[command_name]
+ commands.each do |command_name,command|
return command if (command.aliases && command.aliases.include?(sym))
end
nil
end
@@ -515,6 +517,29 @@
if one_option.aliases
raise ArgumentError.new("#{name} has already been specified as an alias of #{type} #{one_option_name} #{context}") if one_option.aliases.include? name
end
end
end
+
+ # Sets the default values for flags based on the configuration
+ def override_defaults_based_on_config(config)
+ config ||= {}
+ config['commands'] ||= {}
+
+ override_default(flags,config)
+ override_default(switches,config)
+
+ commands.each do |command_name,command|
+ command_config = config['commands'][command_name] || {}
+
+ override_default(command.flags,command_config)
+ override_default(command.switches,command_config)
+ end
+ end
+
+ def override_default(tokens,config)
+ tokens.each do |name,token|
+ token.default_value=config[name] if config[name]
+ end
+ end
+
end