lib/gli.rb in gli-1.0.0 vs lib/gli.rb in gli-1.1.0

- old
+ new

@@ -3,29 +3,33 @@ require 'gli/switch.rb' require 'gli/flag.rb' require 'gli/options.rb' require 'support/help.rb' require 'support/rdoc.rb' +require 'support/initconfig.rb' +require 'etc' # 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 - VERSION = '0.3.0' + VERSION = '1.0.0' @@program_name = $0.split(/\//)[-1] @@post_block = nil @@pre_block = nil @@error_block = nil + @@config_file = nil # Reset the GLI module internal data structures; mostly for testing def reset switches.clear flags.clear commands.clear + @@config_file = nil clear_nexts end # describe the next switch, flag, or command. This should be a # short, one-line description @@ -52,10 +56,22 @@ switch = Switch.new([names].flatten,@@next_desc,@@next_long_desc) switches[switch.name] = switch clear_nexts end + # Sets the config file. If not an absolute path + # sets the path to the user's home directory + def config_file(filename) + if filename =~ /^\// + @@config_file = filename + else + @@config_file = Etc.getpwuid.dir + '/' + filename + end + commands[:initconfig] = InitConfig.new(@@config_file) + @@config_file + end + # Define a command. def command(*names) command = Command.new([names].flatten,@@next_desc,@@next_arg_name,@@next_long_desc) commands[command.name] = command yield command @@ -91,11 +107,12 @@ def run(args) rdoc = RDocCommand.new commands[:rdoc] = rdoc if !commands[:rdoc] commands[:help] = DefaultHelpCommand.new(rdoc) if !commands[:help] begin - global_options,command,options,arguments = parse_options(args) + config = parse_config + global_options,command,options,arguments = parse_options(args,config) proceed = true proceed = @@pre_block.call(global_options,command,options,arguments) if @@pre_block if proceed command = commands[:help] if !command command.execute(global_options,options,arguments) @@ -109,10 +126,20 @@ puts "error: #{ex.message}" end end end + def parse_config + return nil if @@config_file.nil? + require 'yaml' + if File.exist?(@@config_file) + File.open(@@config_file) { |f| YAML::load(f) } + else + {} + end + end + def program_name(override=nil) if override @@program_name = override end @@program_name @@ -121,12 +148,18 @@ # 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) - global_options,command,options,arguments = parse_options_helper(args.clone,Options.new,nil,Options.new,Array.new) + def parse_options(args,config=nil) + 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,Options.new,Array.new,command_configs) 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 @@ -162,10 +195,11 @@ # [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 + # [command_configs] 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 @@ -174,20 +208,25 @@ # 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) + def parse_options_helper(args,global_options,command,command_options,arguments,command_configs) 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 "Unknown command '#{command_name}'" if !command - return parse_options_helper(args,global_options,command,command_options,arguments) + return parse_options_helper(args, + global_options, + command, + default_command_options(command,command_configs), + arguments, + command_configs) else return global_options,command,command_options,arguments + args end elsif non_flag_i == -1 all_flags = true @@ -222,11 +261,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) + return parse_options_helper(rest,global_options,command,command_options,arguments,command_configs) else if command check = rest check = rest + try_me if all_flags check.each() do |arg| @@ -243,13 +282,22 @@ raise "Unknown argument #{command_name}" if command_name =~ /^\-/ command = find_command(command_name) raise "Unknown command '#{command_name}'" if !command - return parse_options_helper(rest,global_options,command,command_options,arguments) + return parse_options_helper(rest, + global_options, + command, + default_command_options(command,command_configs), + arguments, + command_configs) end end + end + + def default_command_options(command,command_configs) + options = (command_configs && command_configs[command.name.to_sym]) || {} end def find_command(name) sym = name.to_sym return commands[name.to_sym] if commands[sym]