trollop 1.11 → 1.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/History.txt +6 -0
  2. data/lib/trollop.rb +158 -151
  3. data/test/test_trollop.rb +44 -5
  4. metadata +2 -2
@@ -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.
@@ -5,7 +5,7 @@
5
5
 
6
6
  module Trollop
7
7
 
8
- VERSION = "1.11"
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
- case opts[:short]
202
- when nil
203
- c = opts[:long].split(//).find { |c| c !~ INVALID_SHORT_ARG_REGEX && !@short.member?(c) }
204
- raise ArgumentError, "can't generate a short option name for #{opts[:long].inspect}: out of unique characters" unless c
205
- c
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 wrap_line str, opts={} # :nodoc:
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 #:nodoc:
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
-
@@ -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
- assert_raises(ArgumentError) { @p.opt :arg4 }
203
- assert_nothing_raised { @p.opt :argf }
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.11"
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-29 00:00:00 -08:00
12
+ date: 2009-01-30 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15