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