bovem 1.2.6 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +1 -1
- data/Gemfile +1 -1
- data/README.md +5 -2
- data/bovem.gemspec +11 -9
- data/doc/Bovem.html +7 -25
- data/doc/Bovem/Configuration.html +30 -43
- data/doc/Bovem/Console.html +225 -4360
- data/doc/Bovem/ConsoleMethods.html +125 -0
- data/doc/Bovem/ConsoleMethods/Interactions.html +575 -0
- data/doc/Bovem/ConsoleMethods/Interactions/ClassMethods.html +231 -0
- data/doc/Bovem/ConsoleMethods/Logging.html +2218 -0
- data/doc/Bovem/ConsoleMethods/Logging/ClassMethods.html +212 -0
- data/doc/Bovem/ConsoleMethods/Output.html +1213 -0
- data/doc/Bovem/ConsoleMethods/StyleHandling.html +274 -0
- data/doc/Bovem/ConsoleMethods/StyleHandling/ClassMethods.html +653 -0
- data/doc/Bovem/Errors.html +3 -3
- data/doc/Bovem/Errors/InvalidConfiguration.html +3 -3
- data/doc/Bovem/Errors/InvalidLogger.html +3 -3
- data/doc/Bovem/Logger.html +112 -12
- data/doc/Bovem/Shell.html +58 -1888
- data/doc/Bovem/ShellMethods.html +125 -0
- data/doc/Bovem/ShellMethods/Directories.html +484 -0
- data/doc/Bovem/ShellMethods/Execute.html +565 -0
- data/doc/Bovem/ShellMethods/General.html +450 -0
- data/doc/Bovem/ShellMethods/Read.html +451 -0
- data/doc/Bovem/ShellMethods/Write.html +676 -0
- data/doc/Bovem/Version.html +6 -6
- data/doc/_index.html +145 -4
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +10 -7
- data/doc/frames.html +1 -1
- data/doc/index.html +10 -7
- data/doc/method_list.html +119 -79
- data/doc/top-level-namespace.html +3 -3
- data/lib/bovem.rb +1 -1
- data/lib/bovem/configuration.rb +24 -13
- data/lib/bovem/console.rb +566 -497
- data/lib/bovem/errors.rb +1 -1
- data/lib/bovem/logger.rb +4 -4
- data/lib/bovem/shell.rb +482 -305
- data/lib/bovem/version.rb +4 -4
- data/locales/en.yml +43 -0
- data/locales/it.yml +43 -0
- data/spec/bovem/configuration_spec.rb +3 -3
- data/spec/bovem/console_spec.rb +17 -10
- data/spec/bovem/logger_spec.rb +1 -1
- data/spec/bovem/shell_spec.rb +9 -5
- data/spec/coverage_helper.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- metadata +32 -22
@@ -6,7 +6,7 @@
|
|
6
6
|
<title>
|
7
7
|
Top Level Namespace
|
8
8
|
|
9
|
-
— Documentation by YARD 0.8.
|
9
|
+
— Documentation by YARD 0.8.3
|
10
10
|
|
11
11
|
</title>
|
12
12
|
|
@@ -103,9 +103,9 @@
|
|
103
103
|
</div>
|
104
104
|
|
105
105
|
<div id="footer">
|
106
|
-
Generated on
|
106
|
+
Generated on Fri Feb 1 23:40:17 2013 by
|
107
107
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
108
|
-
0.8.
|
108
|
+
0.8.3 (ruby-1.9.3).
|
109
109
|
</div>
|
110
110
|
|
111
111
|
</body>
|
data/lib/bovem.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
#
|
3
|
-
# This file is part of the bovem gem. Copyright (C)
|
3
|
+
# This file is part of the bovem gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
4
|
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
5
|
#
|
6
6
|
|
data/lib/bovem/configuration.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
#
|
3
|
-
# This file is part of the bovem gem. Copyright (C)
|
3
|
+
# This file is part of the bovem gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
4
|
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
5
|
#
|
6
6
|
|
@@ -19,6 +19,8 @@ module Bovem
|
|
19
19
|
# config.property = "VALUE"
|
20
20
|
# ```
|
21
21
|
class Configuration
|
22
|
+
include Lazier::I18n
|
23
|
+
|
22
24
|
# Creates a new configuration.
|
23
25
|
#
|
24
26
|
# A configuration file is a plain Ruby file with a top-level {Configuration config} object.
|
@@ -47,20 +49,11 @@ module Bovem
|
|
47
49
|
def parse(file = nil, overrides = {}, logger = nil)
|
48
50
|
file = file.present? ? File.expand_path(file) : nil
|
49
51
|
|
50
|
-
if file then
|
52
|
+
if file then
|
51
53
|
if File.readable?(file) then
|
52
|
-
|
53
|
-
# Open the file
|
54
|
-
path = ::Pathname.new(file).realpath
|
55
|
-
logger.info("Using configuration file #{path}.") if logger
|
56
|
-
self.tap do |config|
|
57
|
-
eval(::File.read(path))
|
58
|
-
end
|
59
|
-
rescue ::Exception => e
|
60
|
-
raise Bovem::Errors::InvalidConfiguration.new("Config file #{file} is not valid.")
|
61
|
-
end
|
54
|
+
read_configuration_file(file, logger)
|
62
55
|
else
|
63
|
-
raise Bovem::Errors::InvalidConfiguration.new(
|
56
|
+
raise Bovem::Errors::InvalidConfiguration.new(self.i18n.configuration.not_found(file))
|
64
57
|
end
|
65
58
|
end
|
66
59
|
|
@@ -89,5 +82,23 @@ module Bovem
|
|
89
82
|
self.instance_variable_set("@#{name}", value)
|
90
83
|
end
|
91
84
|
end
|
85
|
+
|
86
|
+
private
|
87
|
+
# Reads a configuration file.
|
88
|
+
#
|
89
|
+
# @param file [String] The file to read.
|
90
|
+
# @param logger [Logger] The logger to use for notifications.
|
91
|
+
def read_configuration_file(file, logger)
|
92
|
+
begin
|
93
|
+
# Open the file
|
94
|
+
path = ::Pathname.new(file).realpath
|
95
|
+
logger.info(self.i18n.using(path)) if logger
|
96
|
+
self.tap do |config|
|
97
|
+
eval(::File.read(path))
|
98
|
+
end
|
99
|
+
rescue ::Exception => e
|
100
|
+
raise Bovem::Errors::InvalidConfiguration.new(self.i18n.configuration.invalid(file))
|
101
|
+
end
|
102
|
+
end
|
92
103
|
end
|
93
104
|
end
|
data/lib/bovem/console.rb
CHANGED
@@ -1,575 +1,644 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
#
|
3
|
-
# This file is part of the bovem gem. Copyright (C)
|
3
|
+
# This file is part of the bovem gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
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
7
|
module Bovem
|
8
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
|
-
}
|
9
|
+
TERM_COLORS = { black: 0, red: 1, green: 2, yellow: 3, blue: 4, magenta: 5, cyan: 6, white: 7, default: 9}
|
20
10
|
|
21
11
|
# List of valid terminal text effects.
|
22
|
-
TERM_EFFECTS = {
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
12
|
+
TERM_EFFECTS = { reset: 0, bright: 1, italic: 3, underline: 4, blink: 5, inverse: 7, hide: 8 }
|
13
|
+
|
14
|
+
# Methods of the {Console Console} class.
|
15
|
+
module ConsoleMethods
|
16
|
+
# Methods for handling styles in the terminal.
|
17
|
+
module StyleHandling
|
18
|
+
extend ActiveSupport::Concern
|
19
|
+
|
20
|
+
# Class methods for handling styles in the terminal.
|
21
|
+
module ClassMethods
|
22
|
+
# Parse a style and returns terminal codes.
|
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.
|
25
|
+
#
|
26
|
+
# @param style [String] The style to parse.
|
27
|
+
# @return [String] A string with ANSI color codes.
|
28
|
+
def parse_style(style)
|
29
|
+
style = style.ensure_string.strip.parameterize
|
30
|
+
|
31
|
+
if style.present? then
|
32
|
+
sym = style.to_sym
|
33
|
+
|
34
|
+
::Bovem::Console.replace_term_code(Bovem::TERM_EFFECTS, style, 0) ||
|
35
|
+
::Bovem::Console.replace_term_code(Bovem::TERM_COLORS, style, 30) ||
|
36
|
+
::Bovem::Console.replace_term_code(Bovem::TERM_COLORS, style.gsub(/^bg_/, ""), 40) ||
|
37
|
+
""
|
38
|
+
else
|
39
|
+
""
|
40
|
+
end
|
41
|
+
end
|
31
42
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
43
|
+
# Parses a set of styles and returns terminals codes.
|
44
|
+
# 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.
|
45
|
+
#
|
46
|
+
# @param styles [String] The styles to parse.
|
47
|
+
# @return [String] A string with ANSI color codes.
|
48
|
+
def parse_styles(styles)
|
49
|
+
styles.split(/\s*[\s,-]\s*/).collect { |s| self.parse_style(s) }.join("")
|
50
|
+
end
|
36
51
|
|
37
|
-
|
38
|
-
|
52
|
+
#
|
53
|
+
# Replaces a terminal code.
|
54
|
+
#
|
55
|
+
# @param codes [Array] The valid list of codes.
|
56
|
+
# @param code [String] The code to lookup.
|
57
|
+
# @param modifier [Fixnum] The modifier to apply to the code.
|
58
|
+
# @return [String|nil] The terminal code or `nil` if the code was not found.
|
59
|
+
def replace_term_code(codes, code, modifier = 0)
|
60
|
+
sym = code.to_sym
|
61
|
+
codes.include?(sym) ? "\e[#{modifier + codes[sym]}m" : nil
|
62
|
+
end
|
39
63
|
|
40
|
-
|
41
|
-
|
64
|
+
# Replaces colors markers in a string.
|
65
|
+
#
|
66
|
+
# You can specify markers by enclosing in `{mark=[style]}` and `{/mark}` tags. Separate styles with spaces, dashes or commas. Nesting markers is supported.
|
67
|
+
#
|
68
|
+
# Example:
|
69
|
+
#
|
70
|
+
# ```ruby
|
71
|
+
# Bovem::Console.new.replace_markers("{mark=bright bg_red}{mark=green}Hello world!{/mark}{/mark}")
|
72
|
+
# # => "\e[1m\e[41m\e[32mHello world!\e[1m\e[41m\e[0m"
|
73
|
+
# ```
|
74
|
+
#
|
75
|
+
# @param message [String] The message to analyze.
|
76
|
+
# @param plain [Boolean] If ignore (cleanify) color markers into the message.
|
77
|
+
# @return [String] The replaced message.
|
78
|
+
# @see #parse_style
|
79
|
+
def replace_markers(message, plain = false)
|
80
|
+
stack = []
|
81
|
+
|
82
|
+
message.ensure_string.gsub(/((\{mark=([a-z\-_\s,]+)\})|(\{\/mark\}))/mi) do
|
83
|
+
if $1 == "{/mark}" then # If it is a tag, pop from the latest opened.
|
84
|
+
stack.pop
|
85
|
+
plain || stack.blank? ? "" : ::Bovem::Console.parse_styles(stack.last)
|
86
|
+
else
|
87
|
+
styles = $3
|
88
|
+
replacement = plain ? "" : ::Bovem::Console.parse_styles(styles)
|
42
89
|
|
43
|
-
|
44
|
-
|
90
|
+
if replacement.length > 0 then
|
91
|
+
stack << "reset" if stack.blank?
|
92
|
+
stack << styles
|
93
|
+
end
|
45
94
|
|
46
|
-
|
47
|
-
|
95
|
+
replacement
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
48
100
|
|
49
|
-
|
50
|
-
|
101
|
+
# Replaces colors markers in a string.
|
102
|
+
#
|
103
|
+
# @see .replace_markers
|
104
|
+
#
|
105
|
+
# @param message [String] The message to analyze.
|
106
|
+
# @param plain [Boolean] If ignore (cleanify) color markers into the message.
|
107
|
+
# @return [String] The replaced message.
|
108
|
+
def replace_markers(message, plain = false)
|
109
|
+
::Bovem::Console.replace_markers(message, plain)
|
110
|
+
end
|
111
|
+
end
|
51
112
|
|
52
|
-
#
|
53
|
-
|
113
|
+
# Methods for formatting output messages.
|
114
|
+
module Output
|
115
|
+
# Gets the current screen width.
|
116
|
+
#
|
117
|
+
# @return [Fixnum] The screen width.
|
118
|
+
def get_screen_width
|
119
|
+
::Bovem::Console.execute("tput cols").to_integer(80)
|
120
|
+
end
|
54
121
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
@
|
60
|
-
|
122
|
+
# Sets the new indentation width.
|
123
|
+
#
|
124
|
+
# @param width [Fixnum] The new width.
|
125
|
+
# @param is_absolute [Boolean] If the new width should not be added to the current one but rather replace it.
|
126
|
+
# @return [Fixnum] The new indentation width.
|
127
|
+
def set_indentation(width, is_absolute = false)
|
128
|
+
@indentation = [(!is_absolute ? @indentation : 0) + width, 0].max.to_i
|
129
|
+
@indentation
|
130
|
+
end
|
61
131
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
# @return [String] A string with ANSI color codes.
|
68
|
-
def self.parse_style(style)
|
69
|
-
rv = ""
|
70
|
-
style = style.ensure_string.strip.parameterize
|
71
|
-
|
72
|
-
if style.present? && style !~ /^[,-]$/ then
|
73
|
-
style = style.ensure_string
|
74
|
-
sym = style.to_sym
|
75
|
-
|
76
|
-
if ::Bovem::TERM_EFFECTS.include?(sym) then
|
77
|
-
rv = "\e[#{Bovem::TERM_EFFECTS[sym]}m"
|
78
|
-
elsif style.index("bg_") == 0 then
|
79
|
-
sym = style[3, style.length].to_sym
|
80
|
-
rv = "\e[#{40 + ::Bovem::TERM_COLORS[sym]}m" if ::Bovem::TERM_COLORS.include?(sym)
|
81
|
-
elsif style != "reset" then
|
82
|
-
rv = "\e[#{30 + ::Bovem::TERM_COLORS[sym]}m" if ::Bovem::TERM_COLORS.include?(sym)
|
83
|
-
end
|
132
|
+
# Resets indentation width to `0`.
|
133
|
+
#
|
134
|
+
# @return [Fixnum] The new indentation width.
|
135
|
+
def reset_indentation
|
136
|
+
@indentation = 0
|
84
137
|
end
|
85
138
|
|
86
|
-
|
87
|
-
|
139
|
+
# Starts a indented region of text.
|
140
|
+
#
|
141
|
+
# @param width [Fixnum] The new width.
|
142
|
+
# @param is_absolute [Boolean] If the new width should not be added to the current one but rather replace it.
|
143
|
+
# @return [Fixnum] The new indentation width.
|
144
|
+
def with_indentation(width = 3, is_absolute = false)
|
145
|
+
old = @indentation
|
146
|
+
self.set_indentation(width, is_absolute)
|
147
|
+
yield
|
148
|
+
self.set_indentation(old, true)
|
149
|
+
|
150
|
+
@indentation
|
151
|
+
end
|
88
152
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
# # => "\e[1m\e[41m\e[32mHello world!\e[1m\e[41m\e[0m"
|
98
|
-
# ```
|
99
|
-
#
|
100
|
-
# @param message [String] The message to analyze.
|
101
|
-
# @param plain [Boolean] If ignore (cleanify) color markers into the message.
|
102
|
-
# @return [String] The replaced message.
|
103
|
-
# @see #parse_style
|
104
|
-
def self.replace_markers(message, plain = false)
|
105
|
-
stack = []
|
106
|
-
mark_regexp = /((\{mark=([a-z\-_\s,]+)\})|(\{\/mark\}))/mi
|
107
|
-
split_regex = /\s*[\s,-]\s*/
|
108
|
-
|
109
|
-
message = message.ensure_string.gsub(mark_regexp) do
|
110
|
-
tag = $1
|
111
|
-
styles = $3
|
112
|
-
replacement = ""
|
113
|
-
|
114
|
-
if tag == "{/mark}" then # If it is a tag, pop from the latest opened.
|
115
|
-
stack.pop
|
116
|
-
styles = stack.last
|
117
|
-
replacement = plain || stack.blank? ? "" : styles.split(split_regex).collect { |s| self.parse_style(s) }.join("")
|
153
|
+
# Wraps a message in fixed line width.
|
154
|
+
#
|
155
|
+
# @param message [String] The message to wrap.
|
156
|
+
# @param width [Fixnum] The maximum width of a line. Default to the current line width.
|
157
|
+
# @return [String] The wrapped message.
|
158
|
+
def wrap(message, width = nil)
|
159
|
+
if width.to_integer <= 0 then
|
160
|
+
message
|
118
161
|
else
|
119
|
-
|
162
|
+
width = (width == true || width.to_integer < 0 ? self.get_screen_width : width.to_integer)
|
120
163
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
end
|
164
|
+
message.split("\n").collect { |line|
|
165
|
+
line.length > width ? line.gsub(/(.{1,#{width}})(\s+|$)/, "\\1\n").strip : line
|
166
|
+
}.join("\n")
|
125
167
|
end
|
126
|
-
|
127
|
-
replacement
|
128
168
|
end
|
129
169
|
|
130
|
-
message
|
131
|
-
|
170
|
+
# Indents a message.
|
171
|
+
#
|
172
|
+
# @param message [String] The message to indent.
|
173
|
+
# @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.
|
174
|
+
# @param newline_separator [String] The character used for newlines.
|
175
|
+
# @return [String] The indentend message.
|
176
|
+
def indent(message, width = true, newline_separator = "\n")
|
177
|
+
if width.to_integer != 0 then
|
178
|
+
width = (width == true ? 0 : width.to_integer)
|
179
|
+
width = width < 0 ? -width : @indentation + width
|
180
|
+
|
181
|
+
message = message.split(newline_separator).collect {|line|
|
182
|
+
(@indentation_string * width) + line
|
183
|
+
}.join(newline_separator)
|
184
|
+
end
|
132
185
|
|
133
|
-
|
134
|
-
|
135
|
-
def self.min_banner_length
|
136
|
-
1
|
137
|
-
end
|
186
|
+
message
|
187
|
+
end
|
138
188
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
189
|
+
# Formats a message.
|
190
|
+
#
|
191
|
+
# You can style text by using `{mark}` and `{/mark}` syntax.
|
192
|
+
#
|
193
|
+
# @see #replace_markers
|
194
|
+
#
|
195
|
+
# @param message [String] The message to format.
|
196
|
+
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
197
|
+
# @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.
|
198
|
+
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line. `true` means the current line width.
|
199
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
200
|
+
# @return [String] The formatted message.
|
201
|
+
def format(message, suffix = "\n", indent = true, wrap = true, plain = false)
|
202
|
+
rv = message
|
203
|
+
|
204
|
+
rv = self.replace_markers(rv, plain) # Replace markers
|
205
|
+
|
206
|
+
# Compute the real width available for the screen, if we both indent and wrap
|
207
|
+
if wrap == true then
|
208
|
+
wrap = @line_width
|
209
|
+
|
210
|
+
if indent == true then
|
211
|
+
wrap -= @indentation
|
212
|
+
else
|
213
|
+
indent_i = indent.to_integer
|
214
|
+
wrap -= (indent_i > 0 ? @indentation : 0) + indent_i
|
215
|
+
end
|
216
|
+
end
|
146
217
|
|
147
|
-
|
148
|
-
|
149
|
-
@line_width = self.get_screen_width
|
150
|
-
@indentation = 0
|
151
|
-
@indentation_string = " "
|
152
|
-
end
|
218
|
+
rv = self.wrap(rv, wrap) # Wrap
|
219
|
+
rv = self.indent(rv, indent) # Indent
|
153
220
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
def get_screen_width
|
158
|
-
::Bovem::Console.execute("tput cols").to_integer(80)
|
159
|
-
end
|
221
|
+
rv += suffix.ensure_string if suffix # Add the suffix
|
222
|
+
rv
|
223
|
+
end
|
160
224
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
225
|
+
# Formats a message to be written right-aligned.
|
226
|
+
#
|
227
|
+
# @param message [String] The message to format.
|
228
|
+
# @param width [Fixnum] The screen width. If `true`, it is automatically computed.
|
229
|
+
# @param go_up [Boolean] If go up one line before formatting.
|
230
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
231
|
+
# @return [String] The formatted message.
|
232
|
+
def format_right(message, width = true, go_up = true, plain = false)
|
233
|
+
message = self.replace_markers(message, plain)
|
170
234
|
|
171
|
-
|
172
|
-
#
|
173
|
-
# @return [Fixnum] The new indentation width.
|
174
|
-
def reset_indentation
|
175
|
-
self.indentation = 0
|
176
|
-
self.indentation
|
177
|
-
end
|
235
|
+
rv = go_up ? "\e[A" : ""
|
178
236
|
|
179
|
-
|
180
|
-
|
181
|
-
# @param width [Fixnum] The new width.
|
182
|
-
# @param is_absolute [Boolean] If the new width should not be added to the current one but rather replace it.
|
183
|
-
# @return [Fixnum] The new indentation width.
|
184
|
-
def with_indentation(width = 3, is_absolute = false)
|
185
|
-
old = self.indentation
|
186
|
-
self.set_indentation(width, is_absolute)
|
187
|
-
yield
|
188
|
-
self.set_indentation(old, true)
|
189
|
-
|
190
|
-
self.indentation
|
191
|
-
end
|
237
|
+
@screen_width ||= self.get_screen_width
|
238
|
+
width = (width == true || width.to_integer < 1 ? @screen_width : width.to_integer)
|
192
239
|
|
193
|
-
|
194
|
-
|
195
|
-
# @param message [String] The message to wrap.
|
196
|
-
# @param width [Fixnum] The maximum width of a line. Default to the current line width.
|
197
|
-
# @return [String] The wrapped message.
|
198
|
-
def wrap(message, width = nil)
|
199
|
-
if width.to_integer <= 0 then
|
200
|
-
message
|
201
|
-
else
|
202
|
-
width = (width == true || width.to_integer < 0 ? self.get_screen_width : width.to_integer)
|
240
|
+
# Get padding
|
241
|
+
padding = width - message.to_s.gsub(/(\e\[[0-9]*[a-z]?)|(\\n)/i, "").length
|
203
242
|
|
204
|
-
|
205
|
-
|
206
|
-
}.join("\n")
|
243
|
+
# Return
|
244
|
+
rv + "\e[0G\e[#{padding}C" + message
|
207
245
|
end
|
208
246
|
end
|
209
247
|
|
210
|
-
#
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
message = message.split(newline_separator).collect {|line|
|
222
|
-
(@indentation_string * width) + line
|
223
|
-
}.join(newline_separator)
|
248
|
+
# Methods for logging activities to the user.
|
249
|
+
module Logging
|
250
|
+
extend ActiveSupport::Concern
|
251
|
+
|
252
|
+
# Class methods for logging activities to the user.
|
253
|
+
module ClassMethods
|
254
|
+
# Returns the minimum length of a banner, not including brackets and leading spaces.
|
255
|
+
# @return [Fixnum] The minimum length of a banner.
|
256
|
+
def min_banner_length
|
257
|
+
1
|
258
|
+
end
|
224
259
|
end
|
225
260
|
|
226
|
-
message
|
227
|
-
|
261
|
+
# Writes a message.
|
262
|
+
#
|
263
|
+
# @param message [String] The message to format.
|
264
|
+
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
265
|
+
# @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.
|
266
|
+
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
267
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
268
|
+
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
269
|
+
# @return [String] The printed message.
|
270
|
+
#
|
271
|
+
# @see #format
|
272
|
+
def write(message, suffix = "\n", indent = true, wrap = false, plain = false, print = true)
|
273
|
+
rv = self.format(message, suffix, indent, wrap, plain)
|
274
|
+
Kernel.puts(rv) if print
|
275
|
+
rv
|
276
|
+
end
|
228
277
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
278
|
+
# Writes a message, aligning to a call with an empty banner.
|
279
|
+
#
|
280
|
+
# @param message [String] The message to format.
|
281
|
+
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
282
|
+
# @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.
|
283
|
+
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
284
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
285
|
+
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
286
|
+
# @return [String] The printed message.
|
287
|
+
#
|
288
|
+
# @see #format
|
289
|
+
def write_banner_aligned(message, suffix = "\n", indent = true, wrap = false, plain = false, print = true)
|
290
|
+
self.write((" " * (::Bovem::Console.min_banner_length + 3)) + message.ensure_string, suffix, indent, wrap, plain, print)
|
291
|
+
end
|
239
292
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
293
|
+
# Writes a status to the output. Valid values are `:ok`, `:pass`, `:fail`, `:warn`.
|
294
|
+
#
|
295
|
+
# @param status [Symbol] The status to write.
|
296
|
+
# @param plain [Boolean] If not use colors.
|
297
|
+
# @param go_up [Boolean] If go up one line before formatting.
|
298
|
+
# @param right [Boolean] If to print results on the right.
|
299
|
+
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
300
|
+
# @return [Array] An dictionary with `:label` and `:color` keys for the status.
|
301
|
+
def status(status, plain = false, go_up = true, right = true, print = true)
|
302
|
+
statuses = {
|
303
|
+
ok: {label: " OK ", color: "bright green"},
|
304
|
+
pass: {label: "PASS", color: "bright cyan"},
|
305
|
+
warn: {label: "WARN", color: "bright yellow"},
|
306
|
+
fail: {label: "FAIL", color: "bright red"}
|
307
|
+
}
|
308
|
+
statuses.default = statuses[:ok]
|
309
|
+
|
310
|
+
rv = statuses[status]
|
311
|
+
|
312
|
+
if print then
|
313
|
+
banner = self.get_banner(rv[:label], rv[:color])
|
314
|
+
|
315
|
+
if right then
|
316
|
+
Kernel.puts self.format_right(banner + " ", true, go_up, plain)
|
317
|
+
else
|
318
|
+
Kernel.puts self.format(banner + " ", "\n", true, true, plain)
|
319
|
+
end
|
266
320
|
end
|
267
|
-
end
|
268
321
|
|
269
|
-
|
270
|
-
|
322
|
+
rv
|
323
|
+
end
|
271
324
|
|
272
|
-
|
273
|
-
|
274
|
-
|
325
|
+
# Gets a banner for the messages.
|
326
|
+
#
|
327
|
+
# @param label [String] The label for the banner.
|
328
|
+
# @param base_color [String] The color for the label.
|
329
|
+
# @param full_colored [String] If all the message should be of the label color.
|
330
|
+
# @param bracket_color [String] The color of the brackets.
|
331
|
+
# @param brackets [Array] An array of dimension 2 to use for brackets.
|
332
|
+
# @return [String] The banner.
|
333
|
+
# @see #format
|
334
|
+
def get_banner(label, base_color, full_colored = false, bracket_color = "blue", brackets = ["[", "]"])
|
335
|
+
label = label.rjust(Bovem::Console.min_banner_length, " ")
|
336
|
+
brackets = brackets.ensure_array
|
337
|
+
bracket_color = base_color if full_colored
|
338
|
+
"{mark=%s}%s{mark=%s}%s{/mark}%s{/mark}" % [bracket_color.parameterize, brackets[0], base_color.parameterize, label, brackets[1]]
|
339
|
+
end
|
275
340
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
341
|
+
# Writes a message prepending a green banner.
|
342
|
+
#
|
343
|
+
# @param message [String] The message to format.
|
344
|
+
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
345
|
+
# @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.
|
346
|
+
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
347
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
348
|
+
# @param indented_banner [Boolean] If also the banner should be indented.
|
349
|
+
# @param full_colored [Boolean] If the banner should be fully colored.
|
350
|
+
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
351
|
+
#
|
352
|
+
# @see #format
|
353
|
+
def begin(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
|
354
|
+
banner = self.get_banner("*", "bright green")
|
355
|
+
message = self.indent(message, indented_banner ? 0 : indent)
|
356
|
+
self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
|
357
|
+
end
|
285
358
|
|
286
|
-
|
359
|
+
# Writes a message prepending a red banner and then quits the application.
|
360
|
+
#
|
361
|
+
# @param message [String] The message to format.
|
362
|
+
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
363
|
+
# @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.
|
364
|
+
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
365
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
366
|
+
# @param indented_banner [Boolean] If also the banner should be indented.
|
367
|
+
# @param full_colored [Boolean] If the banner should be fully colored.
|
368
|
+
# @param return_code [Fixnum] The code to return to the shell.
|
369
|
+
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
370
|
+
#
|
371
|
+
# @see #format
|
372
|
+
def fatal(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, return_code = -1, print = true)
|
373
|
+
self.error(message, suffix, indent, wrap, plain, indented_banner, full_colored, print)
|
374
|
+
Kernel.exit(return_code.to_integer(-1))
|
375
|
+
end
|
287
376
|
|
288
|
-
|
289
|
-
|
377
|
+
# Writes a message prepending a cyan banner.
|
378
|
+
#
|
379
|
+
# @param message [String] The message to format.
|
380
|
+
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
381
|
+
# @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.
|
382
|
+
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
383
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
384
|
+
# @param indented_banner [Boolean] If also the banner should be indented.
|
385
|
+
# @param full_colored [Boolean] If the banner should be fully colored.
|
386
|
+
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
387
|
+
# @param banner [Array] An array with at last letter and style to use for the banner.
|
388
|
+
#
|
389
|
+
# @see #format
|
390
|
+
def info(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true, *banner)
|
391
|
+
banner = banner.ensure_array.flatten
|
392
|
+
banner = ["I", "bright cyan"] if banner.blank?
|
393
|
+
banner = self.get_banner(banner[0], banner[1], full_colored)
|
394
|
+
message = self.indent(message, indented_banner ? 0 : indent)
|
395
|
+
self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
|
396
|
+
end
|
290
397
|
|
291
|
-
#
|
292
|
-
|
398
|
+
# Writes a message prepending a magenta banner.
|
399
|
+
#
|
400
|
+
# @param message [String] The message to format.
|
401
|
+
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
402
|
+
# @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.
|
403
|
+
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
404
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
405
|
+
# @param indented_banner [Boolean] If also the banner should be indented.
|
406
|
+
# @param full_colored [Boolean] If the banner should be fully colored.
|
407
|
+
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
408
|
+
#
|
409
|
+
# @see #format
|
410
|
+
def debug(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
|
411
|
+
self.info(message, suffix, indent, wrap, plain, indented_banner, full_colored, print, ["D", "bright magenta"])
|
412
|
+
end
|
293
413
|
|
294
|
-
#
|
295
|
-
|
296
|
-
|
414
|
+
# Writes a message prepending a yellow banner.
|
415
|
+
#
|
416
|
+
# @param message [String] The message to format.
|
417
|
+
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
418
|
+
# @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.
|
419
|
+
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
420
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
421
|
+
# @param indented_banner [Boolean] If also the banner should be indented.
|
422
|
+
# @param full_colored [Boolean] If the banner should be fully colored.
|
423
|
+
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
424
|
+
#
|
425
|
+
# @see #format
|
426
|
+
def warn(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
|
427
|
+
warn_banner = ["W", "bright yellow"]
|
428
|
+
self.info(message, suffix, indent, wrap, plain, indented_banner, full_colored, print, warn_banner)
|
429
|
+
end
|
297
430
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
431
|
+
# Writes a message prepending a red banner.
|
432
|
+
#
|
433
|
+
# @param message [String] The message to format.
|
434
|
+
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
435
|
+
# @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.
|
436
|
+
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
437
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
438
|
+
# @param indented_banner [Boolean] If also the banner should be indented.
|
439
|
+
# @param full_colored [Boolean] If the banner should be fully colored.
|
440
|
+
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
441
|
+
#
|
442
|
+
# @see #format
|
443
|
+
def error(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
|
444
|
+
self.info(message, suffix, indent, wrap, plain, indented_banner, full_colored, print, "E", "bright red")
|
445
|
+
end
|
313
446
|
end
|
314
447
|
|
315
|
-
#
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
448
|
+
# Methods to interact with the user and other processes.
|
449
|
+
module Interactions
|
450
|
+
extend ActiveSupport::Concern
|
451
|
+
|
452
|
+
# Class methods to interact with the user and other processes.
|
453
|
+
module ClassMethods
|
454
|
+
# Executes a command and returns its output.
|
455
|
+
#
|
456
|
+
# @param command [String] The command to execute.
|
457
|
+
# @return [String] The command's output.
|
458
|
+
def execute(command)
|
459
|
+
%x{#{command}}
|
460
|
+
end
|
461
|
+
end
|
329
462
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
Kernel.puts self.format_right(banner + " ", true, go_up, plain)
|
354
|
-
else
|
355
|
-
Kernel.puts self.format(banner + " ", "\n", true, true, plain)
|
463
|
+
# Reads a string from the console.
|
464
|
+
#
|
465
|
+
# @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.
|
466
|
+
# @param default_value [String] Default value if user simply pressed the enter key.
|
467
|
+
# @param validator [Array|Regexp] An array of values or a Regexp to match the submitted value against.
|
468
|
+
# @param echo [Boolean] If to show submitted text to the user.
|
469
|
+
def read(prompt = true, default_value = nil, validator = nil, echo = true)
|
470
|
+
prompt = sanitize_prompt(prompt)
|
471
|
+
|
472
|
+
# Adjust validator
|
473
|
+
validator = sanitize_validator(validator)
|
474
|
+
|
475
|
+
with_echo_handling(echo) do
|
476
|
+
begin
|
477
|
+
catch(:reply) do
|
478
|
+
while true do
|
479
|
+
reply = validate_input_value(read_input_value(prompt, default_value), validator)
|
480
|
+
handle_reply(reply)
|
481
|
+
end
|
482
|
+
end
|
483
|
+
rescue Interrupt => e
|
484
|
+
default_value
|
485
|
+
end
|
356
486
|
end
|
357
487
|
end
|
358
488
|
|
359
|
-
|
360
|
-
|
489
|
+
# Executes a block of code in a indentation region and then prints out and ending status message.
|
490
|
+
#
|
491
|
+
# @param message [String] The message to format.
|
492
|
+
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
493
|
+
# @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.
|
494
|
+
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
495
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
496
|
+
# @param indented_banner [Boolean] If also the banner should be indented.
|
497
|
+
# @param full_colored [Boolean] If the banner should be fully colored.
|
498
|
+
# @param block_indentation [Fixnum] The new width for the indented region.
|
499
|
+
# @param block_indentation_absolute [Boolean] If the new width should not be added to the current one but rather replace it.
|
500
|
+
# @return [Symbol] The exit status for the block.
|
501
|
+
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)
|
502
|
+
status = nil
|
503
|
+
|
504
|
+
self.begin(message, suffix, indent, wrap, plain, indented_banner, full_colored) if message.present?
|
505
|
+
self.with_indentation(block_indentation, block_indentation_absolute) do
|
506
|
+
rv = block_given? ? yield.ensure_array : [:ok] # Execute block
|
507
|
+
exit_task(message, rv, plain) # Handle task exit
|
508
|
+
status = rv[0] # Return value
|
361
509
|
|
362
|
-
|
363
|
-
#
|
364
|
-
# @param label [String] The label for the banner.
|
365
|
-
# @param base_color [String] The color for the label.
|
366
|
-
# @param full_colored [String] If all the message should be of the label color.
|
367
|
-
# @param bracket_color [String] The color of the brackets.
|
368
|
-
# @param brackets [Array] An array of dimension 2 to use for brackets.
|
369
|
-
# @return [String] The banner.
|
370
|
-
# @see #format
|
371
|
-
def get_banner(label, base_color, full_colored = false, bracket_color = "blue", brackets = ["[", "]"])
|
372
|
-
label = label.rjust(Bovem::Console.min_banner_length, " ")
|
373
|
-
brackets = brackets.ensure_array
|
374
|
-
bracket_color = base_color if full_colored
|
375
|
-
"{mark=%s}%s{mark=%s}%s{/mark}%s{/mark}" % [bracket_color.parameterize, brackets[0], base_color.parameterize, label, brackets[1]]
|
376
|
-
end
|
510
|
+
end
|
377
511
|
|
378
|
-
|
379
|
-
|
380
|
-
# @param message [String] The message to format.
|
381
|
-
# @param suffix [Object] If not `nil` or `false`, a suffix to add to the message. `true` means to add `\n`.
|
382
|
-
# @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.
|
383
|
-
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
384
|
-
# @param plain [Boolean] If ignore color markers into the message.
|
385
|
-
# @param indented_banner [Boolean] If also the banner should be indented.
|
386
|
-
# @param full_colored [Boolean] If the banner should be fully colored.
|
387
|
-
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
388
|
-
#
|
389
|
-
# @see #format
|
390
|
-
def info(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
|
391
|
-
banner = self.get_banner("I", "bright cyan", full_colored)
|
392
|
-
message = self.indent(message, indented_banner ? 0 : indent)
|
393
|
-
self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
|
394
|
-
end
|
512
|
+
status
|
513
|
+
end
|
395
514
|
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
message = self.indent(message, indented_banner ? 0 : indent)
|
411
|
-
self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
|
412
|
-
end
|
515
|
+
private
|
516
|
+
# Handles task exit.
|
517
|
+
#
|
518
|
+
# @param message [String] The message to format.
|
519
|
+
# @param rv [Array] An array with exit status and exit code.
|
520
|
+
# @param plain [Boolean] If ignore color markers into the message.
|
521
|
+
def exit_task(message, rv, plain)
|
522
|
+
if rv[0] == :fatal then
|
523
|
+
self.status(:fail, plain)
|
524
|
+
exit(rv.length > 1 ? rv[1].to_integer : -1)
|
525
|
+
else
|
526
|
+
self.status(rv[0], plain) if message.present?
|
527
|
+
end
|
528
|
+
end
|
413
529
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
# @see #format
|
426
|
-
def warn(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
|
427
|
-
banner = self.get_banner("W", "bright yellow", full_colored)
|
428
|
-
message = self.indent(message, indented_banner ? 0 : indent)
|
429
|
-
self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
|
430
|
-
end
|
530
|
+
# Returns a prompt for input prompting.
|
531
|
+
#
|
532
|
+
# @param prompt [String]
|
533
|
+
# @return [String|nil] The prompt to use or `nil`, if no message must be prompted.
|
534
|
+
def sanitize_prompt(prompt)
|
535
|
+
if prompt.present?
|
536
|
+
(prompt == true ? self.i18n.console.prompt : prompt).gsub(/:?\s*$/, "") + ": "
|
537
|
+
else
|
538
|
+
nil
|
539
|
+
end
|
540
|
+
end
|
431
541
|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
# @param indented_banner [Boolean] If also the banner should be indented.
|
440
|
-
# @param full_colored [Boolean] If the banner should be fully colored.
|
441
|
-
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
442
|
-
#
|
443
|
-
# @see #format
|
444
|
-
def error(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
|
445
|
-
banner = self.get_banner("E", "bright red", full_colored)
|
446
|
-
message = self.indent(message, indented_banner ? 0 : indent)
|
447
|
-
self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
|
448
|
-
end
|
542
|
+
# Make sure that the validators are an array of string if not a regexp.
|
543
|
+
#
|
544
|
+
# @param validator [String|Regexp] The validator to sanitize.
|
545
|
+
# @return [Object] A list of strings, a Regexp or nil.
|
546
|
+
def sanitize_validator(validator)
|
547
|
+
validator.present? && !validator.is_a?(::Regexp) ? validator.ensure_array.collect {|v| v.ensure_string} : validator
|
548
|
+
end
|
449
549
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
456
|
-
# @param plain [Boolean] If ignore color markers into the message.
|
457
|
-
# @param indented_banner [Boolean] If also the banner should be indented.
|
458
|
-
# @param full_colored [Boolean] If the banner should be fully colored.
|
459
|
-
# @param return_code [Fixnum] The code to return to the shell.
|
460
|
-
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
461
|
-
#
|
462
|
-
# @see #format
|
463
|
-
def fatal(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, return_code = -1, print = true)
|
464
|
-
self.error(message, suffix, indent, wrap, plain, indented_banner, full_colored, print)
|
465
|
-
Kernel.exit(return_code.to_integer(-1))
|
466
|
-
end
|
550
|
+
# Handle terminal echoing.
|
551
|
+
#
|
552
|
+
# @param echo [Boolean] If disabled echoing
|
553
|
+
def with_echo_handling(echo = true)
|
554
|
+
rv = nil
|
467
555
|
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
# @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.
|
473
|
-
# @param wrap [Object] If not `nil` or `false`, the maximum length of a line for wrapped text. `true` means the current line width.
|
474
|
-
# @param plain [Boolean] If ignore color markers into the message.
|
475
|
-
# @param indented_banner [Boolean] If also the banner should be indented.
|
476
|
-
# @param full_colored [Boolean] If the banner should be fully colored.
|
477
|
-
# @param print [Boolean] If `false`, the result will be returned instead of be printed.
|
478
|
-
#
|
479
|
-
# @see #format
|
480
|
-
def debug(message, suffix = "\n", indent = true, wrap = false, plain = false, indented_banner = false, full_colored = false, print = true)
|
481
|
-
banner = self.get_banner("D", "bright magenta", full_colored)
|
482
|
-
message = self.indent(message, indented_banner ? 0 : indent)
|
483
|
-
self.write(banner + " " + message, suffix, indented_banner ? indent : 0, wrap, plain, print)
|
484
|
-
end
|
556
|
+
disable_echo = !echo && @stty.present? && /-echo\b/mix.match(::Bovem::Console.execute(@stty)).nil?
|
557
|
+
::Bovem::Console.execute("#{@stty} -echo") if disable_echo
|
558
|
+
rv = yield
|
559
|
+
::Bovem::Console.execute("#{@stty} echo") if disable_echo
|
485
560
|
|
486
|
-
|
487
|
-
|
488
|
-
# @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.
|
489
|
-
# @param default_value [String] Default value if user simply pressed the enter key.
|
490
|
-
# @param validator [Array|Regexp] An array of values or a Regexp to match the submitted value against.
|
491
|
-
# @param echo [Boolean] If to show submitted text to the user.
|
492
|
-
def read(prompt = true, default_value = nil, validator = nil, echo = true)
|
493
|
-
# Write the prompt
|
494
|
-
prompt = "Please insert a value" if prompt == true
|
495
|
-
final_prompt = !prompt.nil? ? prompt.gsub(/:?\s*$/, "") + ": " : nil
|
496
|
-
|
497
|
-
# Adjust validator
|
498
|
-
validator = validator.ensure_array.collect {|v| v.ensure_string} if validator.present? && !validator.is_a?(::Regexp)
|
499
|
-
|
500
|
-
# Handle echo
|
501
|
-
stty = ::Bovem::Console.execute("which stty").strip
|
502
|
-
disable_echo = !echo && stty.present? && /-echo\b/mix.match(::Bovem::Console.execute(stty)).nil?
|
503
|
-
|
504
|
-
# Disable echo
|
505
|
-
::Bovem::Console.execute("#{stty} -echo") if disable_echo
|
506
|
-
|
507
|
-
begin
|
508
|
-
catch(:reply) do
|
509
|
-
while true do
|
510
|
-
valid = true
|
511
|
-
|
512
|
-
if final_prompt then
|
513
|
-
Kernel.print self.format(final_prompt, false, false)
|
514
|
-
$stdout.flush
|
515
|
-
end
|
561
|
+
rv
|
562
|
+
end
|
516
563
|
|
517
|
-
|
518
|
-
|
564
|
+
# Read an input from the terminal.
|
565
|
+
#
|
566
|
+
# @param prompt [String] A message to show to the user.
|
567
|
+
# @param default_value [Object] A default value to enter if the user just pressed the enter key.
|
568
|
+
# @return [Object] The read value.
|
569
|
+
def read_input_value(prompt, default_value = nil)
|
570
|
+
if prompt then
|
571
|
+
Kernel.print self.format(prompt, false, false)
|
572
|
+
$stdout.flush
|
573
|
+
end
|
519
574
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
valid = false if validator.length > 0 && !validator.include?(reply)
|
524
|
-
elsif validator.is_a?(Regexp) then
|
525
|
-
valid = false if !validator.match(reply)
|
526
|
-
end
|
527
|
-
end
|
575
|
+
reply = $stdin.gets.chop
|
576
|
+
reply.present? ? reply : default_value
|
577
|
+
end
|
528
578
|
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
579
|
+
# Validates a read value from the terminal.
|
580
|
+
#
|
581
|
+
# @param reply [String] The value to validate.
|
582
|
+
# @param validator [Array|Regexp] An array of values or a Regexp to match the submitted value against.
|
583
|
+
# @return [String|nil] The validated value or `nil`, if the value is invalid.
|
584
|
+
def validate_input_value(reply, validator)
|
585
|
+
# Match against the validator
|
586
|
+
if validator.present? then
|
587
|
+
if validator.is_a?(Array) then
|
588
|
+
reply = nil if validator.length > 0 && !validator.include?(reply)
|
589
|
+
elsif validator.is_a?(Regexp) then
|
590
|
+
reply = nil if !validator.match(reply)
|
533
591
|
end
|
534
592
|
end
|
593
|
+
|
594
|
+
reply
|
595
|
+
end
|
596
|
+
|
597
|
+
# Handles a read value from the terminal.
|
598
|
+
#
|
599
|
+
# @param reply [String] The value to handle.
|
600
|
+
def handle_reply(reply)
|
601
|
+
if reply then
|
602
|
+
throw(:reply, reply)
|
603
|
+
else
|
604
|
+
self.write(self.i18n.console.unknown_reply, false, false)
|
605
|
+
end
|
535
606
|
end
|
536
|
-
rescue Interrupt
|
537
|
-
default_value
|
538
|
-
ensure
|
539
|
-
::Bovem::Console.execute("#{stty} echo") if disable_echo
|
540
|
-
end
|
541
607
|
end
|
608
|
+
end
|
542
609
|
|
543
|
-
|
610
|
+
# This is a text utility wrapper console I/O.
|
611
|
+
#
|
612
|
+
# @attr [Fixnum] line_width The line width. Default to `80`.
|
613
|
+
# @attr [Fixnum] screen_width The current screen width.
|
614
|
+
# @attr [Fixnum] indentation Current indentation width.
|
615
|
+
# @attr [String] indentation_string The string used for indentation.
|
616
|
+
class Console
|
617
|
+
attr_accessor :line_width
|
618
|
+
attr_accessor :screen_width
|
619
|
+
attr_accessor :indentation
|
620
|
+
attr_accessor :indentation_string
|
621
|
+
|
622
|
+
include Lazier::I18n
|
623
|
+
include Bovem::ConsoleMethods::StyleHandling
|
624
|
+
include Bovem::ConsoleMethods::Output
|
625
|
+
include Bovem::ConsoleMethods::Logging
|
626
|
+
include Bovem::ConsoleMethods::Interactions
|
627
|
+
|
628
|
+
# Returns a unique instance for Console.
|
544
629
|
#
|
545
|
-
# @
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
# @param plain [Boolean] If ignore color markers into the message.
|
550
|
-
# @param indented_banner [Boolean] If also the banner should be indented.
|
551
|
-
# @param full_colored [Boolean] If the banner should be fully colored.
|
552
|
-
# @param block_indentation [Fixnum] The new width for the indented region.
|
553
|
-
# @param block_indentation_absolute [Boolean] If the new width should not be added to the current one but rather replace it.
|
554
|
-
# @return [Symbol] The exit status for the block.
|
555
|
-
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)
|
556
|
-
status = nil
|
557
|
-
|
558
|
-
self.begin(message, suffix, indent, wrap, plain, indented_banner, full_colored) if message.present?
|
559
|
-
|
560
|
-
self.with_indentation(block_indentation, block_indentation_absolute) do
|
561
|
-
rv = block_given? ? yield.ensure_array : [:ok] # Execute block
|
562
|
-
status = rv[0] # Return value
|
563
|
-
|
564
|
-
if status == :fatal then
|
565
|
-
self.status(:fail, plain)
|
566
|
-
exit(rv.length > 1 ? rv[1].to_integer : -1)
|
567
|
-
else
|
568
|
-
self.status(status, plain) if message.present?
|
569
|
-
end
|
570
|
-
end
|
630
|
+
# @return [Console] A new instance.
|
631
|
+
def self.instance
|
632
|
+
@instance ||= ::Bovem::Console.new
|
633
|
+
end
|
571
634
|
|
572
|
-
|
635
|
+
# Initializes a new Console.
|
636
|
+
def initialize
|
637
|
+
@line_width = self.get_screen_width
|
638
|
+
@indentation = 0
|
639
|
+
@indentation_string = " "
|
640
|
+
@stty = ::Bovem::Console.execute("which stty").strip
|
641
|
+
self.i18n_setup(:bovem, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
|
573
642
|
end
|
574
643
|
end
|
575
644
|
end
|