slop 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 52a2290f6608ad9ab25b6b4b07dd6ec213421edf
4
- data.tar.gz: f752d959151a6f15f978922b389c2952553dfbc9
3
+ metadata.gz: 2621271dc1f31b8d8eac5c0f71169a921768b508
4
+ data.tar.gz: 9f0bbcdf7a7adc210d7f6064e5f86545c2cd0a03
5
5
  SHA512:
6
- metadata.gz: c6d233481d6ce8340a7ee563fb615187f3152f27211bf00f07ab006ec140d7f61ab427c92c3cb6a228351494ad5a7a5c8ee65d297af9f42c888d61bf240c4b6c
7
- data.tar.gz: 97fcb2ff7f34071efa6b0b5091c6cc6058cc0c1d06e7f9669a27df4afb924fe083b3b1813cebfc3b761911c1d7230a95720ef8a298dfd645dfd1f99d9403a5c4
6
+ metadata.gz: 4748eb96ea76d2bbd0f7610cea52af99fbba605f4944924aba7e38223ee0b6e0298b898173ba6a5100a171e7b5c2aa6bfae4b636c64fda072bd9df6489333ad3
7
+ data.tar.gz: 778e986eea0c1ce8cd712b71edc4f0311eddbcc4ca142dabfe84b15508959de917ccbee17f82968c35465af93f9f5709de07387dde508151b0c97ff2742626ea
data/.travis.yml CHANGED
@@ -1,5 +1,8 @@
1
1
  rvm:
2
2
  - 2.0.0
3
+ - 2.1
4
+ - 2.2
5
+ - rbx-2
3
6
  notifications:
4
7
  email:
5
8
  on_success: change
data/CHANGELOG.md ADDED
@@ -0,0 +1,27 @@
1
+ Changelog
2
+ =========
3
+
4
+ v4.1.0 (2015-04-18)
5
+ -------------------
6
+
7
+ Features:
8
+ * Support for FloatOption #156 (Rick Hull)
9
+ * Support for `limit` config to ArrayOption.
10
+ * Support for `tail` config to add options to the bottom of
11
+ the help text.
12
+ * Add explicit setter (#[]=) to Result class. #162
13
+ * Implement flag gettings for UnknownOption and MissingArgument
14
+ error classes. #165 (sigurdsvela)
15
+
16
+ Minor enhancements:
17
+ * Reset parser every time `parse` is called.
18
+
19
+ Bug fixes:
20
+ * Remove "--" from unprocessed arguments #157 (David Rodríguez).
21
+
22
+ v4.0.0 (2014-12-27)
23
+ -------------------
24
+
25
+ Features:
26
+ * Rebuilt from the ground up. See the v3 changelog for all existing
27
+ changes: https://github.com/leejarvis/slop/blob/v3/CHANGES.md
data/README.md CHANGED
@@ -46,6 +46,7 @@ Built in Option types are as follows:
46
46
  o.string #=> Slop::StringOption, expects an argument
47
47
  o.bool #=> Slop::BoolOption, no argument, aliased to BooleanOption
48
48
  o.integer #=> Slop::IntegerOption, expects an argument, aliased to IntOption
49
+ o.float #=> Slop::FloatOption, expects an argument
49
50
  o.array #=> Slop::ArrayOption, expects an argument
50
51
  o.null #=> Slop::NullOption, no argument and ignored from `to_hash`
51
52
  o.on #=> alias for o.null
@@ -248,3 +249,85 @@ As of version 4, Slop does not have built in support for git-style subcommands.
248
249
  You can use version 3 of Slop (see `v3` branch). I also expect there to be some
249
250
  external libraries released soon that wrap around Slop to provide support for
250
251
  this feature. I'll update this document when that happens.
252
+
253
+ Upgrading from version 3
254
+ ------------------------
255
+
256
+ Slop v4 is completely non-backwards compatible. The code has been rewritten
257
+ from the group up. If you're already using version 3 you have *have* to update
258
+ your code to use version 4. Here's an overview of the more fundamental changes:
259
+
260
+ #### No more `instance_eval`
261
+
262
+ Before:
263
+
264
+ ```ruby
265
+ Slop.parse do
266
+ on 'v', 'version' do
267
+ puts VERSION
268
+ end
269
+ end
270
+ ```
271
+
272
+ After:
273
+
274
+ ```ruby
275
+ Slop.parse do |o|
276
+ o.on '-v', '--version' do
277
+ puts VERSION
278
+ end
279
+ end
280
+ ```
281
+
282
+ #### No more `as` for option types
283
+
284
+ Instead, the type is declared in the method call. Before:
285
+
286
+ ```ruby
287
+ on 'port=', as: Integer
288
+ ```
289
+
290
+ After:
291
+
292
+ ```ruby
293
+ o.int '--port' # or integer
294
+ ```
295
+
296
+ See the custom types section of the document.
297
+
298
+ #### No more trailing `=`
299
+
300
+ Instead, the "does this option expect an argument" question is answered by
301
+ the option type (i.e `on` and `bool` options do not expect arguments, all
302
+ others do. They handle type conversion, too.
303
+
304
+ #### Hyphens are required
305
+
306
+ This was a hard decision to make, but you must provide prefixed hyphens when
307
+ declaring your flags. This makes the underlying code much nicer and much less
308
+ ambiguous, which leads to less error prone code. It also means you can easily
309
+ support single hyphen prefix for a long flag, i.e `-hostname` which you
310
+ could not do before. It also provides a hidden feature, which is infinity flag
311
+ aliases: `o.string '-f', '-x', '--foo', '--bar', 'this is insane'`
312
+
313
+ #### Strict is now on by default
314
+
315
+ v3 had a `strict` option. v4 has no such option, and to suppress errors you can
316
+ instead provide the `suppress_errors: true` option to Slop.
317
+
318
+ #### No more parse!
319
+
320
+ Where v3 has both `Slop.parse` and `Slop.parse!`, v4 only has `parse`. The
321
+ former was used to decide whether Slop should or should not mutate the
322
+ original args (usually ARGV). This is almost never what you want, and it
323
+ can lead to confusion. Instead, `Slop::Result` provides an `arguments`
324
+ methods:
325
+
326
+ ```ruby
327
+ opts = Slop.parse do |o|
328
+ o.string '--hostname', '...'
329
+ end
330
+
331
+ # ARGV is "hello --hostname foo bar"
332
+ p opts.arguments #=> ["hello", "bar"]
333
+ ```
data/lib/slop.rb CHANGED
@@ -6,8 +6,7 @@ require 'slop/types'
6
6
  require 'slop/error'
7
7
 
8
8
  module Slop
9
- # The current version of Slop, of course.
10
- VERSION = '4.0.0'
9
+ VERSION = '4.1.0'
11
10
 
12
11
  # Parse an array of options (defaults to ARGV). Accepts an
13
12
  # optional hash of configuration options and block.
data/lib/slop/error.rb CHANGED
@@ -12,9 +12,24 @@ module Slop
12
12
  # executed without one. Suppress with the `suppress_errors`
13
13
  # config option.
14
14
  class MissingArgument < Error
15
+ attr_reader :flags
16
+
17
+ # Get all the flags that matches
18
+ # the option with the missing argument
19
+ def initialize(msg, flags)
20
+ super(msg)
21
+ @flags = flags
22
+ end
15
23
  end
16
24
 
17
25
  # Raised when an unknown option is parsed. Suppress
18
26
  # with the `suppress_errors` config option.
19
- class UnknownOption < Error; end
27
+ class UnknownOption < Error
28
+ attr_reader :flag
29
+
30
+ def initialize(msg, flag)
31
+ super(msg)
32
+ @flag = flag
33
+ end
34
+ end
20
35
  end
data/lib/slop/option.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  module Slop
2
2
  class Option
3
3
  DEFAULT_CONFIG = {
4
- help: true
4
+ help: true,
5
+ tail: false,
5
6
  }
6
7
 
7
8
  # An Array of flags this option matches.
@@ -47,7 +48,7 @@ module Slop
47
48
  @count += 1
48
49
 
49
50
  if value.nil? && expects_argument? && !suppress_errors?
50
- raise Slop::MissingArgument, "missing argument for #{flag}"
51
+ raise Slop::MissingArgument.new("missing argument for #{flag}", flags)
51
52
  end
52
53
 
53
54
  @value = call(value)
@@ -109,6 +110,17 @@ module Slop
109
110
  config[:help]
110
111
  end
111
112
 
113
+ # Returns true if this option should be added to the tail of the help text.
114
+ def tail?
115
+ config[:tail]
116
+ end
117
+
118
+ # Returns 1 if this option should be added to the tail of the help text.
119
+ # Used for sorting.
120
+ def tail
121
+ tail? ? 1 : -1
122
+ end
123
+
112
124
  # Returns the help text for this option (flags and description).
113
125
  def to_s(offset: 0)
114
126
  "%-#{offset}s %s" % [flag, desc]
data/lib/slop/options.rb CHANGED
@@ -101,7 +101,7 @@ module Slop
101
101
  str = config[:banner] ? "#{banner}\n" : ""
102
102
  len = longest_flag_length
103
103
 
104
- options.select(&:help?).each_with_index do |opt, i|
104
+ options.select(&:help?).sort_by(&:tail).each_with_index do |opt, i|
105
105
  # use the index to fetch an associated separator
106
106
  if sep = separators[i]
107
107
  str << "#{sep}\n"
data/lib/slop/parser.rb CHANGED
@@ -34,6 +34,8 @@ module Slop
34
34
  #
35
35
  # Returns a Slop::Result.
36
36
  def parse(strings)
37
+ reset # reset before every parse
38
+
37
39
  pairs = strings.each_cons(2).to_a
38
40
  # this ensures we still support the last string being a flag,
39
41
  # otherwise it'll only be used as an argument.
@@ -42,8 +44,13 @@ module Slop
42
44
  @arguments = strings.dup
43
45
 
44
46
  pairs.each do |flag, arg|
47
+ break if !flag
48
+
45
49
  # ignore everything after '--', flag or not
46
- break if !flag || flag == '--'
50
+ if flag == '--'
51
+ arguments.delete(flag)
52
+ break
53
+ end
47
54
 
48
55
  # support `foo=bar`
49
56
  if flag.include?("=")
@@ -95,7 +102,7 @@ module Slop
95
102
  try_process(last, arg) # send the argument to the last flag
96
103
  else
97
104
  if flag.start_with?("-") && !suppress_errors?
98
- raise UnknownOption, "unknown option `#{flag}'"
105
+ raise UnknownOption.new("unknown option `#{flag}'", "#{flag}")
99
106
  end
100
107
  end
101
108
  end
data/lib/slop/result.rb CHANGED
@@ -20,6 +20,17 @@ module Slop
20
20
  end
21
21
  alias get []
22
22
 
23
+ # Set the value for an option. Raises an ArgumentError if the option
24
+ # does not exist.
25
+ def []=(flag, value)
26
+ if o = option(flag)
27
+ o.value = value
28
+ else
29
+ raise ArgumentError, "no option with flag `#{flag}'"
30
+ end
31
+ end
32
+ alias set []=
33
+
23
34
  # Returns an Option if it exists. Ignores any prefixed hyphens.
24
35
  def option(flag)
25
36
  cleaned = -> (f) { f.to_s.sub(/\A--?/, '') }
data/lib/slop/types.rb CHANGED
@@ -1,10 +1,14 @@
1
1
  module Slop
2
+ # Cast the option argument to a String.
2
3
  class StringOption < Option
3
4
  def call(value)
4
5
  value.to_s
5
6
  end
6
7
  end
7
8
 
9
+ # Cast the option argument to true or false.
10
+ # Override default_value to default to false instead of nil.
11
+ # This option type does not expect an argument.
8
12
  class BoolOption < Option
9
13
  def call(_value)
10
14
  true
@@ -20,6 +24,7 @@ module Slop
20
24
  end
21
25
  BooleanOption = BoolOption
22
26
 
27
+ # Cast the option argument to an Integer.
23
28
  class IntegerOption < Option
24
29
  def call(value)
25
30
  value =~ /\A\d+\z/ && value.to_i
@@ -27,10 +32,20 @@ module Slop
27
32
  end
28
33
  IntOption = IntegerOption
29
34
 
35
+ # Cast the option argument to a Float.
36
+ class FloatOption < Option
37
+ def call(value)
38
+ # TODO: scientific notation, etc.
39
+ value =~ /\A\d*\.*\d+\z/ && value.to_f
40
+ end
41
+ end
42
+
43
+ # Collect multiple items into a single Array. Support
44
+ # arguments separated by commas or multiple occurences.
30
45
  class ArrayOption < Option
31
46
  def call(value)
32
47
  @value ||= []
33
- @value.concat value.split(delimiter)
48
+ @value.concat value.split(delimiter, limit)
34
49
  end
35
50
 
36
51
  def default_value
@@ -40,9 +55,14 @@ module Slop
40
55
  def delimiter
41
56
  config[:delimiter] || ","
42
57
  end
58
+
59
+ def limit
60
+ config[:limit] || 0
61
+ end
43
62
  end
44
63
 
45
- # an option that discards the return value
64
+ # An option that discards the return value, inherits from Bool
65
+ # since it does not expect an argument.
46
66
  class NullOption < BoolOption
47
67
  def null?
48
68
  true
data/test/error_test.rb CHANGED
@@ -7,6 +7,13 @@ describe Slop::MissingArgument do
7
7
  opts = Slop::Options.new
8
8
  opts.string "-n", "--name"
9
9
  assert_raises(Slop::MissingArgument) { opts.parse %w(--name) }
10
+
11
+ #Assert returns the argument question
12
+ begin
13
+ opts.parse %w(--name)
14
+ rescue Slop::MissingArgument => e
15
+ assert_equal(e.flags, ["-n", "--name"])
16
+ end
10
17
  end
11
18
 
12
19
  it "does not raise when errors are suppressed" do
@@ -21,6 +28,13 @@ describe Slop::UnknownOption do
21
28
  opts = Slop::Options.new
22
29
  opts.string "-n", "--name"
23
30
  assert_raises(Slop::UnknownOption) { opts.parse %w(--foo) }
31
+
32
+ #Assert returns the unknown option in question
33
+ begin
34
+ opts.parse %w(--foo)
35
+ rescue Slop::UnknownOption => e
36
+ assert_equal(e.flag, "--foo")
37
+ end
24
38
  end
25
39
 
26
40
  it "does not raise when errors are suppressed" do
data/test/options_test.rb CHANGED
@@ -75,5 +75,11 @@ describe Slop::Options do
75
75
  @options.on "-x", "something", help: false
76
76
  refute_match(/something/, @options.to_s)
77
77
  end
78
+
79
+ it "adds 'tail' options to the bottom of the help text" do
80
+ @options.on "-h", "--help", tail: true
81
+ @options.on "-f", "--foo"
82
+ assert_match(/^ -h, --help/, @options.to_s.lines.last)
83
+ end
78
84
  end
79
85
  end
data/test/parser_test.rb CHANGED
@@ -11,13 +11,13 @@ describe Slop::Parser do
11
11
  end
12
12
 
13
13
  it "ignores everything after --" do
14
- @parser.reset.parse %w(-v -- --name lee)
14
+ @parser.parse %w(-v -- --name lee)
15
15
  assert_equal [@verbose], @parser.used_options
16
16
  end
17
17
 
18
18
  it "parses flag=argument" do
19
19
  @options.integer "-p", "--port"
20
- @result.parser.reset.parse %w(--name=bob -p=123)
20
+ @result.parser.parse %w(--name=bob -p=123)
21
21
  assert_equal "bob", @result[:name]
22
22
  assert_equal 123, @result[:port]
23
23
  end
@@ -28,19 +28,19 @@ describe Slop::Parser do
28
28
  end
29
29
 
30
30
  it "parses boolean flags" do
31
- @result.parser.reset.parse %w(-qv)
31
+ @result.parser.parse %w(-qv)
32
32
  assert_equal true, @result.quiet?
33
33
  assert_equal true, @result.verbose?
34
34
  end
35
35
 
36
36
  it "sends the argument to the last flag" do
37
- @result.parser.reset.parse %w(-qvn foo)
37
+ @result.parser.parse %w(-qvn foo)
38
38
  assert_equal "foo", @result[:name]
39
39
  end
40
40
 
41
41
  it "doesn't screw up single hyphen long options" do
42
42
  @options.string "-host"
43
- @result.parser.reset.parse %w(-host localhost)
43
+ @result.parser.parse %w(-host localhost)
44
44
  assert_equal "localhost", @result[:host]
45
45
  end
46
46
  end
@@ -61,5 +61,10 @@ describe Slop::Parser do
61
61
  it "returns all unparsed arguments" do
62
62
  assert_equal %w(foo argument), @parser.arguments
63
63
  end
64
+
65
+ it "does not return --" do
66
+ @parser.parse %w(-v -- --name lee)
67
+ assert_equal %w(--name lee), @parser.arguments
68
+ end
64
69
  end
65
70
  end
data/test/result_test.rb CHANGED
@@ -22,27 +22,27 @@ describe Slop::Result do
22
22
  it "increments option count" do
23
23
  # test this here so it's more "full stack"
24
24
  assert_equal 1, @verbose.count
25
- @result.parser.reset.parse %w(-v --verbose)
25
+ @result.parser.parse %w(-v --verbose)
26
26
  assert_equal 2, @verbose.count
27
27
  end
28
28
 
29
29
  it "handles default values" do
30
30
  @options.string("--foo", default: "bar")
31
- @result.parser.reset.parse %w()
31
+ @result.parser.parse %w()
32
32
  assert_equal "bar", @result[:foo]
33
33
  end
34
34
 
35
35
  it "handles custom finishing" do
36
36
  @options.string "--foo"
37
37
  @options.reverse_everything "-r"
38
- @result.parser.reset.parse %w(-r --name lee --foo bar)
38
+ @result.parser.parse %w(-r --name lee --foo bar)
39
39
  assert_equal %w(eel rab), @result.to_hash.values_at(:name, :foo)
40
40
  end
41
41
 
42
42
  it "yields arguments to option blocks" do
43
43
  output = nil
44
44
  @options.string("--foo") { |v| output = v }
45
- @result.parser.reset.parse %w(--foo bar)
45
+ @result.parser.parse %w(--foo bar)
46
46
  assert_equal output, "bar"
47
47
  end
48
48
 
@@ -54,6 +54,20 @@ describe Slop::Result do
54
54
  end
55
55
  end
56
56
 
57
+ describe "#[]=" do
58
+ it "sets an options value" do
59
+ assert_equal "lee", @result["name"]
60
+ @result["name"] = "bob"
61
+ assert_equal "bob", @result[:name]
62
+ end
63
+
64
+ it "raises if an option isn't found" do
65
+ assert_raises ArgumentError do
66
+ @result["zomg"] = "something"
67
+ end
68
+ end
69
+ end
70
+
57
71
  describe "#method_missing" do
58
72
  it "checks if options have been used" do
59
73
  assert_equal true, @result.verbose?
data/test/types_test.rb CHANGED
@@ -29,16 +29,35 @@ describe Slop::IntegerOption do
29
29
  end
30
30
 
31
31
  it "returns nil for non-numbers by default" do
32
- @result.parser.reset.parse %w(--age hello)
32
+ @result.parser.parse %w(--age hello)
33
33
  assert_equal nil, @result[:age]
34
34
  end
35
35
  end
36
36
 
37
+ describe Slop::FloatOption do
38
+ before do
39
+ @options = Slop::Options.new
40
+ @apr = @options.float "--apr"
41
+ @apr_value = 2.9
42
+ @result = @options.parse %W(--apr #{@apr_value})
43
+ end
44
+
45
+ it "returns the value as a float" do
46
+ assert_equal @apr_value, @result[:apr]
47
+ end
48
+
49
+ it "returns nil for non-numbers by default" do
50
+ @result.parser.parse %w(--apr hello)
51
+ assert_equal nil, @result[:apr]
52
+ end
53
+ end
54
+
37
55
  describe Slop::ArrayOption do
38
56
  before do
39
57
  @options = Slop::Options.new
40
58
  @files = @options.array "--files"
41
59
  @delim = @options.array "-d", delimiter: ":"
60
+ @limit = @options.array "-l", limit: 2
42
61
  @result = @options.parse %w(--files foo.txt,bar.rb)
43
62
  end
44
63
 
@@ -51,14 +70,19 @@ describe Slop::ArrayOption do
51
70
  end
52
71
 
53
72
  it "collects multiple option values" do
54
- @result.parser.reset.parse %w(--files foo.txt --files bar.rb)
73
+ @result.parser.parse %w(--files foo.txt --files bar.rb)
55
74
  assert_equal %w(foo.txt bar.rb), @result[:files]
56
75
  end
57
76
 
58
77
  it "can use a custom delimiter" do
59
- @result.parser.reset.parse %w(-d foo.txt:bar.rb)
78
+ @result.parser.parse %w(-d foo.txt:bar.rb)
60
79
  assert_equal %w(foo.txt bar.rb), @result[:d]
61
80
  end
81
+
82
+ it "can use a custom limit" do
83
+ @result.parser.parse %w(-l foo,bar,baz)
84
+ assert_equal ["foo", "bar,baz"], @result[:l]
85
+ end
62
86
  end
63
87
 
64
88
  describe Slop::NullOption do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slop
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Jarvis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-27 00:00:00.000000000 Z
11
+ date: 2015-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -46,6 +46,7 @@ extra_rdoc_files: []
46
46
  files:
47
47
  - ".gitignore"
48
48
  - ".travis.yml"
49
+ - CHANGELOG.md
49
50
  - Gemfile
50
51
  - LICENSE
51
52
  - README.md
@@ -85,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
86
  version: '0'
86
87
  requirements: []
87
88
  rubyforge_project:
88
- rubygems_version: 2.2.2
89
+ rubygems_version: 2.4.5
89
90
  signing_key:
90
91
  specification_version: 4
91
92
  summary: Simple Lightweight Option Parsing