lib/gli.rb in gli-1.1.3 vs lib/gli.rb in gli-1.2.0

- old
+ new

@@ -24,10 +24,11 @@ # Reset the GLI module internal data structures; mostly for testing def reset switches.clear flags.clear commands.clear + @@version = nil @@config_file = nil clear_nexts end # describe the next switch, flag, or command. This should be a @@ -44,18 +45,22 @@ # set the default value of the next flag def default_value(val); @@next_default_value = val; end # Create a flag, which is a switch that takes an argument def flag(*names) - flag = Flag.new([names].flatten,@@next_desc,@@next_arg_name,@@next_default_value,@@next_long_desc) + 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 # Create a switch def switch(*names) - switch = Switch.new([names].flatten,@@next_desc,@@next_long_desc) + 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 # Sets the config file. If not an absolute path @@ -101,18 +106,24 @@ # prints out a message) def on_error(&a_proc) @@error_block = a_proc end + # Indicate the version of your application + def version(version) + @@version = version + end + # Runs whatever command is needed based on the arguments. def run(args) rdoc = RDocCommand.new commands[:rdoc] = rdoc if !commands[:rdoc] - commands[:help] = DefaultHelpCommand.new(rdoc) if !commands[:help] + commands[:help] = DefaultHelpCommand.new(@@version,rdoc) if !commands[:help] begin config = parse_config global_options,command,options,arguments = parse_options(args,config) + copy_options_to_aliased_versions(global_options,command,options) 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) @@ -121,15 +132,44 @@ rescue Exception => ex regular_error_handling = true regular_error_handling = @@error_block.call(ex) if @@error_block if regular_error_handling - puts "error: #{ex.message}" + $stderr.puts "error: #{ex.message}" end end end + # 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) + copy_options_to_aliases(global_options,self) + copy_options_to_aliases(options,command) + 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) + 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 return nil if @@config_file.nil? require 'yaml' if File.exist?(@@config_file) File.open(@@config_file) { |f| YAML::load(f) } @@ -318,6 +358,24 @@ return command if (command.aliases && command.aliases.include?(sym)) end nil end + # Checks that the names passed in have not been used in another flag or option + def verify_unused(names,flags,switches,context) + names.each do |name| + verify_unused_in_option(name,flags,"flag",context) + verify_unused_in_option(name,switches,"switch",context) + end + end + + private + + def verify_unused_in_option(name,option_like,type,context) + raise ArgumentError.new("#{name} has already been specified as a #{type} #{context}") if option_like[name] + option_like.each do |one_option_name,one_option| + 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 end