bovem 0.6.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ --exclude lib/devdnsd/patches/.+ --exclude utils/ -m markdown
@@ -1,16 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bovem (0.6.0)
4
+ bovem (0.8.0)
5
5
  lazier (~> 1.0)
6
- rainbow (~> 1.1.0)
7
6
 
8
7
  GEM
9
8
  remote: http://rubygems.org/
10
9
  specs:
11
- actionpack (3.2.7)
12
- activemodel (= 3.2.7)
13
- activesupport (= 3.2.7)
10
+ actionpack (3.2.8)
11
+ activemodel (= 3.2.8)
12
+ activesupport (= 3.2.8)
14
13
  builder (~> 3.0.0)
15
14
  erubis (~> 2.7.0)
16
15
  journey (~> 1.0.4)
@@ -18,22 +17,22 @@ GEM
18
17
  rack-cache (~> 1.2)
19
18
  rack-test (~> 0.6.1)
20
19
  sprockets (~> 2.1.3)
21
- activemodel (3.2.7)
22
- activesupport (= 3.2.7)
20
+ activemodel (3.2.8)
21
+ activesupport (= 3.2.8)
23
22
  builder (~> 3.0.0)
24
- activesupport (3.2.7)
23
+ activesupport (3.2.8)
25
24
  i18n (~> 0.6)
26
25
  multi_json (~> 1.0)
27
26
  builder (3.0.0)
28
27
  coderay (1.0.7)
29
28
  diff-lcs (1.1.3)
30
29
  erubis (2.7.0)
31
- github-markup (0.7.2)
30
+ github-markup (0.7.4)
32
31
  hike (1.2.1)
33
32
  i18n (0.6.0)
34
33
  journey (1.0.4)
35
34
  json (1.7.4)
36
- lazier (1.0.1)
35
+ lazier (1.0.2)
37
36
  actionpack (~> 3.0)
38
37
  json (~> 1.7.0)
39
38
  tzinfo (~> 0.3.0)
@@ -48,17 +47,16 @@ GEM
48
47
  rack (>= 0.4)
49
48
  rack-test (0.6.1)
50
49
  rack (>= 1.0)
51
- rainbow (1.1.4)
52
50
  rake (0.9.2.2)
53
51
  redcarpet (2.1.1)
54
52
  rspec (2.11.0)
55
53
  rspec-core (~> 2.11.0)
56
54
  rspec-expectations (~> 2.11.0)
57
55
  rspec-mocks (~> 2.11.0)
58
- rspec-core (2.11.0)
59
- rspec-expectations (2.11.1)
56
+ rspec-core (2.11.1)
57
+ rspec-expectations (2.11.2)
60
58
  diff-lcs (~> 1.1.3)
61
- rspec-mocks (2.11.1)
59
+ rspec-mocks (2.11.2)
62
60
  simplecov (0.6.4)
63
61
  multi_json (~> 1.0)
64
62
  simplecov-html (~> 0.5.3)
@@ -22,7 +22,6 @@ Gem::Specification.new do |gem|
22
22
  gem.require_paths = ["lib"]
23
23
 
24
24
  gem.add_dependency("lazier", "~> 1.0")
25
- gem.add_dependency("rainbow", "~> 1.1.0")
26
25
 
27
26
  gem.add_development_dependency("rspec", "~> 2.11.0")
28
27
  gem.add_development_dependency("rake", "~> 0.9.0")
@@ -4,7 +4,6 @@
4
4
  # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
5
  #
6
6
 
7
- require "rainbow"
8
7
  require "logger"
9
8
  require "lazier"
10
9
 
@@ -13,4 +12,5 @@ Lazier.load!(:object)
13
12
  require "bovem/version" if !defined?(Bovem::Version)
14
13
  require "bovem/errors"
15
14
  require "bovem/configuration"
16
- require "bovem/logger"
15
+ require "bovem/logger"
16
+ require "bovem/console"
@@ -0,0 +1,527 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the bovem gem. Copyright (C) 2012 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ module Bovem
8
+ # List of valid terminal colors.
9
+ TERM_COLORS = {
10
+ :black => 0,
11
+ :red => 1,
12
+ :green => 2,
13
+ :yellow => 3,
14
+ :blue => 4,
15
+ :magenta => 5,
16
+ :cyan => 6,
17
+ :white => 7,
18
+ :default => 9,
19
+ }
20
+
21
+ # List of valid terminal text effects.
22
+ TERM_EFFECTS = {
23
+ :reset => 0,
24
+ :bright => 1,
25
+ :italic => 3,
26
+ :underline => 4,
27
+ :blink => 5,
28
+ :inverse => 7,
29
+ :hide => 8,
30
+ }
31
+
32
+ # This is a text utility wrapper console I/O.
33
+ class Console
34
+ # The line width. Default to `80`.
35
+ attr_accessor :line_width
36
+
37
+ # The current screen width.
38
+ attr_accessor :screen_width
39
+
40
+ # Current indentation width.
41
+ attr_accessor :indentation
42
+
43
+ # The string used for indentation.
44
+ attr_accessor :indentation_string
45
+
46
+ # Whether to show executed commands.
47
+ # attr_accessor :show_commands
48
+
49
+ # Whether to show output of executed commands.
50
+ # attr_accessor :show_outputs
51
+
52
+ # Whether to simply print commands rather than executing them.
53
+ # attr_accessor :skip_commands
54
+
55
+ # Returns a unique instance for Console.
56
+ #
57
+ # @return [Console] A new instance.
58
+ def self.instance
59
+ @instance ||= ::Bovem::Console.new
60
+ end
61
+
62
+ # Parse a style and returns terminal codes.
63
+ #
64
+ # 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.
65
+ #
66
+ # @param style [String] The style to parse.
67
+ # @return [String] A string with ANSI color codes.
68
+ def self.parse_style(style)
69
+ style = style.ensure_string
70
+ sym = style.to_sym
71
+ rv = ""
72
+
73
+ if ::Bovem::TERM_EFFECTS.include?(sym) then
74
+ rv = "\e[#{Bovem::TERM_EFFECTS[sym]}m"
75
+ elsif style.index("bg_") == 0 then
76
+ sym = style[3, style.length].to_sym
77
+ rv = "\e[#{40 + ::Bovem::TERM_COLORS[sym]}m" if ::Bovem::TERM_COLORS.include?(sym)
78
+ elsif style != "reset" then
79
+ rv = "\e[#{30 + ::Bovem::TERM_COLORS[sym]}m" if ::Bovem::TERM_COLORS.include?(sym)
80
+ end
81
+
82
+ rv
83
+ end
84
+
85
+ # Replaces colors markers in a string.
86
+ #
87
+ # @param message [String] The message to analyze.
88
+ # @param plain [Boolean] If ignore (cleanify) color markers into the message.
89
+ # @return [String] The replaced message.
90
+ # @see #parse_style
91
+ def self.replace_markers(message, plain = false)
92
+ stack = []
93
+
94
+ regexp = /((\{mark=([a-z\-_]+)\})|(\{\/mark\}))/mi
95
+
96
+ message = message.gsub(regexp) do
97
+ tag = $1
98
+ styles = $3
99
+ replacement = ""
100
+
101
+ if tag == "{/mark}" then # If it is a tag, pop from the latest opened.
102
+ stack.pop
103
+ styles = stack.last
104
+ replacement = plain || stack.blank? ? "" : styles.split("-").collect { |s| self.parse_style(s) }.join("")
105
+ else
106
+ replacement = plain ? "" : styles.split("-").collect { |s| self.parse_style(s) }.join("")
107
+
108
+ if replacement.length > 0 then
109
+ stack << "reset" if stack.blank?
110
+ stack << styles
111
+ end
112
+ end
113
+
114
+ replacement
115
+ end
116
+
117
+ message
118
+ end
119
+
120
+ # Executes a command and returns its output.
121
+ #
122
+ # @param command [String] The command to execute.
123
+ # @return [String] The command's output.
124
+ def self.execute(command)
125
+ %x{#{command}}
126
+ end
127
+
128
+ # Initializes a new Console.
129
+ def initialize
130
+ @line_width = 80
131
+ @indentation = 0
132
+ @indentation_string = " "
133
+ end
134
+
135
+ # Gets the current screen width.
136
+ #
137
+ # @return [Fixnum] The screen width.
138
+ def get_screen_width
139
+ ::Bovem::Console.execute("tput cols").to_integer
140
+ end
141
+
142
+ # Sets the new indentation width.
143
+ #
144
+ # @param width [Fixnum] The new width.
145
+ # @param is_absolute [Boolean] If the new width should not be added to the current one but rather replace it.
146
+ # @return [Fixnum] The new indentation width.
147
+ def set_indentation(width, is_absolute = false)
148
+ self.indentation = [(!is_absolute ? self.indentation : 0) + width, 0].max.to_i
149
+ self.indentation
150
+ end
151
+
152
+ # Resets indentation width to `0`.
153
+ #
154
+ # @return [Fixnum] The new indentation width.
155
+ def reset_indentation
156
+ self.indentation = 0
157
+ self.indentation
158
+ end
159
+
160
+ # Starts a indented region of text.
161
+ #
162
+ # @param width [Fixnum] The new width.
163
+ # @param is_absolute [Boolean] If the new width should not be added to the current one but rather replace it.
164
+ # @return [Fixnum] The new indentation width.
165
+ def with_indentation(width, is_absolute = false)
166
+ old = self.indentation
167
+ self.set_indentation(width, is_absolute)
168
+ yield
169
+ self.set_indentation(old, true)
170
+
171
+ self.indentation
172
+ end
173
+
174
+ # Wraps a message in fixed line width.
175
+ #
176
+ # @param message [String] The message to wrap.
177
+ # @param width [Fixnum] The maximum width of a line. Default to the current line width.
178
+ # @return [String] The wrapped message.
179
+ def wrap(message, width = nil)
180
+ if width.to_integer <= 0 then
181
+ message
182
+ else
183
+ width = (width == true || width.to_integer < 0 ? @line_width : width.to_integer)
184
+
185
+ message.split("\n").collect { |line|
186
+ line.length > width ? line.gsub(/(.{1,#{width}})(\s+|$)/, "\\1\n").strip : line
187
+ }.join("\n")
188
+ end
189
+ end
190
+
191
+ # Indents a message.
192
+ #
193
+ # @param message [String] The message to indent.
194
+ # @param width [Fixnum] The indentation width. `true` means to use thecurrent indentation, a negative value of `-x` will indent of `x` absolute spaces. `nil` or `false` will skip indentation.
195
+ # @param newline_separator [String] The character used for newlines.
196
+ # @return [String] The indentend message.
197
+ def indent(message, width = true, newline_separator = "\n")
198
+ if width.to_integer != 0 then
199
+ width = (width == true ? 0 : width.to_integer)
200
+ width = width < 0 ? -width : @indentation + width
201
+
202
+ message = message.split(newline_separator).collect {|line|
203
+ (@indentation_string * width) + line
204
+ }.join(newline_separator)
205
+ end
206
+
207
+ message
208
+ end
209
+
210
+ # Replaces colors markers in a string.
211
+ #
212
+ # 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.
213
+ #
214
+ # @param message [String] The message to analyze.
215
+ # @param plain [Boolean] If ignore (cleanify )color markers into the message.
216
+ # @return [String] The replaced message.
217
+ def replace_markers(message, plain = false)
218
+ ::Bovem::Console.replace_markers(message, plain)
219
+ end
220
+
221
+ # Formats a message.
222
+ #
223
+ # You can style text by using `{color}` and `{reset}` syntax.
224
+ #
225
+ # @param message [String] The message to format.
226
+ # @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
227
+ # @param indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use thecurrent indentation, a negative value of `-x` will indent of `x` absolute spaces.
228
+ # @param wrap [Object] If not `nil` or `false`, the maximum length of a line. `true` means the current line width.
229
+ # @param plain [Boolean] If ignore color markers into the message.
230
+ # @return [String] The formatted message.
231
+ def format(message, suffix = "\n", indent = true, wrap = true, plain = false)
232
+ rv = message
233
+
234
+ rv = self.replace_markers(rv, plain) # Replace markers
235
+ rv = self.wrap(rv, wrap) # Wrap
236
+ rv = self.indent(rv, indent) # Indent
237
+
238
+ rv += suffix if suffix # Add the suffix
239
+ rv
240
+ end
241
+
242
+ # Formats a message to be written right-aligned.
243
+ #
244
+ # @param message [String] The message to format.
245
+ # @param width [Fixnum] The screen width. If `true`, it is automatically computed.
246
+ # @param go_up [Boolean] If go up one line before formatting.
247
+ # @param plain [Boolean] If ignore color markers into the message.
248
+ # @return [String] The formatted message.
249
+ def format_right(message, width = true, go_up = true, plain = false)
250
+ message = self.replace_markers(message, plain)
251
+
252
+ rv = go_up ? "\e[A" : ""
253
+
254
+ @screen_width ||= self.get_screen_width
255
+ width = (width == true || width.to_integer < 1 ? @screen_width : width.to_integer)
256
+
257
+ # Get padding
258
+ padding = width - message.to_s.gsub(/(\e\[[0-9]*[a-z]?)|(\\n)/i, "").length
259
+
260
+ # Return
261
+ rv + "\e[0G\e[#{padding}C" + message
262
+ end
263
+
264
+ # Writes a message.
265
+ #
266
+ # @param message [String] The message to format.
267
+ # @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
268
+ # @param indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use thecurrent indentation, a negative value of `-x` will indent of `x` absolute spaces.
269
+ # @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
270
+ # @param plain [Boolean] If ignore color markers into the message.
271
+ # @param print [Boolean] If `false`, the result will be returned instead of be printed.
272
+ # @return [String] The printed message.
273
+ #
274
+ # @see #format
275
+ def write(message, suffix = "\n", indent = true, wrap = false, plain = false, print = true)
276
+ rv = self.format(message, suffix, indent, wrap, plain)
277
+ Kernel.puts(rv) if print
278
+ rv
279
+ end
280
+
281
+ # Writes a status to the output. Valid values are `:ok`, `:pass`, `:fail`, `:warn`.
282
+ #
283
+ # @param status [Symbol] The status to write.
284
+ # @param plain [Boolean] If not use colors.
285
+ # @param go_up [Boolean] If go up one line before formatting.
286
+ # @param right [Boolean] If to print results on the right.
287
+ # @param print [Boolean] If `false`, the result will be returned instead of be printed.
288
+ # @return [Array] An dictionary with `:label` and `:color` keys for the status.
289
+ def status(status, plain = false, go_up = true, right = true, print = true)
290
+ statuses = {
291
+ :ok => {:label => " OK ", :color => "bright green"},
292
+ :pass => {:label => "PASS", :color => "bright cyan"},
293
+ :warn => {:label => "WARN", :color => "bright yellow"},
294
+ :fail => {:label => "FAIL", :color => "bright red"}
295
+ }
296
+ statuses.default = statuses[:pass]
297
+
298
+ rv = statuses[status]
299
+
300
+ if print then
301
+ banner = self.get_banner(rv[:label], rv[:color])
302
+
303
+ if right then
304
+ Kernel.puts self.format_right(banner + " ", true, go_up, plain)
305
+ else
306
+ Kernel.puts self.format(banner + " ", "\n", true, true, plain)
307
+ end
308
+ end
309
+
310
+ rv
311
+ end
312
+
313
+ # Gets a banner for the messages.
314
+ #
315
+ # @param label [String] The label for the banner.
316
+ # @param base_color [String] The color for the label.
317
+ # @param full_colored [String] If all the message should be of the label color.
318
+ # @param bracket_color [String] The color of the brackets.
319
+ # @param brackets [Array] An array of dimension 2 to use for brackets.
320
+ # @return [String] The banner.
321
+ # @see #format
322
+ def get_banner(label, base_color, full_colored = false, bracket_color = "blue", brackets = ["[", "]"])
323
+ brackets = brackets.ensure_array
324
+ bracket_color = base_color if full_colored
325
+ "{mark=%s}%s{mark=%s}%s{/mark}%s{/mark}" % [bracket_color.parameterize, brackets[0], base_color.parameterize, label, brackets[1]]
326
+ end
327
+
328
+ # Writes a message prepending a cyan type banner.
329
+ #
330
+ # @param message [String] The message to format.
331
+ # @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
332
+ # @param indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use thecurrent indentation, a negative value of `-x` will indent of `x` absolute spaces.
333
+ # @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
334
+ # @param plain [Boolean] If ignore color markers into the message.
335
+ # @param indented_banner [Boolean] If also the banner should be indented.
336
+ # @param full_colored [Boolean] If the banner should be fully colored.
337
+ # @param print [Boolean] If `false`, the result will be returned instead of be printed.
338
+ #
339
+ # @see #format
340
+ def info(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
341
+ banner = self.get_banner(" INFO", "bright cyan", full_colored)
342
+ message = self.indent(message, indented_banner ? 0 : indent)
343
+ self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
344
+ end
345
+
346
+ # Writes a message prepending a green type banner.
347
+ #
348
+ # @param message [String] The message to format.
349
+ # @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
350
+ # @param indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use thecurrent indentation, a negative value of `-x` will indent of `x` absolute spaces.
351
+ # @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
352
+ # @param plain [Boolean] If ignore color markers into the message.
353
+ # @param indented_banner [Boolean] If also the banner should be indented.
354
+ # @param full_colored [Boolean] If the banner should be fully colored.
355
+ # @param print [Boolean] If `false`, the result will be returned instead of be printed.
356
+ #
357
+ # @see #format
358
+ def begin(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
359
+ banner = " " + self.get_banner("*", "bright green")
360
+ message = self.indent(message, indented_banner ? 0 : indent)
361
+ self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
362
+ end
363
+
364
+ # Writes a message prepending a yellow type banner.
365
+ #
366
+ # @param message [String] The message to format.
367
+ # @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
368
+ # @param indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use thecurrent indentation, a negative value of `-x` will indent of `x` absolute spaces.
369
+ # @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
370
+ # @param plain [Boolean] If ignore color markers into the message.
371
+ # @param indented_banner [Boolean] If also the banner should be indented.
372
+ # @param full_colored [Boolean] If the banner should be fully colored.
373
+ # @param print [Boolean] If `false`, the result will be returned instead of be printed.
374
+ #
375
+ # @see #format
376
+ def warn(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
377
+ banner = self.get_banner(" WARN", "bright yellow", full_colored)
378
+ message = self.indent(message, indented_banner ? 0 : indent)
379
+ self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
380
+ end
381
+
382
+ # Writes a message prepending a red type banner.
383
+ #
384
+ # @param message [String] The message to format.
385
+ # @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
386
+ # @param indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use thecurrent indentation, a negative value of `-x` will indent of `x` absolute spaces.
387
+ # @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
388
+ # @param plain [Boolean] If ignore color markers into the message.
389
+ # @param indented_banner [Boolean] If also the banner should be indented.
390
+ # @param full_colored [Boolean] If the banner should be fully colored.
391
+ # @param print [Boolean] If `false`, the result will be returned instead of be printed.
392
+ #
393
+ # @see #format
394
+ def error(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
395
+ banner = self.get_banner("ERROR", "bright red", full_colored)
396
+ message = self.indent(message, indented_banner ? 0 : indent)
397
+ self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
398
+ end
399
+
400
+ # Writes a message prepending a red type banner and then quits the application.
401
+ #
402
+ # @param message [String] The message to format.
403
+ # @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
404
+ # @param indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use thecurrent indentation, a negative value of `-x` will indent of `x` absolute spaces.
405
+ # @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
406
+ # @param plain [Boolean] If ignore color markers into the message.
407
+ # @param indented_banner [Boolean] If also the banner should be indented.
408
+ # @param full_colored [Boolean] If the banner should be fully colored.
409
+ # @param return_code [Fixnum] The code to return to the shell.
410
+ # @param print [Boolean] If `false`, the result will be returned instead of be printed.
411
+ #
412
+ # @see #format
413
+ def fatal(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, return_code = -1, print = true)
414
+ self.error(message, suffix, indent, wrap, plain, indented_banner, full_colored, print)
415
+ Kernel.abort(return_code)
416
+ end
417
+
418
+ # Writes a message prepending a magenta type banner.
419
+ #
420
+ # @param message [String] The message to format.
421
+ # @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
422
+ # @param indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use thecurrent indentation, a negative value of `-x` will indent of `x` absolute spaces.
423
+ # @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
424
+ # @param plain [Boolean] If ignore color markers into the message.
425
+ # @param indented_banner [Boolean] If also the banner should be indented.
426
+ # @param full_colored [Boolean] If the banner should be fully colored.
427
+ # @param print [Boolean] If `false`, the result will be returned instead of be printed.
428
+ #
429
+ # @see #format
430
+ def debug(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
431
+ banner = self.get_banner("DEBUG", "bright magenta", full_colored)
432
+ message = self.indent(message, indented_banner ? 0 : indent)
433
+ self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
434
+ end
435
+
436
+ # Reads a string from the console.
437
+ #
438
+ # @param prompt [String|Boolean] A prompt to show. If `true`, `Please insert a value:` will be used, if `nil` or `false` no prompt will be shown.
439
+ # @param default_value [String] Default value if user simply pressed the enter key.
440
+ # @param validator [Array|Regexp] An array of values or a Regexp to match the submitted value against.
441
+ # @param echo [Boolean] If to show submitted text to the user.
442
+ def read(prompt = true, default_value = nil, validator = nil, echo = true)
443
+ # TODO: Echo and print prompt without newline
444
+
445
+ # Write the prompt
446
+ prompt = "Please insert a value" if prompt == true
447
+ final_prompt = !prompt.nil? ? prompt.gsub(/:?\s*$/, "") + ": " : nil
448
+
449
+ # Adjust validator
450
+ validator = validator.ensure_array.collect {|v| v.ensure_string} if validator.present? && !validator.is_a?(::Regexp)
451
+
452
+ # Handle echo
453
+ stty = ::Bovem::Console.execute("which stty").strip
454
+ disable_echo = !echo && stty.present? && /-echo\b/mix.match(::Bovem::Console.execute(stty)).nil?
455
+
456
+ # Disable echo
457
+ ::Bovem::Console.execute("#{stty} -echo") if disable_echo
458
+
459
+ begin
460
+ catch(:reply) do
461
+ while true do
462
+ valid = true
463
+
464
+ if final_prompt then
465
+ Kernel.print self.format(final_prompt, false, false)
466
+ $stdout.flush
467
+ end
468
+
469
+ reply = Kernel.gets.chop
470
+ reply = default_value if reply.empty?
471
+
472
+ # Match against the validator
473
+ if validator.present? then
474
+ if validator.is_a?(Array) then
475
+ valid = false if validator.length > 0 && !validator.include?(reply)
476
+ elsif validator.is_a?(Regexp) then
477
+ valid = false if !validator.match(reply)
478
+ end
479
+ end
480
+
481
+ if !valid then
482
+ self.write("Sorry, your reply was not understood. Please try again.", false, false)
483
+ else
484
+ throw(:reply, reply)
485
+ end
486
+ end
487
+ end
488
+ rescue Interrupt
489
+ default_value
490
+ ensure
491
+ ::Bovem::Console.execute("#{stty} echo") if disable_echo
492
+ end
493
+ end
494
+
495
+ # Execute a block of code in a indentation region and then prints out and ending status message.
496
+ #
497
+ # @param message [String] The message to format.
498
+ # @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
499
+ # @param indent [Object] If not `nil` or `false`, the width to use for indentation. `true` means to use thecurrent indentation, a negative value of `-x` will indent of `x` absolute spaces.
500
+ # @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
501
+ # @param plain [Boolean] If ignore color markers into the message.
502
+ # @param indented_banner [Boolean] If also the banner should be indented.
503
+ # @param full_colored [Boolean] If the banner should be fully colored.
504
+ # @param block_indentation [Fixnum] The new width for the indented region.
505
+ # @param block_indentation_absolute [Boolean] If the new width should not be added to the current one but rather replace it.
506
+ # @return [Symbol] The exit status for the block.
507
+ 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)
508
+ status = nil
509
+
510
+ self.begin(message, suffix, indent, wrap, plain, indented_banner, full_colored) if message.present?
511
+
512
+ self.with_indentation(block_indentation, block_indentation_absolute) do
513
+ rv = block_given? ? yield.ensure_array : [:ok] # Execute block
514
+ status = rv[0] # Return value
515
+
516
+ if status == :fatal then
517
+ self.status(:fail, plain)
518
+ exit(rv.length > 1 ? rv[1].to_integer : -1)
519
+ else
520
+ self.status(status, plain)
521
+ end
522
+ end
523
+
524
+ status
525
+ end
526
+ end
527
+ end
@@ -75,8 +75,7 @@ module Bovem
75
75
  else :white
76
76
  end
77
77
 
78
- header = ("[%s T+%0.5f] %s:" %[datetime.strftime("%Y/%b/%d %H:%M:%S"), [datetime.to_f - self.start_time.to_f, 0].max, severity.rjust(5)]).bright
79
- header = header.color(color) if color.present?
78
+ header = ::Bovem::Console.replace_markers("{mark=bright-#{color}}[%s T+%0.5f] %s:{/mark}" %[datetime.strftime("%Y/%b/%d %H:%M:%S"), [datetime.to_f - self.start_time.to_f, 0].max, severity.rjust(5)])
80
79
  "%s %s\n" % [header, msg]
81
80
  }
82
81
  end
@@ -14,7 +14,7 @@ module Bovem
14
14
  MAJOR = 0
15
15
 
16
16
  # The minor version.
17
- MINOR = 6
17
+ MINOR = 8
18
18
 
19
19
  # The patch version.
20
20
  PATCH = 0
@@ -7,7 +7,7 @@
7
7
  require "spec_helper"
8
8
 
9
9
  describe Bovem::Configuration do
10
- class BaseConfiguration < Bovem::Configuration
10
+ class BaseConfiguration < ::Bovem::Configuration
11
11
  property :property
12
12
  end
13
13
 
@@ -27,8 +27,8 @@ describe Bovem::Configuration do
27
27
  file1 = ::File.open("#{test_prefix}-1", "w") {|f| f.write("config.property = ") }
28
28
  file2 = ::File.open("#{test_prefix}-2", "w") {|f| f.write("config.non_property = 1234") }
29
29
 
30
- expect { config = BaseConfiguration.new("#{test_prefix}-1")}.to raise_error(Bovem::Errors::InvalidConfiguration)
31
- expect { config = BaseConfiguration.new("#{test_prefix}-2")}.to raise_error(Bovem::Errors::InvalidConfiguration)
30
+ expect { config = BaseConfiguration.new("#{test_prefix}-1")}.to raise_error(::Bovem::Errors::InvalidConfiguration)
31
+ expect { config = BaseConfiguration.new("#{test_prefix}-2")}.to raise_error(::Bovem::Errors::InvalidConfiguration)
32
32
 
33
33
  File.unlink("#{test_prefix}-1")
34
34
  File.unlink("#{test_prefix}-2")
@@ -0,0 +1,419 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the bovem gem. Copyright (C) 2012 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ require "spec_helper"
8
+
9
+ describe Bovem::Console do
10
+ let(:console) { ::Bovem::Console.new }
11
+
12
+ before(:each) do
13
+ Kernel.stub(:puts).and_return(nil)
14
+ end
15
+
16
+ describe ".instance" do
17
+ it "should always return the same instance" do
18
+ instance = ::Bovem::Console.instance
19
+ expect(::Bovem::Console.instance).to be(instance)
20
+ end
21
+ end
22
+
23
+ describe ".parse_style" do
24
+ it "should correctly parse styles" do
25
+ expect(::Bovem::Console.parse_style("red")).to eq("\e[31m")
26
+ expect(::Bovem::Console.parse_style("bg_green")).to eq("\e[42m")
27
+ expect(::Bovem::Console.parse_style("bright")).to eq("\e[1m")
28
+ expect(::Bovem::Console.parse_style("FOO")).to eq("")
29
+ expect(::Bovem::Console.parse_style(nil)).to eq("")
30
+ expect(::Bovem::Console.parse_style(["A"])).to eq("")
31
+ end
32
+ end
33
+
34
+ describe ".replace_markers" do
35
+ it "should correct replace markers" do
36
+ expect(::Bovem::Console.replace_markers("{mark=red}RED{/mark}")).to eq("\e[31mRED\e[0m")
37
+ expect(::Bovem::Console.replace_markers("{mark=red}RED {mark=green}GREEN{/mark}{/mark}")).to eq("\e[31mRED \e[32mGREEN\e[31m\e[0m")
38
+ expect(::Bovem::Console.replace_markers("{mark=red}RED {mark=bright-green}GREEN {mark=blue}BLUE{mark=NONE}RED{/mark}{/mark}{/mark}{/mark}")).to eq("\e[31mRED \e[1m\e[32mGREEN \e[34mBLUERED\e[1m\e[32m\e[31m\e[0m")
39
+ expect(::Bovem::Console.replace_markers("{mark=bg_red}RED{mark=reset}NORMAL{/mark}{/mark}")).to eq("\e[41mRED\e[0mNORMAL\e[41m\e[0m")
40
+ expect(::Bovem::Console.replace_markers("{mark=NONE}RED{/mark}")).to eq("RED")
41
+ end
42
+
43
+ it "should clean up markers if requested" do
44
+ expect(::Bovem::Console.replace_markers("{mark=red}RED{/mark}", true)).to eq("RED")
45
+ end
46
+ end
47
+
48
+ describe ".execute_command" do
49
+ it "should execute a command" do
50
+ expect(::Bovem::Console.execute("echo OK")).to eq("OK\n")
51
+ end
52
+ end
53
+
54
+ describe "#initialize" do
55
+ it "should correctly set defaults" do
56
+ expect(console.indentation).to eq(0)
57
+ expect(console.line_width).to eq(80)
58
+ expect(console.indentation_string).to eq(" ")
59
+ end
60
+ end
61
+
62
+ describe "#get_screen_width" do
63
+ it "should execute tput cols" do
64
+ ::Bovem::Console.should_receive("execute").with("tput cols")
65
+ console.get_screen_width
66
+ end
67
+
68
+ it "should return a number >= 0" do
69
+ expect(console.get_screen_width).to be >= 0
70
+ end
71
+ end
72
+
73
+ describe "#set_indentation" do
74
+ it "should correctly set indentation" do
75
+ expect(console.indentation).to eq(0)
76
+ console.set_indentation(5)
77
+ expect(console.indentation).to eq(5)
78
+ console.set_indentation(-2)
79
+ expect(console.indentation).to eq(3)
80
+ console.set_indentation(10, true)
81
+ expect(console.indentation).to eq(10)
82
+ end
83
+ end
84
+
85
+ describe "#reset_indentation" do
86
+ it "should correctly reset indentation" do
87
+ console.set_indentation(5)
88
+ expect(console.indentation).to eq(5)
89
+ console.reset_indentation
90
+ expect(console.indentation).to eq(0)
91
+ end
92
+ end
93
+
94
+ describe "#with_indentation" do
95
+ it "should correctly wrap indentation" do
96
+ console.set_indentation(5)
97
+ expect(console.indentation).to eq(5)
98
+
99
+ console.with_indentation(7) do
100
+ expect(console.indentation).to eq(12)
101
+ end
102
+ expect(console.indentation).to eq(5)
103
+
104
+ console.with_indentation(3, true) do
105
+ expect(console.indentation).to eq(3)
106
+ end
107
+ expect(console.indentation).to eq(5)
108
+ end
109
+ end
110
+
111
+ describe "#wrap" do
112
+ it "should correct wrap text" do
113
+ message = " ABC__DEF GHI JKL"
114
+ expect(console.wrap(message, 2)).to eq("ABC__DEF\nGHI\nJKL")
115
+ expect(console.wrap(message, 3)).to eq("ABC__DEF\nGHI\nJKL")
116
+ expect(console.wrap(message, 4)).to eq("ABC__DEF\nGHI\nJKL")
117
+ expect(console.wrap(message, 5)).to eq("ABC__DEF\nGHI\nJKL")
118
+ expect(console.wrap(message, 20)).to eq(" ABC__DEF GHI JKL")
119
+
120
+ expect(console.wrap(message, nil)).to eq(message)
121
+ expect(console.wrap(message, -1)).to eq(message)
122
+ end
123
+
124
+ it "should work well with #indent" do
125
+ message = "AB CD"
126
+ console.set_indentation(2)
127
+ expect(console.wrap(console.indent(message), 2)).to eq("AB\nCD")
128
+ end
129
+ end
130
+
131
+ describe "#indent" do
132
+ it "should correctly indent messages" do
133
+ message = "ABC\nCDE"
134
+ console.set_indentation(2)
135
+
136
+ expect(console.indent(message)).to eq(" ABC\n CDE")
137
+ expect(console.indent(message, -1)).to eq(" ABC\n CDE")
138
+ expect(console.indent(message, 1)).to eq(" ABC\n CDE")
139
+ expect(console.indent(message, true, "D")).to eq(" ABC\nCD E")
140
+
141
+ expect(console.indent(message, 0)).to eq(message)
142
+ expect(console.indent(message, nil)).to eq(message)
143
+ expect(console.indent(message, false)).to eq(message)
144
+ expect(console.indent(message, "A")).to eq(message)
145
+ end
146
+ end
147
+
148
+ describe "#format" do
149
+ it "should apply modifications to the message" do
150
+ message = "ABC"
151
+ console.set_indentation(2)
152
+ expect(console.format(message, "\n", false)).to eq("ABC\n")
153
+ expect(console.format(message, "A")).to eq(" ABCA")
154
+ expect(console.format(message, "A", 3)).to eq(" ABCA")
155
+ expect(console.format(message, "A", 3, 4)).to eq(" ABCA")
156
+ expect(console.format("{mark=red}ABC{/mark}", "\n", true, true, true)).to eq(" ABC\n")
157
+ end
158
+ end
159
+
160
+ describe "#replace_markers" do
161
+ it "should just forwards to .replace_markers" do
162
+ ::Bovem::Console.should_receive("replace_markers").with("A", "B")
163
+ console.replace_markers("A", "B")
164
+ end
165
+ end
166
+
167
+ describe "#format_right" do
168
+ it "should correctly align messages" do
169
+ message = "ABCDE"
170
+ extended_message = "ABC\e[AD\e[3mE"
171
+ console.screen_width = 80
172
+
173
+ expect(console.format_right(message)).to eq("\e[A\e[0G\e[#{75}CABCDE")
174
+ expect(console.format_right(message, 10)).to eq("\e[A\e[0G\e[#{5}CABCDE")
175
+ expect(console.format_right(extended_message)).to eq("\e[A\e[0G\e[#{75}CABC\e[AD\e[3mE")
176
+ expect(console.format_right(message, nil, false)).to eq("\e[0G\e[#{75}CABCDE")
177
+ console.screen_width = 10
178
+ expect(console.format_right(message)).to eq("\e[A\e[0G\e[#{5}CABCDE")
179
+ end
180
+ end
181
+
182
+ describe "#write" do
183
+ it "should call #format" do
184
+ console.should_receive("format").with("A", "B", "C", "D", "E")
185
+ console.write("A", "B", "C", "D", "E")
186
+ end
187
+ end
188
+
189
+ describe "#get_banner" do
190
+ it "should correctly format arguments" do
191
+ expect(console.get_banner("LABEL", "red")).to eq("{mark=blue}[{mark=red}LABEL{/mark}]{/mark}")
192
+ expect(console.get_banner("LABEL", "red", true)).to eq("{mark=red}[{mark=red}LABEL{/mark}]{/mark}")
193
+ expect(console.get_banner("LABEL", "red", false, "yellow")).to eq("{mark=yellow}[{mark=red}LABEL{/mark}]{/mark}")
194
+ expect(console.get_banner("LABEL", "red", false, "blue", nil)).to eq("{mark=blue}{mark=red}LABEL{/mark}{/mark}")
195
+ expect(console.get_banner("LABEL", "red", false, "blue", "A")).to eq("{mark=blue}A{mark=red}LABEL{/mark}{/mark}")
196
+ expect(console.get_banner("LABEL", "red", false, "blue", ["A", "B"])).to eq("{mark=blue}A{mark=red}LABEL{/mark}B{/mark}")
197
+ end
198
+ end
199
+
200
+ describe "#info" do
201
+ it "should forward everything to #get_banner" do
202
+ console.should_receive("get_banner").with(" INFO", "bright cyan", false).at_least(1).and_return("")
203
+ console.info("OK", "\n", true, false, false, false, false, false)
204
+ console.should_receive("get_banner").with(" INFO", "bright cyan", true).at_least(1).and_return("")
205
+ console.info("OK", "\n", true, false, false, false, true, false)
206
+ end
207
+
208
+ it "should forward everything to #write" do
209
+ console.should_receive("write").with(/.+/, "B", "C", "D", "E", false)
210
+ console.info("A", "B", "C", "D", "E", "F", "G", false)
211
+ end
212
+ end
213
+
214
+ describe "#begin" do
215
+ it "should forward everything to #get_banner" do
216
+ console.should_receive("get_banner").with("*", "bright green").at_least(1).and_return("")
217
+ console.begin("OK", "\n", true, false, false, false, false, false)
218
+ end
219
+
220
+ it "should forward everything to #write" do
221
+ console.should_receive("write").with(/.+/, "B", "C", "D", "E", false)
222
+ console.begin("A", "B", "C", "D", "E", "F", "G", false)
223
+ end
224
+ end
225
+
226
+ describe "#warn" do
227
+ it "should forward everything to #get_banner" do
228
+ console.should_receive("get_banner").with(" WARN", "bright yellow", false).at_least(1).and_return("")
229
+ console.warn("OK", "\n", true, false, false, false, false, false)
230
+ console.should_receive("get_banner").with(" WARN", "bright yellow", true).at_least(1).and_return("")
231
+ console.warn("OK", "\n", true, false, false, false, true, false)
232
+ end
233
+
234
+ it "should forward everything to #write" do
235
+ console.should_receive("write").with(/.+/, "B", "C", "D", "E", false)
236
+ console.warn("A", "B", "C", "D", "E", "F", "G", false)
237
+ end
238
+ end
239
+
240
+ describe "#error" do
241
+ it "should forward everything to #get_banner" do
242
+ console.should_receive("get_banner").with("ERROR", "bright red", false).at_least(1).and_return("")
243
+ console.error("OK", "\n", true, false, false, false, false, false)
244
+ console.should_receive("get_banner").with("ERROR", "bright red", true).at_least(1).and_return("")
245
+ console.error("OK", "\n", true, false, false, false, true, false)
246
+ end
247
+
248
+ it "should forward everything to #write" do
249
+ console.should_receive("write").with(/.+/, "B", "C", "D", "E", false)
250
+ console.error("A", "B", "C", "D", "E", "F", "G", false)
251
+ end
252
+ end
253
+
254
+ describe "#fatal" do
255
+ it "should forward anything to #error" do
256
+ Kernel.stub(:abort).and_return(true)
257
+ console.should_receive("error").with("A", "B", "C", "D", "E", "F", "G", false)
258
+ console.fatal("A", "B", "C", "D", "E", "F", "G", "H", false)
259
+ end
260
+
261
+ it "should call abort with the right error code" do
262
+ Kernel.stub(:abort).and_return(true)
263
+
264
+ Kernel.should_receive("abort").with(-1).at_least(1)
265
+ console.fatal("A", "B", "C", "D", "E", "F", "G", -1, false)
266
+ Kernel.should_receive("abort").with("H").at_least(1)
267
+ console.fatal("A", "B", "C", "D", "E", "F", "G", "H", false)
268
+ end
269
+ end
270
+
271
+ describe "#debug" do
272
+ it "should forward everything to #get_banner" do
273
+ console.should_receive("get_banner").with("DEBUG", "bright magenta", false).at_least(1).and_return("")
274
+ console.debug("OK", "\n", true, false, false, false, false, false)
275
+ console.should_receive("get_banner").with("DEBUG", "bright magenta", true).at_least(1).and_return("")
276
+ console.debug("OK", "\n", true, false, false, false, true, false)
277
+ end
278
+
279
+ it "should forward everything to #write" do
280
+ console.should_receive("write").with(/.+/, "B", "C", "D", "E", false)
281
+ console.debug("A", "B", "C", "D", "E", "F", "G", false)
282
+ end
283
+ end
284
+
285
+ describe "status" do
286
+ it "should get the right status" do
287
+ expect(console.status(:ok, false, true, false)).to eq({:label => " OK ", :color => "bright green"})
288
+ expect(console.status(:pass, false, true, false)).to eq({:label => "PASS", :color => "bright cyan"})
289
+ expect(console.status(:warn, false, true, false)).to eq({:label => "WARN", :color => "bright yellow"})
290
+ expect(console.status(:fail, false, true, false)).to eq({:label => "FAIL", :color => "bright red"})
291
+ expect(console.status("NO", false, true, false)).to eq({:label => "PASS", :color => "bright cyan"})
292
+ expect(console.status(nil, false, true, false)).to eq({:label => "PASS", :color => "bright cyan"})
293
+ end
294
+
295
+ it "should create the banner" do
296
+ console.should_receive("get_banner").with(" OK ", "bright green").and_return("")
297
+ console.status(:ok)
298
+ end
299
+
300
+ it "should format correctly" do
301
+ console.should_receive("format_right").with(/.+/, true, true, false)
302
+ console.status(:ok, false, true)
303
+ console.should_receive("format").with(/.+/, "\n", true, true, false)
304
+ console.status(:ok, false, true, false)
305
+ end
306
+ end
307
+
308
+ describe "#read" do
309
+ it "should show a prompt" do
310
+ prompt = "PROMPT"
311
+ Kernel.should_receive("print").with("Please insert a value: ")
312
+ console.read(true)
313
+ Kernel.should_receive("print").with(prompt + ": ")
314
+ console.read(prompt)
315
+ Kernel.should_not_receive("print")
316
+ console.read(nil)
317
+ end
318
+
319
+ it "should read a value or a default" do
320
+ Kernel.stub(:gets).and_return("VALUE\n")
321
+ expect(console.read(nil, "DEFAULT")).to eq("VALUE")
322
+ Kernel.stub(:gets).and_return("\n")
323
+ expect(console.read(nil, "DEFAULT")).to eq("DEFAULT")
324
+ end
325
+
326
+ it "should return the default value if the user quits" do
327
+ Kernel.stub(:gets).and_raise(Interrupt)
328
+ expect(console.read(nil, "DEFAULT")).to eq("DEFAULT")
329
+ end
330
+
331
+ it "should validate against an object or array validator" do
332
+ count = 0
333
+
334
+ Kernel.stub(:gets) do
335
+ if count == 0 then
336
+ count += 1
337
+ "2\n"
338
+ else
339
+ raise Interrupt
340
+ end
341
+ end
342
+
343
+ console.should_receive("write").with("Sorry, your reply was not understood. Please try again.", false, false).exactly(4)
344
+ count = 0
345
+ console.read(nil, nil, "A")
346
+ count = 0
347
+ console.read(nil, nil, "1")
348
+ count = 0
349
+ console.read(nil, nil, "nil")
350
+ count = 0
351
+ console.read(nil, nil, ["A", 1])
352
+ end
353
+
354
+ it "should validate against an regexp validator" do
355
+ count = 0
356
+
357
+ Kernel.stub(:gets) do
358
+ if count == 0 then
359
+ count += 1
360
+ "2\n"
361
+ else
362
+ raise Interrupt
363
+ end
364
+ end
365
+
366
+ console.should_receive("write").with("Sorry, your reply was not understood. Please try again.", false, false)
367
+ console.read(nil, nil, /[abc]/)
368
+ end
369
+
370
+ it "should hide echo to the user when the terminal shows echo" do
371
+ stty = %x{which stty}.strip
372
+
373
+ ::Bovem::Console.should_receive("execute").with("which stty").and_return(stty)
374
+ ::Bovem::Console.should_receive("execute").with(stty).and_return("speed 9600 baud;\nlflags: echoe echoke echoctl pendin\niflags: iutf8\noflags: -oxtabs\ncflags: cs8 -parenb")
375
+ ::Bovem::Console.should_receive("execute").with("#{stty} -echo")
376
+ ::Bovem::Console.should_receive("execute").with("#{stty} echo")
377
+ console.read(nil, nil, nil, false)
378
+ end
379
+
380
+ it "shouldn't hide echo again when the terminal already hides it" do
381
+ stty = %x{which stty}.strip
382
+
383
+ ::Bovem::Console.should_receive("execute").with("which stty").and_return(stty)
384
+ ::Bovem::Console.should_receive("execute").with(stty).and_return("speed 9600 baud;\nlflags: -echo echoe echoke echoctl pendin\niflags: iutf8\noflags: -oxtabs\ncflags: cs8 -parenb")
385
+ ::Bovem::Console.should_not_receive("execute").with("#{stty} -echo")
386
+ ::Bovem::Console.should_not_receive("execute").with("#{stty} echo")
387
+ console.read(nil, nil, nil, false)
388
+ end
389
+ end
390
+
391
+ describe "#task" do
392
+ it "should not print the message by default" do
393
+ console.should_not_receive("begin")
394
+ console.task { :ok }
395
+ end
396
+
397
+ it "should print the message and indentate correctly" do
398
+ console.should_receive("begin").with("A", "B", "C", "D", "E", "F", "G")
399
+ console.should_receive("with_indentation").with("H", "I")
400
+ console.task("A", "B", "C", "D", "E", "F", "G", "H", "I") { :ok }
401
+ end
402
+
403
+ it "should execute the given block" do
404
+ ::Bovem::Console.should_receive("foo")
405
+ console.task { ::Bovem::Console.foo }
406
+ end
407
+
408
+ it "should write the correct status" do
409
+ console.should_receive(:status).with(:ok, false)
410
+ console.task { :ok }
411
+ console.should_receive(:status).with(:fail, false)
412
+ expect { console.task { :fatal }}.to raise_error(SystemExit)
413
+ end
414
+
415
+ it "should abort correctly" do
416
+ expect { console.task { [:fatal, -1] }}.to raise_error(SystemExit)
417
+ end
418
+ end
419
+ end
@@ -7,41 +7,37 @@
7
7
  require "spec_helper"
8
8
 
9
9
  describe Bovem::Logger do
10
- before(:each) do
11
- Sickill::Rainbow.enabled = false
12
- end
13
-
14
10
  describe ".create" do
15
11
  it("should create a new default logger") do
16
- logger = Bovem::Logger.create
17
- expect(logger.device).to eq(Bovem::Logger.default_file)
12
+ logger = ::Bovem::Logger.create
13
+ expect(logger.device).to eq(::Bovem::Logger.default_file)
18
14
  expect(logger.level).to eq(::Logger::INFO)
19
- expect(logger.formatter).to eq(Bovem::Logger.default_formatter)
15
+ expect(logger.formatter).to eq(::Bovem::Logger.default_formatter)
20
16
  end
21
17
 
22
18
  it("should create a logger with a custom file and level") do
23
- logger = Bovem::Logger.create("/dev/null", ::Logger::WARN)
19
+ logger = ::Bovem::Logger.create("/dev/null", ::Logger::WARN)
24
20
  expect(logger.device).to eq("/dev/null")
25
21
  expect(logger.level).to eq(::Logger::WARN)
26
- expect(logger.formatter).to eq(Bovem::Logger.default_formatter)
22
+ expect(logger.formatter).to eq(::Bovem::Logger.default_formatter)
27
23
  end
28
24
 
29
25
  it("should create a logger with a custom formatter") do
30
26
  formatter = Proc.new {|severity, datetime, progname, msg| msg }
31
- logger = Bovem::Logger.create("/dev/null", ::Logger::WARN, formatter)
27
+ logger = ::Bovem::Logger.create("/dev/null", ::Logger::WARN, formatter)
32
28
  expect(logger.device).to eq("/dev/null")
33
29
  expect(logger.level).to eq(::Logger::WARN)
34
30
  expect(logger.formatter).to eq(formatter)
35
31
  end
36
32
 
37
33
  it("should raise exceptions for invalid files") do
38
- expect { Bovem::Logger.create("/invalid/file") }.to raise_error(Bovem::Errors::InvalidLogger)
34
+ expect { ::Bovem::Logger.create("/invalid/file") }.to raise_error(::Bovem::Errors::InvalidLogger)
39
35
  end
40
36
  end
41
37
 
42
38
  describe ".default_formatter" do
43
39
  let(:output) { ::StringIO.new }
44
- let(:logger) { Bovem::Logger.create(output, Logger::DEBUG) }
40
+ let(:logger) { ::Bovem::Logger.create(output, Logger::DEBUG) }
45
41
 
46
42
  def get_last_line(buffer)
47
43
  buffer.string.split("\n").last.strip.gsub(/ T\+\d+\.\d+/, "")
@@ -49,52 +45,52 @@ describe Bovem::Logger do
49
45
 
50
46
  it "should correctly format a DEBUG message" do
51
47
  logger.debug("Message.")
52
- expect(get_last_line(output)).to eq("[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] DEBUG: Message.")
48
+ expect(get_last_line(output)).to eq("\e[1m\e[36m[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] DEBUG:\e[0m Message.")
53
49
  end
54
50
 
55
51
  it "should correctly format a INFO message" do
56
52
  logger.info("Message.")
57
- expect(get_last_line(output)).to eq("[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] INFO: Message.")
53
+ expect(get_last_line(output)).to eq("\e[1m\e[32m[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] INFO:\e[0m Message.")
58
54
  end
59
55
 
60
56
  it "should correctly format a WARN message" do
61
57
  logger.warn("Message.")
62
- expect(get_last_line(output)).to eq("[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] WARN: Message.")
58
+ expect(get_last_line(output)).to eq("\e[1m\e[33m[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] WARN:\e[0m Message.")
63
59
  end
64
60
 
65
61
  it "should correctly format a ERROR message" do
66
62
  logger.error("Message.")
67
- expect(get_last_line(output)).to eq("[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] ERROR: Message.")
63
+ expect(get_last_line(output)).to eq("\e[1m\e[31m[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] ERROR:\e[0m Message.")
68
64
  end
69
65
 
70
66
  it "should correctly format a FATAL message" do
71
67
  logger.fatal("Message.")
72
- expect(get_last_line(output)).to eq("[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] FATAL: Message.")
68
+ expect(get_last_line(output)).to eq("\e[1m\e[35m[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] FATAL:\e[0m Message.")
73
69
  end
74
70
 
75
71
  it "should correctly format a INVALID message" do
76
72
  logger.log(::Logger::UNKNOWN, "Message.")
77
- expect(get_last_line(output)).to eq("[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] ANY: Message.")
73
+ expect(get_last_line(output)).to eq("\e[1m\e[37m[#{::Time.now.strftime("%Y/%b/%d %H:%M:%S")}] ANY:\e[0m Message.")
78
74
  end
79
75
  end
80
76
 
81
77
  describe ".get_real_file" do
82
78
  it("should return the standard ouput") do
83
- expect(Bovem::Logger.get_real_file("STDOUT")).to eq($stdout )
79
+ expect(::Bovem::Logger.get_real_file("STDOUT")).to eq($stdout )
84
80
  end
85
81
 
86
82
  it("should return the standard error") do
87
- expect(Bovem::Logger.get_real_file("STDERR")).to eq($stderr )
83
+ expect(::Bovem::Logger.get_real_file("STDERR")).to eq($stderr )
88
84
  end
89
85
 
90
86
  it("should return the file") do
91
- expect(Bovem::Logger.get_real_file("/dev/null")).to eq("/dev/null" )
87
+ expect(::Bovem::Logger.get_real_file("/dev/null")).to eq("/dev/null" )
92
88
  end
93
89
  end
94
90
 
95
91
  describe ".default_file" do
96
92
  it("should return the standard output") do
97
- expect(Bovem::Logger.default_file).to eq($stdout)
93
+ expect(::Bovem::Logger.default_file).to eq($stdout)
98
94
  end
99
95
  end
100
96
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bovem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-04 00:00:00.000000000 Z
12
+ date: 2012-08-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: lazier
@@ -27,22 +27,6 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: '1.0'
30
- - !ruby/object:Gem::Dependency
31
- name: rainbow
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ~>
36
- - !ruby/object:Gem::Version
37
- version: 1.1.0
38
- type: :runtime
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ~>
44
- - !ruby/object:Gem::Version
45
- version: 1.1.0
46
30
  - !ruby/object:Gem::Dependency
47
31
  name: rspec
48
32
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +148,7 @@ extra_rdoc_files: []
164
148
  files:
165
149
  - .gitignore
166
150
  - .travis.yml
151
+ - .yardopts
167
152
  - Gemfile
168
153
  - Gemfile.lock
169
154
  - README.md
@@ -171,10 +156,12 @@ files:
171
156
  - bovem.gemspec
172
157
  - lib/bovem.rb
173
158
  - lib/bovem/configuration.rb
159
+ - lib/bovem/console.rb
174
160
  - lib/bovem/errors.rb
175
161
  - lib/bovem/logger.rb
176
162
  - lib/bovem/version.rb
177
163
  - spec/bovem/configuration_spec.rb
164
+ - spec/bovem/console_spec.rb
178
165
  - spec/bovem/logger_spec.rb
179
166
  - spec/coverage_helper.rb
180
167
  - spec/spec_helper.rb
@@ -192,7 +179,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
192
179
  version: '0'
193
180
  segments:
194
181
  - 0
195
- hash: 2994685413523034481
182
+ hash: 1005901381076848041
196
183
  required_rubygems_version: !ruby/object:Gem::Requirement
197
184
  none: false
198
185
  requirements:
@@ -201,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
201
188
  version: '0'
202
189
  segments:
203
190
  - 0
204
- hash: 2994685413523034481
191
+ hash: 1005901381076848041
205
192
  requirements: []
206
193
  rubyforge_project: bovem
207
194
  rubygems_version: 1.8.24
@@ -210,6 +197,7 @@ specification_version: 3
210
197
  summary: A collection of utilities for developers.
211
198
  test_files:
212
199
  - spec/bovem/configuration_spec.rb
200
+ - spec/bovem/console_spec.rb
213
201
  - spec/bovem/logger_spec.rb
214
202
  - spec/coverage_helper.rb
215
203
  - spec/spec_helper.rb