bovem 3.0.5 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -3
- data/.rubocop.yml +82 -0
- data/.travis-gemfile +4 -5
- data/.travis.yml +8 -6
- data/CHANGELOG.md +12 -0
- data/Gemfile +9 -8
- data/README.md +1 -1
- data/Rakefile +22 -6
- data/bovem.gemspec +5 -5
- data/doc/Bovem.html +10 -10
- data/doc/Bovem/Application.html +670 -318
- data/doc/Bovem/Command.html +1447 -1125
- data/doc/Bovem/CommandMethods.html +4 -4
- data/doc/Bovem/CommandMethods/Children.html +173 -179
- data/doc/Bovem/CommandMethods/Help.html +9 -9
- data/doc/Bovem/Configuration.html +239 -24
- data/doc/Bovem/Console.html +267 -128
- data/doc/Bovem/ConsoleMethods.html +4 -4
- data/doc/Bovem/ConsoleMethods/Interactions.html +57 -70
- data/doc/Bovem/ConsoleMethods/Interactions/ClassMethods.html +9 -9
- data/doc/Bovem/ConsoleMethods/Logging.html +258 -298
- data/doc/Bovem/ConsoleMethods/Logging/ClassMethods.html +8 -8
- data/doc/Bovem/ConsoleMethods/Output.html +96 -118
- data/doc/Bovem/ConsoleMethods/StyleHandling.html +8 -8
- data/doc/Bovem/ConsoleMethods/StyleHandling/ClassMethods.html +26 -39
- data/doc/Bovem/Errors.html +4 -4
- data/doc/Bovem/Errors/Error.html +4 -4
- data/doc/Bovem/Errors/InvalidConfiguration.html +4 -4
- data/doc/Bovem/Errors/InvalidLogger.html +4 -4
- data/doc/Bovem/I18n.html +175 -0
- data/doc/Bovem/Logger.html +95 -83
- data/doc/Bovem/Option.html +669 -862
- data/doc/Bovem/Parser.html +10 -10
- data/doc/Bovem/ParserMethods.html +4 -4
- data/doc/Bovem/ParserMethods/General.html +4 -4
- data/doc/Bovem/ParserMethods/General/ClassMethods.html +26 -38
- data/doc/Bovem/Shell.html +169 -48
- data/doc/Bovem/ShellMethods.html +4 -4
- data/doc/Bovem/ShellMethods/Directories.html +46 -62
- data/doc/Bovem/ShellMethods/Execute.html +51 -99
- data/doc/Bovem/ShellMethods/General.html +4 -445
- data/doc/Bovem/ShellMethods/Read.html +56 -61
- data/doc/Bovem/ShellMethods/Write.html +22 -242
- data/doc/Bovem/Version.html +6 -6
- data/doc/_index.html +18 -18
- data/doc/class_list.html +6 -2
- data/doc/css/style.css +1 -0
- data/doc/file.README.html +5 -5
- data/doc/file_list.html +5 -1
- data/doc/frames.html +1 -1
- data/doc/index.html +5 -5
- data/doc/js/full_list.js +4 -1
- data/doc/method_list.html +161 -157
- data/doc/top-level-namespace.html +4 -4
- data/lib/bovem.rb +3 -4
- data/lib/bovem/application.rb +47 -39
- data/lib/bovem/command.rb +175 -193
- data/lib/bovem/configuration.rb +28 -29
- data/lib/bovem/console.rb +244 -171
- data/lib/bovem/errors.rb +1 -1
- data/lib/bovem/i18n.rb +18 -0
- data/lib/bovem/logger.rb +26 -26
- data/lib/bovem/option.rb +49 -58
- data/lib/bovem/parser.rb +174 -222
- data/lib/bovem/shell.rb +272 -320
- data/lib/bovem/version.rb +2 -2
- data/locales/en.yml +39 -38
- data/locales/it.yml +39 -38
- data/spec/bovem/application_spec.rb +6 -5
- data/spec/bovem/command_spec.rb +23 -23
- data/spec/bovem/console_spec.rb +101 -102
- data/spec/bovem/i18n_spec.rb +21 -0
- data/spec/bovem/logger_spec.rb +4 -4
- data/spec/bovem/option_spec.rb +43 -43
- data/spec/bovem/parser_spec.rb +13 -13
- data/spec/bovem/shell_spec.rb +106 -115
- data/spec/spec_helper.rb +19 -6
- metadata +14 -13
- data/doc/Bovem/Localizer.html +0 -376
- data/lib/bovem/localizer.rb +0 -27
- data/spec/coverage_helper.rb +0 -20
data/lib/bovem/configuration.rb
CHANGED
@@ -18,7 +18,11 @@ module Bovem
|
|
18
18
|
# # Configuration file
|
19
19
|
# config.property = "VALUE"
|
20
20
|
# ```
|
21
|
+
#
|
22
|
+
# @attribute [r] i18n
|
23
|
+
# @return [I18n] A i18n helper.
|
21
24
|
class Configuration < Lazier::Configuration
|
25
|
+
attr_reader :i18n
|
22
26
|
# Creates a new configuration.
|
23
27
|
#
|
24
28
|
# A configuration file is a plain Ruby file with a top-level {Configuration config} object.
|
@@ -30,7 +34,7 @@ module Bovem
|
|
30
34
|
def initialize(file = nil, overrides = {}, logger = nil)
|
31
35
|
super()
|
32
36
|
|
33
|
-
|
37
|
+
@i18n = Bovem::I18n.new(root: "bovem.configuration", path: Bovem::Application::LOCALE_ROOT)
|
34
38
|
parse(file, overrides, logger)
|
35
39
|
end
|
36
40
|
|
@@ -50,41 +54,36 @@ module Bovem
|
|
50
54
|
def parse(file = nil, overrides = {}, logger = nil)
|
51
55
|
file = file.present? ? File.expand_path(file) : nil
|
52
56
|
|
53
|
-
if file
|
54
|
-
|
55
|
-
|
56
|
-
else
|
57
|
-
raise Bovem::Errors::InvalidConfiguration.new(i18n.configuration.not_found(file))
|
58
|
-
end
|
57
|
+
if file
|
58
|
+
raise(Bovem::Errors::InvalidConfiguration, i18n.not_found(file)) unless File.readable?(file)
|
59
|
+
read_configuration_file(file, logger)
|
59
60
|
end
|
60
61
|
|
61
62
|
# Apply overrides
|
62
|
-
overrides.each_pair { |k, v| send("#{k}=", v) if
|
63
|
+
overrides.each_pair { |k, v| send("#{k}=", v) if respond_to?("#{k}=") } if overrides.is_a?(::Hash)
|
63
64
|
|
64
65
|
self
|
65
66
|
end
|
66
67
|
|
67
68
|
private
|
68
|
-
# Reads a configuration file.
|
69
|
-
#
|
70
|
-
# @param file [String] The file to read.
|
71
|
-
# @param logger [Logger] The logger to use for notifications.
|
72
|
-
def read_configuration_file(file, logger)
|
73
|
-
begin
|
74
|
-
# Open the file
|
75
|
-
path = file =~ /^#{File::SEPARATOR}/ ? file : ::Pathname.new(file).realpath
|
76
|
-
logger.info(i18n.configuration.using(path)) if logger
|
77
|
-
eval_file(path)
|
78
|
-
rescue Exception
|
79
|
-
raise Bovem::Errors::InvalidConfiguration.new(i18n.configuration.invalid(file))
|
80
|
-
end
|
81
|
-
end
|
82
69
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
70
|
+
# :nodoc:
|
71
|
+
# rubocop:disable RescueException
|
72
|
+
def read_configuration_file(file, logger)
|
73
|
+
# Open the file
|
74
|
+
path = file =~ /^#{File::SEPARATOR}/ ? file : ::Pathname.new(file).realpath
|
75
|
+
logger.info(i18n.configuration.using(path)) if logger
|
76
|
+
eval_file(path)
|
77
|
+
rescue Exception
|
78
|
+
raise(Bovem::Errors::InvalidConfiguration, i18n.invalid(file))
|
79
|
+
end
|
80
|
+
# rubocop:enable RescueException
|
81
|
+
|
82
|
+
# :nodoc:
|
83
|
+
def eval_file(path)
|
84
|
+
# rubocop:disable UnusedBlockArgument, Eval
|
85
|
+
tap { |config| eval(File.read(path)) }
|
86
|
+
# rubocop:enable UnusedBlockArgument, Eval
|
87
|
+
end
|
89
88
|
end
|
90
|
-
end
|
89
|
+
end
|
data/lib/bovem/console.rb
CHANGED
@@ -6,10 +6,10 @@
|
|
6
6
|
|
7
7
|
module Bovem
|
8
8
|
# List of valid terminal colors.
|
9
|
-
TERM_COLORS = {
|
9
|
+
TERM_COLORS = {black: 0, red: 1, green: 2, yellow: 3, blue: 4, magenta: 5, cyan: 6, white: 7, default: 9}.freeze
|
10
10
|
|
11
11
|
# List of valid terminal text effects.
|
12
|
-
TERM_EFFECTS = {
|
12
|
+
TERM_EFFECTS = {reset: 0, bright: 1, italic: 3, underline: 4, blink: 5, inverse: 7, hide: 8}.freeze
|
13
13
|
|
14
14
|
# Methods of the {Console Console} class.
|
15
15
|
module ConsoleMethods
|
@@ -21,14 +21,15 @@ module Bovem
|
|
21
21
|
module ClassMethods
|
22
22
|
# Parse a style and returns terminal codes.
|
23
23
|
#
|
24
|
-
# Supported styles and colors are those in {Bovem::TERM\_COLORS} and {Bovem::TERM\_EFFECTS}.
|
24
|
+
# Supported styles and colors are those in {Bovem::TERM\_COLORS} and {Bovem::TERM\_EFFECTS}.
|
25
|
+
# You can also prefix colors with `bg_` (like `bg_red`) for background colors.
|
25
26
|
#
|
26
27
|
# @param style [String] The style to parse.
|
27
28
|
# @return [String] A string with ANSI color codes.
|
28
29
|
def parse_style(style)
|
29
30
|
style = style.ensure_string.strip.parameterize
|
30
31
|
|
31
|
-
if style.present?
|
32
|
+
if style.present?
|
32
33
|
Bovem::Console.replace_term_code(Bovem::TERM_EFFECTS, style, 0) ||
|
33
34
|
Bovem::Console.replace_term_code(Bovem::TERM_COLORS, style, 30) ||
|
34
35
|
Bovem::Console.replace_term_code(Bovem::TERM_COLORS, style.gsub(/^bg_/, ""), 40) ||
|
@@ -39,7 +40,8 @@ module Bovem
|
|
39
40
|
end
|
40
41
|
|
41
42
|
# Parses a set of styles and returns terminals codes.
|
42
|
-
# Supported styles and colors are those in {Bovem::TERM\_COLORS} and {Bovem::TERM\_EFFECTS}.
|
43
|
+
# Supported styles and colors are those in {Bovem::TERM\_COLORS} and {Bovem::TERM\_EFFECTS}.
|
44
|
+
# You can also prefix colors with `bg_` (like `bg_red`) for background colors.
|
43
45
|
#
|
44
46
|
# @param styles [String] The styles to parse.
|
45
47
|
# @return [String] A string with ANSI color codes.
|
@@ -61,7 +63,8 @@ module Bovem
|
|
61
63
|
|
62
64
|
# Replaces colors markers in a string.
|
63
65
|
#
|
64
|
-
# You can specify markers by enclosing in `{mark=[style]}` and `{/mark}` tags.
|
66
|
+
# You can specify markers by enclosing in `{mark=[style]}` and `{/mark}` tags.
|
67
|
+
# Separate styles with spaces, dashes or commas. Nesting markers is supported.
|
65
68
|
#
|
66
69
|
# Example:
|
67
70
|
#
|
@@ -78,21 +81,28 @@ module Bovem
|
|
78
81
|
stack = []
|
79
82
|
|
80
83
|
message.ensure_string.gsub(/((\{mark=([a-z\-_\s,]+)\})|(\{\/mark\}))/mi) do
|
81
|
-
if $1 == "{/mark}"
|
84
|
+
if $LAST_MATCH_INFO[1] == "{/mark}" # If it is a tag, pop from the latest opened.
|
82
85
|
stack.pop
|
83
86
|
plain || stack.blank? ? "" : Bovem::Console.parse_styles(stack.last)
|
84
87
|
else
|
85
|
-
|
86
|
-
|
88
|
+
add_style($LAST_MATCH_INFO[3], plain, stack)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
87
92
|
|
88
|
-
|
89
|
-
stack << "reset" if stack.blank?
|
90
|
-
stack << styles
|
91
|
-
end
|
93
|
+
private
|
92
94
|
|
93
|
-
|
94
|
-
|
95
|
+
# :nodoc:
|
96
|
+
def add_style(styles, plain, stack)
|
97
|
+
styles = styles.ensure_string
|
98
|
+
replacement = plain ? "" : Bovem::Console.parse_styles(styles)
|
99
|
+
|
100
|
+
unless replacement.empty?
|
101
|
+
stack << "reset" if stack.blank?
|
102
|
+
stack << styles
|
95
103
|
end
|
104
|
+
|
105
|
+
replacement
|
96
106
|
end
|
97
107
|
end
|
98
108
|
|
@@ -146,31 +156,36 @@ module Bovem
|
|
146
156
|
# @param width [Fixnum] The maximum width of a line. Default to the current line width.
|
147
157
|
# @return [String] The wrapped message.
|
148
158
|
def wrap(message, width = nil)
|
149
|
-
if width.to_integer <= 0
|
159
|
+
if width.to_integer <= 0
|
150
160
|
message
|
151
161
|
else
|
152
162
|
width = (width == true || width.to_integer < 0 ? line_width : width.to_integer)
|
153
163
|
|
154
|
-
message.split("\n").map
|
155
|
-
line
|
156
|
-
|
164
|
+
rv = message.split("\n").map do |line|
|
165
|
+
wrap_line(line, width)
|
166
|
+
end
|
167
|
+
|
168
|
+
rv.join("\n")
|
157
169
|
end
|
158
170
|
end
|
159
171
|
|
160
172
|
# Indents a message.
|
161
173
|
#
|
162
174
|
# @param message [String] The message to indent.
|
163
|
-
# @param width [Fixnum] The indentation width. `true` means to use the current indentation, a negative value of `-x`
|
175
|
+
# @param width [Fixnum] The indentation width. `true` means to use the current indentation, a negative value of `-x`
|
176
|
+
# will indent of `x` absolute spaces. `nil` or `false` will skip indentation.
|
164
177
|
# @param newline_separator [String] The character used for newlines.
|
165
178
|
# @return [String] The indented message.
|
166
179
|
def indent(message, width = true, newline_separator = "\n")
|
167
|
-
if width.to_integer != 0
|
180
|
+
if width.to_integer != 0
|
168
181
|
width = (width.is_a?(TrueClass) ? 0 : width.to_integer)
|
169
182
|
width = width < 0 ? -width : @indentation + width
|
170
183
|
|
171
|
-
|
184
|
+
rv = message.split(newline_separator).map do |line|
|
172
185
|
(@indentation_string * width) + line
|
173
|
-
|
186
|
+
end
|
187
|
+
|
188
|
+
message = rv.join(newline_separator)
|
174
189
|
end
|
175
190
|
|
176
191
|
message
|
@@ -184,28 +199,20 @@ module Bovem
|
|
184
199
|
#
|
185
200
|
# @param message [String] The message to format.
|
186
201
|
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
187
|
-
# @param
|
202
|
+
# @param indented [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation,
|
203
|
+
# a negative value of `-x` will indent of `x` absolute spaces.
|
188
204
|
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line. `true` means the current line width.
|
189
205
|
# @param plain [Boolean] If ignore color markers into the message.
|
190
206
|
# @return [String] The formatted message.
|
191
|
-
def format(message, suffix
|
207
|
+
def format(message, suffix: "\n", indented: true, wrap: true, plain: false)
|
192
208
|
rv = message
|
193
209
|
|
194
210
|
rv = replace_markers(rv, plain) # Replace markers
|
195
211
|
|
196
212
|
# Compute the real width available for the screen, if we both indent and wrap
|
197
|
-
if wrap.is_a?(TrueClass)
|
198
|
-
wrap = line_width
|
213
|
+
wrap = compute_wrap(indented) if wrap.is_a?(TrueClass)
|
199
214
|
|
200
|
-
|
201
|
-
wrap -= @indentation
|
202
|
-
else
|
203
|
-
indent_i = indent.to_integer
|
204
|
-
wrap -= (indent_i > 0 ? @indentation : 0) + indent_i
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
rv = indent(wrap(rv, wrap), indent) # Wrap & Indent
|
215
|
+
rv = indent(wrap(rv, wrap), indented) # Wrap & Indent
|
209
216
|
rv += (suffix.is_a?(TrueClass) ? "\n" : suffix.ensure_string) if suffix # Add the suffix
|
210
217
|
rv
|
211
218
|
end
|
@@ -217,7 +224,7 @@ module Bovem
|
|
217
224
|
# @param go_up [Boolean] If go up one line before formatting.
|
218
225
|
# @param plain [Boolean] If ignore color markers into the message.
|
219
226
|
# @return [String] The formatted message.
|
220
|
-
def format_right(message, width
|
227
|
+
def format_right(message, width: true, go_up: true, plain: false)
|
221
228
|
message = replace_markers(message, plain)
|
222
229
|
|
223
230
|
width = (width == true || width.to_integer < 1 ? line_width : to_integer)
|
@@ -237,12 +244,40 @@ module Bovem
|
|
237
244
|
def emphasize(message, style = "bright")
|
238
245
|
"{mark=#{style}}#{message}{/mark}"
|
239
246
|
end
|
247
|
+
|
248
|
+
private
|
249
|
+
|
250
|
+
# :nodoc:
|
251
|
+
def wrap_line(line, width)
|
252
|
+
line.length > width ? line.gsub(/(\S{1,#{width}})(\s+|$)/, "\\1\n#{@indentation_string * @indentation}").rstrip : line
|
253
|
+
end
|
254
|
+
|
255
|
+
# :nodoc:
|
256
|
+
def compute_wrap(indent)
|
257
|
+
wrap = line_width
|
258
|
+
|
259
|
+
if indent.is_a?(TrueClass)
|
260
|
+
wrap -= @indentation
|
261
|
+
else
|
262
|
+
indent_i = indent.to_integer
|
263
|
+
wrap -= (indent_i > 0 ? @indentation : 0) + indent_i
|
264
|
+
end
|
265
|
+
wrap
|
266
|
+
end
|
240
267
|
end
|
241
268
|
|
242
269
|
# Methods for logging activities to the user.
|
243
270
|
module Logging
|
244
271
|
extend ActiveSupport::Concern
|
245
272
|
|
273
|
+
DEFAULT_STATUSES = {
|
274
|
+
ok: {label: " OK ", color: "bright green"},
|
275
|
+
pass: {label: "PASS", color: "bright cyan"},
|
276
|
+
warn: {label: "WARN", color: "bright yellow"},
|
277
|
+
fail: {label: "FAIL", color: "bright red"},
|
278
|
+
skip: {label: "SKIP", color: "gray"}
|
279
|
+
}.freeze
|
280
|
+
|
246
281
|
# Class methods for logging activities to the user.
|
247
282
|
module ClassMethods
|
248
283
|
# Returns the minimum length of a banner, not including brackets and leading spaces.
|
@@ -256,15 +291,16 @@ module Bovem
|
|
256
291
|
#
|
257
292
|
# @param message [String] The message to format.
|
258
293
|
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
259
|
-
# @param
|
294
|
+
# @param indented [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation,
|
295
|
+
# a negative value of `-x` will indent of `x` absolute spaces.
|
260
296
|
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
261
297
|
# @param plain [Boolean] If ignore color markers into the message.
|
262
298
|
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
263
299
|
# @return [String] The printed message.
|
264
300
|
#
|
265
301
|
# @see #format
|
266
|
-
def write(message, suffix
|
267
|
-
rv = format(message, suffix,
|
302
|
+
def write(message, suffix: "\n", indented: true, wrap: false, plain: false, print: true)
|
303
|
+
rv = format(message, suffix: suffix, indented: indented, wrap: wrap, plain: plain)
|
268
304
|
Kernel.puts(rv) if print
|
269
305
|
rv
|
270
306
|
end
|
@@ -273,18 +309,26 @@ module Bovem
|
|
273
309
|
#
|
274
310
|
# @param message [String] The message to format.
|
275
311
|
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
276
|
-
# @param
|
312
|
+
# @param indented [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation,
|
313
|
+
# a negative value of `-x` will indent of `x` absolute spaces.
|
277
314
|
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
278
315
|
# @param plain [Boolean] If ignore color markers into the message.
|
279
316
|
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
280
317
|
# @return [String] The printed message.
|
281
318
|
#
|
282
319
|
# @see #format
|
283
|
-
def write_banner_aligned(message, suffix
|
284
|
-
write(
|
320
|
+
def write_banner_aligned(message, suffix: "\n", indented: true, wrap: false, plain: false, print: true)
|
321
|
+
write(
|
322
|
+
(" " * (Bovem::Console.min_banner_length + 3)) + message.ensure_string,
|
323
|
+
suffix: suffix,
|
324
|
+
indented: indented,
|
325
|
+
wrap: wrap,
|
326
|
+
plain: plain,
|
327
|
+
print: print
|
328
|
+
)
|
285
329
|
end
|
286
330
|
|
287
|
-
# Writes a status to the output. Valid values are `:ok`, `:pass`, `:fail`, `:warn`.
|
331
|
+
# Writes a status to the output. Valid values are `:ok`, `:pass`, `:fail`, `:warn`, `skip`.
|
288
332
|
#
|
289
333
|
# @param status [Symbol] The status to write.
|
290
334
|
# @param plain [Boolean] If not use colors.
|
@@ -292,24 +336,19 @@ module Bovem
|
|
292
336
|
# @param right [Boolean] If to print results on the right.
|
293
337
|
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
294
338
|
# @return [Array] An dictionary with `:label` and `:color` keys for the status.
|
295
|
-
def status(status, plain
|
296
|
-
statuses =
|
297
|
-
ok: {label: " OK ", color: "bright green"},
|
298
|
-
pass: {label: "PASS", color: "bright cyan"},
|
299
|
-
warn: {label: "WARN", color: "bright yellow"},
|
300
|
-
fail: {label: "FAIL", color: "bright red"}
|
301
|
-
}
|
339
|
+
def status(status, plain: false, go_up: true, right: true, print: true)
|
340
|
+
statuses = DEFAULT_STATUSES.dup
|
302
341
|
statuses.default = statuses[:ok]
|
303
342
|
|
304
343
|
rv = statuses[status]
|
305
344
|
|
306
|
-
if print
|
345
|
+
if print
|
307
346
|
banner = get_banner(rv[:label], rv[:color])
|
308
347
|
|
309
|
-
if right
|
310
|
-
Kernel.puts(format_right(banner + " ", true, go_up, plain))
|
348
|
+
if right
|
349
|
+
Kernel.puts(format_right(banner + " ", width: true, go_up: go_up, plain: plain))
|
311
350
|
else
|
312
|
-
Kernel.puts(format(banner + " ", "\n", true, true, plain))
|
351
|
+
Kernel.puts(format(banner + " ", suffix: "\n", indent: true, wrap: true, plain: plain))
|
313
352
|
end
|
314
353
|
end
|
315
354
|
|
@@ -325,11 +364,11 @@ module Bovem
|
|
325
364
|
# @param brackets [Array] An array of dimension 2 to use for brackets.
|
326
365
|
# @return [String] The banner.
|
327
366
|
# @see #format
|
328
|
-
def get_banner(label, base_color, full_colored
|
367
|
+
def get_banner(label, base_color, full_colored: false, bracket_color: "blue", brackets: ["[", "]"])
|
329
368
|
label = label.rjust(Bovem::Console.min_banner_length, " ")
|
330
369
|
brackets = brackets.ensure_array
|
331
370
|
bracket_color = base_color if full_colored
|
332
|
-
"{mark=%s}%s{mark=%s}%s{/mark}%s{/mark}"
|
371
|
+
sprintf("{mark=%s}%s{mark=%s}%s{/mark}%s{/mark}", bracket_color.parameterize, brackets[0], base_color.parameterize, label, brackets[1])
|
333
372
|
end
|
334
373
|
|
335
374
|
# Formats a progress for pretty printing.
|
@@ -339,15 +378,13 @@ module Bovem
|
|
339
378
|
# @param type [Symbol] The progress type. Can be `:list` (e.g. 01/15) or `:percentage` (e.g. 99.56%).
|
340
379
|
# @param precision [Fixnum] The precision of the percentage to return. *Ignored for list progress.*
|
341
380
|
# @return [String] The formatted progress.
|
342
|
-
def progress(current, total, type
|
343
|
-
if type == :list
|
344
|
-
|
345
|
-
@progress_list_widths[total] ||= total.to_s.length
|
346
|
-
"%0#{@progress_list_widths[total]}d/%d" % [current, total]
|
381
|
+
def progress(current, total, type: :list, precision: 0)
|
382
|
+
if type == :list
|
383
|
+
compute_list_progress(current, total)
|
347
384
|
else
|
348
385
|
precision = [0, precision].max
|
349
386
|
result = total == 0 ? 100 : (100 * (current.to_f / total))
|
350
|
-
("%0.#{precision}f %%"
|
387
|
+
sprintf("%0.#{precision}f %%", result.round(precision)).rjust(5 + (precision > 0 ? precision + 1 : 0))
|
351
388
|
end
|
352
389
|
end
|
353
390
|
|
@@ -355,7 +392,8 @@ module Bovem
|
|
355
392
|
#
|
356
393
|
# @param message [String] The message to format.
|
357
394
|
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
358
|
-
# @param
|
395
|
+
# @param indented [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation,
|
396
|
+
# a negative value of `-x` will indent of `x` absolute spaces.
|
359
397
|
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
360
398
|
# @param plain [Boolean] If ignore color markers into the message.
|
361
399
|
# @param indented_banner [Boolean] If also the banner should be indented.
|
@@ -363,17 +401,18 @@ module Bovem
|
|
363
401
|
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
364
402
|
#
|
365
403
|
# @see #format
|
366
|
-
def begin(message, suffix
|
367
|
-
banner = get_banner("*", "bright green", full_colored)
|
368
|
-
message = indent(message, indented_banner ? 0 :
|
369
|
-
write(banner + " " + message, suffix, indented_banner ?
|
404
|
+
def begin(message, suffix: "\n", indented: true, wrap: false, plain: false, indented_banner: false, full_colored: false, print: true)
|
405
|
+
banner = get_banner("*", "bright green", full_colored: full_colored)
|
406
|
+
message = indent(message, indented_banner ? 0 : indented)
|
407
|
+
write(banner + " " + message, suffix: suffix, indented: indented_banner ? indented : 0, wrap: wrap, plain: plain, print: print)
|
370
408
|
end
|
371
409
|
|
372
410
|
# Writes a message prepending a red banner and then quits the application.
|
373
411
|
#
|
374
412
|
# @param message [String] The message to format.
|
375
413
|
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
376
|
-
# @param
|
414
|
+
# @param indented [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation,
|
415
|
+
# a negative value of `-x` will indent of `x` absolute spaces.
|
377
416
|
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
378
417
|
# @param plain [Boolean] If ignore color markers into the message.
|
379
418
|
# @param indented_banner [Boolean] If also the banner should be indented.
|
@@ -382,8 +421,8 @@ module Bovem
|
|
382
421
|
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
383
422
|
#
|
384
423
|
# @see #format
|
385
|
-
def fatal(message, suffix
|
386
|
-
error(message, suffix,
|
424
|
+
def fatal(message, suffix: "\n", indented: true, wrap: false, plain: false, indented_banner: false, full_colored: false, return_code: -1, print: true)
|
425
|
+
error(message, suffix: suffix, indented: indented, wrap: wrap, plain: plain, indented_banner: indented_banner, full_colored: full_colored, print: print)
|
387
426
|
Kernel.exit(return_code.to_integer(-1))
|
388
427
|
end
|
389
428
|
|
@@ -391,7 +430,8 @@ module Bovem
|
|
391
430
|
#
|
392
431
|
# @param message [String] The message to format.
|
393
432
|
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
394
|
-
# @param
|
433
|
+
# @param indented [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation,
|
434
|
+
# a negative value of `-x` will indent of `x` absolute spaces.
|
395
435
|
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
396
436
|
# @param plain [Boolean] If ignore color markers into the message.
|
397
437
|
# @param indented_banner [Boolean] If also the banner should be indented.
|
@@ -400,19 +440,20 @@ module Bovem
|
|
400
440
|
# @param banner [Array] An array with at last letter and style to use for the banner.
|
401
441
|
#
|
402
442
|
# @see #format
|
403
|
-
def info(message, suffix
|
404
|
-
banner = banner.ensure_array(
|
443
|
+
def info(message, suffix: "\n", indented: true, wrap: false, plain: false, indented_banner: false, full_colored: false, print: true, banner: [])
|
444
|
+
banner = banner.ensure_array(no_duplicates: true, compact: true, flatten: true)
|
405
445
|
banner = ["I", "bright cyan"] if banner.blank?
|
406
|
-
banner = get_banner(banner[0], banner[1], full_colored)
|
407
|
-
message = indent(message, indented_banner ? 0 :
|
408
|
-
write(banner + " " + message, suffix, indented_banner ?
|
446
|
+
banner = get_banner(banner[0], banner[1], full_colored: full_colored)
|
447
|
+
message = indent(message, indented_banner ? 0 : indented)
|
448
|
+
write(banner + " " + message, suffix: suffix, indented: indented_banner ? indented : 0, wrap: wrap, plain: plain, print: print)
|
409
449
|
end
|
410
450
|
|
411
451
|
# Writes a message prepending a magenta banner.
|
412
452
|
#
|
413
453
|
# @param message [String] The message to format.
|
414
454
|
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
415
|
-
# @param
|
455
|
+
# @param indented [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation,
|
456
|
+
# a negative value of `-x` will indent of `x` absolute spaces.
|
416
457
|
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
417
458
|
# @param plain [Boolean] If ignore color markers into the message.
|
418
459
|
# @param indented_banner [Boolean] If also the banner should be indented.
|
@@ -420,15 +461,26 @@ module Bovem
|
|
420
461
|
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
421
462
|
#
|
422
463
|
# @see #format
|
423
|
-
def debug(message, suffix
|
424
|
-
info(
|
464
|
+
def debug(message, suffix: "\n", indented: true, wrap: false, plain: false, indented_banner: false, full_colored: false, print: true)
|
465
|
+
info(
|
466
|
+
message,
|
467
|
+
suffix: suffix,
|
468
|
+
indented: indented,
|
469
|
+
wrap: wrap,
|
470
|
+
plain: plain,
|
471
|
+
indented_banner: indented_banner,
|
472
|
+
full_colored: full_colored,
|
473
|
+
print: print,
|
474
|
+
banner: ["D", "bright magenta"]
|
475
|
+
)
|
425
476
|
end
|
426
477
|
|
427
478
|
# Writes a message prepending a yellow banner.
|
428
479
|
#
|
429
480
|
# @param message [String] The message to format.
|
430
481
|
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
431
|
-
# @param
|
482
|
+
# @param indented [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation,
|
483
|
+
# a negative value of `-x` will indent of `x` absolute spaces.
|
432
484
|
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
433
485
|
# @param plain [Boolean] If ignore color markers into the message.
|
434
486
|
# @param indented_banner [Boolean] If also the banner should be indented.
|
@@ -436,16 +488,26 @@ module Bovem
|
|
436
488
|
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
437
489
|
#
|
438
490
|
# @see #format
|
439
|
-
def warn(message, suffix
|
440
|
-
|
441
|
-
|
491
|
+
def warn(message, suffix: "\n", indented: true, wrap: false, plain: false, indented_banner: false, full_colored: false, print: true)
|
492
|
+
info(
|
493
|
+
message,
|
494
|
+
suffix: suffix,
|
495
|
+
indented: indented,
|
496
|
+
wrap: wrap,
|
497
|
+
plain: plain,
|
498
|
+
indented_banner: indented_banner,
|
499
|
+
full_colored: full_colored,
|
500
|
+
print: print,
|
501
|
+
banner: ["W", "bright yellow"]
|
502
|
+
)
|
442
503
|
end
|
443
504
|
|
444
505
|
# Writes a message prepending a red banner.
|
445
506
|
#
|
446
507
|
# @param message [String] The message to format.
|
447
508
|
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
448
|
-
# @param
|
509
|
+
# @param indented [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation,
|
510
|
+
# a negative value of `-x` will indent of `x` absolute spaces.
|
449
511
|
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
450
512
|
# @param plain [Boolean] If ignore color markers into the message.
|
451
513
|
# @param indented_banner [Boolean] If also the banner should be indented.
|
@@ -453,8 +515,27 @@ module Bovem
|
|
453
515
|
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
454
516
|
#
|
455
517
|
# @see #format
|
456
|
-
def error(message, suffix
|
457
|
-
info(
|
518
|
+
def error(message, suffix: "\n", indented: true, wrap: false, plain: false, indented_banner: false, full_colored: false, print: true)
|
519
|
+
info(
|
520
|
+
message,
|
521
|
+
suffix: suffix,
|
522
|
+
indented: indented,
|
523
|
+
wrap: wrap,
|
524
|
+
plain: plain,
|
525
|
+
indented_banner: indented_banner,
|
526
|
+
full_colored: full_colored,
|
527
|
+
print: print,
|
528
|
+
banner: ["E", "bright red"]
|
529
|
+
)
|
530
|
+
end
|
531
|
+
|
532
|
+
private
|
533
|
+
|
534
|
+
# :nodoc:
|
535
|
+
def compute_list_progress(current, total)
|
536
|
+
@progress_list_widths ||= {}
|
537
|
+
@progress_list_widths[total] ||= total.to_s.length
|
538
|
+
sprintf("%0#{@progress_list_widths[total]}d/%d", current, total)
|
458
539
|
end
|
459
540
|
end
|
460
541
|
|
@@ -469,7 +550,7 @@ module Bovem
|
|
469
550
|
# @param command [String] The command to execute.
|
470
551
|
# @return [String] The command's output.
|
471
552
|
def execute(command)
|
472
|
-
|
553
|
+
`#{command}`
|
473
554
|
end
|
474
555
|
end
|
475
556
|
|
@@ -479,13 +560,13 @@ module Bovem
|
|
479
560
|
# @param default_value [String] Default value if user simply pressed the enter key.
|
480
561
|
# @param validator [Array|Regexp] An array of values or a Regexp to match the submitted value against.
|
481
562
|
# @param echo [Boolean] If to show submitted text to the user. **Not supported and thus ignored on Rubinius.**
|
482
|
-
def read(prompt
|
563
|
+
def read(prompt: true, default_value: nil, validator: nil, echo: true)
|
483
564
|
prompt = sanitize_prompt(prompt)
|
484
565
|
validator = sanitize_validator(validator)
|
485
566
|
|
486
567
|
begin
|
487
568
|
catch(:reply) do
|
488
|
-
|
569
|
+
loop do
|
489
570
|
reply = validate_input_value(read_input_value(prompt, echo, default_value), validator)
|
490
571
|
handle_reply(reply)
|
491
572
|
end
|
@@ -499,7 +580,8 @@ module Bovem
|
|
499
580
|
#
|
500
581
|
# @param message [String] The message to format.
|
501
582
|
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
502
|
-
# @param
|
583
|
+
# @param indented [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation,
|
584
|
+
# a negative value of `-x` will indent of `x` absolute spaces.
|
503
585
|
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
504
586
|
# @param plain [Boolean] If ignore color markers into the message.
|
505
587
|
# @param indented_banner [Boolean] If also the banner should be indented.
|
@@ -507,99 +589,91 @@ module Bovem
|
|
507
589
|
# @param block_indentation [Fixnum] The new width for the indented region.
|
508
590
|
# @param block_indentation_absolute [Boolean] If the new width should not be added to the current one but rather replace it.
|
509
591
|
# @return [Symbol] The exit status for the block.
|
510
|
-
def task(
|
592
|
+
def task(
|
593
|
+
message = nil, suffix: "\n", indented: true, wrap: false, plain: false, indented_banner: false,
|
594
|
+
full_colored: false, block_indentation: 2, block_indentation_absolute: false
|
595
|
+
)
|
511
596
|
status = nil
|
512
597
|
|
513
|
-
|
598
|
+
if message.present?
|
599
|
+
self.begin(message, suffix: suffix, indented: indented, wrap: wrap, plain: plain, indented_banner: indented_banner, full_colored: full_colored)
|
600
|
+
end
|
601
|
+
|
514
602
|
with_indentation(block_indentation, block_indentation_absolute) do
|
515
603
|
rv = block_given? ? yield.ensure_array : [:ok] # Execute block
|
516
604
|
exit_task(message, rv, plain) # Handle task exit
|
517
605
|
status = rv[0] # Return value
|
518
|
-
|
519
606
|
end
|
520
607
|
|
521
608
|
status
|
522
609
|
end
|
523
610
|
|
524
611
|
private
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
exit(rv.length > 1 ? rv[1].to_integer : -1)
|
534
|
-
else
|
535
|
-
status(rv[0], plain) if message.present?
|
536
|
-
end
|
612
|
+
|
613
|
+
# :nodoc:
|
614
|
+
def exit_task(message, rv, plain)
|
615
|
+
if rv[0] == :fatal
|
616
|
+
status(:fail, plain: plain)
|
617
|
+
exit(rv.length > 1 ? rv[1].to_integer : -1)
|
618
|
+
elsif message.present?
|
619
|
+
status(rv[0], plain: plain)
|
537
620
|
end
|
621
|
+
end
|
538
622
|
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
623
|
+
# :nodoc:
|
624
|
+
def sanitize_prompt(prompt)
|
625
|
+
return nil unless prompt.present?
|
626
|
+
(prompt.is_a?(TrueClass) ? i18n.prompt : prompt).gsub(/:?\s*$/, "") + ": "
|
627
|
+
end
|
628
|
+
|
629
|
+
# :nodoc:
|
630
|
+
def sanitize_validator(validator)
|
631
|
+
if validator.present? && !validator.is_a?(::Regexp)
|
632
|
+
validator.ensure_array(no_duplicates: true, compact: true, flatten: true, sanitizer: :ensure_string)
|
633
|
+
else
|
634
|
+
validator
|
549
635
|
end
|
636
|
+
end
|
550
637
|
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
validator.present? && !validator.is_a?(::Regexp) ? validator.ensure_array(nil, true, true, true, :ensure_string) : validator
|
638
|
+
# :nodoc:
|
639
|
+
def read_input_value(prompt, echo, default_value = nil)
|
640
|
+
if prompt
|
641
|
+
Kernel.print(format(prompt, suffix: false, indented: false))
|
642
|
+
$stdout.flush
|
557
643
|
end
|
558
644
|
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
# @param echo [Boolean] If disable echoing. **Not supported and therefore ignored on Rubinius.**
|
563
|
-
# @param default_value [Object] A default value to enter if the user just pressed the enter key.
|
564
|
-
# @return [Object] The read value.
|
565
|
-
def read_input_value(prompt, echo, default_value = nil)
|
566
|
-
if prompt then
|
567
|
-
Kernel.print(format(prompt, false, false))
|
568
|
-
$stdout.flush
|
569
|
-
end
|
645
|
+
reply = (echo || !$stdin.respond_to?(:noecho) ? $stdin.gets : $stdin.noecho(&:gets)).ensure_string.chop
|
646
|
+
reply.present? ? reply : default_value
|
647
|
+
end
|
570
648
|
|
571
|
-
|
572
|
-
|
649
|
+
# :nodoc:
|
650
|
+
def validate_input_value(reply, validator)
|
651
|
+
# Match against the validator
|
652
|
+
if validator.present?
|
653
|
+
if validator.is_a?(Array)
|
654
|
+
reply = validate_array(reply, validator)
|
655
|
+
elsif validator.is_a?(Regexp)
|
656
|
+
reply = nil unless validator.match(reply)
|
657
|
+
end
|
573
658
|
end
|
574
659
|
|
575
|
-
|
576
|
-
|
577
|
-
# @param reply [String] The value to validate.
|
578
|
-
# @param validator [Array|Regexp] An array of values or a Regexp to match the submitted value against.
|
579
|
-
# @return [String|nil] The validated value or `nil`, if the value is invalid.
|
580
|
-
def validate_input_value(reply, validator)
|
581
|
-
# Match against the validator
|
582
|
-
if validator.present? then
|
583
|
-
if validator.is_a?(Array) then
|
584
|
-
reply = nil if validator.length > 0 && !validator.include?(reply)
|
585
|
-
elsif validator.is_a?(Regexp) then
|
586
|
-
reply = nil if !validator.match(reply)
|
587
|
-
end
|
588
|
-
end
|
660
|
+
reply
|
661
|
+
end
|
589
662
|
|
590
|
-
|
591
|
-
|
663
|
+
# :nodoc:
|
664
|
+
def validate_array(reply, validator)
|
665
|
+
reply = nil if !validator.empty? && !validator.include?(reply)
|
666
|
+
reply
|
667
|
+
end
|
592
668
|
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
else
|
600
|
-
write(i18n.console.unknown_reply, false, false)
|
601
|
-
end
|
669
|
+
# :nodoc:
|
670
|
+
def handle_reply(reply)
|
671
|
+
if reply
|
672
|
+
throw(:reply, reply)
|
673
|
+
else
|
674
|
+
write(i18n.unknown_reply, false, false)
|
602
675
|
end
|
676
|
+
end
|
603
677
|
end
|
604
678
|
end
|
605
679
|
|
@@ -609,11 +683,12 @@ module Bovem
|
|
609
683
|
# @return [Fixnum] Current indentation width.
|
610
684
|
# @attribute indentation_string
|
611
685
|
# @return [String] The string used for indentation.
|
686
|
+
# @attribute [r] i18n
|
687
|
+
# @return [I18n] A i18n helper.
|
612
688
|
class Console
|
613
|
-
attr_accessor :indentation
|
614
|
-
|
689
|
+
attr_accessor :indentation, :indentation_string
|
690
|
+
attr_reader :i18n
|
615
691
|
|
616
|
-
include Lazier::I18n
|
617
692
|
include Bovem::ConsoleMethods::StyleHandling
|
618
693
|
include Bovem::ConsoleMethods::Output
|
619
694
|
include Bovem::ConsoleMethods::Logging
|
@@ -630,19 +705,17 @@ module Bovem
|
|
630
705
|
def initialize
|
631
706
|
@indentation = 0
|
632
707
|
@indentation_string = " "
|
633
|
-
|
708
|
+
@i18n = Bovem::I18n.new(root: "bovem.console", path: Bovem::Application::LOCALE_ROOT)
|
634
709
|
end
|
635
710
|
|
636
711
|
# Get the width of the terminal.
|
637
712
|
#
|
638
713
|
# @return [Fixnum] The current width of the terminal. If not possible to retrieve the width, it returns `80.
|
639
714
|
def line_width
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
80
|
645
|
-
end
|
715
|
+
require "io/console" unless defined?($stdin.winsize)
|
716
|
+
$stdin.winsize[1]
|
717
|
+
rescue
|
718
|
+
80
|
646
719
|
end
|
647
720
|
end
|
648
|
-
end
|
721
|
+
end
|