cliutils 1.4.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/HISTORY.md +9 -0
- data/README.md +15 -639
- data/lib/cliutils/constants.rb +1 -1
- data/lib/cliutils/messaging.rb +112 -0
- data/lib/cliutils/prefs/pref.rb +113 -66
- data/lib/cliutils/prefs/pref_actions/open_url_action.rb +6 -2
- data/lib/cliutils/prefs/pref_actions/pref_action.rb +18 -9
- data/lib/cliutils/prefs/pref_behaviors/capitalize_behavior.rb +11 -0
- data/lib/cliutils/prefs/pref_behaviors/expand_filepath_behavior.rb +12 -0
- data/lib/cliutils/prefs/pref_behaviors/lowercase_behavior.rb +11 -0
- data/lib/cliutils/prefs/pref_behaviors/pref_behavior.rb +26 -0
- data/lib/cliutils/prefs/pref_behaviors/prefix_behavior.rb +11 -0
- data/lib/cliutils/prefs/pref_behaviors/suffix_behavior.rb +11 -0
- data/lib/cliutils/prefs/pref_behaviors/titlecase_behavior.rb +11 -0
- data/lib/cliutils/prefs/pref_behaviors/uppercase_behavior.rb +11 -0
- data/lib/cliutils/prefs/pref_validators/alphabetic_validator.rb +13 -0
- data/lib/cliutils/prefs/pref_validators/alphanumeric_validator.rb +14 -0
- data/lib/cliutils/prefs/pref_validators/date_validator.rb +13 -0
- data/lib/cliutils/prefs/pref_validators/datetime_validator.rb +13 -0
- data/lib/cliutils/prefs/pref_validators/filepath_exists_validator.rb +13 -0
- data/lib/cliutils/prefs/pref_validators/non_nil_validator.rb +13 -0
- data/lib/cliutils/prefs/pref_validators/number_validator.rb +13 -0
- data/lib/cliutils/prefs/pref_validators/pref_validator.rb +31 -0
- data/lib/cliutils/prefs/pref_validators/time_validator.rb +13 -0
- data/lib/cliutils/prefs/pref_validators/url_validator.rb +15 -0
- data/lib/cliutils/pretty_io.rb +0 -112
- data/lib/cliutils.rb +1 -0
- data/test/configurator_test.rb +1 -1
- data/test/hash_extensions_test.rb +1 -1
- data/test/logger_extensions_test.rb +1 -1
- data/test/messenging_test.rb +1 -1
- data/test/prefs_test.rb +1 -1
- data/test/string_extesions_test.rb +1 -1
- data/test/test_files/prefstest.yaml +29 -9
- data/test/test_helper.rb +6 -0
- metadata +22 -4
- data/lib/cliutils/prefs/pref_behavior.rb +0 -58
- data/lib/cliutils/prefs/pref_validation.rb +0 -96
data/lib/cliutils/messaging.rb
CHANGED
@@ -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
|
data/lib/cliutils/prefs/pref.rb
CHANGED
@@ -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
|
-
#
|
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
|
-
|
109
|
-
|
110
|
-
@
|
111
|
-
|
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
|
-
|
135
|
-
|
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
|
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
|
176
|
+
def _check_validators(text)
|
159
177
|
ret = true
|
160
|
-
if @
|
161
|
-
@
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
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 =
|
184
|
-
action_obj.
|
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 =
|
196
|
-
action_obj.
|
197
|
-
|
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
|
-
#
|
202
|
-
#
|
203
|
-
#
|
204
|
-
#
|
205
|
-
|
206
|
-
|
207
|
-
|
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
|
-
|
212
|
-
|
213
|
-
|
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__),
|
218
|
-
|
219
|
-
|
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
|
226
|
-
Object.const_get("CLIUtils::#{
|
227
|
-
rescue
|
228
|
-
messenger.warn("Skipping undefined Pref
|
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
|
-
|
4
|
-
|
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
|
-
#
|
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
|
14
|
+
# is implementing this Action.
|
15
|
+
# @!attribute pref
|
9
16
|
# @return [Pref]
|
10
17
|
attr_accessor :pref
|
11
18
|
|
12
|
-
# Runs the
|
13
|
-
# method implemented here
|
14
|
-
# an
|
15
|
-
#
|
16
|
-
#
|
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
|
20
|
-
|
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
|