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