cliutils 1.4.2 → 2.0.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/HISTORY.md +9 -0
  4. data/README.md +15 -639
  5. data/lib/cliutils/constants.rb +1 -1
  6. data/lib/cliutils/messaging.rb +112 -0
  7. data/lib/cliutils/prefs/pref.rb +113 -66
  8. data/lib/cliutils/prefs/pref_actions/open_url_action.rb +6 -2
  9. data/lib/cliutils/prefs/pref_actions/pref_action.rb +18 -9
  10. data/lib/cliutils/prefs/pref_behaviors/capitalize_behavior.rb +11 -0
  11. data/lib/cliutils/prefs/pref_behaviors/expand_filepath_behavior.rb +12 -0
  12. data/lib/cliutils/prefs/pref_behaviors/lowercase_behavior.rb +11 -0
  13. data/lib/cliutils/prefs/pref_behaviors/pref_behavior.rb +26 -0
  14. data/lib/cliutils/prefs/pref_behaviors/prefix_behavior.rb +11 -0
  15. data/lib/cliutils/prefs/pref_behaviors/suffix_behavior.rb +11 -0
  16. data/lib/cliutils/prefs/pref_behaviors/titlecase_behavior.rb +11 -0
  17. data/lib/cliutils/prefs/pref_behaviors/uppercase_behavior.rb +11 -0
  18. data/lib/cliutils/prefs/pref_validators/alphabetic_validator.rb +13 -0
  19. data/lib/cliutils/prefs/pref_validators/alphanumeric_validator.rb +14 -0
  20. data/lib/cliutils/prefs/pref_validators/date_validator.rb +13 -0
  21. data/lib/cliutils/prefs/pref_validators/datetime_validator.rb +13 -0
  22. data/lib/cliutils/prefs/pref_validators/filepath_exists_validator.rb +13 -0
  23. data/lib/cliutils/prefs/pref_validators/non_nil_validator.rb +13 -0
  24. data/lib/cliutils/prefs/pref_validators/number_validator.rb +13 -0
  25. data/lib/cliutils/prefs/pref_validators/pref_validator.rb +31 -0
  26. data/lib/cliutils/prefs/pref_validators/time_validator.rb +13 -0
  27. data/lib/cliutils/prefs/pref_validators/url_validator.rb +15 -0
  28. data/lib/cliutils/pretty_io.rb +0 -112
  29. data/lib/cliutils.rb +1 -0
  30. data/test/configurator_test.rb +1 -1
  31. data/test/hash_extensions_test.rb +1 -1
  32. data/test/logger_extensions_test.rb +1 -1
  33. data/test/messenging_test.rb +1 -1
  34. data/test/prefs_test.rb +1 -1
  35. data/test/string_extesions_test.rb +1 -1
  36. data/test/test_files/prefstest.yaml +29 -9
  37. data/test/test_helper.rb +6 -0
  38. metadata +22 -4
  39. data/lib/cliutils/prefs/pref_behavior.rb +0 -58
  40. data/lib/cliutils/prefs/pref_validation.rb +0 -96
@@ -13,6 +13,11 @@ module CLIUtils
13
13
  k.extend(self)
14
14
  end
15
15
 
16
+ # Empty method so that Messaging doesn't freak
17
+ # out when passed a debug message.
18
+ # @return [void]
19
+ def debug(m); end
20
+
16
21
  # Returns a default instance of LoggerDelegator that
17
22
  # delegates to STDOUT only.
18
23
  # @return [LoggerDelegator]
@@ -25,11 +30,118 @@ module CLIUtils
25
30
  LoggerDelegator.new(STDOUT: stdout_logger)
26
31
  end
27
32
 
33
+ # Outputs a formatted-red error message.
34
+ # @param [String] m The message to output
35
+ # @return [void]
36
+ def error(m)
37
+ puts _word_wrap(m, '# ').red
38
+ end
39
+
40
+ # Outputs a formatted-blue informational message.
41
+ # @param [String] m The message to output
42
+ # @return [void]
43
+ def info(m)
44
+ puts _word_wrap(m, '# ').blue
45
+ end
46
+
47
+ # Wraps a block in an opening and closing info message.
48
+ # @param [String] m1 The opening message to output
49
+ # @param [String] m2 The closing message to output
50
+ # @param [<True, False>] multiline Whether the message should be multiline
51
+ # @yield
52
+ # @return [void]
53
+ def info_block(m1, m2 = 'Done.', multiline = false)
54
+ if block_given?
55
+ if multiline
56
+ info(m1)
57
+ else
58
+ print _word_wrap(m1, '# ').blue
59
+ end
60
+
61
+ yield
62
+
63
+ if multiline
64
+ info(m2)
65
+ else
66
+ puts _word_wrap(m2, '# ').blue
67
+ end
68
+ else
69
+ fail 'Did not specify a valid block'
70
+ end
71
+ end
72
+
73
+ # Empty method so that Messaging doesn't freak
74
+ # out when passed a log message.
75
+ # @return [void]
76
+ def log(m); end
77
+
28
78
  # Singleton method to return (or initialize, if needed)
29
79
  # a LoggerDelegator.
30
80
  # @return [LoggerDelegator]
31
81
  def messenger
32
82
  @@messenger ||= default_instance
33
83
  end
84
+
85
+ # Outputs a prompt, collects the user's response, and
86
+ # returns it.
87
+ # @param [String] prompt The prompt to output
88
+ # @param [String] default The default option
89
+ # @param [String] start_dir The directory to start from for autocompletion
90
+ # @return [String]
91
+ def prompt(prompt, default = nil, start_dir = '')
92
+ Readline.completion_append_character = nil
93
+ Readline.completion_proc = lambda do |prefix|
94
+ files = Dir["#{start_dir}#{prefix}*"]
95
+ files.map { |f| File.expand_path(f) }
96
+ .map { |f| File.directory?(f) ? "#{ f }/" : f }
97
+ end
98
+ p = "# #{ prompt }#{ default.nil? ? ':' : " [default: #{ default }]:" } "
99
+ choice = Readline.readline(p.cyan)
100
+ if choice.empty?
101
+ default
102
+ else
103
+ choice
104
+ end
105
+ end
106
+
107
+ # Outputs a formatted-purple section message.
108
+ # @param [String] m The message to output
109
+ # @return [void]
110
+ def section(m)
111
+ puts _word_wrap(m, '---> ').purple
112
+ end
113
+
114
+ # Wraps a block in an opening and closing section message.
115
+ # @param [String] m The opening message to output
116
+ # @param [<True, False>] multiline Whether the message should be multiline
117
+ # @yield
118
+ # @return [void]
119
+ def section_block(m, multiline = true)
120
+ if block_given?
121
+ if multiline
122
+ section(m)
123
+ else
124
+ print _word_wrap(m, '---> ').purple
125
+ end
126
+
127
+ yield
128
+ else
129
+ fail 'Did not specify a valid block'
130
+ end
131
+ end
132
+
133
+ # Outputs a formatted-green success message.
134
+ # @param [String] m The message to output
135
+ # @return [void]
136
+ def success(m)
137
+ puts _word_wrap(m, '# ').green
138
+ end
139
+
140
+ # Outputs a formatted-yellow warning message.
141
+ # @param [String] m The message to output
142
+ # @return [void]
143
+ def warn(m)
144
+ puts _word_wrap(m, '# ').yellow
145
+ end
34
146
  end
35
147
  end
@@ -1,17 +1,35 @@
1
- require 'cliutils/messaging'
2
- require 'cliutils/prefs/pref_behavior'
3
- require 'cliutils/prefs/pref_validation'
4
-
5
1
  module CLIUtils
6
2
  # Pref Class
7
3
  # An individual preference
8
4
  class Pref
9
5
  include Messaging
10
6
 
7
+ # Constant defining an Action
8
+ ASSET_TYPE_ACTION = 0
9
+
10
+ # Constant defining a Behavior
11
+ ASSET_TYPE_BEHAVIOR = 1
12
+
13
+ # Constant defining a Validator
14
+ ASSET_TYPE_VALIDATOR = 2
15
+
16
+ # Contains a listing of asset names for classes and
17
+ # file suffixes.
18
+ # @return [Array]
19
+ @@asset_labels = [
20
+ { class_suffix: 'Action', file_suffix: 'action' },
21
+ { class_suffix: 'Behavior', file_suffix: 'behavior' },
22
+ { class_suffix: 'Validator', file_suffix: 'validator' }
23
+ ]
24
+
11
25
  # Stores the answer to this Pref.
12
26
  # @return [String, Symbol]
13
27
  attr_accessor :answer
14
28
 
29
+ # Stores instantiated Behavior objects.
30
+ # @return [Array]
31
+ attr_accessor :behavior_objects
32
+
15
33
  # Stores the behaviors that this Pref conforms to.
16
34
  # @return [Array]
17
35
  attr_accessor :behaviors
@@ -54,17 +72,29 @@ module CLIUtils
54
72
  # @return [String]
55
73
  attr_accessor :prompt_text
56
74
 
75
+ # Stores instantiated Validators
76
+ # @return [Array]
77
+ attr_accessor :validator_objects
78
+
57
79
  # Stores key/value combinations required to show this Pref.
58
80
  # @return [Hash]
59
81
  attr_accessor :validators
60
82
 
61
- # Initializes a new Pref via passed-in parameters.
83
+ # Initializes a new Pref via passed-in parameters. Also
84
+ # initializes objects for each Validator and Behavior on
85
+ # this Pref.
62
86
  # @param [Hash] params Parameters to initialize
63
87
  # @return [void]
64
88
  def initialize(params = {})
89
+ @behavior_objects = []
90
+ @validator_objects = []
91
+
92
+ # Assign all of the passed params as instance variables.
65
93
  params.each { |key, value| send("#{ key }=", value) }
66
-
67
- # _load_validators if @validators
94
+
95
+ # Instantiate any listed Behaviors or Validators.
96
+ @behaviors.each { |b| _init_and_add_behavior(b) } if @behaviors
97
+ @validators.each { |v| _init_and_add_validator(v) } if @validators
68
98
  end
69
99
 
70
100
  # Custom equality operator for this class.
@@ -105,25 +135,13 @@ module CLIUtils
105
135
  # @param [String] text The text to evaluate
106
136
  # @return [String]
107
137
  def evaluate_behaviors(text)
108
- if @behaviors
109
- modified_text = text
110
- @behaviors.each do |method|
111
- if method.is_a?(Hash)
112
- parameter = method.values[0]
113
- method = method.keys[0]
114
- end
115
-
116
- args = [modified_text, parameter]
117
- if PrefBehavior.respond_to?(method)
118
- modified_text = PrefBehavior.send(method, *args)
119
- else
120
- messenger.warn("Skipping undefined Pref Behavior: #{ b }")
121
- end
138
+ modified_text = text
139
+ if @behavior_objects
140
+ @behavior_objects.each do |b|
141
+ modified_text = b.evaluate(modified_text)
122
142
  end
123
- modified_text
124
- else
125
- text
126
143
  end
144
+ modified_text
127
145
  end
128
146
 
129
147
  # Validates a text against this pref's options and
@@ -131,8 +149,8 @@ module CLIUtils
131
149
  # @param [String] text The text to validate
132
150
  # @return [Boolean]
133
151
  def validate(text)
134
- _confirm_options(text) &&
135
- _confirm_validators(text)
152
+ _check_options(text) &&
153
+ _check_validators(text)
136
154
  end
137
155
 
138
156
  private
@@ -140,7 +158,7 @@ module CLIUtils
140
158
  # Validates a text against the options for this Pref
141
159
  # @param [String] text The text to validate
142
160
  # @return [Boolean]
143
- def _confirm_options(text)
161
+ def _check_options(text)
144
162
  ret = true
145
163
  if @options
146
164
  unless @options.include?(text)
@@ -155,18 +173,14 @@ module CLIUtils
155
173
  # Validates a text against the validators for this Pref
156
174
  # @param [String] text The text to validate
157
175
  # @return [Boolean]
158
- def _confirm_validators(text)
176
+ def _check_validators(text)
159
177
  ret = true
160
- if @validators
161
- @validators.each do |v|
162
- if PrefValidation.respond_to?(v)
163
- validator = PrefValidation.send(v, text)
164
- unless validator.code
165
- @last_error_message = validator.message
166
- ret = false
167
- end
168
- else
169
- messenger.warn("Skipping undefined Pref Validator: #{ v }")
178
+ if @validator_objects
179
+ @validator_objects.each do |v|
180
+ v.validate(text)
181
+ unless v.is_valid
182
+ @last_error_message = v.message
183
+ ret = false
170
184
  end
171
185
  end
172
186
  end
@@ -178,11 +192,10 @@ module CLIUtils
178
192
  def _eval_pre
179
193
  info(@pre[:message])
180
194
  prompt('Press enter to continue')
181
-
195
+
182
196
  if (@pre[:action])
183
- action_obj = _load_action(@pre[:action])
184
- action_obj.pref = self
185
- action_obj.run(@pre[:action_parameters][0])
197
+ action_obj = _init_action(@pre[:action][:name])
198
+ action_obj.run
186
199
  end
187
200
  end
188
201
 
@@ -192,45 +205,79 @@ module CLIUtils
192
205
  info(@post[:message])
193
206
 
194
207
  if (@post[:action])
195
- action_obj = _load_action(@post[:action])
196
- action_obj.pref = self
197
- action_obj.run(@post[:action_parameters][0])
208
+ action_obj = _init_action(@post[:action][:name])
209
+ action_obj.run
210
+ end
211
+ end
212
+
213
+ # Attempts to instantiate a Pre or Post Action based on name; if
214
+ # successful, the new object gets placed in @validator_objects
215
+ # @param [String] path_or_name The path to or name of the Action
216
+ # @return [void]
217
+ def _init_action(path_or_name)
218
+ obj = _load_asset(ASSET_TYPE_ACTION, path_or_name)
219
+ unless obj.nil?
220
+ obj.pref = self
221
+ obj.parameters = @pre[:action][:parameters]
198
222
  end
223
+ obj
199
224
  end
200
225
 
201
- # Loads a Pref Action, instantiates it (if it exists),
202
- # and returns that instance. Note that the passed
203
- # String can be a name (thus translating to an included
204
- # Action) or a filepath to a user-defined Action.
205
- # @param [String] path_or_name The name of or path to an Action
206
- # @return [Object]
207
- def _load_action(path_or_name)
226
+ # Attempts to instantiate a Behavior based on name; if
227
+ # successful, the new object gets placed in @behavior_objects
228
+ # @param [Hash] behavior_hash The Behavior attributes
229
+ # @return [void]
230
+ def _init_and_add_behavior(behavior_hash)
231
+ obj = _load_asset(ASSET_TYPE_BEHAVIOR, behavior_hash[:name])
232
+ unless obj.nil?
233
+ obj.pref = self
234
+ obj.parameters = behavior_hash[:parameters]
235
+ @behavior_objects << obj
236
+ end
237
+ end
238
+
239
+ # Attempts to instantiate a Validator based on name; if
240
+ # successful, the new object gets placed in @validator_objects
241
+ # @param [String] path_or_name The path to or name of the Validator
242
+ # @return [void]
243
+ def _init_and_add_validator(path_or_name)
244
+ obj = _load_asset(ASSET_TYPE_VALIDATOR, path_or_name)
245
+ unless obj.nil?
246
+ obj.pref = self
247
+ @validator_objects << obj
248
+ end
249
+ end
250
+
251
+ # General function to load an asset (a Validator or Behavior).
252
+ # Note that if an asset isn't found, the user is warned, but
253
+ # execution continues.
254
+ # @param [Integer] type ASSET_TYPE_BEHAVIOR or ASSET_TYPE_VALIDATOR
255
+ # @param [String] path_or_name The path to or name of the asset
256
+ # @return [Object]
257
+ def _load_asset(type, path_or_name)
208
258
  if File.exist?(path_or_name)
209
259
  # If the file exists, we're assuming that the user
210
260
  # passed a filepath.
211
- action_path = File.expand_path(path_or_name) if path_or_name.start_with?('~')
212
- action_path = "#{ path_or_name }_action"
213
- action_name = File.basename(path_or_name, '.*').camelize
261
+ asset_path = File.expand_path(path_or_name) if path_or_name.start_with?('~')
262
+ asset_path = "#{ path_or_name }_#{ @@asset_labels[type][:file_suffix] }"
263
+ asset_name = File.basename(path_or_name, '.*').camelize
214
264
  else
215
265
  # If it doesn't, we're assuming that the user
216
266
  # passed a class name.
217
- _default = File.join(File.dirname(__FILE__), 'pref_actions')
218
- action_path = File.join(_default, "#{ path_or_name }_action")
219
- action_name = path_or_name.camelize
267
+ _default = File.join(File.dirname(__FILE__), "pref_#{ @@asset_labels[type][:file_suffix] }s")
268
+ asset_path = File.join(_default, "#{ path_or_name }_#{ @@asset_labels[type][:file_suffix] }")
269
+ asset_name = path_or_name.camelize
220
270
  end
221
271
 
222
272
  # Try to load and instantiate the Action. If that fails, warn
223
273
  # the user with a message and skip over it.
224
274
  begin
225
- require action_path
226
- Object.const_get("CLIUtils::#{ action_name }Action").new
227
- rescue
228
- messenger.warn("Skipping undefined Pref Action: #{ path_or_name }")
275
+ require asset_path
276
+ Object.const_get("CLIUtils::#{ asset_name }#{ @@asset_labels[type][:class_suffix] }").new
277
+ rescue LoadError
278
+ messenger.warn("Skipping undefined Pref #{ @@asset_labels[type][:class_suffix] }: #{ path_or_name }")
279
+ nil
229
280
  end
230
281
  end
231
-
232
- def _load_validators
233
-
234
- end
235
282
  end
236
283
  end
@@ -1,7 +1,11 @@
1
1
  module CLIUtils
2
+ # Pref Action to open a URL in the default
3
+ # browser.
2
4
  class OpenUrlAction < PrefAction
3
- def run(parameters)
4
- `open #{ parameters[:url] }`
5
+ # Runs the action.
6
+ # @return [void]
7
+ def run
8
+ `open #{ @parameters[:url] }`
5
9
  end
6
10
  end
7
11
  end
@@ -1,23 +1,32 @@
1
1
  module CLIUtils
2
2
  # The generic base class for a Pref
3
- # action.
3
+ # Action.
4
4
  class PrefAction
5
5
  include Messaging
6
6
 
7
+ # Holds the parameters that apply to
8
+ # this Action.
9
+ # @!attribute parameters
10
+ # @return [Hash]
11
+ attr_accessor :parameters
12
+
7
13
  # Holds a reference to the pref that
8
- # is implementing this action.
14
+ # is implementing this Action.
15
+ # @!attribute pref
9
16
  # @return [Pref]
10
17
  attr_accessor :pref
11
18
 
12
- # Runs the plugin. Note that the
13
- # method implemented here shows
14
- # an error (indicating that it
15
- # needs to be implemented in a
16
- # subclass).
19
+ # Runs the Action. Note that the
20
+ # method implemented here will throw
21
+ # an exception by default, meaning that
22
+ # the user's subclass *needs* to
23
+ # implement it.
17
24
  # @parameter [Hash] parameters
25
+ # @raise [StandardError] if the subclass
26
+ # doesn't implement this method.
18
27
  # @return [void]
19
- def run(parameters = {})
20
- messenger.error("`run` method not implemented on caller: #{ self.class }")
28
+ def run
29
+ fail "`run` method not implemented on caller: #{ self.class }"
21
30
  end
22
31
  end
23
32
  end
@@ -0,0 +1,11 @@
1
+ module CLIUtils
2
+ # A Behavior to capitalize a Pref answer
3
+ class CapitalizeBehavior < PrefBehavior
4
+ # Evaluates the behavior against the text.
5
+ # @param [Object] text The "text" to evaluate
6
+ # @return [String]
7
+ def evaluate(text)
8
+ text.to_s.capitalize
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ module CLIUtils
2
+ # A Behavior to run File.expand_path on a
3
+ # Pref answer
4
+ class ExpandFilepathBehavior < PrefBehavior
5
+ # Evaluates the behavior against the text.
6
+ # @param [Object] text The "text" to evaluate
7
+ # @return [String]
8
+ def evaluate(text)
9
+ File.expand_path(text.to_s)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module CLIUtils
2
+ # A Behavior to lowecase a Pref answer
3
+ class LowercaseBehavior < PrefBehavior
4
+ # Evaluates the behavior against the text.
5
+ # @param [Object] text The "text" to evaluate
6
+ # @return [String]
7
+ def evaluate(text)
8
+ text.to_s.downcase
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ module CLIUtils
2
+ # The generic base class for a Pref
3
+ # Behavior.
4
+ class PrefBehavior
5
+ include Messaging
6
+
7
+ # Holds the parameters associated with
8
+ # this behavior.
9
+ # @return [Hash]
10
+ attr_accessor :parameters
11
+
12
+ # Holds a reference to the Pref that
13
+ # is applying this Behavior.
14
+ # @return [Pref]
15
+ attr_accessor :pref
16
+
17
+ # Evaluate the Behavior!
18
+ # @parameter [Hash] parameters
19
+ # @raise [StandardError] if the subclass
20
+ # doesn't implement this method.
21
+ # @return [void]
22
+ def evaluate(text = '')
23
+ fail "`evaluate` method not implemented on caller: #{ self.class }"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+ module CLIUtils
2
+ # A Behavior to prefix a Pref answer with a string
3
+ class PrefixBehavior < PrefBehavior
4
+ # Evaluates the behavior against the text.
5
+ # @param [Object] text The "text" to evaluate
6
+ # @return [String]
7
+ def evaluate(text)
8
+ @parameters[:prefix] + text.to_s
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module CLIUtils
2
+ # A Behavior to suffix a Pref answer with a string
3
+ class SuffixBehavior < PrefBehavior
4
+ # Evaluates the behavior against the text.
5
+ # @param [Object] text The "text" to evaluate
6
+ # @return [String]
7
+ def evaluate(text)
8
+ text.to_s + @parameters[:suffix]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module CLIUtils
2
+ # A Behavior to titlecase a Pref answer
3
+ class TitlecaseBehavior < PrefBehavior
4
+ # Evaluates the behavior against the text.
5
+ # @param [Object] text The "text" to evaluate
6
+ # @return [String]
7
+ def evaluate(text)
8
+ text.to_s.split.map(&:capitalize).join(' ')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module CLIUtils
2
+ # A Behavior to uppercase a Pref answer
3
+ class UppercaseBehavior < PrefBehavior
4
+ # Evaluates the behavior against the text.
5
+ # @param [Object] text The "text" to evaluate
6
+ # @return [String]
7
+ def evaluate(text)
8
+ text.to_s.upcase
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module CLIUtils
2
+ # A Validator to verify whether a Pref answer
3
+ # is alphabetic (made up of letters and spaces).
4
+ class AlphabeticValidator < PrefValidator
5
+ # Runs the Validator against the answer.
6
+ # @param [Object] text The "text" to evaluate
7
+ # @return [String]
8
+ def validate(text)
9
+ @is_valid = text.to_s =~ /\A[A-Za-z\s]+\z/
10
+ @message = "Response is not alphabetic: #{ text }"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module CLIUtils
2
+ # A Validator to verify whether a Pref answer
3
+ # is alphanumeric (made up of letters, numbers
4
+ # and spaces).
5
+ class AlphanumericValidator < PrefValidator
6
+ # Runs the Validator against the answer.
7
+ # @param [Object] text The "text" to evaluate
8
+ # @return [String]
9
+ def validate(text)
10
+ @is_valid = text.to_s =~ /\A[A-Za-z0-9\s]+\z/
11
+ @message = "Response is not alphanumeric: #{ text }"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module CLIUtils
2
+ # A Validator to verify whether a Pref answer
3
+ # is a date.
4
+ class DateValidator < PrefValidator
5
+ # Runs the Validator against the answer.
6
+ # @param [Object] text The "text" to evaluate
7
+ # @return [String]
8
+ def validate(text)
9
+ @is_valid = !(Date.parse(text) rescue nil).nil?
10
+ @message = "Response is not a date: #{ text }"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module CLIUtils
2
+ # A Validator to verify whether a Pref answer
3
+ # is a datetime.
4
+ class DatetimeValidator < PrefValidator
5
+ # Runs the Validator against the answer.
6
+ # @param [Object] text The "text" to evaluate
7
+ # @return [String]
8
+ def validate(text)
9
+ @is_valid = !(DateTime.parse(text) rescue nil).nil?
10
+ @message = "Response is not a datetime: #{ text }"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module CLIUtils
2
+ # A Validator to verify whether a Pref answer
3
+ # is a local filepath that exists.
4
+ class FilepathExistsValidator < PrefValidator
5
+ # Runs the Validator against the answer.
6
+ # @param [Object] text The "text" to evaluate
7
+ # @return [String]
8
+ def validate(text)
9
+ @is_valid = Pathname.new(text.to_s).exist?
10
+ @message = "Path does not exist locally: #{ text }"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module CLIUtils
2
+ # A Validator to verify whether a Pref answer
3
+ # is not empty or nil.
4
+ class NonNilValidator < PrefValidator
5
+ # Runs the Validator against the answer.
6
+ # @param [Object] text The "text" to evaluate
7
+ # @return [String]
8
+ def validate(text)
9
+ @is_valid = !text.nil? && !text.empty?
10
+ @message = 'Nil text not allowed'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module CLIUtils
2
+ # A Validator to verify whether a Pref answer
3
+ # is not a number.
4
+ class NumberValidator < PrefValidator
5
+ # Runs the Validator against the answer.
6
+ # @param [Object] text The "text" to evaluate
7
+ # @return [String]
8
+ def validate(text)
9
+ @is_valid = text.to_s =~ /\A[-+]?\d*\.?\d+\z/
10
+ @message = "Response is not a number: #{ text }"
11
+ end
12
+ end
13
+ end