slop 1.9.0 → 1.9.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|