bovem 3.0.5 → 4.0.0

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