switches.rb 0.9.15

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.
Files changed (6) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +211 -0
  3. data/lib/Switches.rb +471 -0
  4. data/spec/all.rb +222 -0
  5. data/switches.rb.gemspec +23 -0
  6. metadata +47 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f576247bc19561658a5bef4cda1a46f90e62b569fa15a6800507e5aeb05e7601
4
+ data.tar.gz: c5c805d86f2c5fa6d3cb757118d6024c9dea9261b6ec0172e4c8c0c73018d7c8
5
+ SHA512:
6
+ metadata.gz: e355d5bbb5bf7ee88fd4dabd45761d7eeb4ea2d20bc443228cf9881929411d605ab92c594d0d66c4d081bd16f1d4c896caf597f938f1a1d92cf4877531b6658b
7
+ data.tar.gz: 1f8f0162b5eb238df5e8e6143fe69348754fcfab16d31cb9480e378e31459fc974472916dab1cf00910c1adfa3a1422eb776ce9f93adf6c637a94d0faf5ade16
data/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # Switches
2
+
3
+ ## Description
4
+
5
+ Switches provides for a nice wrapper to OptionParser to also act as a store for switches supplied.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'switches'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install switches
20
+
21
+
22
+ ## Usage
23
+
24
+ ```Ruby
25
+
26
+ # With optional switch
27
+
28
+ switches = Switches.new do |s|
29
+ s.set(:a)
30
+ # OR
31
+ s.optional(:a)
32
+ end
33
+ switches.a
34
+
35
+ # With argument required
36
+
37
+ switches = Switches.new do |s|
38
+ s.set!(:a)
39
+ # OR
40
+ s.optional!(:a)
41
+ end
42
+ switches.a
43
+
44
+ # With switch required
45
+
46
+ switches = Switches.new do |s|
47
+ s.set(:a, required: true)
48
+ # OR
49
+ s.required(:a)
50
+ end
51
+ switches.a
52
+
53
+ # With switch and argument required
54
+
55
+ switches = Switches.new do |s|
56
+ s.set!(:a, required: true)
57
+ # OR
58
+ s.required!(:a)
59
+ end
60
+ switches.a
61
+
62
+ # With boolean switch
63
+
64
+ switches = Switches.new do |s|
65
+ s.set(:a?)
66
+ # OR
67
+ s.boolean(:a)
68
+ end
69
+ switches.a?
70
+
71
+ # With a default value
72
+
73
+ switches = Switches.new do |s|
74
+ s.set(:a, default: 31)
75
+ end
76
+ switches.a # => 31
77
+
78
+ # With switch cast to an integer
79
+
80
+ switches = Switches.new(include_casting_interface_methods: true) do |s|
81
+ s.set(:a, cast: Integer)
82
+ # OR
83
+ s.set(:a, type: Integer)
84
+ # OR
85
+ s.set(:a, class: Integer)
86
+ # OR
87
+ s.integer(:a)
88
+ end
89
+ switches.a.class # => Integer
90
+
91
+ # With switch cast to a float
92
+
93
+ switches = Switches.new(include_casting_interface_methods: true) do |s|
94
+ s.set(:a, cast: Float)
95
+ # OR
96
+ s.set(:a, type: Float)
97
+ # OR
98
+ s.set(:a, class: Float)
99
+ # OR
100
+ s.float(:a)
101
+ end
102
+ switches.a.class # => Float
103
+
104
+ # With switch cast to an array
105
+
106
+ switches = Switches.new(include_casting_interface_methods: true) do |s|
107
+ s.set(:a, cast: Array)
108
+ # OR
109
+ s.set(:a, type: Array)
110
+ # OR
111
+ s.set(:a, class: Array)
112
+ # OR
113
+ s.float(:a)
114
+ end
115
+ switches.a.class # => Array
116
+
117
+ # With switch cast to a regex
118
+
119
+ switches = Switches.new(include_casting_interface_methods: true) do |s|
120
+ s.set(:a, cast: Regexp)
121
+ # OR
122
+ s.set(:a, type: Regexp)
123
+ # OR
124
+ s.set(:a, class: Regexp)
125
+ # OR
126
+ s.regexp(:a)
127
+ end
128
+ switches.a.class # => Regexp
129
+
130
+ # With a default value and cast to an integer
131
+
132
+ switches = Switches.new(include_casting_interface_methods: true) do |s|
133
+ s.set(:a, default: 31, cast: Integer)
134
+ # OR
135
+ s.set(:a, default: 31, type: Integer)
136
+ # OR
137
+ s.set(:a, default: 31, class: Integer)
138
+ # OR
139
+ s.integer(:a, default: 31)
140
+ end
141
+ switches.a # => 31 if no argument supplied
142
+ switches.a.class # => Integer
143
+
144
+ # With a description of the switch
145
+
146
+ switches = Switches.new do |s|
147
+ s.set(:a){'This is the -a switch.'}
148
+ end
149
+
150
+ # With a banner
151
+
152
+ switches = Switches.new do |s|
153
+ s.banner = 'Here is a banner for the switches.'
154
+ end
155
+
156
+ # Return a hash instead of an object of class Switches
157
+
158
+ switches = Switches.new(to_h: true) do |s|
159
+ s.set(:a)
160
+ end
161
+ # OR
162
+ switches = Switches.as_h do |s|
163
+ s.set(:a)
164
+ end
165
+
166
+ switches[:a]
167
+ switches.class # => Hash
168
+
169
+ # Without a block
170
+
171
+ switches = Switches.new
172
+ switches.set(:a)
173
+ switches.parse!
174
+ switches.a
175
+
176
+ # With an action
177
+
178
+ switches = Switches.new do |s|
179
+ switches.perform(:a){puts 'a'}
180
+ switches.parse! # => a
181
+
182
+ # With an action uses the argument
183
+
184
+ switches = Switches.new do |s|
185
+ switches.perform(:a){|block_arg| puts block_arg.upcase}
186
+ switches.parse! # => A
187
+
188
+ # With multiple features combined
189
+
190
+ switches = Switches.new(include_casting_interface_methods: true, to_h: true) do |s|
191
+ s.set(:a, default: 31, cast: Integer){'This is the switch -a. It has a default of 31.'}
192
+ # OR
193
+ s.set(:a, default: 31, type: Integer){'This is the switch -a. It has a default of 31.'}
194
+ # OR
195
+ s.set(:a, default: 31, class: Integer){'This is the switch -a. It has a default of 31.'}
196
+ # OR
197
+ s.integer(:a, default: 31){'This is the switch -a. It has a default of 31.'}
198
+ end
199
+ switches[:a] # => 31 if no argument supplied
200
+ switches.a.class # => Integer
201
+ switches.class # => Hash
202
+
203
+ ```
204
+
205
+ ## Contributing
206
+
207
+ 1. Fork it ( https://github.com/thoran/HTTP/fork )
208
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
209
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
210
+ 4. Push to the branch (`git push origin my-new-feature`)
211
+ 5. Create a new pull request
data/lib/Switches.rb ADDED
@@ -0,0 +1,471 @@
1
+ # Switches.rb
2
+ # Switches
3
+
4
+ # 20180403
5
+ # 0.9.15
6
+
7
+ # Description: Switches provides for a nice wrapper to OptionParser to also act as a store for switches supplied.
8
+
9
+ # Todo:
10
+ # 1. Clean up #set. Done as of 0.4.0.
11
+ # 2. Reinstitute some specs. Done as of 0.9.8.
12
+
13
+ # Ideas:
14
+ # 1. Use ! for options with required switches? Done as of 0.6.0. (Changed to being for required arguments in 0.9.0 however.)
15
+ # 2. Do away with optional arguments entirely. Since when does anyone want to specify a non-boolean switch and then supply no arguments anyway?... OK, maybe sometimes, but this is pretty obscure IMO. OK, bad idea. These can be used as action oriented sub-commands.
16
+ # 3. Allow for any one of the switches OpenStruct methods to assign values for any of the other associated methods, so as it is more than a read once switch and can be used for storage through out the application; although this might be stepping on Attributes.rb's toes?...
17
+
18
+ # Notes:
19
+ # 1. A limitation is the inability to use the switch, "-?", since there is no Ruby method, #?.
20
+ # 2. An additional limitation is that the Switches class cannot have methods which are the same as any OptionParser methods since these will be forwarded to the OptionParser instance, @op.
21
+ # 3. In 0.9.0 there is finally now a clear demarcation between switch arguments and switches themselves being mandatory or optional.
22
+ # 4. It mostly makes sense that the Switches interface methods are bang methods, since it is modifying that switch in place with a required argument, rather than relying upon a default or otherwise set value elsewhere and presumably later than when the switch was set.
23
+
24
+ # Dependencies:
25
+ # 1. Standard Ruby Library.
26
+
27
+ # Changes since 0.8:
28
+ # (Renamed this project/class from Options to Switches since there are required switches now and required options don't make sense.)
29
+ # 1. /Options/Switches/.
30
+ # 2. /RequiredOptionMissing/RequiredSwitchMissing/.
31
+ # 3. /String#boolean_arg?/String#boolean_switch?/.
32
+ # 4. Other references to options changed to switches.
33
+ # 5. + Switches#required/mandatory/necessary.
34
+ # 6. + Swtiches#optional.
35
+ # 7. + Switches#supplied_switches.
36
+ # 8. + Switches#set_unused_switches_to_nil.
37
+ # 9. ~ self-run section to reflect new interface.
38
+ # 0/1 (Removed ! from switch setting methods and moved those to the Switches interface methods.)
39
+ # 10. + Switches#do_set.
40
+ # 11. ~ Switches#set.
41
+ # 12. + Switches#set!.
42
+ # 13. + Switches#required!.
43
+ # 14. - String#required_arg?.
44
+ # 15. ~ Switches#on_args + requires_argument.
45
+ # 1/2 (Added casting to nominated Ruby classes.)
46
+ # 16. ~ Switches#on_args + options.
47
+ # 17. + Array#extract_options!.
48
+ # 18. + Switches#allowed.
49
+ # 19. + Switches#allowed!.
50
+ # 20. + Swithces#mandatory.
51
+ # 21. + Switches#necessary.
52
+ # 22. ~ Switches#do_set + ...options.
53
+ # 23. ~ Switches#on_args + ...options[:cast].
54
+ # 24. ~ self-run section to do a simple test of casting.
55
+ # 2/3 (Renaming the library file.)
56
+ # 25. /Options.rb/Switches.rb/.
57
+ # 3/4 (+ casting interface methods)
58
+ # 26. + CastingInterfaceMethods#integer(!).
59
+ # 27. + CastingInterfaceMethods#float(!).
60
+ # 28. + CastingInterfaceMethods#array(!).
61
+ # 29. + CastingInterfaceMethods#regex(p)(!).
62
+ # 30. + CastingInterfaceMethods#boolean(!).
63
+ # 31. ~ Switches#initialize + include_casting_interface_methods.
64
+ # 32. /String#short_arg?/String#short_switch?/.
65
+ # 33. /String#long_arg?/String#long_switch?/.
66
+ # 34. ~ Switches#on_args - boolean_switch.
67
+ # 4/5 (Added default values for switches.)
68
+ # 35. ~ CastingInterfaceMethods to extract any options before pushing a cast option, since it was overwriting for those casting interface methods.
69
+ # 36. ~ Switches#initialize, + @defaults.
70
+ # 37. /Switches#set_unused_switches_to_nil/Switches#set_unused_switches/.
71
+ # 38. ~ Switches#set_unused_switches, so as it handles setting unused switches with a default.
72
+ # 5/6 (Setting of defaults was overriding supplied switch values.)
73
+ # 39. ~ Switches#set_unused_switches, to make use of #switch_defaults and #unused_switches.
74
+ # 40. + Switches#switch_defaults, as an interface method since it might be useful for querying at some point?
75
+ # 41. + Switches#unused_switches, also as an interface method since it might also be useful for querying at some point?
76
+ # 42. ~ Switches#on_args, so as to enable alternate hash keys (:type and :class) for type casting.
77
+ # 43. ~ self-run section to reflect the optionalness/optionality(?) of summaries.
78
+ # 6/7 (Some small tidyups and removal of self-run section.)
79
+ # 44. ~ Switches#on_args, shorter when handling casting arguments.
80
+ # 45. /unused_switches/unset_switches/.
81
+ # 46. ~ Switches#check_required_switches, so that the message is not being assigned until a switch is missing.
82
+ # 47. Removed the self-run section and moved it to ./test/run.rb.
83
+ # 7/8 (Addition of #perform and #perform! methods, as well the #do_action method and changes to #on_args to facilitate #perform* methods.)
84
+ # 48. ~ Switches#on_args, so as if a block is supplied which is not returning a String, then it will not be placed into the on_args argument list.
85
+ # 49. + Switches#perform, interface for actions which don't require an argument.
86
+ # 50. + Switches#perform!, interface for actions which do require an argument.
87
+ # 51. + Switches#do_action, executes a block when called by either of #perform or #perform!.
88
+ # 8/9
89
+ # 52. ~ Switches#check_required_switches, so as it now assembles the complete list of missing switches rather than failing on and reporting only the first.
90
+ # 53. + Switches#required_perform
91
+ # 54. + Switches#required_perform!
92
+ # 55. - OptionParse#soft_parse, since this was never used here, but only in Attributes.
93
+ # 56. + Object#default_is(et.al.)
94
+ # 57. + NilClass#default_is(et.al.) overrides Object#default_is for the specific case of nil.
95
+ # 58. /switches_defaults/switches_with_defaults/.
96
+ # 59. + Array#peek_options.
97
+ # 60. + Array#poke_options!.
98
+ # 61. + Array#all_but_last.
99
+ # 62. + Array#last!.
100
+ # 63. + Module#alias_methods.
101
+ # 64. ~ CastingInterfaceMethods, to make use of Array#poke_options.
102
+ # 65. + CastingInterfaceMethods#flag.
103
+ # 66. + Switches.as_h (and associated aliased interfaces).
104
+ # 67. ~ Switches#initialize, arguments are now a splat with the intention of allowing both casting_interface_methods and as_h being specified as a hash supplied to the initialiser.
105
+ # 68. ~ Switches, to make use of Module#alias_methods.
106
+ # 69. ~ Switches, to make use of Array#peek_options and Array#poke_options!.
107
+ # 70. + Switches#required_perform.
108
+ # 71. + Switches#required_perform!.
109
+ # 72. + Switches#switches_with_defaults.
110
+ # 73. + Switches#switches_with_castings.
111
+ # 74. + Swtiches#to_h.
112
+ # 75. + Switches#set_if_required_switch.
113
+ # 76. + Switches#set_switches_with_defaults.
114
+ # 77. ~ Switches#parse!, + set_switches_with_defaults() and + to_h().
115
+ # 78. ~ Switches#do_set, + set_if_required_switch().
116
+ # 79. ~ Switches#do_action, + set_if_required_switch().
117
+ # 80. ~ Switches#on_args, so as it can handle castings.
118
+ # 9/10
119
+ # 81. + OpenStruct#to_h.
120
+ # 82. ~ Switches#to_h.
121
+ # 10/11 (Whoops! The defaults were overwriting the supplied settings.)
122
+ # 83. ~ Switches#set_switches_with_defaults to check if a setting had been set before applying a default value.
123
+ # 10/11
124
+ # 84.
125
+ # 11/12 (Removed default aliases for default_to, since it clashes with the mail gem's Mail::Message#default method.)
126
+ # 85. - Object#default.
127
+ # 86. - NilClass#default.
128
+ # 12/13
129
+ # 87. Swapped out a couple of @settings.instance_variable_get(:@table)'s for OpenStruct#to_h's.
130
+ # 13/14
131
+ # 88. README is now markdown.
132
+ # 89. - examples directory
133
+ # 90. Version number bump to 0.9.14.
134
+ # 91. Turned into a gem (+ switches.gemspec).
135
+ # 14/15
136
+ # 92. switches gem name taken, so renamed the gem to switches.rb.
137
+ # 93. Version number bump to 0.9.15.
138
+ # 94. Tidied some comments in spec/all.rb.
139
+
140
+ require 'optparse'
141
+ require 'ostruct'
142
+
143
+ class OpenStruct
144
+
145
+ def to_h
146
+ @table
147
+ end
148
+
149
+ end
150
+
151
+ class String
152
+
153
+ def short_switch?
154
+ self =~ /^.$/ || self =~ /^.\?$/ || self =~ /^.\!$/
155
+ end
156
+
157
+ def long_switch?
158
+ (self =~ /^..+$/ && !short_switch?) || self =~ /^..+\?$/ || self =~ /^..+!$/
159
+ end
160
+
161
+ def boolean_switch?
162
+ self =~ /\?$/
163
+ end
164
+
165
+ end
166
+
167
+ class Array
168
+
169
+ def extract_options!
170
+ last.is_a?(::Hash) ? pop : {}
171
+ end
172
+
173
+ def peek_options
174
+ last.is_a?(::Hash) ? last : {}
175
+ end
176
+
177
+ def poke_options!(h)
178
+ self << self.extract_options!.merge(h)
179
+ end
180
+
181
+ alias_method :last!, :pop
182
+
183
+ def all_but_last
184
+ d = self.dup
185
+ d.last!
186
+ d
187
+ end
188
+
189
+ end
190
+
191
+ class Object
192
+
193
+ def default_is(o)
194
+ self
195
+ end
196
+ alias_method :defaults_to, :default_is
197
+ alias_method :default_to, :default_is
198
+
199
+ end
200
+
201
+ class NilClass
202
+
203
+ def default_is(o)
204
+ o
205
+ end
206
+ alias_method :defaults_to, :default_is
207
+ alias_method :default_to, :default_is
208
+
209
+ end
210
+
211
+ class Module
212
+
213
+ def alias_methods(*args)
214
+ args.all_but_last.each{|e| alias_method e.to_sym, args.last.to_sym}
215
+ end
216
+
217
+ end
218
+
219
+ module CastingInterfaceMethods
220
+
221
+ def integer(*attrs, &block)
222
+ attrs.poke_options!({:cast => Integer})
223
+ set(*attrs, &block)
224
+ end
225
+
226
+ def integer!(*attrs, &block)
227
+ attrs.poke_options!({:cast => Integer})
228
+ set!(*attrs, &block)
229
+ end
230
+
231
+ def float(*attrs, &block)
232
+ attrs.poke_options!({:cast => Float})
233
+ set(*attrs, &block)
234
+ end
235
+
236
+ def float!(*attrs, &block)
237
+ attrs.poke_options!({:cast => Float})
238
+ set!(*attrs, &block)
239
+ end
240
+
241
+ def array(*attrs, &block)
242
+ attrs.poke_options!({:cast => Array})
243
+ set(*attrs, &block)
244
+ end
245
+
246
+ def array!(*attrs, &block)
247
+ attrs.poke_options!({:cast => Array})
248
+ set!(*attrs, &block)
249
+ end
250
+
251
+ def regexp(*attrs, &block)
252
+ attrs.poke_options!({:cast => Regexp})
253
+ set(*attrs, &block)
254
+ end
255
+ alias_method :regex, :regexp
256
+
257
+ def regexp!(*attrs, &block)
258
+ attrs.poke_options!({:cast => Regexp})
259
+ set!(*attrs, &block)
260
+ end
261
+ alias_method :regex!, :regexp!
262
+
263
+ def boolean(*attrs, &block)
264
+ attrs.collect!{|a| a.to_s =~ /\?$/ ? a : (a.to_s + '?').to_sym}
265
+ set(*attrs, &block)
266
+ end
267
+ alias_method :flag, :boolean
268
+
269
+ end
270
+
271
+ class RequiredSwitchMissing < RuntimeError; end
272
+
273
+ class Switches
274
+
275
+ class << self
276
+
277
+ def as_h(*args)
278
+ switches = new(*args)
279
+ switches.to_h
280
+ end
281
+ alias_methods :to_h, :as_hash, :as_a_hash, :as_h
282
+
283
+ end
284
+
285
+ attr_accessor :settings
286
+
287
+ def initialize(*args)
288
+ options = args.extract_options!
289
+ self.class.send(:include, CastingInterfaceMethods) if options[:include_casting_interface_methods].default_is(true)
290
+ @as_h = (options[:as_h] || options[:to_h] || options[:as_hash] || options[:as_a_hash]).default_is(false)
291
+ @settings = OpenStruct.new
292
+ @op = OptionParser.new
293
+ @required_switches = []
294
+ @all_switches = []
295
+ @defaults = {}
296
+ @castings = {}
297
+ if block_given?
298
+ yield self
299
+ parse!
300
+ end
301
+ end
302
+
303
+ def set(*attrs, &block)
304
+ do_set(false, *attrs, &block)
305
+ end
306
+ alias_methods :optional_switch, :optional, :set
307
+
308
+ def set!(*attrs, &block)
309
+ do_set(true, *attrs, &block)
310
+ end
311
+ alias_methods :optional_switch!, :optional!, :set!
312
+
313
+ def required(*attrs, &block)
314
+ attrs.poke_options!({:required => true})
315
+ set(*attrs, &block)
316
+ end
317
+ alias_method :required_switch, :required
318
+
319
+ def required!(*attrs, &block)
320
+ attrs.poke_options!({:required => true})
321
+ set!(*attrs, &block)
322
+ end
323
+ alias_method :required_switch!, :required!
324
+
325
+ def perform(*attrs, &block)
326
+ do_action(false, *attrs, &block)
327
+ end
328
+ alias_methods :optionally_perform, :optional_perform, :perform
329
+
330
+ def perform!(*attrs, &block)
331
+ do_action(true, *attrs, &block)
332
+ end
333
+ alias_methods :optionally_perform!, :optional_perform!, :perform!
334
+
335
+ def required_perform(*attrs, &block)
336
+ attrs.poke_options!({:required => true})
337
+ perform(*attrs, &block)
338
+ end
339
+
340
+ def required_perform!(*attrs, &block)
341
+ attrs.poke_options!({:required => true})
342
+ perform!(*attrs, &block)
343
+ end
344
+
345
+ def parse!
346
+ @op.parse!
347
+ check_required_switches
348
+ set_switches_with_defaults
349
+ set_unset_switches
350
+ to_h if @as_h
351
+ end
352
+
353
+ def supplied_switches
354
+ @settings.to_h.keys.collect{|s| s.to_s}
355
+ end
356
+
357
+ def switches_with_defaults
358
+ @defaults.keys.collect{|default| default.to_s}
359
+ end
360
+
361
+ def switches_with_castings
362
+ @castings.keys.collect{|default| default.to_s}
363
+ end
364
+
365
+ def unset_switches
366
+ @all_switches - supplied_switches - switches_with_defaults
367
+ end
368
+
369
+ def to_h
370
+ @settings.to_h
371
+ end
372
+
373
+ private
374
+
375
+ def do_set(requires_argument, *attrs, &block)
376
+ set_if_required_switch(*attrs)
377
+ options = attrs.extract_options!
378
+ @all_switches = @all_switches + attrs.collect{|a| a.to_s}
379
+ @op.on(*on_args(requires_argument, options, *attrs, &block)) do |o|
380
+ attrs.each do |attr|
381
+ @settings.send(attr.to_s + '=', o)
382
+ end
383
+ end
384
+ end
385
+
386
+ def do_action(requires_argument, *attrs, &block)
387
+ attrs.each do |attr|
388
+ @settings.send(attr.to_s + '=', nil) # Needs to be set prior to checking for required switches, since that check relies upon the key having been set in @settings.
389
+ end
390
+ set_if_required_switch(*attrs)
391
+ options = attrs.extract_options!
392
+ @all_switches = @all_switches + attrs.collect{|a| a.to_s}
393
+ @op.on(*on_args(requires_argument, options, *attrs)) do |o|
394
+ yield o if block
395
+ end
396
+ end
397
+
398
+ def method_missing(method_name, *args, &block)
399
+ if (@op.methods - Switches.instance_methods).include?(method_name.to_s)
400
+ @op.send(method_name.to_s, *args, &block)
401
+ else
402
+ @settings.send(method_name.to_s, *args, &block)
403
+ end
404
+ end
405
+
406
+ def on_args(requires_argument, options, *attrs, &block)
407
+ on_args = []
408
+ attrs.collect{|e| e.to_s}.each do |attr|
409
+ @defaults[attr] = options[:default] if options[:default]
410
+ @castings[attr] = (options[:cast] || options[:type] || options[:class]) if (options[:cast] || options[:type] || options[:class])
411
+ on_args << "-#{attr.long_switch? ? '-' : ''}#{attr.to_s.delete('?')}"
412
+ end
413
+ if requires_argument
414
+ on_args << (on_args.pop + ' REQUIRED_ARGUMENT')
415
+ elsif !!attrs.last.to_s.boolean_switch?
416
+ on_args << (on_args.pop)
417
+ else
418
+ on_args << (on_args.pop + ' [OPTIONAL_ARGUMENT]')
419
+ end
420
+ on_args << (options[:cast] || options[:type] || options[:class]) if (options[:cast] || options[:type] || options[:class])
421
+ if block
422
+ yield_result = yield
423
+ on_args << yield_result if yield_result.class == String
424
+ end
425
+ on_args
426
+ end
427
+
428
+ def check_required_switches
429
+ messages = []
430
+ @required_switches.each do |required_switch|
431
+ unless supplied_switches.include?(required_switch)
432
+ messages << "required switch, -#{required_switch.long_switch? ? '-' : ''}#{required_switch.to_s.delete('?')}, is missing"
433
+ end
434
+ end
435
+ unless messages.empty?
436
+ raise RequiredSwitchMissing, messages.join("\n")
437
+ end
438
+ end
439
+
440
+ def set_switches_with_defaults
441
+ switches_with_defaults.each do |switch|
442
+ if @settings.to_h[switch.to_sym].nil?
443
+ if switches_with_castings.include?(switch)
444
+ cast_value = (
445
+ case @castings[switch]
446
+ when Integer; @defaults[switch].to_i
447
+ when Float; @defaults[switch].to_f
448
+ when Array; @defaults[switch].to_a
449
+ when Regexp; Regexp.new(@defaults[switch])
450
+ end
451
+ )
452
+ @settings.send(switch + '=', cast_value)
453
+ else
454
+ @settings.send(switch + '=', @defaults[switch])
455
+ end
456
+ end
457
+ end
458
+ end
459
+
460
+ def set_unset_switches
461
+ unset_switches.each{|switch| @settings.send(switch + '=', nil)}
462
+ end
463
+
464
+ def set_if_required_switch(*attrs)
465
+ if (attrs.peek_options[:required] || attrs.peek_options[:required_switch])
466
+ attrs.extract_options!
467
+ @required_switches = @required_switches + attrs.collect{|a| a.to_s}
468
+ end
469
+ end
470
+
471
+ end
data/spec/all.rb ADDED
@@ -0,0 +1,222 @@
1
+ require "#{File.dirname(__FILE__)}/../lib/Switches"
2
+
3
+ class Array
4
+
5
+ alias_method :empty!, :clear
6
+
7
+ end
8
+
9
+ describe Switches do
10
+
11
+ describe ".new" do
12
+
13
+ it "should return an object of class Switches" do
14
+ Switches.new.class.should == Switches
15
+ end
16
+
17
+ end
18
+
19
+ describe "#set" do
20
+
21
+ def setup(switches_string = '')
22
+ ARGV.empty!
23
+ switches_string.split.each{|a| ARGV << a}
24
+ Switches.new do |s|
25
+ s.set :v?, :verbose?
26
+ s.set :p, :port
27
+ s.set :host, :h
28
+ end
29
+ end
30
+
31
+ it "should set a short boolean switch or flag to true when supplied with a short switch" do
32
+ setup('-v').v?.should == true
33
+ end
34
+
35
+ it "should set a long boolean switch value to true when supplied with a short switch" do
36
+ setup('-v').verbose?.should == true
37
+ end
38
+
39
+ it "should set a short boolean switch or flag to true when supplied with a long switch" do
40
+ setup('--verbose').v?.should == true
41
+ end
42
+
43
+ it "should set a long boolean switch or flag to true when supplied with a long switch" do
44
+ setup('--verbose').verbose?.should == true
45
+ end
46
+
47
+ it "should set a short switch value to the value supplied when supplied with a short switch" do
48
+ setup('-p 22').p.should == '22'
49
+ end
50
+
51
+ it "should set a long switch value to the value supplied when supplied with a short switch" do
52
+ setup('-p 22').port.should == '22'
53
+ end
54
+
55
+ it "should set a short switch value to the value supplied when supplied with a long switch" do
56
+ setup('--port 22').p.should == '22'
57
+ end
58
+
59
+ it "should set a long switch value to the value supplied when supplied with a long switch" do
60
+ setup('--port 22').port.should == '22'
61
+ end
62
+
63
+ it "shouldn't matter in which order the short and long switches are given" do
64
+ setup('-h example.com').h.should == 'example.com'
65
+ setup('--host example.com').h.should == 'example.com'
66
+ end
67
+
68
+ end # describe "#set"
69
+
70
+ describe "#set!" do
71
+
72
+ def setup(switches_string = '')
73
+ ARGV.empty!
74
+ switches_string.split.each{|a| ARGV << a}
75
+ Switches.new do |s|
76
+ s.set! :p, :port
77
+ end
78
+ end
79
+
80
+ it "should set a short switch value to the argument supplied with a short switch" do
81
+ setup('-p 22').p.should == '22'
82
+ end
83
+
84
+ it "should set a long switch value to the argument supplied with a short switch" do
85
+ setup('-p 22').port.should == '22'
86
+ end
87
+
88
+ it "should set a short switch value to the argument supplied with a long switch" do
89
+ setup('--port 22').p.should == '22'
90
+ end
91
+
92
+ it "should set a long switch value to the argument supplied with a long switch" do
93
+ setup('--port 22').port.should == '22'
94
+ end
95
+
96
+ it "should raise a MissingArgument error when no argument is supplied to a short switch" do
97
+ switches = lambda{setup('-p')}
98
+ switches.should{raise MissingArgument}
99
+ end
100
+
101
+ it "should raise a MissingArgument error when no argument is supplied to a long switch" do
102
+ switches = lambda{setup('--port')}
103
+ switches.should{raise MissingArgument}
104
+ end
105
+
106
+ end # describe "#set!"
107
+
108
+ describe "#required" do
109
+
110
+ def setup(switches_string = '')
111
+ ARGV.empty!
112
+ switches_string.split.each{|a| ARGV << a}
113
+ Switches.new do |s|
114
+ s.required :p, :port
115
+ end
116
+ end
117
+
118
+ it "should set a short switch value to the argument supplied with a short switch" do
119
+ setup('-p 22').p.should == '22'
120
+ end
121
+
122
+ it "should set a long switch value to the argument supplied with a short switch" do
123
+ setup('-p 22').port.should == '22'
124
+ end
125
+
126
+ it "should set a short switch value to the argument supplied with a long switch" do
127
+ setup('--port 22').p.should == '22'
128
+ end
129
+
130
+ it "should set a long switch value to the argument supplied with a long switch" do
131
+ setup('--port 22').port.should == '22'
132
+ end
133
+
134
+ it "should raise a RequiredSwitchMissing error no switch is supplied" do
135
+ switches = lambda{setup}
136
+ switches.should{raise RequiredSwitchMissing}
137
+ end
138
+
139
+ end # describe "#required"
140
+
141
+ describe "#required!" do
142
+
143
+ def setup(switches_string = '')
144
+ ARGV.empty!
145
+ switches_string.split.each{|a| ARGV << a}
146
+ Switches.new do |s|
147
+ s.required! :p, :port
148
+ end
149
+ end
150
+
151
+ it "should set a short switch value to the argument supplied with a short switch" do
152
+ setup('-p 22').p.should == '22'
153
+ end
154
+
155
+ it "should set a long switch value to the argument supplied with a short switch" do
156
+ setup('-p 22').port.should == '22'
157
+ end
158
+
159
+ it "should set a short switch value to the argument supplied with a long switch" do
160
+ setup('--port 22').p.should == '22'
161
+ end
162
+
163
+ it "should set a long switch value to the argument supplied with a long switch" do
164
+ setup('--port 22').port.should == '22'
165
+ end
166
+
167
+ it "should raise a MissingArgument error when no argument is supplied to a short switch" do
168
+ switches = lambda{setup('-p')}
169
+ switches.should{raise MissingArgument}
170
+ end
171
+
172
+ it "should raise a MissingArgument error when no argument is supplied to a long switch" do
173
+ switches = lambda{setup('-p')}
174
+ switches.should{raise MissingArgument}
175
+ end
176
+
177
+ it "should raise a RequiredSwitchMissing error no switch is supplied" do
178
+ switches = lambda{setup}
179
+ switches.should{raise RequiredSwitchMissing}
180
+ end
181
+
182
+ end # describe "#required!"
183
+
184
+ describe "#perform" do
185
+
186
+ def setup(switches_string = '')
187
+ ARGV.empty!
188
+ switches_string.split.each{|a| ARGV << a}
189
+ Switches.new do |s|
190
+ s.perform(:action){an_action}
191
+ end
192
+ end
193
+
194
+ def an_action
195
+ 'value'
196
+ end
197
+
198
+ it "should send(:an_action)"
199
+
200
+ end # describe "#perform"
201
+
202
+ describe "#perform!" do
203
+
204
+ def setup(switches_string = '')
205
+ ARGV.empty!
206
+ switches_string.split.each{|a| ARGV << a}
207
+ Switches.new do |s|
208
+ s.perform(:action){an_action}
209
+ end
210
+ end
211
+
212
+ def an_action
213
+ 'value'
214
+ end
215
+
216
+ it "should send(:an_action)"
217
+
218
+ it "should require a block parameter"
219
+
220
+ end # describe "#perform!"
221
+
222
+ end # describe Switches
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'switches.rb' # I would have preferred 'switches', but there's a gem with the name of switches.
3
+
4
+ s.version = '0.9.15'
5
+ s.date = '2018-04-03'
6
+
7
+ s.summary = "The easiest way to provide switches to a Ruby program."
8
+ s.description = "Switches provides for a nice wrapper to OptionParser to also act as a store for switches supplied."
9
+ s.author = 'thoran'
10
+ s.email = 'code@thoran.com'
11
+ s.homepage = "http://github.com/thoran/switches"
12
+
13
+ s.files = [
14
+ 'README.md',
15
+ 'switches.rb.gemspec',
16
+ Dir['lib/**/*.rb'],
17
+ Dir['spec/**/*.rb']
18
+ ].flatten
19
+
20
+ s.require_paths = ['lib']
21
+
22
+ s.has_rdoc = false
23
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: switches.rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.15
5
+ platform: ruby
6
+ authors:
7
+ - thoran
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-03 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Switches provides for a nice wrapper to OptionParser to also act as a
14
+ store for switches supplied.
15
+ email: code@thoran.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - README.md
21
+ - lib/Switches.rb
22
+ - spec/all.rb
23
+ - switches.rb.gemspec
24
+ homepage: http://github.com/thoran/switches
25
+ licenses: []
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 2.7.4
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: The easiest way to provide switches to a Ruby program.
47
+ test_files: []