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.
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