trollop 1.11 → 1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +6 -0
- data/lib/trollop.rb +158 -151
- data/test/test_trollop.rb +44 -5
- metadata +2 -2
data/History.txt
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
== 1.12 / 2009-01-30
|
|
2
|
+
* Fix some unit test failures in the last release. Should be more careful.
|
|
3
|
+
* Make default short options only be assigned *after* all user-specified
|
|
4
|
+
short options. Now there's a little less juggling to do when you just
|
|
5
|
+
want to specify a few short options.
|
|
6
|
+
|
|
1
7
|
== 1.11 / 2009-01-29
|
|
2
8
|
* Set <opt>_given keys in the results hash for options that were specified
|
|
3
9
|
on the commandline.
|
data/lib/trollop.rb
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
module Trollop
|
|
7
7
|
|
|
8
|
-
VERSION = "1.
|
|
8
|
+
VERSION = "1.12"
|
|
9
9
|
|
|
10
10
|
## Thrown by Parser in the event of a commandline error. Not needed if
|
|
11
11
|
## you're using the Trollop::options entry.
|
|
@@ -197,21 +197,12 @@ class Parser
|
|
|
197
197
|
|
|
198
198
|
## fill in :short
|
|
199
199
|
opts[:short] = opts[:short].to_s if opts[:short] unless opts[:short] == :none
|
|
200
|
-
opts[:short] =
|
|
201
|
-
|
|
202
|
-
when nil
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
when /^-(.)$/
|
|
207
|
-
$1
|
|
208
|
-
when /^.$/
|
|
209
|
-
opts[:short]
|
|
210
|
-
when :none
|
|
211
|
-
nil
|
|
212
|
-
else
|
|
213
|
-
raise ArgumentError, "invalid short option name '#{opts[:short].inspect}'"
|
|
214
|
-
end
|
|
200
|
+
opts[:short] = case opts[:short]
|
|
201
|
+
when /^-(.)$/; $1
|
|
202
|
+
when nil, :none, /^.$/; opts[:short]
|
|
203
|
+
else raise ArgumentError, "invalid short option name '#{opts[:short].inspect}'"
|
|
204
|
+
end
|
|
205
|
+
|
|
215
206
|
if opts[:short]
|
|
216
207
|
raise ArgumentError, "short option name #{opts[:short].inspect} is already taken; please specify a (different) :short" if @short[opts[:short]]
|
|
217
208
|
raise ArgumentError, "a short option name can't be a number or a dash" if opts[:short] =~ INVALID_SHORT_ARG_REGEX
|
|
@@ -228,7 +219,7 @@ class Parser
|
|
|
228
219
|
|
|
229
220
|
opts[:desc] ||= desc
|
|
230
221
|
@long[opts[:long]] = name
|
|
231
|
-
@short[opts[:short]] = name if opts[:short]
|
|
222
|
+
@short[opts[:short]] = name if opts[:short] && opts[:short] != :none
|
|
232
223
|
@specs[name] = opts
|
|
233
224
|
@order << [:opt, name]
|
|
234
225
|
end
|
|
@@ -278,78 +269,6 @@ class Parser
|
|
|
278
269
|
@stop_on_unknown = true
|
|
279
270
|
end
|
|
280
271
|
|
|
281
|
-
## yield successive arg, parameter pairs
|
|
282
|
-
def each_arg args # :nodoc:
|
|
283
|
-
remains = []
|
|
284
|
-
i = 0
|
|
285
|
-
|
|
286
|
-
until i >= args.length
|
|
287
|
-
if @stop_words.member? args[i]
|
|
288
|
-
remains += args[i .. -1]
|
|
289
|
-
return remains
|
|
290
|
-
end
|
|
291
|
-
case args[i]
|
|
292
|
-
when /^--$/ # arg terminator
|
|
293
|
-
remains += args[(i + 1) .. -1]
|
|
294
|
-
return remains
|
|
295
|
-
when /^--(\S+?)=(\S+)$/ # long argument with equals
|
|
296
|
-
yield "--#{$1}", [$2]
|
|
297
|
-
i += 1
|
|
298
|
-
when /^--(\S+)$/ # long argument
|
|
299
|
-
params = collect_argument_parameters(args, i + 1)
|
|
300
|
-
unless params.empty?
|
|
301
|
-
num_params_taken = yield args[i], params
|
|
302
|
-
unless num_params_taken
|
|
303
|
-
if @stop_on_unknown
|
|
304
|
-
remains += args[i + 1 .. -1]
|
|
305
|
-
return remains
|
|
306
|
-
else
|
|
307
|
-
remains += params
|
|
308
|
-
end
|
|
309
|
-
end
|
|
310
|
-
i += 1 + num_params_taken
|
|
311
|
-
else # long argument no parameter
|
|
312
|
-
yield args[i], nil
|
|
313
|
-
i += 1
|
|
314
|
-
end
|
|
315
|
-
when /^-(\S+)$/ # one or more short arguments
|
|
316
|
-
shortargs = $1.split(//)
|
|
317
|
-
shortargs.each_with_index do |a, j|
|
|
318
|
-
if j == (shortargs.length - 1)
|
|
319
|
-
params = collect_argument_parameters(args, i + 1)
|
|
320
|
-
unless params.empty?
|
|
321
|
-
num_params_taken = yield "-#{a}", params
|
|
322
|
-
unless num_params_taken
|
|
323
|
-
if @stop_on_unknown
|
|
324
|
-
remains += args[i + 1 .. -1]
|
|
325
|
-
return remains
|
|
326
|
-
else
|
|
327
|
-
remains += params
|
|
328
|
-
end
|
|
329
|
-
end
|
|
330
|
-
i += 1 + num_params_taken
|
|
331
|
-
else # argument no parameter
|
|
332
|
-
yield "-#{a}", nil
|
|
333
|
-
i += 1
|
|
334
|
-
end
|
|
335
|
-
else
|
|
336
|
-
yield "-#{a}", nil
|
|
337
|
-
end
|
|
338
|
-
end
|
|
339
|
-
else
|
|
340
|
-
if @stop_on_unknown
|
|
341
|
-
remains += args[i .. -1]
|
|
342
|
-
return remains
|
|
343
|
-
else
|
|
344
|
-
remains << args[i]
|
|
345
|
-
i += 1
|
|
346
|
-
end
|
|
347
|
-
end
|
|
348
|
-
end
|
|
349
|
-
|
|
350
|
-
remains
|
|
351
|
-
end
|
|
352
|
-
|
|
353
272
|
## Parses the commandline. Typically called by Trollop::options.
|
|
354
273
|
def parse cmdline=ARGV
|
|
355
274
|
vals = {}
|
|
@@ -363,6 +282,8 @@ class Parser
|
|
|
363
282
|
vals[sym] = opts[:default]
|
|
364
283
|
end
|
|
365
284
|
|
|
285
|
+
resolve_default_short_options
|
|
286
|
+
|
|
366
287
|
## resolve symbols
|
|
367
288
|
given_args = {}
|
|
368
289
|
@leftovers = each_arg cmdline do |arg, params|
|
|
@@ -467,56 +388,6 @@ class Parser
|
|
|
467
388
|
vals
|
|
468
389
|
end
|
|
469
390
|
|
|
470
|
-
def parse_integer_parameter param, arg #:nodoc:
|
|
471
|
-
raise CommandlineError, "option '#{arg}' needs an integer" unless param =~ /^\d+$/
|
|
472
|
-
param.to_i
|
|
473
|
-
end
|
|
474
|
-
|
|
475
|
-
def parse_float_parameter param, arg #:nodoc:
|
|
476
|
-
raise CommandlineError, "option '#{arg}' needs a floating-point number" unless param =~ FLOAT_RE
|
|
477
|
-
param.to_f
|
|
478
|
-
end
|
|
479
|
-
|
|
480
|
-
def parse_io_parameter param, arg #:nodoc:
|
|
481
|
-
case param
|
|
482
|
-
when /^(stdin|-)$/i; $stdin
|
|
483
|
-
else
|
|
484
|
-
require 'open-uri'
|
|
485
|
-
begin
|
|
486
|
-
open param
|
|
487
|
-
rescue SystemCallError => e
|
|
488
|
-
raise CommandlineError, "file or url for option '#{arg}' cannot be opened: #{e.message}"
|
|
489
|
-
end
|
|
490
|
-
end
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
def collect_argument_parameters args, start_at #:nodoc:
|
|
494
|
-
params = []
|
|
495
|
-
pos = start_at
|
|
496
|
-
while args[pos] && args[pos] !~ PARAM_RE && !@stop_words.member?(args[pos]) do
|
|
497
|
-
params << args[pos]
|
|
498
|
-
pos += 1
|
|
499
|
-
end
|
|
500
|
-
params
|
|
501
|
-
end
|
|
502
|
-
|
|
503
|
-
def width #:nodoc:
|
|
504
|
-
@width ||=
|
|
505
|
-
if $stdout.tty?
|
|
506
|
-
begin
|
|
507
|
-
require 'curses'
|
|
508
|
-
Curses::init_screen
|
|
509
|
-
x = Curses::cols
|
|
510
|
-
Curses::close_screen
|
|
511
|
-
x
|
|
512
|
-
rescue Exception
|
|
513
|
-
80
|
|
514
|
-
end
|
|
515
|
-
else
|
|
516
|
-
80
|
|
517
|
-
end
|
|
518
|
-
end
|
|
519
|
-
|
|
520
391
|
## Print the help message to +stream+.
|
|
521
392
|
def educate stream=$stdout
|
|
522
393
|
width # just calculate it now; otherwise we have to be careful not to
|
|
@@ -525,7 +396,7 @@ class Parser
|
|
|
525
396
|
left = {}
|
|
526
397
|
@specs.each do |name, spec|
|
|
527
398
|
left[name] = "--#{spec[:long]}" +
|
|
528
|
-
(spec[:short] ? ", -#{spec[:short]}" : "") +
|
|
399
|
+
(spec[:short] && spec[:short] != :none ? ", -#{spec[:short]}" : "") +
|
|
529
400
|
case spec[:type]
|
|
530
401
|
when :flag; ""
|
|
531
402
|
when :int; " <i>"
|
|
@@ -580,7 +451,152 @@ class Parser
|
|
|
580
451
|
end
|
|
581
452
|
end
|
|
582
453
|
|
|
583
|
-
def
|
|
454
|
+
def width #:nodoc:
|
|
455
|
+
@width ||= if $stdout.tty?
|
|
456
|
+
begin
|
|
457
|
+
require 'curses'
|
|
458
|
+
Curses::init_screen
|
|
459
|
+
x = Curses::cols
|
|
460
|
+
Curses::close_screen
|
|
461
|
+
x
|
|
462
|
+
rescue Exception
|
|
463
|
+
80
|
|
464
|
+
end
|
|
465
|
+
else
|
|
466
|
+
80
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
def wrap str, opts={} # :nodoc:
|
|
471
|
+
if str == ""
|
|
472
|
+
[""]
|
|
473
|
+
else
|
|
474
|
+
str.split("\n").map { |s| wrap_line s, opts }.flatten
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
private
|
|
479
|
+
|
|
480
|
+
## yield successive arg, parameter pairs
|
|
481
|
+
def each_arg args
|
|
482
|
+
remains = []
|
|
483
|
+
i = 0
|
|
484
|
+
|
|
485
|
+
until i >= args.length
|
|
486
|
+
if @stop_words.member? args[i]
|
|
487
|
+
remains += args[i .. -1]
|
|
488
|
+
return remains
|
|
489
|
+
end
|
|
490
|
+
case args[i]
|
|
491
|
+
when /^--$/ # arg terminator
|
|
492
|
+
remains += args[(i + 1) .. -1]
|
|
493
|
+
return remains
|
|
494
|
+
when /^--(\S+?)=(\S+)$/ # long argument with equals
|
|
495
|
+
yield "--#{$1}", [$2]
|
|
496
|
+
i += 1
|
|
497
|
+
when /^--(\S+)$/ # long argument
|
|
498
|
+
params = collect_argument_parameters(args, i + 1)
|
|
499
|
+
unless params.empty?
|
|
500
|
+
num_params_taken = yield args[i], params
|
|
501
|
+
unless num_params_taken
|
|
502
|
+
if @stop_on_unknown
|
|
503
|
+
remains += args[i + 1 .. -1]
|
|
504
|
+
return remains
|
|
505
|
+
else
|
|
506
|
+
remains += params
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
i += 1 + num_params_taken
|
|
510
|
+
else # long argument no parameter
|
|
511
|
+
yield args[i], nil
|
|
512
|
+
i += 1
|
|
513
|
+
end
|
|
514
|
+
when /^-(\S+)$/ # one or more short arguments
|
|
515
|
+
shortargs = $1.split(//)
|
|
516
|
+
shortargs.each_with_index do |a, j|
|
|
517
|
+
if j == (shortargs.length - 1)
|
|
518
|
+
params = collect_argument_parameters(args, i + 1)
|
|
519
|
+
unless params.empty?
|
|
520
|
+
num_params_taken = yield "-#{a}", params
|
|
521
|
+
unless num_params_taken
|
|
522
|
+
if @stop_on_unknown
|
|
523
|
+
remains += args[i + 1 .. -1]
|
|
524
|
+
return remains
|
|
525
|
+
else
|
|
526
|
+
remains += params
|
|
527
|
+
end
|
|
528
|
+
end
|
|
529
|
+
i += 1 + num_params_taken
|
|
530
|
+
else # argument no parameter
|
|
531
|
+
yield "-#{a}", nil
|
|
532
|
+
i += 1
|
|
533
|
+
end
|
|
534
|
+
else
|
|
535
|
+
yield "-#{a}", nil
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
else
|
|
539
|
+
if @stop_on_unknown
|
|
540
|
+
remains += args[i .. -1]
|
|
541
|
+
return remains
|
|
542
|
+
else
|
|
543
|
+
remains << args[i]
|
|
544
|
+
i += 1
|
|
545
|
+
end
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
remains
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
def parse_integer_parameter param, arg
|
|
553
|
+
raise CommandlineError, "option '#{arg}' needs an integer" unless param =~ /^\d+$/
|
|
554
|
+
param.to_i
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
def parse_float_parameter param, arg
|
|
558
|
+
raise CommandlineError, "option '#{arg}' needs a floating-point number" unless param =~ FLOAT_RE
|
|
559
|
+
param.to_f
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
def parse_io_parameter param, arg
|
|
563
|
+
case param
|
|
564
|
+
when /^(stdin|-)$/i; $stdin
|
|
565
|
+
else
|
|
566
|
+
require 'open-uri'
|
|
567
|
+
begin
|
|
568
|
+
open param
|
|
569
|
+
rescue SystemCallError => e
|
|
570
|
+
raise CommandlineError, "file or url for option '#{arg}' cannot be opened: #{e.message}"
|
|
571
|
+
end
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
def collect_argument_parameters args, start_at
|
|
576
|
+
params = []
|
|
577
|
+
pos = start_at
|
|
578
|
+
while args[pos] && args[pos] !~ PARAM_RE && !@stop_words.member?(args[pos]) do
|
|
579
|
+
params << args[pos]
|
|
580
|
+
pos += 1
|
|
581
|
+
end
|
|
582
|
+
params
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
def resolve_default_short_options
|
|
586
|
+
@order.each do |type, name|
|
|
587
|
+
next unless type == :opt
|
|
588
|
+
opts = @specs[name]
|
|
589
|
+
next if opts[:short]
|
|
590
|
+
|
|
591
|
+
c = opts[:long].split(//).find { |c| c !~ INVALID_SHORT_ARG_REGEX && !@short.member?(c) }
|
|
592
|
+
raise ArgumentError, "can't generate a default short option name for #{opts[:long].inspect}: out of unique characters" unless c
|
|
593
|
+
|
|
594
|
+
opts[:short] = c
|
|
595
|
+
@short[c] = name
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
def wrap_line str, opts={}
|
|
584
600
|
prefix = opts[:prefix] || 0
|
|
585
601
|
width = opts[:width] || (self.width - 1)
|
|
586
602
|
start = 0
|
|
@@ -600,17 +616,9 @@ class Parser
|
|
|
600
616
|
ret
|
|
601
617
|
end
|
|
602
618
|
|
|
603
|
-
def wrap str, opts={} # :nodoc:
|
|
604
|
-
if str == ""
|
|
605
|
-
[""]
|
|
606
|
-
else
|
|
607
|
-
str.split("\n").map { |s| wrap_line s, opts }.flatten
|
|
608
|
-
end
|
|
609
|
-
end
|
|
610
|
-
|
|
611
619
|
## instance_eval but with ability to handle block arguments
|
|
612
620
|
## thanks to why: http://redhanded.hobix.com/inspect/aBlockCostume.html
|
|
613
|
-
def cloaker &b
|
|
621
|
+
def cloaker &b
|
|
614
622
|
(class << self; self; end).class_eval do
|
|
615
623
|
define_method :cloaker_, &b
|
|
616
624
|
meth = instance_method :cloaker_
|
|
@@ -704,4 +712,3 @@ end
|
|
|
704
712
|
module_function :options, :die
|
|
705
713
|
|
|
706
714
|
end # module
|
|
707
|
-
|
data/test/test_trollop.rb
CHANGED
|
@@ -173,7 +173,6 @@ class Trollop < ::Test::Unit::TestCase
|
|
|
173
173
|
@p.opt "arg"
|
|
174
174
|
@p.opt "arg2"
|
|
175
175
|
@p.opt "arg3"
|
|
176
|
-
assert_raise(ArgumentError) { @p.opt "gra" }
|
|
177
176
|
opts = @p.parse %w(-a -g)
|
|
178
177
|
assert_equal true, opts["arg"]
|
|
179
178
|
assert_equal false, opts["arg2"]
|
|
@@ -199,8 +198,8 @@ class Trollop < ::Test::Unit::TestCase
|
|
|
199
198
|
@p.opt :arg1 # auto: a
|
|
200
199
|
@p.opt :arg2 # auto: r
|
|
201
200
|
@p.opt :arg3 # auto: g
|
|
202
|
-
|
|
203
|
-
|
|
201
|
+
@p.opt :arg4 # auto: uh oh!
|
|
202
|
+
assert_raises(ArgumentError) { @p.parse [] }
|
|
204
203
|
end
|
|
205
204
|
|
|
206
205
|
def test_short_can_be_nothing
|
|
@@ -839,7 +838,7 @@ EOM
|
|
|
839
838
|
@p.opt :global_param, "Global parameter", :short => "-p", :default => 5
|
|
840
839
|
@p.stop_on_unknown
|
|
841
840
|
|
|
842
|
-
expected_opts = { :global_flag =>true, :help =>false, :global_param =>5 }
|
|
841
|
+
expected_opts = { :global_flag => true, :help => false, :global_param => 5, :global_flag_given => true }
|
|
843
842
|
expected_leftovers = [ "my_subcommand", "-c" ]
|
|
844
843
|
|
|
845
844
|
assert_parses_correctly @p, %w(--global-flag my_subcommand -c), \
|
|
@@ -847,7 +846,7 @@ EOM
|
|
|
847
846
|
assert_parses_correctly @p, %w(-g my_subcommand -c), \
|
|
848
847
|
expected_opts, expected_leftovers
|
|
849
848
|
|
|
850
|
-
expected_opts = { :global_flag =>false, :help =>false, :global_param =>5 }
|
|
849
|
+
expected_opts = { :global_flag => false, :help => false, :global_param => 5, :global_param_given => true }
|
|
851
850
|
expected_leftovers = [ "my_subcommand", "-c" ]
|
|
852
851
|
|
|
853
852
|
assert_parses_correctly @p, %w(-p 5 my_subcommand -c), \
|
|
@@ -951,6 +950,46 @@ EOM
|
|
|
951
950
|
opts = @p.parse %w()
|
|
952
951
|
assert_equal ["potato", "rhubarb"], opts[:arg4]
|
|
953
952
|
end
|
|
953
|
+
|
|
954
|
+
def test_given_keys
|
|
955
|
+
@p.opt :arg1
|
|
956
|
+
@p.opt :arg2
|
|
957
|
+
|
|
958
|
+
opts = @p.parse %w(--arg1)
|
|
959
|
+
assert opts[:arg1_given]
|
|
960
|
+
assert !opts[:arg2_given]
|
|
961
|
+
|
|
962
|
+
opts = @p.parse %w(--arg2)
|
|
963
|
+
assert !opts[:arg1_given]
|
|
964
|
+
assert opts[:arg2_given]
|
|
965
|
+
|
|
966
|
+
opts = @p.parse []
|
|
967
|
+
assert !opts[:arg1_given]
|
|
968
|
+
assert !opts[:arg2_given]
|
|
969
|
+
|
|
970
|
+
opts = @p.parse %w(--arg1 --arg2)
|
|
971
|
+
assert opts[:arg1_given]
|
|
972
|
+
assert opts[:arg2_given]
|
|
973
|
+
end
|
|
974
|
+
|
|
975
|
+
def test_default_shorts_assigned_only_after_user_shorts
|
|
976
|
+
@p.opt :aab, "aaa" # should be assigned to -b
|
|
977
|
+
@p.opt :ccd, "bbb" # should be assigned to -d
|
|
978
|
+
@p.opt :user1, "user1", :short => 'a'
|
|
979
|
+
@p.opt :user2, "user2", :short => 'c'
|
|
980
|
+
|
|
981
|
+
opts = @p.parse %w(-a -b)
|
|
982
|
+
assert opts[:user1]
|
|
983
|
+
assert !opts[:user2]
|
|
984
|
+
assert opts[:aab]
|
|
985
|
+
assert !opts[:ccd]
|
|
986
|
+
|
|
987
|
+
opts = @p.parse %w(-c -d)
|
|
988
|
+
assert !opts[:user1]
|
|
989
|
+
assert opts[:user2]
|
|
990
|
+
assert !opts[:aab]
|
|
991
|
+
assert opts[:ccd]
|
|
992
|
+
end
|
|
954
993
|
end
|
|
955
994
|
|
|
956
995
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: trollop
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: "1.
|
|
4
|
+
version: "1.12"
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- William Morgan
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-01-
|
|
12
|
+
date: 2009-01-30 00:00:00 -08:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|