clasp-ruby 0.20.3 → 0.21.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5d4b4a9b8453b84575f693c6c1cf3d58c0af5999843c360295f799d60dc6b57d
4
+ data.tar.gz: 2089b0ead4ef6161d6cdda4d2129f2361567d434ea5aa3bcb257918093bdad7a
5
+ SHA512:
6
+ metadata.gz: c24103543ec9d290ae1731ab49a8937e02148b48e567c199ed1c3bb7a12edda0c892b4cd36eeb0fa6a8232fd9936db2fbae254e8db1a835bdf054a3df0f82af0
7
+ data.tar.gz: c1ea7534927c52c7c138da6da8f43c2c28f13222f35ff751c5d6b4a6aa456d18b6e655de5eaec3373d21aee864913d4ae6dc70d32e7d6e0b33815dc3fe40f57e
@@ -46,7 +46,8 @@
46
46
 
47
47
 
48
48
 
49
- require File.join(File.dirname(__FILE__), 'specifications.rb')
49
+ require File.join(File.dirname(__FILE__), 'specifications')
50
+ require File.join(File.dirname(__FILE__), 'util', 'value_parser')
50
51
 
51
52
  require 'yaml'
52
53
 
@@ -136,17 +137,40 @@ class Arguments
136
137
  # Class that represents a parsed option
137
138
  class OptionArgument
138
139
 
140
+ include ::CLASP::Util::ValueParser
141
+
139
142
  # @!visibility private
140
143
  #
141
144
  # [PRIVATE] This method is subject to changed between versions and
142
145
  # should not be called directly from application code
143
146
  def initialize(arg, given_index, given_name, resolved_name, argument_spec, given_hyphens, given_label, value, extras) # :nodoc:
144
147
 
145
- actual_value = value
148
+ resolved_value = nil
149
+
150
+ if argument_spec
151
+
152
+ case constraint = (argument_spec.constraint || {})
153
+ =begin
154
+ when Proc
155
+
156
+ resolved_value = value_from_Proc(constraint, value, arg, given_index, given_name, argument_spec, extras)
157
+ =end
158
+ when Hash
159
+
160
+ if constraint.empty?
161
+
162
+ resolved_value = (value || '').empty? ? argument_spec.default_value : value
163
+ else
164
+
165
+ resolved_value = value_from_Hash(constraint, value, arg, given_index, given_name, argument_spec, extras)
166
+ end
167
+ else
146
168
 
147
- if (value || '').empty? && argument_spec
169
+ warn "unexpected constraint on argument specification #{argument_spec} when parsing argument '#{arg}'"
170
+ end
171
+ else
148
172
 
149
- actual_value = argument_spec.default_value
173
+ resolved_value = value
150
174
  end
151
175
 
152
176
  @arg = arg
@@ -155,7 +179,8 @@ class Arguments
155
179
  @argument_specification = argument_spec
156
180
  @given_hyphens = given_hyphens
157
181
  @given_label = given_label
158
- @value = actual_value
182
+ @given_value = value
183
+ @value = resolved_value
159
184
  @name = resolved_name || given_name
160
185
  @extras = extras.nil? ? {} : extras
161
186
  end
@@ -172,7 +197,9 @@ class Arguments
172
197
  attr_reader :given_label
173
198
  # (String) The resolved name of the argument
174
199
  attr_reader :name
175
- # (String) The value of the option
200
+ # (String) The given value of the option
201
+ attr_reader :given_value
202
+ # (????) The value of the option, which may be of a type other than string subject to the option specification's constraint
176
203
  attr_reader :value
177
204
  # (Object, Hash) The extras associated with the argument
178
205
  attr_reader :extras
@@ -458,7 +485,7 @@ class Arguments
458
485
  values = []
459
486
 
460
487
  forced_value = false
461
- want_option_value = false
488
+ pending_option = nil
462
489
 
463
490
  argv.each_with_index do |arg, index|
464
491
 
@@ -563,15 +590,22 @@ class Arguments
563
590
 
564
591
  if argument_spec and argument_spec.is_a? CLASP::OptionSpecification and not value
565
592
 
566
- want_option_value = true
567
- options << OptionArgument.new(arg, index, given_name, resolved_name, argument_spec, hyphens.size, given_label, nil, argument_spec ? argument_spec.extras : nil)
593
+ pending_option = {
594
+
595
+ arg: arg,
596
+ index: index,
597
+ given_name: given_name,
598
+ resolved_name: resolved_name,
599
+ argument_spec: argument_spec,
600
+ hyphens_size: hyphens.size,
601
+ given_label: given_label,
602
+ extras: argument_spec ? argument_spec.extras : nil,
603
+ }
568
604
  elsif value
569
605
 
570
- want_option_value = false
571
606
  options << OptionArgument.new(arg, index, given_name, resolved_name, argument_spec, hyphens.size, given_label, value, argument_spec ? argument_spec.extras : nil)
572
607
  else
573
608
 
574
- want_option_value = false
575
609
  flags << FlagArgument.new(arg, index, given_name, resolved_name, argument_spec, hyphens.size, given_label, argument_spec ? argument_spec.extras : nil)
576
610
  end
577
611
 
@@ -579,20 +613,31 @@ class Arguments
579
613
  end
580
614
  end
581
615
 
582
- if want_option_value and not forced_value
616
+ if pending_option
583
617
 
584
- option = options[-1]
585
- option.instance_eval("@value='#{arg}'")
586
- want_option_value = false
587
- else
618
+ value = forced_value ? nil : arg
588
619
 
589
- arg = arg.dup
590
- arg_ix = ::Integer === index ? index : index.dup
620
+ options << OptionArgument.new(pending_option[:arg], pending_option[:index], pending_option[:given_name], pending_option[:resolved_name], pending_option[:argument_spec], pending_option[:hyphens_size], pending_option[:given_label], value, pending_option[:extras])
591
621
 
592
- arg.define_singleton_method(:given_index) { arg_ix }
622
+ pending_option = nil
593
623
 
594
- values << arg
624
+ next unless forced_value
595
625
  end
626
+
627
+ arg = arg.dup
628
+ arg_ix = ::Integer === index ? index : index.dup
629
+
630
+ arg.define_singleton_method(:given_index) { arg_ix }
631
+
632
+ values << arg
633
+ end
634
+
635
+ if pending_option
636
+
637
+ value = nil
638
+
639
+ options << OptionArgument.new(pending_option[:arg], pending_option[:index], pending_option[:given_name], pending_option[:resolved_name], pending_option[:argument_spec], pending_option[:hyphens_size], pending_option[:given_label], value, pending_option[:extras])
640
+
596
641
  end
597
642
 
598
643
  return flags, options, values
data/lib/clasp/clasp.rb CHANGED
@@ -50,6 +50,15 @@ require 'clasp/specifications'
50
50
  require 'clasp/cli'
51
51
  require 'clasp/version'
52
52
 
53
+ module CLASP
54
+
55
+ # TBC (but is a shorthand for calling +Arguments.new()+
56
+ def self.parse(argv = ARGV, specifications = nil, options = {})
57
+
58
+ return Arguments.new(argv, specifications, options)
59
+ end
60
+ end # module CLASP
61
+
53
62
  # ############################## end of file ############################# #
54
63
 
55
64
 
@@ -69,6 +69,8 @@ class FlagSpecification
69
69
  # - +aliases+ (+Array+) 0 or more strings specifying short-form or option-value aliases
70
70
  # - +help+ (+String+) The help string, which may be +nil+
71
71
  # - +extras+ An application-defined additional parameter. If +nil+, it is assigned an empty +Hash+
72
+ #
73
+ # *NOTE:* Users should prefer the +CLASP::Flag()+ method
72
74
  def initialize(name, aliases, help, extras = nil)
73
75
 
74
76
  @name = name
@@ -169,8 +171,11 @@ class OptionSpecification
169
171
  # - +default_value+ (+String+) The default value of the option, which will be used in the case where an option is specified without a value. May be +nil+
170
172
  # - +required+ (boolean) Whether the option is required. May be +nil+
171
173
  # - +required_message+ (::String) Message to be used when reporting that a required option is missing. May be +nil+ in which case a message of the form "<option-name> not specified; use --help for usage". If begins with the nul character ("\0"), then is used in the place of the <option-name> and placed into the rest of the standard form message
174
+ # - +constraint+ (Hash) Constraint to be applied to the parsed values of options matching this specification. NOTE: only integer constraints are supported in the current version
172
175
  # - +extras+ An application-defined additional parameter. If +nil+, it is assigned an empty +Hash+
173
- def initialize(name, aliases, help, values_range, default_value, required, required_message, extras = nil)
176
+ #
177
+ # *NOTE:* Users should prefer the +CLASP::Option()+ method
178
+ def initialize(name, aliases, help, values_range, default_value, required, required_message, constraint, extras = nil)
174
179
 
175
180
  @name = name
176
181
  @aliases = (aliases || []).select { |a| a and not a.empty? }
@@ -179,6 +184,7 @@ class OptionSpecification
179
184
  @default_value = default_value
180
185
  @required = required
181
186
  @required_message = nil
187
+ @constraint = constraint || {}
182
188
  @extras = extras || {}
183
189
 
184
190
  rm_name = nil
@@ -214,16 +220,17 @@ class OptionSpecification
214
220
  attr_reader :default_value
215
221
  # Indicates whether the option is required
216
222
  def required?; @required; end
217
- # The message to be used when reporting that a required option is
218
- # missing
223
+ # The message to be used when reporting that a required option is missing
219
224
  attr_reader :required_message
225
+ # The value constraint
226
+ attr_reader :constraint
220
227
  # The option's extras
221
228
  attr_reader :extras
222
229
 
223
230
  # String form of the option
224
231
  def to_s
225
232
 
226
- "{#{name}; aliases=#{aliases.join(', ')}; values_range=[ #{values_range.join(', ')} ]; default_value='#{default_value}'; help='#{help}'; required?=#{required?}; extras=#{extras}}"
233
+ "{#{name}; aliases=#{aliases.join(', ')}; values_range=[ #{values_range.join(', ')} ]; default_value='#{default_value}'; help='#{help}'; required?=#{required?}; required_message=#{required_message}; constraint=#{constraint}; extras=#{extras}}"
227
234
  end
228
235
 
229
236
  # @!visibility private
@@ -366,6 +373,7 @@ end
366
373
  # - +required+ (boolean) Whether the option is required. May be +nil+
367
374
  # - +required_message+ (::String) Message to be used when reporting that a required option is missing. May be +nil+ in which case a message of the form "<option-name> not specified; use --help for usage". If begins with the nul character ("\0"), then is used in the place of the <option-name> and placed into the rest of the standard form message
368
375
  # - +extras+ An application-defined additional parameter. If +nil+, it is assigned an empty +Hash+.
376
+ # - +constraint+ (Hash) Constraint to be applied to the parsed values of options matching this specification. NOTE: only integer constraints are supported in the current version
369
377
  # - +:values_range+ (::Array) An array defining the accepted values for the option
370
378
  # - +:values+ [DEPRECATED] Alternative to +:values_range+
371
379
  def CLASP.Option(name, options = {})
@@ -376,6 +384,7 @@ def CLASP.Option(name, options = {})
376
384
  default_value = nil
377
385
  required = false
378
386
  require_message = nil
387
+ constraint = nil
379
388
  extras = nil
380
389
 
381
390
  options.each do |k, v|
@@ -407,6 +416,9 @@ def CLASP.Option(name, options = {})
407
416
  when :extras
408
417
 
409
418
  extras = v
419
+ when :constraint
420
+
421
+ constraint = v
410
422
  else
411
423
 
412
424
  raise ArgumentError, "invalid option for option: '#{k}' => '#{v}'"
@@ -417,7 +429,7 @@ def CLASP.Option(name, options = {})
417
429
  end
418
430
  end
419
431
 
420
- CLASP::OptionSpecification.new(name, aliases, help, values_range, default_value, required, require_message, extras)
432
+ CLASP::OptionSpecification.new(name, aliases, help, values_range, default_value, required, require_message, constraint, extras)
421
433
  end
422
434
 
423
435
  def CLASP.Alias(name, *args)
@@ -0,0 +1,82 @@
1
+
2
+ # ######################################################################## #
3
+ # File: clasp/util/exceptions.rb
4
+ #
5
+ # Purpose: Exception classes
6
+ #
7
+ # Created: 20th April 2019
8
+ # Updated: 28th April 2019
9
+ #
10
+ # Home: http://github.com/synesissoftware/CLASP.Ruby
11
+ #
12
+ # Author: Matthew Wilson
13
+ #
14
+ # Copyright (c) 2019, Matthew Wilson and Synesis Software
15
+ # All rights reserved.
16
+ #
17
+ # Redistribution and use in source and binary forms, with or without
18
+ # modification, are permitted provided that the following conditions are
19
+ # met:
20
+ #
21
+ # * Redistributions of source code must retain the above copyright
22
+ # notice, this list of conditions and the following disclaimer.
23
+ #
24
+ # * Redistributions in binary form must reproduce the above copyright
25
+ # notice, this list of conditions and the following disclaimer in the
26
+ # documentation and/or other materials provided with the distribution.
27
+ #
28
+ # * Neither the names of the copyright holder nor the names of its
29
+ # contributors may be used to endorse or promote products derived from
30
+ # this software without specific prior written permission.
31
+ #
32
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
33
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
34
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
35
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
36
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
37
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
38
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
39
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
40
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
+ #
44
+ # ######################################################################## #
45
+
46
+
47
+
48
+ =begin
49
+ =end
50
+
51
+ module CLASP # :nodoc:
52
+
53
+ # Exceptions
54
+ module Exceptions
55
+
56
+ # Root exception for CLASP
57
+ class CLASPException < RuntimeError; end
58
+
59
+ # Root exception for value parsing
60
+ class ValueParserException < CLASPException; end
61
+
62
+ # No value specified (and no default value) for an option
63
+ class MissingValueException < ValueParserException; end
64
+
65
+ # Exception class indicating invalid values (as opposed to types)
66
+ class InvalidValueException < ValueParserException; end
67
+
68
+ # The given value could not be recognised as a (properly-formatted) number
69
+ class InvalidNumberException < InvalidValueException; end
70
+
71
+ # The given value could not be recognised as a (properly-formatted) integer
72
+ class InvalidIntegerException < InvalidNumberException; end
73
+
74
+ # The value was a valid integer but is out of range
75
+ class IntegerOutOfRangeException < InvalidValueException; end
76
+
77
+ end # module Exceptions
78
+ end # module CLASP
79
+
80
+ # ############################## end of file ############################# #
81
+
82
+
@@ -0,0 +1,222 @@
1
+
2
+ # ######################################################################## #
3
+ # File: clasp/util/value_parser.rb
4
+ #
5
+ # Purpose: Utility component for typed values
6
+ #
7
+ # Created: 20th April 2019
8
+ # Updated: 28th April 2019
9
+ #
10
+ # Home: http://github.com/synesissoftware/CLASP.Ruby
11
+ #
12
+ # Author: Matthew Wilson
13
+ #
14
+ # Copyright (c) 2019, Matthew Wilson and Synesis Software
15
+ # All rights reserved.
16
+ #
17
+ # Redistribution and use in source and binary forms, with or without
18
+ # modification, are permitted provided that the following conditions are
19
+ # met:
20
+ #
21
+ # * Redistributions of source code must retain the above copyright
22
+ # notice, this list of conditions and the following disclaimer.
23
+ #
24
+ # * Redistributions in binary form must reproduce the above copyright
25
+ # notice, this list of conditions and the following disclaimer in the
26
+ # documentation and/or other materials provided with the distribution.
27
+ #
28
+ # * Neither the names of the copyright holder nor the names of its
29
+ # contributors may be used to endorse or promote products derived from
30
+ # this software without specific prior written permission.
31
+ #
32
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
33
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
34
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
35
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
36
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
37
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
38
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
39
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
40
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
+ #
44
+ # ######################################################################## #
45
+
46
+
47
+
48
+ require File.join(File.dirname(__FILE__), 'exceptions')
49
+
50
+ =begin
51
+ =end
52
+
53
+ module CLASP # :nodoc:
54
+ module Util # :nodoc:
55
+
56
+ # @!visibility private
57
+ module ValueParser # :nodoc: all
58
+
59
+ module Internal_ # :nodoc: all
60
+
61
+ include Exceptions
62
+
63
+ def self.is_integer? type
64
+
65
+ h = {}
66
+
67
+ return true if Integer == type
68
+ return true if :integer == type
69
+
70
+ false
71
+ end
72
+
73
+ def self.obtain_integer value, constraint, argument_spec
74
+
75
+ # If no value is given, then use the default (and don't do any
76
+ # range testing)
77
+
78
+ if (value || '').empty?
79
+
80
+ def_value = argument_spec.default_value
81
+
82
+ if (def_value || '').to_s.empty?
83
+
84
+ msg = "no value specified for the option '#{argument_spec.name}', which has no default value either"
85
+
86
+ warn msg if $DEBUG
87
+
88
+ raise MissingValueException, msg
89
+ end
90
+
91
+ begin
92
+
93
+ return Integer(def_value)
94
+ rescue ArgumentError => x
95
+
96
+ msg = "default value '#{def_value}' specified for option '#{argument_spec.name}' that requires the value to be an integer"
97
+
98
+ warn msg if $DEBUG
99
+
100
+ raise InvalidIntegerException, msg
101
+ end
102
+ end
103
+
104
+ # obtain the integer from the value
105
+
106
+ v = nil
107
+
108
+ begin
109
+
110
+ v = Integer(value)
111
+ rescue ArgumentError => x
112
+
113
+ msg = "value '#{value}' specified for option '#{argument_spec.name}' that requires the value to be an integer"
114
+
115
+ warn msg if $DEBUG
116
+
117
+ raise InvalidIntegerException, msg
118
+ end
119
+
120
+ # Is there a value constraint?:
121
+ #
122
+ # - values (obtained from argument_spec#values)
123
+ # - range
124
+ # - minimum & maximum
125
+
126
+ values_range = argument_spec.values_range
127
+
128
+ unless values_range.empty?
129
+
130
+ v_s = v.to_s
131
+
132
+ v_s = '+' + v_s unless '-' == v_s[0]
133
+
134
+ vr_s = values_range.map { |x| x.to_s }.map { |x| '-' == x[0] ? x : '+' + x }
135
+
136
+ unless vr_s.include? v_s
137
+
138
+ msg = "given value '#{value}' specified for option '#{argument_spec.name}' does not fall within the required range"
139
+
140
+ raise IntegerOutOfRangeException, msg
141
+ end
142
+ else
143
+
144
+ case range = constraint[:range]
145
+ when :negative
146
+
147
+ if v >= 0
148
+
149
+ msg = "given value '#{value}' specified for option '#{argument_spec.name}' must be a negative integer"
150
+
151
+ raise IntegerOutOfRangeException, msg
152
+ end
153
+ when :positive
154
+
155
+ if v < 1
156
+
157
+ msg = "given value '#{value}' specified for option '#{argument_spec.name}' must be a positive integer"
158
+
159
+ raise IntegerOutOfRangeException, msg
160
+ end
161
+ when :non_positive
162
+
163
+ if v > 0
164
+
165
+ msg = "given value '#{value}' specified for option '#{argument_spec.name}' must be a non-positive integer"
166
+
167
+ raise IntegerOutOfRangeException, msg
168
+ end
169
+ when :non_negative
170
+
171
+ if v < 0
172
+
173
+ msg = "given value '#{value}' specified for option '#{argument_spec.name}' must be a non-negative integer"
174
+
175
+ raise IntegerOutOfRangeException, msg
176
+ end
177
+ when Range
178
+
179
+ unless range.include?
180
+
181
+ msg = "given value '#{value}' specified for option '#{argument_spec.name}' does not fall within the required range"
182
+
183
+ raise IntegerOutOfRangeException, msg
184
+ end
185
+ else
186
+
187
+ ;
188
+ end
189
+ end
190
+
191
+ v
192
+ end
193
+ end # module Internal_
194
+
195
+ def value_from_Proc(constraint, value, arg, given_index, given_name, argument_spec, extras)
196
+
197
+ value
198
+ end
199
+
200
+ def value_from_Hash(constraint, value, arg, given_index, given_name, argument_spec, extras)
201
+
202
+ # Check if type is specified; if not, String is assumed
203
+
204
+ type = constraint[:type]
205
+
206
+
207
+ if Internal_.is_integer?(type)
208
+
209
+ return Internal_.obtain_integer(value, constraint, argument_spec)
210
+ end
211
+
212
+
213
+ value
214
+ end
215
+ end # module ValueParser
216
+
217
+ end # module util
218
+ end # module CLASP
219
+
220
+ # ############################## end of file ############################# #
221
+
222
+
data/lib/clasp/version.rb CHANGED
@@ -51,7 +51,7 @@
51
51
  module CLASP
52
52
 
53
53
  # Current version of the CLASP.Ruby library
54
- VERSION = '0.20.3'
54
+ VERSION = '0.21.0'
55
55
 
56
56
  private
57
57
  # @!visibility private
@@ -0,0 +1,310 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), '../..', 'lib')
4
+
5
+ require 'clasp'
6
+
7
+ require 'xqsr3/extensions/test/unit' if RUBY_VERSION >= '2'
8
+
9
+ require 'test/unit'
10
+
11
+ class Test_TypedOptionValues < Test::Unit::TestCase
12
+
13
+ if RUBY_VERSION < '2'
14
+
15
+ def assert_raise_with_message(type_spec, message_spec, *args, &block)
16
+
17
+ assert_raise(type_spec, *args, &block)
18
+ end
19
+ end
20
+
21
+ def test_Integer_no_range
22
+
23
+ specifications = [
24
+
25
+ CLASP.Option('--level', default_value: 1234, constraint: { type: Integer })
26
+ ]
27
+
28
+ # with no arguments
29
+ begin
30
+
31
+ argv = []
32
+ args = CLASP.parse argv, specifications
33
+
34
+ assert_equal 0, args.flags.size
35
+ assert_equal 0, args.options.size
36
+ assert_equal 0, args.values.size
37
+ end
38
+
39
+ # with default value
40
+ begin
41
+
42
+ argv = [ '--level=' ]
43
+
44
+ args = CLASP.parse argv, specifications
45
+
46
+ assert_equal 0, args.flags.size
47
+ assert_equal 1, args.options.size
48
+ assert_equal 0, args.values.size
49
+
50
+ opt = args.options[0]
51
+
52
+ assert_equal 0, opt.given_index
53
+ assert_equal specifications[0], opt.argument_specification
54
+ assert_equal '--level', opt.name
55
+ assert_equal '', opt.given_value
56
+ assert_equal 1234, opt.value
57
+ end
58
+
59
+ # with explicit value 0
60
+ begin
61
+
62
+ argv = [ '--level=0' ]
63
+
64
+ args = CLASP.parse argv, specifications
65
+
66
+ assert_equal 0, args.flags.size
67
+ assert_equal 1, args.options.size
68
+ assert_equal 0, args.values.size
69
+
70
+ opt = args.options[0]
71
+
72
+ assert_equal 0, opt.given_index
73
+ assert_equal specifications[0], opt.argument_specification
74
+ assert_equal '--level', opt.name
75
+ assert_equal '0', opt.given_value
76
+ assert_equal 0, opt.value
77
+ end
78
+
79
+ # with explicit value -100
80
+ begin
81
+
82
+ argv = [ '--level=-100' ]
83
+
84
+ args = CLASP.parse argv, specifications
85
+
86
+ assert_equal 0, args.flags.size
87
+ assert_equal 1, args.options.size
88
+ assert_equal 0, args.values.size
89
+
90
+ opt = args.options[0]
91
+
92
+ assert_equal 0, opt.given_index
93
+ assert_equal specifications[0], opt.argument_specification
94
+ assert_equal '--level', opt.name
95
+ assert_equal '-100', opt.given_value
96
+ assert_equal -100, opt.value
97
+ end
98
+
99
+ # with explicit value 123456789
100
+ begin
101
+
102
+ argv = [ '--level=123456789' ]
103
+
104
+ args = CLASP.parse argv, specifications
105
+
106
+ assert_equal 0, args.flags.size
107
+ assert_equal 1, args.options.size
108
+ assert_equal 0, args.values.size
109
+
110
+ opt = args.options[0]
111
+
112
+ assert_equal 0, opt.given_index
113
+ assert_equal specifications[0], opt.argument_specification
114
+ assert_equal '--level', opt.name
115
+ assert_equal '123456789', opt.given_value
116
+ assert_equal 123456789, opt.value
117
+ end
118
+
119
+ # with explicit value +123456789
120
+ begin
121
+
122
+ argv = [ '--level=+123456789' ]
123
+
124
+ args = CLASP.parse argv, specifications
125
+
126
+ assert_equal 0, args.flags.size
127
+ assert_equal 1, args.options.size
128
+ assert_equal 0, args.values.size
129
+
130
+ opt = args.options[0]
131
+
132
+ assert_equal 0, opt.given_index
133
+ assert_equal specifications[0], opt.argument_specification
134
+ assert_equal '--level', opt.name
135
+ assert_equal '+123456789', opt.given_value
136
+ assert_equal 123456789, opt.value
137
+ end
138
+ end
139
+
140
+ def test_Integer_positive
141
+
142
+ specifications = [
143
+
144
+ CLASP.Option('--level', default_value: 1234, constraint: { type: Integer, range: :positive })
145
+ ]
146
+
147
+ # with no arguments
148
+ begin
149
+
150
+ argv = []
151
+ args = CLASP.parse argv, specifications
152
+
153
+ assert_equal 0, args.flags.size
154
+ assert_equal 0, args.options.size
155
+ assert_equal 0, args.values.size
156
+ end
157
+
158
+ # with default value
159
+ begin
160
+
161
+ argv = [ '--level=' ]
162
+
163
+ args = CLASP.parse argv, specifications
164
+
165
+ assert_equal 0, args.flags.size
166
+ assert_equal 1, args.options.size
167
+ assert_equal 0, args.values.size
168
+
169
+ opt = args.options[0]
170
+
171
+ assert_equal 0, opt.given_index
172
+ assert_equal specifications[0], opt.argument_specification
173
+ assert_equal '--level', opt.name
174
+ assert_equal '', opt.given_value
175
+ assert_equal 1234, opt.value
176
+ end
177
+
178
+ # with explicit value 0
179
+ begin
180
+
181
+ argv = [ '--level=0' ]
182
+
183
+ assert_raise_with_message(CLASP::Exceptions::IntegerOutOfRangeException, /\b0\b.*--level.*must be a positive integer/) { CLASP.parse argv, specifications }
184
+ end
185
+
186
+ # with explicit value -100
187
+ begin
188
+
189
+ argv = [ '--level=-100' ]
190
+
191
+ assert_raise_with_message(CLASP::Exceptions::IntegerOutOfRangeException, /-100\b.*--level.*must be a positive integer/) { CLASP.parse argv, specifications }
192
+ end
193
+
194
+ # with explicit value 123456789
195
+ begin
196
+
197
+ argv = [ '--level=123456789' ]
198
+
199
+ args = CLASP.parse argv, specifications
200
+
201
+ assert_equal 0, args.flags.size
202
+ assert_equal 1, args.options.size
203
+ assert_equal 0, args.values.size
204
+
205
+ opt = args.options[0]
206
+
207
+ assert_equal 0, opt.given_index
208
+ assert_equal specifications[0], opt.argument_specification
209
+ assert_equal '--level', opt.name
210
+ assert_equal '123456789', opt.given_value
211
+ assert_equal 123456789, opt.value
212
+ end
213
+
214
+ # with explicit value +123456789
215
+ begin
216
+
217
+ argv = [ '--level=+123456789' ]
218
+
219
+ args = CLASP.parse argv, specifications
220
+
221
+ assert_equal 0, args.flags.size
222
+ assert_equal 1, args.options.size
223
+ assert_equal 0, args.values.size
224
+
225
+ opt = args.options[0]
226
+
227
+ assert_equal 0, opt.given_index
228
+ assert_equal specifications[0], opt.argument_specification
229
+ assert_equal '--level', opt.name
230
+ assert_equal '+123456789', opt.given_value
231
+ assert_equal 123456789, opt.value
232
+ end
233
+ end
234
+
235
+ def test_Integer_range_values_range
236
+
237
+ specifications = [
238
+
239
+ CLASP.Option('--level', default_value: 1234, values_range: [ 1234, -1234, 7, 19 ], constraint: { type: Integer })
240
+ ]
241
+
242
+ # with no arguments
243
+ begin
244
+
245
+ argv = []
246
+ args = CLASP.parse argv, specifications
247
+
248
+ assert_equal 0, args.flags.size
249
+ assert_equal 0, args.options.size
250
+ assert_equal 0, args.values.size
251
+ end
252
+
253
+ # with default value
254
+ begin
255
+
256
+ argv = [ '--level=' ]
257
+
258
+ args = CLASP.parse argv, specifications
259
+
260
+ assert_equal 0, args.flags.size
261
+ assert_equal 1, args.options.size
262
+ assert_equal 0, args.values.size
263
+
264
+ opt = args.options[0]
265
+
266
+ assert_equal 0, opt.given_index
267
+ assert_equal specifications[0], opt.argument_specification
268
+ assert_equal '--level', opt.name
269
+ assert_equal '', opt.given_value
270
+ assert_equal 1234, opt.value
271
+ end
272
+
273
+ # with explicit value 0
274
+ begin
275
+
276
+ argv = [ '--level=0' ]
277
+
278
+ assert_raise_with_message(CLASP::Exceptions::IntegerOutOfRangeException, /\b0\b.*--level.*does not fall within the required range/) { CLASP.parse argv, specifications }
279
+ end
280
+
281
+ spec0 = specifications[0]
282
+ values = spec0.values_range.sort[0]..spec0.values_range.sort[-1]
283
+
284
+ values.each do |val|
285
+
286
+ argv = [ "--level=#{val}" ]
287
+
288
+ if spec0.values_range.include? val
289
+
290
+ args = CLASP.parse argv, specifications
291
+
292
+ assert_equal 0, args.flags.size
293
+ assert_equal 1, args.options.size
294
+ assert_equal 0, args.values.size
295
+
296
+ opt = args.options[0]
297
+
298
+ assert_equal 0, opt.given_index
299
+ assert_equal specifications[0], opt.argument_specification
300
+ assert_equal '--level', opt.name
301
+ assert_equal val.to_s, opt.given_value
302
+ assert_equal val, opt.value
303
+ else
304
+
305
+ assert_raise_with_message(CLASP::Exceptions::IntegerOutOfRangeException, /#{val}\b.*--level.*does not fall within the required range/) { CLASP.parse argv, specifications }
306
+ end
307
+ end
308
+ end
309
+ end
310
+
metadata CHANGED
@@ -1,72 +1,66 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clasp-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.3
5
- prerelease:
4
+ version: 0.21.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Matt Wilson
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2019-04-20 00:00:00.000000000 Z
11
+ date: 2019-04-28 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: xqsr3
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0.30'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0.30'
30
- description: ! 'Command-Line Argument Sorting and Parsing library that provides a
31
- powerful
32
-
33
- abstraction of command-line interpretation facilities. CLASP.Ruby is a Ruby port
34
- of the popular CLASP (C/C++) library, and provides declarative specification of
35
- command-line flags and options, aliasing, flag combination, UNIX de-facto standard
36
- flag processing, and a number of utility functions for expressing usage and version
37
- information.
38
-
39
- '
27
+ description: |
28
+ Command-Line Argument Sorting and Parsing library that provides a powerful
29
+ abstraction of command-line interpretation facilities. CLASP.Ruby is a Ruby port of the popular CLASP (C/C++) library, and provides declarative specification of command-line flags and options, aliasing, flag combination, UNIX de-facto standard flag processing, and a number of utility functions for expressing usage and version information.
40
30
  email: matthew@synesis.com.au
41
31
  executables: []
42
32
  extensions: []
43
33
  extra_rdoc_files: []
44
34
  files:
35
+ - LICENSE
36
+ - README.md
45
37
  - examples/cr-example.rb
46
38
  - examples/flag_and_option_specifications.md
47
39
  - examples/flag_and_option_specifications.rb
48
40
  - examples/show_usage_and_version.md
49
41
  - examples/show_usage_and_version.rb
50
42
  - examples/simple_command_line_no_specifications.rb
43
+ - lib/clasp-ruby.rb
44
+ - lib/clasp.rb
51
45
  - lib/clasp/arguments.rb
52
46
  - lib/clasp/clasp.rb
53
47
  - lib/clasp/cli.rb
54
48
  - lib/clasp/doc_.rb
55
49
  - lib/clasp/old_module.rb
56
50
  - lib/clasp/specifications.rb
51
+ - lib/clasp/util/exceptions.rb
52
+ - lib/clasp/util/value_parser.rb
57
53
  - lib/clasp/version.rb
58
- - lib/clasp-ruby.rb
59
- - lib/clasp.rb
60
54
  - test/scratch/test_list_command_line.rb
61
55
  - test/scratch/test_specifications.rb
62
56
  - test/scratch/test_usage.rb
63
57
  - test/scratch/test_usage_from_DATA.rb
64
58
  - test/scratch/test_usage_with_duplicate_specifications.rb
59
+ - test/unit/tc_ARGV_rewrite.rb
65
60
  - test/unit/tc_arguments_1.rb
66
61
  - test/unit/tc_arguments_2.rb
67
62
  - test/unit/tc_arguments_3.rb
68
63
  - test/unit/tc_arguments_inspect.rb
69
- - test/unit/tc_ARGV_rewrite.rb
70
64
  - test/unit/tc_cli.rb
71
65
  - test/unit/tc_default_value.rb
72
66
  - test/unit/tc_defaults_1.rb
@@ -75,33 +69,31 @@ files:
75
69
  - test/unit/tc_option_required.rb
76
70
  - test/unit/tc_option_value_aliases.rb
77
71
  - test/unit/tc_specifications.rb
72
+ - test/unit/tc_typed_options.rb
78
73
  - test/unit/tc_usage.rb
79
74
  - test/unit/ts_all.rb
80
- - README.md
81
- - LICENSE
82
75
  homepage: http://github.com/synesissoftware/CLASP.Ruby
83
76
  licenses:
84
77
  - BSD-3-Clause
78
+ metadata: {}
85
79
  post_install_message:
86
80
  rdoc_options: []
87
81
  require_paths:
88
82
  - lib
89
83
  required_ruby_version: !ruby/object:Gem::Requirement
90
- none: false
91
84
  requirements:
92
- - - ! '>='
85
+ - - ">="
93
86
  - !ruby/object:Gem::Version
94
87
  version: 1.9.3
95
88
  required_rubygems_version: !ruby/object:Gem::Requirement
96
- none: false
97
89
  requirements:
98
- - - ! '>='
90
+ - - ">="
99
91
  - !ruby/object:Gem::Version
100
92
  version: '0'
101
93
  requirements: []
102
94
  rubyforge_project:
103
- rubygems_version: 1.8.23.2
95
+ rubygems_version: 2.7.6
104
96
  signing_key:
105
- specification_version: 3
97
+ specification_version: 4
106
98
  summary: CLASP.Ruby
107
99
  test_files: []