cliutils 1.4.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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