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.
- data/CHANGES.md +8 -2
- data/lib/slop.rb +45 -20
- data/slop.gemspec +1 -1
- data/test/slop_test.rb +7 -2
- metadata +4 -4
data/CHANGES.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
-
|
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.
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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? &&
|
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
|
-
|
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
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
|
295
|
-
|
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:
|
4
|
+
hash: 49
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
version: 1.9.
|
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-
|
18
|
+
date: 2011-06-16 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|