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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -3
  3. data/.rubocop.yml +82 -0
  4. data/.travis-gemfile +4 -5
  5. data/.travis.yml +8 -6
  6. data/CHANGELOG.md +12 -0
  7. data/Gemfile +9 -8
  8. data/README.md +1 -1
  9. data/Rakefile +22 -6
  10. data/bovem.gemspec +5 -5
  11. data/doc/Bovem.html +10 -10
  12. data/doc/Bovem/Application.html +670 -318
  13. data/doc/Bovem/Command.html +1447 -1125
  14. data/doc/Bovem/CommandMethods.html +4 -4
  15. data/doc/Bovem/CommandMethods/Children.html +173 -179
  16. data/doc/Bovem/CommandMethods/Help.html +9 -9
  17. data/doc/Bovem/Configuration.html +239 -24
  18. data/doc/Bovem/Console.html +267 -128
  19. data/doc/Bovem/ConsoleMethods.html +4 -4
  20. data/doc/Bovem/ConsoleMethods/Interactions.html +57 -70
  21. data/doc/Bovem/ConsoleMethods/Interactions/ClassMethods.html +9 -9
  22. data/doc/Bovem/ConsoleMethods/Logging.html +258 -298
  23. data/doc/Bovem/ConsoleMethods/Logging/ClassMethods.html +8 -8
  24. data/doc/Bovem/ConsoleMethods/Output.html +96 -118
  25. data/doc/Bovem/ConsoleMethods/StyleHandling.html +8 -8
  26. data/doc/Bovem/ConsoleMethods/StyleHandling/ClassMethods.html +26 -39
  27. data/doc/Bovem/Errors.html +4 -4
  28. data/doc/Bovem/Errors/Error.html +4 -4
  29. data/doc/Bovem/Errors/InvalidConfiguration.html +4 -4
  30. data/doc/Bovem/Errors/InvalidLogger.html +4 -4
  31. data/doc/Bovem/I18n.html +175 -0
  32. data/doc/Bovem/Logger.html +95 -83
  33. data/doc/Bovem/Option.html +669 -862
  34. data/doc/Bovem/Parser.html +10 -10
  35. data/doc/Bovem/ParserMethods.html +4 -4
  36. data/doc/Bovem/ParserMethods/General.html +4 -4
  37. data/doc/Bovem/ParserMethods/General/ClassMethods.html +26 -38
  38. data/doc/Bovem/Shell.html +169 -48
  39. data/doc/Bovem/ShellMethods.html +4 -4
  40. data/doc/Bovem/ShellMethods/Directories.html +46 -62
  41. data/doc/Bovem/ShellMethods/Execute.html +51 -99
  42. data/doc/Bovem/ShellMethods/General.html +4 -445
  43. data/doc/Bovem/ShellMethods/Read.html +56 -61
  44. data/doc/Bovem/ShellMethods/Write.html +22 -242
  45. data/doc/Bovem/Version.html +6 -6
  46. data/doc/_index.html +18 -18
  47. data/doc/class_list.html +6 -2
  48. data/doc/css/style.css +1 -0
  49. data/doc/file.README.html +5 -5
  50. data/doc/file_list.html +5 -1
  51. data/doc/frames.html +1 -1
  52. data/doc/index.html +5 -5
  53. data/doc/js/full_list.js +4 -1
  54. data/doc/method_list.html +161 -157
  55. data/doc/top-level-namespace.html +4 -4
  56. data/lib/bovem.rb +3 -4
  57. data/lib/bovem/application.rb +47 -39
  58. data/lib/bovem/command.rb +175 -193
  59. data/lib/bovem/configuration.rb +28 -29
  60. data/lib/bovem/console.rb +244 -171
  61. data/lib/bovem/errors.rb +1 -1
  62. data/lib/bovem/i18n.rb +18 -0
  63. data/lib/bovem/logger.rb +26 -26
  64. data/lib/bovem/option.rb +49 -58
  65. data/lib/bovem/parser.rb +174 -222
  66. data/lib/bovem/shell.rb +272 -320
  67. data/lib/bovem/version.rb +2 -2
  68. data/locales/en.yml +39 -38
  69. data/locales/it.yml +39 -38
  70. data/spec/bovem/application_spec.rb +6 -5
  71. data/spec/bovem/command_spec.rb +23 -23
  72. data/spec/bovem/console_spec.rb +101 -102
  73. data/spec/bovem/i18n_spec.rb +21 -0
  74. data/spec/bovem/logger_spec.rb +4 -4
  75. data/spec/bovem/option_spec.rb +43 -43
  76. data/spec/bovem/parser_spec.rb +13 -13
  77. data/spec/bovem/shell_spec.rb +106 -115
  78. data/spec/spec_helper.rb +19 -6
  79. metadata +14 -13
  80. data/doc/Bovem/Localizer.html +0 -376
  81. data/lib/bovem/localizer.rb +0 -27
  82. data/spec/coverage_helper.rb +0 -20
@@ -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
- i18n_setup(:bovem, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
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 then
54
- if File.readable?(file) then
55
- read_configuration_file(file, logger)
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 self.respond_to?("#{k}=") } if overrides.is_a?(::Hash)
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
- # Eval a configuration file.
84
- #
85
- # @param path [String] The file to read.
86
- def eval_file(path)
87
- tap { |config| eval(::File.read(path)) }
88
- end
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
@@ -6,10 +6,10 @@
6
6
 
7
7
  module Bovem
8
8
  # List of valid terminal colors.
9
- TERM_COLORS = { black: 0, red: 1, green: 2, yellow: 3, blue: 4, magenta: 5, cyan: 6, white: 7, default: 9}
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 = { reset: 0, bright: 1, italic: 3, underline: 4, blink: 5, inverse: 7, hide: 8 }
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}. You can also prefix colors with `bg_` (like `bg_red`) for background colors.
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? then
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}. You can also prefix colors with `bg_` (like `bg_red`) for background colors.
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. Separate styles with spaces, dashes or commas. Nesting markers is supported.
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}" then # If it is a tag, pop from the latest opened.
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
- styles = $3.ensure_string
86
- replacement = plain ? "" : Bovem::Console.parse_styles(styles)
88
+ add_style($LAST_MATCH_INFO[3], plain, stack)
89
+ end
90
+ end
91
+ end
87
92
 
88
- if replacement.length > 0 then
89
- stack << "reset" if stack.blank?
90
- stack << styles
91
- end
93
+ private
92
94
 
93
- replacement
94
- end
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 then
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 { |line|
155
- line.length > width ? line.gsub(/(.{1,#{width}})(\s+|$)/, "\\1\n").strip : line
156
- }.join("\n")
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` will indent of `x` absolute spaces. `nil` or `false` will skip indentation.
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 then
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
- message = message.split(newline_separator).map {|line|
184
+ rv = message.split(newline_separator).map do |line|
172
185
  (@indentation_string * width) + line
173
- }.join(newline_separator)
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 indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation, a negative value of `-x` will indent of `x` absolute spaces.
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 = "\n", indent = true, wrap = true, plain = false)
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) then
198
- wrap = line_width
213
+ wrap = compute_wrap(indented) if wrap.is_a?(TrueClass)
199
214
 
200
- if indent.is_a?(TrueClass) then
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 = true, go_up = true, plain = false)
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 indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation, a negative value of `-x` will indent of `x` absolute spaces.
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 = "\n", indent = true, wrap = false, plain = false, print = true)
267
- rv = format(message, suffix, indent, wrap, plain)
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 indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation, a negative value of `-x` will indent of `x` absolute spaces.
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 = "\n", indent = true, wrap = false, plain = false, print = true)
284
- write((" " * (Bovem::Console.min_banner_length + 3)) + message.ensure_string, suffix, indent, wrap, plain, print)
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 = false, go_up = true, right = true, print = true)
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 then
345
+ if print
307
346
  banner = get_banner(rv[:label], rv[:color])
308
347
 
309
- if right then
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 = false, bracket_color = "blue", brackets = ["[", "]"])
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}" % [bracket_color.parameterize, brackets[0], base_color.parameterize, label, brackets[1]]
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 = :list, precision = 0)
343
- if type == :list then
344
- @progress_list_widths ||= {}
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 %%" % result.round(precision)).rjust(5 + (precision > 0 ? precision + 1 : 0))
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 indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation, a negative value of `-x` will indent of `x` absolute spaces.
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 = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
367
- banner = get_banner("*", "bright green", full_colored)
368
- message = indent(message, indented_banner ? 0 : indent)
369
- write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
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 indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation, a negative value of `-x` will indent of `x` absolute spaces.
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 = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, return_code = -1, print = true)
386
- error(message, suffix, indent, wrap, plain, indented_banner, full_colored, print)
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 indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation, a negative value of `-x` will indent of `x` absolute spaces.
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 = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true, *banner)
404
- banner = banner.ensure_array(nil, true, true, true)
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 : indent)
408
- write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
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 indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation, a negative value of `-x` will indent of `x` absolute spaces.
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 = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
424
- info(message, suffix, indent, wrap, plain, indented_banner, full_colored, print, ["D", "bright magenta"])
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 indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation, a negative value of `-x` will indent of `x` absolute spaces.
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 = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
440
- warn_banner = ["W", "bright yellow"]
441
- info(message, suffix, indent, wrap, plain, indented_banner, full_colored, print, warn_banner)
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 indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation, a negative value of `-x` will indent of `x` absolute spaces.
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 = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
457
- info(message, suffix, indent, wrap, plain, indented_banner, full_colored, print, "E", "bright red")
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
- %x{#{command}}
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 = true, default_value = nil, validator = nil, echo = true)
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
- while true do
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 indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use the current indentation, a negative value of `-x` will indent of `x` absolute spaces.
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(message = nil, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, block_indentation = 2, block_indentation_absolute = false)
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
- self.begin(message, suffix, indent, wrap, plain, indented_banner, full_colored) if message.present?
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
- # Handles task exit.
526
- #
527
- # @param message [String] The message to format.
528
- # @param rv [Array] An array with exit status and exit code.
529
- # @param plain [Boolean] If ignore color markers into the message.
530
- def exit_task(message, rv, plain)
531
- if rv[0] == :fatal then
532
- status(:fail, plain)
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
- # Returns a prompt for input prompting.
540
- #
541
- # @param prompt [String]
542
- # @return [String|nil] The prompt to use or `nil`, if no message must be prompted.
543
- def sanitize_prompt(prompt)
544
- if prompt.present?
545
- (prompt.is_a?(TrueClass) ? i18n.console.prompt : prompt).gsub(/:?\s*$/, "") + ": "
546
- else
547
- nil
548
- end
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
- # Make sure that the validators are an array of string if not a regexp.
552
- #
553
- # @param validator [String|Regexp] The validator to sanitize.
554
- # @return [Object] A list of strings, a Regexp or nil.
555
- def sanitize_validator(validator)
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
- # Read an input from the terminal.
560
- #
561
- # @param prompt [String] A message to show to the user.
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
- reply = (echo || !$stdin.respond_to?(:noecho) ? $stdin.gets : $stdin.noecho(&:gets)).ensure_string.chop
572
- reply.present? ? reply : default_value
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
- # Validates a read value from the terminal.
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
- reply
591
- end
663
+ # :nodoc:
664
+ def validate_array(reply, validator)
665
+ reply = nil if !validator.empty? && !validator.include?(reply)
666
+ reply
667
+ end
592
668
 
593
- # Handles a read value from the terminal.
594
- #
595
- # @param reply [String] The value to handle.
596
- def handle_reply(reply)
597
- if reply then
598
- throw(:reply, reply)
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
- attr_accessor :indentation_string
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
- i18n_setup(:bovem, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
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
- begin
641
- require "io/console" if !defined?($stdin.winsize)
642
- $stdin.winsize[1]
643
- rescue
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