trollop 1.11 → 1.12
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|