bovem 3.0.5 → 4.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.
- 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
|