slop 1.9.0 → 1.9.1

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