Module: Rubycom::ParameterExtract
- Defined in:
- lib/rubycom/parameter_extract.rb
Class Method Summary collapse
-
.check(command, parsed_command_line, command_doc) ⇒ Array
Provides upfront checking for this inputs to #extract_parameters and raises a ParameterExtractError if parsed_command_line includes a help argument, option, or flag.
-
.extract!(long_name, short_name, opts, flags, args) ⇒ Hash
Searches opts, then flags, then args for a key matching the given long_name or short_name The first matched key will be removed from the set.
-
.extract_command_args!(command_name, command_line) ⇒ Hash
Trims command_line down to the entries which occur after command_name.
-
.extract_parameters(command, parsed_command_line, command_doc) ⇒ Hash
Calls #resolve_params with the given parameters after calling #check to assert the state of the inputs.
-
.get_param_names(params) ⇒ Hash
Creates a long and short name for each symbol in the given params.
-
.join(left, right) ⇒ Hash
Calls #update on left passing in right and resolving conflicts by combining left and right values in an array.
-
.resolve_opt!(param_name, long_name, short_name, default_value, command_line) ⇒ Hash
Extracts the a value from command_line for the param_name or returns the default with command_line has no values.
-
.resolve_others!(param_name, type, default_value, command_line) ⇒ Hash
Extracts a value from the command_line or returns the default_value if the command_line has no values.
-
.resolve_params(command, command_line, command_doc) ⇒ Hash
Matches parameter names in command.parameters to values from command_line or their default values in command_doc.
-
.resolve_rest!(param_name, default_value, command_line) ⇒ Array
Extracts the remaining values from command_line as an Array or returns the default with command_line has no values.
Class Method Details
.check(command, parsed_command_line, command_doc) ⇒ Array
Provides upfront checking for this inputs to #extract_parameters and raises a ParameterExtractError if parsed_command_line includes a help argument, option, or flag
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/rubycom/parameter_extract.rb', line 28 def self.check(command, parsed_command_line, command_doc) has_help_optional = false command.parameters.select { |type, _| type == :opt }.map { |_, name| name.to_s }.each { |param| has_help_optional = ['help', 'h'].include?(param) } if command.class == Method help_opt = !parsed_command_line[:opts].nil? && [ parsed_command_line[:opts]['help'], parsed_command_line[:opts]['h'] ].include?(true) help_flag = !parsed_command_line[:flags].nil? && [ parsed_command_line[:flags]['help'], parsed_command_line[:flags]['h'] ].include?(true) if !has_help_optional && (help_opt || help_flag) raise ParameterExtractError, 'Help Requested' end raise ParameterExtractError, "No command specified." if command.nil? raise ParameterExtractError, "No command specified." if command.class == Module raise ParameterExtractError, "Unrecognized command." unless [Method, Module].include?(command.class) raise "#{parsed_command_line} should be a Hash but was #{parsed_command_line.class}" if parsed_command_line.class != Hash raise ArgumentError, "command_doc should be a Hash but was #{command_doc.class}" unless command_doc.class == Hash raise ArgumentError, "command_doc should have key :parameters" unless command_doc.has_key?(:parameters) raise ArgumentError, "command_doc[:parameters] should be an array but was #{command_doc[:parameters].class}" unless command_doc[:parameters].class == Array command_doc[:parameters].each { |param_hsh| raise ArgumentError, "parameter #{param_hsh} should be a Hash but was #{param_hsh.class}" unless param_hsh.class == Hash raise ArgumentError, "parameter #{param_hsh} should have key :param_name" unless param_hsh.has_key?(:param_name) raise ArgumentError, "parameter #{param_hsh} should have key :type" unless param_hsh.has_key?(:type) raise ArgumentError, "parameter #{param_hsh} should have key :default" unless param_hsh.has_key?(:default) } [command, parsed_command_line, command_doc] end |
.extract!(long_name, short_name, opts, flags, args) ⇒ Hash
Searches opts, then flags, then args for a key matching the given long_name or short_name The first matched key will be removed from the set. The valued paired to the matched key will be returned along with a hash containing the remaining args, opts, and flags. !destructively modifies opts, flags, and args by deleting or shifting a matched value out of the Hash/Array
value is left is args then the first value in args will be pulled as the value to return
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/rubycom/parameter_extract.rb', line 241 def self.extract!(long_name, short_name, opts, flags, args) opts = {} if opts.nil? flags = {} if flags.nil? args = [] if args.nil? if opts.has_key?(long_name) opts.delete(long_name) elsif opts.has_key?(short_name) opts.delete(short_name) elsif flags.has_key?(long_name) flags.delete(long_name) elsif flags.has_key?(short_name) flags.delete(short_name) elsif args.size > 0 args.shift else :rubycom_no_value end end |
.extract_command_args!(command_name, command_line) ⇒ Hash
Trims command_line down to the entries which occur after command_name
108 109 110 111 112 113 114 115 116 117 |
# File 'lib/rubycom/parameter_extract.rb', line 108 def self.extract_command_args!(command_name, command_line) raise ArgumentError, "command_name should be a String|Symbol but was #{command_name}" unless [String, Symbol].include?(command_name.class) raise ArgumentError, "command_line should be a hash but was #{command_line}" unless command_line.class == Hash return command_line if command_line[:args].nil? i = command_line[:args].index(command_name.to_s) command_line[:args] = (i.nil?) ? [] : command_line[:args][i..-1] command_line[:args].shift if command_line[:args].first == command_name.to_s command_line end |
.extract_parameters(command, parsed_command_line, command_doc) ⇒ Hash
Calls #resolve_params with the given parameters after calling #check to assert the state of the inputs
13 14 15 16 |
# File 'lib/rubycom/parameter_extract.rb', line 13 def self.extract_parameters(command, parsed_command_line, command_doc) command, parsed_command_line, command_doc = self.check(command, parsed_command_line, command_doc) self.resolve_params(command, parsed_command_line, command_doc) end |
.get_param_names(params) ⇒ Hash
Creates a long and short name for each symbol in the given params
short => the first char in symbol if unique in params or the string form of symbol if not
140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/rubycom/parameter_extract.rb', line 140 def self.get_param_names(params) first_char_map = params.group_by { |_, sym| sym.to_s[0] } params.map { |_, sym| { sym => { long: sym.to_s, short: (first_char_map[sym.to_s[0]].size == 1) ? sym.to_s[0] : sym.to_s } } }.reduce({}, &:merge) end |
.join(left, right) ⇒ Hash
Calls #update on left passing in right and resolving conflicts by combining left and right values in an array
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/rubycom/parameter_extract.rb', line 192 def self.join(left, right) left.update(right) { |_, left_val, right_val| if left_val.class == Array combined = left_val else combined = [left_val] end if right_val.class == Array right_val.each { |rv| combined << rv } else combined << right_val end combined } end |
.resolve_opt!(param_name, long_name, short_name, default_value, command_line) ⇒ Hash
Extracts the a value from command_line for the param_name or returns the default with command_line has no values
125 126 127 128 129 130 131 132 133 |
# File 'lib/rubycom/parameter_extract.rb', line 125 def self.resolve_opt!(param_name, long_name, short_name, default_value, command_line) raise ArgumentError, "command_line should be a hash but was #{command_line}" unless command_line.class == Hash extraction = self.extract!(long_name, short_name, command_line[:opts], command_line[:flags], command_line[:args]) if extraction == :rubycom_no_value {param_name => default_value} else {param_name => extraction} end end |
.resolve_others!(param_name, type, default_value, command_line) ⇒ Hash
Extracts a value from the command_line or returns the default_value if the command_line has no values. Raises a ParameterExtractError if the type was :req and no value was found.
220 221 222 223 224 225 226 227 |
# File 'lib/rubycom/parameter_extract.rb', line 220 def self.resolve_others!(param_name, type, default_value, command_line) if command_line[:args].size > 0 {param_name => (command_line[:args].shift)} else raise ParameterExtractError, "Missing required argument: #{param_name}" if type == :req {param_name => default_value} end end |
.resolve_params(command, command_line, command_doc) ⇒ Hash
Matches parameter names in command.parameters to values from command_line or their default values in command_doc
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/rubycom/parameter_extract.rb', line 71 def self.resolve_params(command, command_line, command_doc) raise ArgumentError, "command should be a Method but was #{command.class}" unless command.class == Method command_line = command_line.clone.map { |type, entry| {type => entry.clone} }.reduce({}, &:merge) command_line = self.extract_command_args!(command.name.to_s, command_line) params = command.parameters param_names = self.get_param_names(params) raise ArgumentError, "command_doc should have key :parameters but was #{command_doc}" unless command_doc.has_key?(:parameters) param_docs = command_doc[:parameters].map { |param_hsh| if param_hsh[:type] == :rest {param_hsh.fetch(:param_name).reverse.chomp('*').reverse.to_sym => param_hsh.reject { |k, _| k == :param_name }} else {param_hsh.fetch(:param_name).to_sym => param_hsh.reject { |k, _| k == :param_name }} end }.reduce({}, &:merge) params.map { |type, sym| case type when :opt unless param_docs.has_key?(sym) && param_docs[sym].has_key?(:default) raise ArgumentError, "#{sym} should exist in command_doc[:parameters] and have key :default but has values #{param_docs[sym]}" end self.resolve_opt!(sym, param_names[sym][:long], param_names[sym][:short], param_docs[sym][:default], command_line) when :rest self.resolve_rest!(sym, param_docs[sym][:default], command_line) else self.resolve_others!(sym, type, param_docs[sym][:default], command_line) end }.reduce({}, &:merge).reject { |_, val| val == :rubycom_no_value } end |
.resolve_rest!(param_name, default_value, command_line) ⇒ Array
Extracts the remaining values from command_line as an Array or returns the default with command_line has no values
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/rubycom/parameter_extract.rb', line 158 def self.resolve_rest!(param_name, default_value, command_line) args = command_line[:args] || [] opts = command_line[:opts] || {} flags = command_line[:flags] || {} # TODO seems like we still can not call out a rest param on the command line, not sure if that is a problem rest_arr = { param_name => if args.empty? && opts.empty? && flags.empty? default_value elsif !args.empty? && opts.empty? && flags.empty? args elsif args.empty? && (!opts.empty? || !flags.empty?) joined = self.join(flags, opts) keyed = joined[param_name] || [] keyed.to_a << joined.reject { |k, _| k == param_name } else joined = self.join(flags, opts) keyed = joined[param_name] || [] rest = keyed.to_a << joined.reject { |k, _| k == param_name } args + rest end } command_line[:opts] = {} unless command_line[:opts].nil? command_line[:flags] = {} unless command_line[:flags].nil? command_line[:args] = [] unless command_line[:args].nil? rest_arr end |