| Class | Argvector |
| In: |
lib/more/facets/argvector.rb
|
| Parent: | Object |
Argvector provides a very simple means of parsing command line arguments.
Unlike other more complex libs this provides only the most basic and standard parsing functionality. In many cases that‘s all one really needs.
Usage is straight foward. Simply instantiate the class and query it for the particular "views" of the command line you want.
cargs = Argvector.new("-a foo -b=2")
cargs.parameters #=> [['foo'],{'a'=>true,'b'=>'2'}]
cargs.flags #=> ['a']
cargs.preoptions #=> {'a'=>true}
cargs.preflags #=> ['a']
cargs.subcommand #=> ['foo',{'b'=>'2'}]
| argv | [R] | |
| arity | [R] | |
| line | [R] |
# File lib/more/facets/argvector.rb, line 67
67: def self.parameters(*args)
68: new.parameters(*args)
69: end
Returns operand array.
# File lib/more/facets/argvector.rb, line 91
91: def operands
92: @operands
93: end
Like parameters but without allowing for duplicate options.
# File lib/more/facets/argvector.rb, line 188
188: def parameters_without_duplicates
189: opts = {}
190: @options.each do |k,v|
191: if Array===v
192: opts[k] = v[0]
193: else
194: opts[k] = v
195: end
196: end
197: return @operands, opts
198: end
Same as flags but only returns flags in the preoptions.
# File lib/more/facets/argvector.rb, line 175
175: def preflags
176: preopts, remainder = *parse_preoptions(argv)
177: f = []
178: preopts.each do |k, v|
179: if TrueClass===v or FalseClass===v # not that it's ever false
180: f << k
181: end
182: end
183: return f
184: end
Returns a hash of options that occur before the first operand. This works well with subcommand to get the main command‘s options.
line = "--trace stamp --file VERSION"
cargs = Argvector.new(line)
opts = cargs.preoptions
opts #=> {"trace"=>true}
# File lib/more/facets/argvector.rb, line 167
167: def preoptions
168: preopts, remainder = *parse_preoptions(argv)
169: return preopts
170: end
Assumes the first operand is a "subcommand" and returns it and the argments following it as another Arguments object.
TODO: This probably should be called ‘subcommand’.
# File lib/more/facets/argvector.rb, line 151
151: def subcommand_with_arguments
152: opts, args = *parse_preoptions(argv)
153: cmd = args.shift
154: subargs = self.class.new(args, @arity)
155: return cmd, subargs
156: end
Assumes the first operand is a "subcommand" and returns it and the argments following it as parameters.
# File lib/more/facets/argvector.rb, line 127
127: def subcommand_with_parameters
128: opts, args = *parse_preoptions(argv)
129: cmd = args.shift
130: subargs = self.class.new(args, @arity)
131: return [cmd, *subargs.parameters]
132: end
# File lib/more/facets/argvector.rb, line 137
137: def subcommand_with_preoptions
138: pre, args = *parse_preoptions(argv)
139: cmd = args.shift
140: subargs = self.class.new(args, @arity)
141: args, opts = *subargs.parameters
142: return [cmd, args, pre.merge(opts)]
143: end
Parse flags takes the command line and transforms it such that flags (eg. -x and —x) are elemental associative arrays.
line = "--foo hello --try=this" parse_flags(line) #=> [ [foo,true], hello, ["try","this"] ]
# File lib/more/facets/argvector.rb, line 294
294: def assoc_options(args)
295: #args = args.dup
296: args = multi_flag(args) #unless opts.include?(:simple)
297:
298: i = 0
299: while i < args.size
300: arg = args[i]
301: case arg
302: when /^-/
303: arg = arg.sub(/^-{1,2}/,'')
304: if arg.index('=')
305: key, val = arg.split('=')
306: args[i] = [key, val||true]
307: elsif arity.key?(arg)
308: cnt = arity[arg]
309: key = arg
310: val = args[i+1,cnt]
311: args[i,cnt+1] = [[key, *val]]
312: i += (cnt - 1)
313: else
314: key = arg
315: args[i] = [key,true]
316: end
317: end
318: i += 1
319: end
320: return args
321: end
Format flag options. This converts the associative array of options/flags into a hash. Repeat options will be placed in arrays.
# File lib/more/facets/argvector.rb, line 340
340: def format_options(assoc_options)
341: opts = {}
342: assoc_options.each do |k,v|
343: if opts.key?(k)
344: opts[k] = [opts[k]].flatten << v
345: else
346: opts[k] = v
347: end
348: end
349: return opts
350: end
Split single letter option groupings into separate options. ie. -xyz => -x -y -z
# File lib/more/facets/argvector.rb, line 326
326: def multi_flag(args=nil)
327: args ||= argv
328: args.collect { |arg|
329: if md = /^-(\w{2,})/.match( arg )
330: md[1].split(//).collect { |c| "-#{c}" }
331: else
332: arg.dup
333: end
334: }.flatten
335: end
Basic parser partitions the command line into options and operands. Options are converted to a hash and the two parts are returned.
line = "--trace stamp --file=VERSION"
args, keys = *parse_command(line)
args #=> ["stamp"]
keys #=> {"trace"=>true, "file"=>"VERSION"}
# File lib/more/facets/argvector.rb, line 213
213: def parse
214: args = assoc_options(argv) #, *opts_arity)
215:
216: opts, opds = args.partition{ |a| Array === a }
217:
218: @operands = opds
219: @options = format_options(opts)
220:
221: return @operands, @options
222: end
Ensure arity is uniform.
# File lib/more/facets/argvector.rb, line 253
253: def parse_arity(arity)
254: arity2 = {}
255: arity.each{ |k,v| arity2[k.to_s] = v.to_i }
256: return arity2
257: end
First pass parser to split the command line into an array using Shellwords, if not already so divided.
# File lib/more/facets/argvector.rb, line 227
227: def parse_line(line=nil)
228: if line
229: case line
230: when String
231: argv = Shellwords.shellwords(line)
232: else
233: argv = line.to_ary.dup
234: line = argv.join(' ')
235: end
236: else
237: argv = ARGV.dup
238: line = argv.join(' ')
239: end
240: return line, argv
241: end
Parse preoptions. A "preoption" is one that occurs before the first operans (if any).
# File lib/more/facets/argvector.rb, line 262
262: def parse_preoptions(args)
263: #args = args.dup
264: args = multi_flag(args) #unless opts.include?(:simple)
265:
266: flags = []
267: while args.first =~ /^-/
268: key = args.shift
269: key.sub!(/^-{1,2}/,'')
270: if key.index('=')
271: key, val = key.split('=')
272: elsif a = arity[key]
273: val = args.slice!(0,a)
274: val = val.first if a == 1
275: else
276: val = true
277: end
278: flags << [key, val]
279: end
280:
281: flags = format_options(flags)
282:
283: return flags, args
284: end