optout 0.0.1 → 0.0.2
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/README.rdoc +31 -8
- data/lib/optout.rb +238 -62
- data/spec/optout_spec.rb +369 -217
- metadata +9 -9
data/README.rdoc
CHANGED
@@ -20,7 +20,7 @@ arguments and define validation rules that must be met before the command line a
|
|
20
20
|
:gem => "rake",
|
21
21
|
:os => "mswin",
|
22
22
|
:version => "0.9.2",
|
23
|
-
:user =>
|
23
|
+
:user => truep
|
24
24
|
}
|
25
25
|
|
26
26
|
exec "gem", *optout.argv(options)
|
@@ -68,13 +68,30 @@ in a different format. +Optout+ accepts various configuration options that can r
|
|
68
68
|
optout = Optout.options do
|
69
69
|
on :path, "--path", :arg_separator => "=", :required => true
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
optout.shell(:path => "/home/sshaw")
|
73
73
|
# Returns: --path='/home/sshaw'
|
74
74
|
|
75
75
|
optout.shell({})
|
76
76
|
# Raises: Optout::OptionRequired
|
77
77
|
|
78
|
+
Options can be grouped into required and optional:
|
79
|
+
|
80
|
+
Optout.options :arg_separator => "=" do
|
81
|
+
required do
|
82
|
+
on :in, "if"
|
83
|
+
on :out, "of"
|
84
|
+
end
|
85
|
+
|
86
|
+
optional do
|
87
|
+
on :size, "size"
|
88
|
+
on :count, "count"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
optout.shell(:in => "/dev/zero", :out => "/var/log/secure")
|
93
|
+
# Returns: in='/dev/zero' out='/var/log/secure'
|
94
|
+
|
78
95
|
== Validating Options
|
79
96
|
|
80
97
|
+Optout+ can validate your options too. Just specify the validation rule after the option's key or switch:
|
@@ -85,7 +102,7 @@ in a different format. +Optout+ accepts various configuration options that can r
|
|
85
102
|
end
|
86
103
|
|
87
104
|
optout = Optout.options do
|
88
|
-
# Must be true, false, or nil
|
105
|
+
# Must be true, false, or nil (add :required => true to allow only true or false)
|
89
106
|
on :path, "-p", Optout::Boolean
|
90
107
|
end
|
91
108
|
|
@@ -95,20 +112,24 @@ in a different format. +Optout+ accepts various configuration options that can r
|
|
95
112
|
end
|
96
113
|
|
97
114
|
optout = Optout.options do
|
98
|
-
# Must be a diretory under "/
|
99
|
-
on :path, Optout::Dir.under("/home").permissions("
|
115
|
+
# Must be a diretory under "/home" and have user read and write permissions
|
116
|
+
on :path, Optout::Dir.under("/home").permissions("rw")
|
100
117
|
end
|
101
118
|
|
102
119
|
optout.shell(:path => "/root")
|
103
120
|
# Raises: Optout::OptionInvalid
|
104
121
|
|
105
|
-
|
122
|
+
== TODOs
|
123
|
+
|
124
|
+
* Proper <code>cmd.exe</code> quoting
|
125
|
+
* Mutually exclusive options
|
126
|
+
* Split options i.e., <code>:jvm => %w[A B C]</code> would be created as <code>-XA -XB -XC</code>
|
106
127
|
|
107
128
|
== More Info
|
108
129
|
|
109
130
|
=== RDoc
|
110
131
|
|
111
|
-
http://rubydoc.info/github/sshaw/optout/frames
|
132
|
+
http://rubydoc.info/github/sshaw/optout/frames (with RDoc -> YARD incompatibilities :)
|
112
133
|
|
113
134
|
=== Bugs
|
114
135
|
|
@@ -120,4 +141,6 @@ Skye Shaw [sshaw AT lucas.cis.temple.edu]
|
|
120
141
|
|
121
142
|
== License
|
122
143
|
|
123
|
-
|
144
|
+
Copyright (c) 2011-2012 Skye Shaw
|
145
|
+
|
146
|
+
Released under the MIT License: http://www.opensource.org/licenses/MIT
|
data/lib/optout.rb
CHANGED
@@ -2,7 +2,7 @@ require "rbconfig"
|
|
2
2
|
require "pathname"
|
3
3
|
|
4
4
|
class Optout
|
5
|
-
VERSION = "0.0.
|
5
|
+
VERSION = "0.0.2"
|
6
6
|
|
7
7
|
class OptionError < StandardError
|
8
8
|
attr :key
|
@@ -32,20 +32,26 @@ class Optout
|
|
32
32
|
|
33
33
|
class << self
|
34
34
|
##
|
35
|
-
# Define a set of options
|
35
|
+
# Define a set of options.
|
36
|
+
# After the options are defined call Optout#argv or Optout#shell to create them.
|
37
|
+
#
|
38
|
+
# optz = Optout.options config do
|
39
|
+
# on :key, "-switch", ValidationRule, :multiple => false, :required => true
|
40
|
+
# # ...
|
41
|
+
# end
|
36
42
|
#
|
37
43
|
# === Parameters
|
38
44
|
#
|
39
45
|
# [config (Hash)] Configuration options
|
40
|
-
# [
|
46
|
+
# [block (Proc)] Option definitions
|
41
47
|
#
|
42
48
|
# === Configuration Options
|
43
49
|
#
|
44
|
-
# [:arg_separator] Set the default for all subsequent options defined via
|
45
|
-
# [:check_keys] If +true+ an
|
50
|
+
# [:arg_separator] Set the default argument seperator (i.e., the char used to seperate a switch from its value) for all subsequent options defined via Optout#on.
|
51
|
+
# [:check_keys] If +true+ an +OptionUnknown+ error will be raised when the incoming option hash contains a key that has not been associated with an option via Optout#on.
|
46
52
|
# Defaults to +true+.
|
47
|
-
# [:multiple] Set the default for all subsequent options defined via +on+. See Optout#on
|
48
|
-
# [:required] Set the default for all subsequent options defined via +on+. See Optout#on
|
53
|
+
# [:multiple] Set the default for all subsequent options defined via +on+. See Optout#on.
|
54
|
+
# [:required] Set the default for all subsequent options defined via +on+. See Optout#on.
|
49
55
|
#
|
50
56
|
# === Errors
|
51
57
|
#
|
@@ -59,20 +65,20 @@ class Optout
|
|
59
65
|
# on :file, Optout::File.under("/home/sshaw"), :default => "/home/sshaw/tmp"
|
60
66
|
# end
|
61
67
|
#
|
62
|
-
# optz.shell(:all => true, :size => 1024, :file => "/home/sshaw/some file")
|
63
|
-
# # Creates: "-a -b '1024' '/home/sshaw/some file'
|
64
|
-
#
|
65
68
|
# optz = Optout.options :required => true, :check_keys => false do
|
66
|
-
# on :lib
|
69
|
+
# on :lib
|
67
70
|
# on :prefix, "--prefix" , %w{/sshaw/lib /sshaw/usr/lib}, :arg_separator => "="
|
68
71
|
# end
|
69
72
|
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
73
|
+
# # Same as above
|
74
|
+
# optz = Optout.options :check_keys => false do
|
75
|
+
# required do
|
76
|
+
# on :lib
|
77
|
+
# on :prefix, "--prefix" , %w{/sshaw/lib /sshaw/usr/lib}, :arg_separator => "="
|
78
|
+
# end
|
79
|
+
# end
|
74
80
|
#
|
75
|
-
|
81
|
+
|
76
82
|
def options(config = {}, &block)
|
77
83
|
optout = new(config)
|
78
84
|
optout.instance_eval(&block) if block_given?
|
@@ -85,7 +91,8 @@ class Optout
|
|
85
91
|
def initialize(args = {})
|
86
92
|
@options = {}
|
87
93
|
@check_keys = args.include?(:check_keys) ? args[:check_keys] : true
|
88
|
-
|
94
|
+
@required_context = option_context(:required => true)
|
95
|
+
@optional_context = option_context(:required => false)
|
89
96
|
@default_opt_options = {
|
90
97
|
:required => args[:required],
|
91
98
|
:multiple => args[:multiple],
|
@@ -98,45 +105,103 @@ class Optout
|
|
98
105
|
#
|
99
106
|
# === Parameters
|
100
107
|
#
|
101
|
-
# [key (Symbol)] The key of the option in the option hash
|
108
|
+
# [key (Symbol)] The key of the option in the option hash passed to +shell+ or +argv+.
|
102
109
|
# [switch (String)] Optional. The option's command line switch. If no switch is given only the option's value is output.
|
103
|
-
# [rule (Object)] Optional. Validation rule, see
|
104
|
-
# [options (Hash)] Additional option configuration, see
|
110
|
+
# [rule (Object)] Optional. Validation rule, see Optout#on@Validating.
|
111
|
+
# [options (Hash)] Additional option configuration, see Optout#on@Options.
|
105
112
|
#
|
106
113
|
# === Options
|
107
114
|
#
|
108
|
-
# [:arg_separator] The +String+ used to separate the option's switch from its value. Defaults to <code>" "</code> (space).
|
115
|
+
# [:arg_separator] The +String+ used to separate the option's switch from its value. Defaults to <code>" "</code> (space). This can be set globally via Optout::options.
|
109
116
|
# [:default] The option's default value. This will be used if the option is +nil+ or +empty?+.
|
110
|
-
# [:
|
111
|
-
# [:
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
# [
|
117
|
+
# [:multiple] If +true+ the option will accept multiple values. If +false+ an <code>Optout::OptionInvalid</code> error will be raised if the option contains multiple values. By default multiple values are joined on a comma, you can set this to a +String+ to join on that string instead. Defaults to +false+. This can be set globally via Optout::options.
|
118
|
+
# [:required] If +true+ the option must contian a value i.e., it must not be +false+ or +nil+ otherwise an <code>Optout::OptionRequired</code> exception will be raised.
|
119
|
+
# Defaults to +false+. This can be set globally via Optout::options or for a set of options via Optout#required or Optout#optional.
|
120
|
+
#
|
121
|
+
# === Errors
|
122
|
+
#
|
123
|
+
# [ArgumentError] An +ArgumentError+ is raised if +key+ is +nil+ or has already been defined
|
117
124
|
#
|
118
125
|
# === Validating
|
119
126
|
#
|
120
|
-
#
|
121
|
-
# to +on+ when defining the option. Validation rules can be in one of the following forms:
|
127
|
+
# An option's value can be restricted by a validation rule. If validation fails an Optout::OptionInvalid exception is raised.
|
122
128
|
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
# [Class] Restrict the option's value to instances of the given class.
|
126
|
-
# [Optout::Boolean] Restrict the option's value to something boolean, i.e., +true+, +false+, or +nil+.
|
127
|
-
# [Optout::File] The option's value must be a file. Note that the file does not have to exist. <code>Optout::File</code> has several methods that can be used to tune validation, see Optout::File.
|
128
|
-
# [Optout::Dir] The option's value must be a directory. <code>Optout::Dir</code> has several methods that can be used to tune validation, see Optout::Dir.
|
129
|
-
#
|
130
|
-
# === Errors
|
129
|
+
# Validation rules will only be applied if the option hash contains a non-nil value for the given option's key.
|
130
|
+
# If the option is required you must either define it in a Optout#required block or set the +:required+ option to +true+ when calling Optout#on.
|
131
131
|
#
|
132
|
-
#
|
133
|
-
|
132
|
+
# Validation rules can be in one of the following forms:
|
133
|
+
#
|
134
|
+
# ==== Regex
|
135
|
+
#
|
136
|
+
# A pattern to match the option's value against.
|
137
|
+
#
|
138
|
+
# on :key, /\d+/
|
139
|
+
# on :key, "-switch", /\d+/
|
140
|
+
#
|
141
|
+
# ==== Array
|
142
|
+
#
|
143
|
+
# Only accept value(s) contained in the given array.
|
144
|
+
#
|
145
|
+
# on :key, %w(item_a item_b item_c)
|
146
|
+
# on :key, "-switch", %w(item_a item_b item_c)
|
147
|
+
#
|
148
|
+
# ==== Class
|
149
|
+
#
|
150
|
+
# Must be an instance of the given class.
|
151
|
+
#
|
152
|
+
# on :key, Fixnum
|
153
|
+
# on :key, "-switch", Fixnum
|
154
|
+
#
|
155
|
+
# ==== Optout::Boolean
|
156
|
+
#
|
157
|
+
# Must be +true+ or +false+.
|
158
|
+
#
|
159
|
+
# on :key, Optout::Boolean
|
160
|
+
# on :key, "-switch", Optout::Boolean
|
161
|
+
#
|
162
|
+
# ==== Optout::File
|
163
|
+
#
|
164
|
+
# Must be a file. Note that the file does not have to exist.
|
165
|
+
#
|
166
|
+
# on :key, Optout::File
|
167
|
+
# on :key, "-switch", Optout::File
|
168
|
+
#
|
169
|
+
# <code>Optout::File</code> has several methods that can be used to tune validation:
|
170
|
+
#
|
171
|
+
# on :key, "-switch", Optout::File.named(/-\d{2}$/).under("/home/sshaw")
|
172
|
+
#
|
173
|
+
# In this case the file's basename must match the given regexp and exist under the given directory. See Optout::File for more info.
|
174
|
+
#
|
175
|
+
# ==== Optout::Dir
|
176
|
+
#
|
177
|
+
# Like <code>Optout::File</code> except for directories. <code>Optout::Dir</code> has several methods that can be used to tune validation, see Optout::Dir.
|
178
|
+
#
|
179
|
+
# on :key, Optout::Dir
|
180
|
+
# on :key, "-switch", Optout::Dir
|
181
|
+
#
|
182
|
+
# ==== Custom Validator
|
183
|
+
#
|
184
|
+
# A class that responds to +validate!+ and accepts a single argument containing the option (as an instance of Optout::Option).
|
185
|
+
#
|
186
|
+
# class MyValidator
|
187
|
+
# def validate!(option)
|
188
|
+
# if option.empty? || option.value.size % 2 != 1
|
189
|
+
# raise Optout::OptionInvalid.new(option.key, "bad option!")
|
190
|
+
# end
|
191
|
+
# end
|
192
|
+
# end
|
193
|
+
#
|
194
|
+
# on :key, MyValidator.new
|
195
|
+
# on :key, "-switch", MyValidator.new
|
196
|
+
|
134
197
|
def on(*args)
|
135
198
|
key = args.shift
|
136
199
|
|
137
200
|
# switch is optional, this could be a validation rule
|
138
201
|
switch = args.shift if String === args[0]
|
139
202
|
raise ArgumentError, "option key required" if key.nil?
|
203
|
+
|
204
|
+
key = key.to_sym
|
140
205
|
raise ArgumentError, "option already defined: '#{key}'" if @options[key]
|
141
206
|
|
142
207
|
opt_options = Hash === args.last ? @default_opt_options.merge(args.pop) : @default_opt_options.dup
|
@@ -146,41 +211,120 @@ class Optout
|
|
146
211
|
@options[key] = Option.create(key, switch, opt_options)
|
147
212
|
end
|
148
213
|
|
214
|
+
##
|
215
|
+
# Create a set of options that are optional. This can also be set on a per option basis, see Optout#on.
|
216
|
+
#
|
217
|
+
# === Examples
|
218
|
+
#
|
219
|
+
# optz = Optout.options do
|
220
|
+
# optional do
|
221
|
+
# on :ignore, "-i"
|
222
|
+
# on :recurse, "-r"
|
223
|
+
# end
|
224
|
+
# end
|
225
|
+
#
|
226
|
+
# optz.optional { on :path, Optout::File }
|
227
|
+
|
228
|
+
def optional(&block)
|
229
|
+
@optional_context.instance_eval(&block)
|
230
|
+
end
|
231
|
+
|
232
|
+
##
|
233
|
+
# Create a set of options that are required.
|
234
|
+
#
|
235
|
+
# If any +required+ option is missing from the option hash passed to Optout#argv or Optout#shell an
|
236
|
+
# <code>Optout::OptionRequired</code> exception is raised.
|
237
|
+
#
|
238
|
+
# This can also be set on a per option basis, see Optout#on.
|
239
|
+
#
|
240
|
+
# === Examples
|
241
|
+
#
|
242
|
+
# optz = Optout.options do
|
243
|
+
# required do
|
244
|
+
# on :ignore, "-i"
|
245
|
+
# on :recurse, "-r"
|
246
|
+
# end
|
247
|
+
# end
|
248
|
+
#
|
249
|
+
# optz.required { on :path, Optout::File }
|
250
|
+
#
|
251
|
+
|
252
|
+
def required(&block)
|
253
|
+
@required_context.instance_eval(&block)
|
254
|
+
end
|
255
|
+
|
149
256
|
##
|
150
257
|
# Create an argument string that can be to passed to a +system+ like function.
|
258
|
+
# Options must first be defined via Optout#on.
|
151
259
|
#
|
152
260
|
# === Parameters
|
261
|
+
#
|
153
262
|
# [options (Hash)] The option hash used to construct the argument string.
|
154
263
|
#
|
155
264
|
# === Returns
|
265
|
+
#
|
156
266
|
# [String] The argument string.
|
157
267
|
#
|
158
268
|
# === Errors
|
269
|
+
#
|
159
270
|
# See Optout#argv@Errors
|
271
|
+
#
|
272
|
+
# === Examples
|
273
|
+
#
|
274
|
+
# Create <code>"-a -b '1024' '/home/sshaw/some file'"</code>
|
275
|
+
#
|
276
|
+
# optz = Optout.options do
|
277
|
+
# on :all, "-a"
|
278
|
+
# on :size, "-b", /\A\d+\z/, :required => true
|
279
|
+
# on :file, Optout::File.under("/home/sshaw"), :default => "/home/sshaw/tmp"
|
280
|
+
# end
|
281
|
+
#
|
282
|
+
# optz.shell(:all => true, :size => 1024, :file => "/home/sshaw/some file")
|
283
|
+
|
160
284
|
def shell(options = {})
|
161
285
|
create_options(options).map { |opt| opt.to_s }.join " "
|
162
286
|
end
|
163
287
|
|
164
288
|
##
|
165
289
|
# Create an +argv+ array that can be to passed to an +exec+ like function.
|
290
|
+
# Options must first be defined via Optout#on.
|
166
291
|
#
|
167
292
|
# === Parameters
|
293
|
+
#
|
168
294
|
# [options (Hash)] The options hash used to construct the +argv+ array.
|
169
295
|
#
|
170
296
|
# === Returns
|
297
|
+
#
|
171
298
|
# [Array] The +argv+ array, each element is a +String+
|
172
299
|
#
|
173
300
|
# === Errors
|
301
|
+
#
|
302
|
+
# [ArgumentError] If options are not a +Hash+
|
174
303
|
# [Optout::OptionRequired] The option hash is missing a required value.
|
175
304
|
# [Optout::OptionUnknown] The option hash contains an unknown key.
|
176
305
|
# [Optout::OptionInvalid] The option hash contains a value the does not conform to the defined specification.
|
177
|
-
|
306
|
+
#
|
307
|
+
# === Examples
|
308
|
+
#
|
309
|
+
# Create <code>["--prefix='/sshaw/usr/lib'", "libssl2"]</code>
|
310
|
+
#
|
311
|
+
# optz = Optout.options do
|
312
|
+
# on :all, "-a"
|
313
|
+
# on :size, "-b", /\A\d+\z/, :required => true
|
314
|
+
# on :file, Optout::File.under("/home/sshaw"), :default => "/home/sshaw/tmp"
|
315
|
+
# end
|
316
|
+
#
|
317
|
+
# optz.argv(:lib => "libssl2",
|
318
|
+
# :prefix => "/sshaw/usr/lib")
|
319
|
+
|
178
320
|
def argv(options = {})
|
179
321
|
create_options(options).map { |opt| opt.to_a }.flatten
|
180
322
|
end
|
181
323
|
|
182
324
|
private
|
183
|
-
def create_options(options = {})
|
325
|
+
def create_options(options = {})
|
326
|
+
raise ArgumentError, "options must be a Hash" unless Hash === options
|
327
|
+
|
184
328
|
argv = []
|
185
329
|
options = options.dup
|
186
330
|
|
@@ -199,12 +343,24 @@ class Optout
|
|
199
343
|
sort_by { |opt| opt.index }
|
200
344
|
end
|
201
345
|
|
346
|
+
def option_context(forced_options)
|
347
|
+
klass = self
|
348
|
+
Class.new do
|
349
|
+
define_method(:on) do |*args|
|
350
|
+
options = Hash === args.last ? args.pop.dup : {}
|
351
|
+
options.merge!(forced_options)
|
352
|
+
args << options
|
353
|
+
klass.on *args
|
354
|
+
end
|
355
|
+
end.new
|
356
|
+
end
|
357
|
+
|
202
358
|
class Option
|
203
359
|
attr :key
|
204
360
|
attr :value
|
205
361
|
attr :index
|
206
362
|
|
207
|
-
##
|
363
|
+
##
|
208
364
|
# Creates a subclass of +Option+
|
209
365
|
#
|
210
366
|
# === Parameters
|
@@ -246,7 +402,7 @@ class Optout
|
|
246
402
|
|
247
403
|
##
|
248
404
|
# Turn the option into a string that can be to passed to a +system+ like function.
|
249
|
-
# This
|
405
|
+
# This _does_ _not_ validate the option. You must call <code>validate!</code>.
|
250
406
|
#
|
251
407
|
# === Examples
|
252
408
|
#
|
@@ -300,7 +456,7 @@ class Optout
|
|
300
456
|
#
|
301
457
|
# [OptionRequired] The option is missing a required value
|
302
458
|
# [OptionUnknown] The option contains an unknown key
|
303
|
-
# [OptionInvalid] The option contains a value
|
459
|
+
# [OptionInvalid] The option contains a value that does not conform to the defined specification
|
304
460
|
#
|
305
461
|
def validate!
|
306
462
|
@validators.each { |v| v.validate!(self) }
|
@@ -324,28 +480,29 @@ class Optout
|
|
324
480
|
end
|
325
481
|
|
326
482
|
def unix?
|
327
|
-
RbConfig::CONFIG["host_os"] !~ /mswin|mingw/i
|
483
|
+
RbConfig::CONFIG["host_os"] !~ /mswin|mingw|msys/i
|
328
484
|
end
|
329
|
-
|
485
|
+
|
330
486
|
def normalize(value)
|
331
487
|
value.respond_to?(:entries) ? value.entries.join(@joinon) : value.to_s.strip
|
332
488
|
end
|
333
489
|
end
|
334
|
-
|
490
|
+
|
335
491
|
module Validator #:nodoc: all
|
336
492
|
def self.for(setting)
|
337
493
|
if setting.respond_to?(:validate!)
|
338
494
|
setting
|
339
495
|
else
|
340
496
|
# Load validator based on the setting's name or the name of its class
|
341
|
-
|
497
|
+
# Note that on 1.9 calling class.name on anonymous classes (i.e., Class.new.new) returns nil
|
498
|
+
validator = setting.class.name.to_s
|
342
499
|
if validator == "Class"
|
343
|
-
name = setting.name.split("::", 2)
|
500
|
+
name = setting.name.to_s.split("::", 2)
|
344
501
|
validator = name[1] if name[1] && name[0] == "Optout"
|
345
502
|
end
|
346
503
|
|
347
|
-
# Support 1.8 and 1.9, avoid String/Symbol and const_defined? differences
|
348
|
-
if !constants.include?(validator) && !constants.include?(validator.to_sym)
|
504
|
+
# Support 1.8 and 1.9, avoid String/Symbol and const_defined? differences
|
505
|
+
if validator.empty? || !constants.include?(validator) && !constants.include?(validator.to_sym)
|
349
506
|
raise ArgumentError, "don't know how to validate with #{setting}"
|
350
507
|
end
|
351
508
|
|
@@ -355,7 +512,7 @@ class Optout
|
|
355
512
|
|
356
513
|
Base = Struct.new :setting
|
357
514
|
|
358
|
-
#
|
515
|
+
# Checks for multiple values
|
359
516
|
class Multiple < Base
|
360
517
|
def validate!(opt)
|
361
518
|
if !opt.empty? && opt.value.respond_to?(:entries) && opt.value.entries.size > 1 && !multiple_values_allowed?
|
@@ -384,6 +541,8 @@ class Optout
|
|
384
541
|
|
385
542
|
class Array < Base
|
386
543
|
def validate!(opt)
|
544
|
+
return if opt.empty?
|
545
|
+
|
387
546
|
values = [opt.value].flatten
|
388
547
|
values.each do |e|
|
389
548
|
if !setting.include?(e)
|
@@ -403,7 +562,7 @@ class Optout
|
|
403
562
|
|
404
563
|
class Class < Base
|
405
564
|
def validate!(opt)
|
406
|
-
if !(setting === opt.value)
|
565
|
+
if !opt.empty? && !(setting === opt.value)
|
407
566
|
raise OptionInvalid.new(opt.key, "value '#{opt.value}' must be type #{setting}")
|
408
567
|
end
|
409
568
|
end
|
@@ -412,6 +571,7 @@ class Optout
|
|
412
571
|
class Boolean < Base
|
413
572
|
def validate!(opt)
|
414
573
|
if !(opt.value == true || opt.value == false || opt.value.nil?)
|
574
|
+
# TODO: Better message
|
415
575
|
raise OptionInvalid.new(opt.key, "does not accept an argument")
|
416
576
|
end
|
417
577
|
end
|
@@ -485,6 +645,7 @@ class Optout
|
|
485
645
|
@file.parent.expand_path.to_s == ::File.expand_path(@under))
|
486
646
|
end
|
487
647
|
|
648
|
+
# TODO: Should probably make correct_type? a separate check
|
488
649
|
def creatable?
|
489
650
|
@file.exist? && correct_type? ||
|
490
651
|
!@file.exist? && @file.parent.exist? && @file.parent.writable?
|
@@ -501,22 +662,24 @@ class Optout
|
|
501
662
|
|
502
663
|
|
503
664
|
#
|
504
|
-
#
|
505
|
-
#
|
665
|
+
# The following are shortcuts and/or marker classes used by Optout's public. They enable Validator.for()
|
666
|
+
# to load the appropriate validation class.
|
506
667
|
#
|
507
668
|
|
508
669
|
##
|
509
670
|
# <code>Optout::File</code> is a validaton rule that can be used to check that an option's value is a path to a file.
|
510
671
|
# By default <code>Optout::File</code> *does* *not* *check* that the file exists. Instead, it checks that the file's parent directory
|
511
672
|
# exists. This is done so that you can validate a path that _will_ be created by the program the options are for.
|
512
|
-
# If you
|
673
|
+
# If you do want the file to exist just call the +exists+ method.
|
513
674
|
#
|
514
675
|
# Validation rules can be combined:
|
515
676
|
#
|
516
677
|
# Optout.options do
|
517
678
|
# on :path, "--path", Optout::File.exists.under("/home").named(/\.txt$/)
|
518
679
|
# end
|
519
|
-
#
|
680
|
+
#
|
681
|
+
# To validate directories use Optout::Dir.
|
682
|
+
#
|
520
683
|
class File
|
521
684
|
class << self
|
522
685
|
Validator::File::RULES.each do |r|
|
@@ -554,11 +717,15 @@ class Optout
|
|
554
717
|
# :call-seq:
|
555
718
|
# permissions(symbolic_mode)
|
556
719
|
#
|
557
|
-
# The option's user permissions must match the given permission(s).
|
720
|
+
# The option's *user* *permissions* must match the given permission(s).
|
721
|
+
#
|
558
722
|
#
|
559
723
|
# === Parameters
|
560
724
|
#
|
561
|
-
# A +String+ denoting the desired permission.
|
725
|
+
# A <code>chmod(1)</code> symbolic mode +String+ denoting the desired permission(s).
|
726
|
+
# Any combination of <code>"r"</code>, <code>"w"</code> and <code>"x"</code> is supported.
|
727
|
+
#
|
728
|
+
# Note that permissions are system dependent, certain modes might not be supported by your OS.
|
562
729
|
|
563
730
|
##
|
564
731
|
#
|
@@ -576,7 +743,9 @@ class Optout
|
|
576
743
|
|
577
744
|
##
|
578
745
|
# <code>Optout::Dir</code> is a validaton rule that can be used to check that an option's value is a path to a directory.
|
579
|
-
#
|
746
|
+
# This class proivdes the same functionality for directories that Optout::File provides for files. See Optout::File for more info.
|
747
|
+
#
|
748
|
+
# Validation rules can be combined:
|
580
749
|
#
|
581
750
|
# Optout.options do
|
582
751
|
# on :path, "--path", Optout::Dir.exists.under("/tmp").named(/\d$/)
|
@@ -590,7 +759,14 @@ class Optout
|
|
590
759
|
end
|
591
760
|
end
|
592
761
|
|
593
|
-
|
762
|
+
##
|
763
|
+
# <code>Optout::Boolean</code> is a validaton rule that can be used to check that an option's value is +true+ or +false+.
|
764
|
+
#
|
765
|
+
# Optout.options do
|
766
|
+
# on :force, "-f", Optout::Boolean
|
767
|
+
# end
|
768
|
+
|
769
|
+
class Boolean
|
594
770
|
end
|
595
771
|
end
|
596
772
|
|