slop 1.9.0 → 1.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/CHANGES.md +8 -2
  2. data/lib/slop.rb +45 -20
  3. data/slop.gemspec +1 -1
  4. data/test/slop_test.rb +7 -2
  5. metadata +4 -4
data/CHANGES.md CHANGED
@@ -1,5 +1,11 @@
1
- TBA
2
- ---
1
+ 1.9.1 (2011-06-16)
2
+ ------------------
3
+
4
+ * Ensure optional items with no arguments still return true when searching
5
+ for presence
6
+
7
+ 1.9.0 (2011-06-15)
8
+ ------------------
3
9
 
4
10
  * Add command completion and support for an error message when ambiguous
5
11
  commands are used
data/lib/slop.rb CHANGED
@@ -16,7 +16,7 @@ class Slop
16
16
  class InvalidOptionError < RuntimeError; end
17
17
 
18
18
  # @return [String] The current version string
19
- VERSION = '1.9.0'
19
+ VERSION = '1.9.1'
20
20
 
21
21
  # Parses the items from a CLI format into a friendly object
22
22
  #
@@ -65,7 +65,7 @@ class Slop
65
65
  attr_accessor :longest_flag
66
66
 
67
67
  # @return [Array] A list of aliases this command uses
68
- attr_reader :aliases
68
+ attr_accessor :aliases
69
69
 
70
70
  # @option opts [Boolean] :help
71
71
  # * Automatically add the `help` option
@@ -123,7 +123,6 @@ class Slop
123
123
  @longest_flag = 0
124
124
  @invalid_options = []
125
125
 
126
- @aliases = Array(sloptions[:aliases] || sloptions[:alias])
127
126
  @banner = sloptions[:banner]
128
127
  @strict = sloptions[:strict]
129
128
  @ignore_case = sloptions[:ignore_case]
@@ -266,18 +265,18 @@ class Slop
266
265
  # # ARGV is `create -v`
267
266
  # opts.commands[:create].verbose? #=> true
268
267
  # @since 1.5.0
268
+ # @raise [ArgumentError] When this command already exists
269
269
  # @return [Slop] a new instance of Slop namespaced to +label+
270
270
  def command(label, options={}, &block)
271
271
  if @commands[label]
272
272
  raise ArgumentError, "command `#{label}` already exists"
273
273
  end
274
274
 
275
- slop = Slop.new @sloptions.merge options
275
+ slop = Slop.new @sloptions.merge(options)
276
+ slop.aliases = Array(options.delete(:aliases) || options.delete(:alias))
276
277
  @commands[label] = slop
277
278
 
278
- Array(options[:aliases] || options[:alias]).each do |a|
279
- @commands[a] = @commands[label]
280
- end
279
+ slop.aliases.each { |a| @commands[a] = @commands[label] }
281
280
 
282
281
  if block_given?
283
282
  block.arity == 1 ? yield(slop) : slop.instance_eval(&block)
@@ -363,7 +362,7 @@ class Slop
363
362
  # @return [Boolean] true if this option is present, false otherwise
364
363
  def method_missing(meth, *args, &block)
365
364
  super unless meth.to_s[-1, 1] == '?'
366
- present = present? meth.to_s.chomp '?'
365
+ present = present? meth.to_s.chomp('?')
367
366
 
368
367
  (class << self; self; end).instance_eval do
369
368
  define_method(meth) { present }
@@ -381,7 +380,7 @@ class Slop
381
380
  # @since 1.5.0
382
381
  # @return [Boolean] true if this option is present, false otherwise
383
382
  def present?(option_name)
384
- !!get(option_name)
383
+ @options[option_name] && @options[option_name].count > 0
385
384
  end
386
385
 
387
386
  # Returns the banner followed by available options listed on the next line
@@ -406,6 +405,8 @@ class Slop
406
405
  end
407
406
  alias :help :to_s
408
407
 
408
+ # @return [String] This Slop object will options and configuration
409
+ # settings revealed
409
410
  def inspect
410
411
  "#<Slop config_options=#{@sloptions.inspect}\n " +
411
412
  options.map(&:inspect).join("\n ") + "\n>"
@@ -428,6 +429,14 @@ class Slop
428
429
  end
429
430
  end
430
431
 
432
+ # traverse through the list of items sent to parse() or parse!() and
433
+ # attempt to do the following:
434
+ #
435
+ # * Find an option object
436
+ # * Assign an argument to this option
437
+ # * Validate an option and/or argument depending on configuration options
438
+ # * Remove non-parsed items if `delete` is true
439
+ # * Yield any non-options to the block (if one is given)
431
440
  def parse_items(items, delete=false, &block)
432
441
  if items.empty? && @on_empty.respond_to?(:call)
433
442
  @on_empty.call self
@@ -460,7 +469,7 @@ class Slop
460
469
  end
461
470
 
462
471
  if option
463
- option.count += 1
472
+ option.count += 1 unless item[/\A--no-/]
464
473
  trash << index
465
474
  next if option.forced
466
475
  option.argument_value = true
@@ -469,7 +478,7 @@ class Slop
469
478
  argument ||= items.at(index + 1)
470
479
  trash << index + 1
471
480
 
472
- if !option.accepts_optional_argument? && flag?(argument)
481
+ if !option.accepts_optional_argument? && argument =~ /\A--?[a-zA-Z][a-zA-Z0-9_-]*\z/
473
482
  raise MissingArgumentError, "'#{option.key}' expects an argument, none given"
474
483
  end
475
484
 
@@ -513,6 +522,11 @@ class Slop
513
522
  raise InvalidOptionError, message
514
523
  end
515
524
 
525
+ # if multiple_switches is enabled, this method filters through an items
526
+ # characters and attempts to find an Option object for each flag.
527
+ #
528
+ # Raises if a flag expects an argument or strict mode is enabled and a
529
+ # flag was not found
516
530
  def enable_multiple_switches(item)
517
531
  item[1..-1].each_char do |switch|
518
532
  if option = @options[switch]
@@ -520,20 +534,19 @@ class Slop
520
534
  raise MissingArgumentError, "'-#{switch}' expects an argument, used in multiple_switch context"
521
535
  end
522
536
  option.argument_value = true
537
+ option.count += 1
523
538
  else
524
539
  raise InvalidOptionError, "Unknown option '-#{switch}'" if @strict
525
540
  end
526
541
  end
527
542
  end
528
543
 
544
+ # wrap and indent a string, used to wrap and indent a description string
529
545
  def wrap_and_indent(string, width, indentation)
530
- # Wrap and indent each paragraph
531
546
  string.lines.map do |paragraph|
532
- # Initialize
533
547
  lines = []
534
548
  line = ''
535
549
 
536
- # Split into words
537
550
  paragraph.split(/\s/).each do |word|
538
551
  # Begin new line if it's too long
539
552
  if (line + ' ' + word).length >= width
@@ -546,11 +559,13 @@ class Slop
546
559
  end
547
560
  lines << line
548
561
 
549
- # Join lines
550
562
  lines.map { |l| ' '*indentation + l }.join("\n")
551
563
  end.join("\n")
552
564
  end
553
565
 
566
+ # attempt to extract an option from an argument, this method allows us
567
+ # to parse things like 'foo=bar' and '--no-value' for negative values
568
+ # returns an array of the Option object and an argument if one was found
554
569
  def extract_option(item, flag)
555
570
  if item[0, 1] == '-'
556
571
  option = @options[flag]
@@ -575,6 +590,10 @@ class Slop
575
590
  [option, argument]
576
591
  end
577
592
 
593
+ # attempt to execute a command if one exists, returns a positive (tru-ish)
594
+ # result if the command was found and executed. If completion is enabled
595
+ # and a flag is found to be ambiguous, this method prints an error message
596
+ # to the @io object informing the user
578
597
  def execute_command(items, delete)
579
598
  str = items[0]
580
599
 
@@ -601,13 +620,23 @@ class Slop
601
620
  end
602
621
  end
603
622
 
623
+ # If autocreation is enabled this method simply generates an option
624
+ # and add's it to the existing list of options
604
625
  def autocreate(flag, index, items)
605
626
  return if present? flag
606
627
  short, long = clean_options Array(flag)
607
628
  arg = (items[index + 1] && items[index + 1] !~ /\A--?/)
608
- @options << Option.new(self, short, long, nil, arg, {})
629
+ option = Option.new(self, short, long, nil, arg, {})
630
+ option.count = 1
631
+ @options << option
609
632
  end
610
633
 
634
+ # Clean up arguments sent to `on` and return a list of 5 elements:
635
+ # * short flag (or nil)
636
+ # * long flag (or nil)
637
+ # * description (or nil)
638
+ # * true/false if this option takes an argument or not
639
+ # * extra options (ie: :as, :optional, and :help)
611
640
  def clean_options(args)
612
641
  options = []
613
642
  extras = {}
@@ -640,8 +669,4 @@ class Slop
640
669
  options.push @arguments ? true : (args.shift ? true : false)
641
670
  options.push extras
642
671
  end
643
-
644
- def flag?(str)
645
- str =~ /\A--?[a-zA-Z][a-zA-Z0-9_-]*\z/
646
- end
647
672
  end
data/slop.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'slop'
3
- s.version = '1.9.0'
3
+ s.version = '1.9.1'
4
4
  s.summary = 'Option gathering made easy'
5
5
  s.description = 'A simple DSL for gathering options and parsing the command line'
6
6
  s.author = 'Lee Jarvis'
data/test/slop_test.rb CHANGED
@@ -291,11 +291,16 @@ class SlopTest < TestCase
291
291
  end
292
292
 
293
293
  test 'options are present' do
294
- opts = Slop.new { on :f, 'foo-bar'; on :b, 'bar-baz' }
295
- opts.parse %w/--foo-bar/
294
+ opts = Slop.new do
295
+ on :f, 'foo-bar'
296
+ on :b, 'bar-baz'
297
+ on :h, :optional => true
298
+ end
299
+ opts.parse %w/--foo-bar -h/
296
300
 
297
301
  assert opts.present?('foo-bar')
298
302
  refute opts.present?('bar-baz')
303
+ assert opts.present?(:h)
299
304
  end
300
305
 
301
306
  test 'raises if an option expects an argument and none is given' do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slop
3
3
  version: !ruby/object:Gem::Version
4
- hash: 51
4
+ hash: 49
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 9
9
- - 0
10
- version: 1.9.0
9
+ - 1
10
+ version: 1.9.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Lee Jarvis
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-15 00:00:00 +01:00
18
+ date: 2011-06-16 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies: []
21
21