console 1.29.3 → 1.30.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/console/capture.rb +26 -1
- data/lib/console/clock.rb +6 -1
- data/lib/console/compatible/logger.rb +30 -1
- data/lib/console/config.rb +93 -0
- data/lib/console/event/failure.rb +32 -3
- data/lib/console/event/generic.rb +14 -0
- data/lib/console/event/spawn.rb +38 -6
- data/lib/console/event.rb +6 -0
- data/lib/console/filter.rb +62 -2
- data/lib/console/format/safe.rb +35 -7
- data/lib/console/format.rb +3 -0
- data/lib/console/interface.rb +17 -9
- data/lib/console/logger.rb +22 -37
- data/lib/console/output/default.rb +11 -5
- data/lib/console/output/failure.rb +8 -1
- data/lib/console/output/null.rb +4 -1
- data/lib/console/output/sensitive.rb +41 -0
- data/lib/console/output/serialized.rb +25 -4
- data/lib/console/output/split.rb +11 -0
- data/lib/console/output/terminal.rb +66 -14
- data/lib/console/output/wrapper.rb +11 -0
- data/lib/console/output.rb +11 -0
- data/lib/console/progress.rb +55 -8
- data/lib/console/resolver.rb +18 -1
- data/lib/console/terminal/formatter/failure.rb +17 -5
- data/lib/console/terminal/formatter/progress.rb +15 -2
- data/lib/console/terminal/formatter/spawn.rb +15 -4
- data/lib/console/terminal/formatter.rb +16 -0
- data/lib/console/terminal/text.rb +60 -19
- data/lib/console/terminal/xterm.rb +16 -1
- data/lib/console/terminal.rb +6 -8
- data/lib/console/version.rb +1 -1
- data/lib/console/warn.rb +1 -1
- data/lib/console.rb +1 -0
- data/readme.md +7 -1
- data/releases.md +24 -1
- data.tar.gz.sig +0 -0
- metadata +4 -2
- metadata.gz.sig +0 -0
data/lib/console/format/safe.rb
CHANGED
@@ -6,16 +6,27 @@
|
|
6
6
|
require "json"
|
7
7
|
|
8
8
|
module Console
|
9
|
+
# @namespace
|
9
10
|
module Format
|
10
|
-
#
|
11
|
-
#
|
11
|
+
# A safe format for converting objects to strings.
|
12
|
+
#
|
13
|
+
# Handles issues like circular references and encoding errors.
|
12
14
|
class Safe
|
15
|
+
# Create a new safe format.
|
16
|
+
#
|
17
|
+
# @parameter format [JSON] The format to use for serialization.
|
18
|
+
# @parameter limit [Integer] The maximum depth to recurse into objects.
|
19
|
+
# @parameter encoding [Encoding] The encoding to use for strings.
|
13
20
|
def initialize(format: ::JSON, limit: 8, encoding: ::Encoding::UTF_8)
|
14
21
|
@format = format
|
15
22
|
@limit = limit
|
16
23
|
@encoding = encoding
|
17
24
|
end
|
18
25
|
|
26
|
+
# Dump the given object to a string.
|
27
|
+
#
|
28
|
+
# @parameter object [Object] The object to dump.
|
29
|
+
# @returns [String] The dumped object.
|
19
30
|
def dump(object)
|
20
31
|
@format.dump(object, @limit)
|
21
32
|
rescue SystemStackError, StandardError => error
|
@@ -24,6 +35,10 @@ module Console
|
|
24
35
|
|
25
36
|
private
|
26
37
|
|
38
|
+
# Filter the backtrace to remove duplicate frames and reduce verbosity.
|
39
|
+
#
|
40
|
+
# @parameter error [Exception] The exception to filter.
|
41
|
+
# @returns [Array(String)] The filtered backtrace.
|
27
42
|
def filter_backtrace(error)
|
28
43
|
frames = error.backtrace
|
29
44
|
filtered = {}
|
@@ -61,6 +76,13 @@ module Console
|
|
61
76
|
return frames
|
62
77
|
end
|
63
78
|
|
79
|
+
# Dump the given object to a string, replacing it with a safe representation if there is an error.
|
80
|
+
#
|
81
|
+
# This is a slow path so we try to avoid it.
|
82
|
+
#
|
83
|
+
# @parameter object [Object] The object to dump.
|
84
|
+
# @parameter error [Exception] The error that occurred while dumping the object.
|
85
|
+
# @returns [Hash] The dumped (truncated) object including error details.
|
64
86
|
def safe_dump(object, error)
|
65
87
|
object = safe_dump_recurse(object)
|
66
88
|
|
@@ -74,6 +96,10 @@ module Console
|
|
74
96
|
return object
|
75
97
|
end
|
76
98
|
|
99
|
+
# Replace the given object with a safe truncated representation.
|
100
|
+
#
|
101
|
+
# @parameter object [Object] The object to replace.
|
102
|
+
# @returns [String] The replacement string.
|
77
103
|
def replacement_for(object)
|
78
104
|
case object
|
79
105
|
when Array
|
@@ -85,15 +111,17 @@ module Console
|
|
85
111
|
end
|
86
112
|
end
|
87
113
|
|
114
|
+
# Create a new hash with identity comparison.
|
88
115
|
def default_objects
|
89
116
|
Hash.new.compare_by_identity
|
90
117
|
end
|
91
118
|
|
92
|
-
# This will recursively generate a safe version of the object.
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
119
|
+
# This will recursively generate a safe version of the object. Nested hashes and arrays will be transformed recursively. Strings will be encoded with the given encoding. Primitive values will be returned as-is. Other values will be converted using `as_json` if available, otherwise `to_s`.
|
120
|
+
#
|
121
|
+
# @parameter object [Object] The object to dump.
|
122
|
+
# @parameter limit [Integer] The maximum depth to recurse into objects.
|
123
|
+
# @parameter objects [Hash] The objects that have already been visited.
|
124
|
+
# @returns [Object] The dumped object as a primitive representation.
|
97
125
|
def safe_dump_recurse(object, limit = @limit, objects = default_objects)
|
98
126
|
if limit <= 0 || objects[object]
|
99
127
|
return replacement_for(object)
|
data/lib/console/format.rb
CHANGED
data/lib/console/interface.rb
CHANGED
@@ -3,51 +3,59 @@
|
|
3
3
|
# Released under the MIT License.
|
4
4
|
# Copyright, 2024-2025, by Samuel Williams.
|
5
5
|
|
6
|
-
|
6
|
+
require "fiber/local"
|
7
|
+
require_relative "config"
|
7
8
|
|
8
9
|
module Console
|
9
10
|
# The public logger interface.
|
10
11
|
module Interface
|
12
|
+
extend Fiber::Local
|
13
|
+
|
14
|
+
# Create a new (thread local) logger instance.
|
15
|
+
def self.local
|
16
|
+
Config::DEFAULT.make_logger
|
17
|
+
end
|
18
|
+
|
11
19
|
# Get the current logger instance.
|
12
20
|
def logger
|
13
|
-
|
21
|
+
Interface.instance
|
14
22
|
end
|
15
23
|
|
16
24
|
# Set the current logger instance.
|
17
25
|
#
|
18
26
|
# The current logger instance is assigned per-fiber.
|
19
27
|
def logger= instance
|
20
|
-
|
28
|
+
Interface.instance= instance
|
21
29
|
end
|
22
30
|
|
23
31
|
# Emit a debug log message.
|
24
32
|
def debug(...)
|
25
|
-
|
33
|
+
Interface.instance.debug(...)
|
26
34
|
end
|
27
35
|
|
28
36
|
# Emit an informational log message.
|
29
37
|
def info(...)
|
30
|
-
|
38
|
+
Interface.instance.info(...)
|
31
39
|
end
|
32
40
|
|
33
41
|
# Emit a warning log message.
|
34
42
|
def warn(...)
|
35
|
-
|
43
|
+
Interface.instance.warn(...)
|
36
44
|
end
|
37
45
|
|
38
46
|
# Emit an error log message.
|
39
47
|
def error(...)
|
40
|
-
|
48
|
+
Interface.instance.error(...)
|
41
49
|
end
|
42
50
|
|
43
51
|
# Emit a fatal log message.
|
44
52
|
def fatal(...)
|
45
|
-
|
53
|
+
Interface.instance.fatal(...)
|
46
54
|
end
|
47
55
|
|
48
56
|
# Emit a log message with arbitrary arguments and options.
|
49
57
|
def call(...)
|
50
|
-
|
58
|
+
Interface.instance.call(...)
|
51
59
|
end
|
52
60
|
end
|
53
61
|
end
|
data/lib/console/logger.rb
CHANGED
@@ -8,61 +8,40 @@
|
|
8
8
|
require_relative "output"
|
9
9
|
require_relative "output/failure"
|
10
10
|
|
11
|
-
require_relative "filter"
|
12
|
-
require_relative "event"
|
13
|
-
require_relative "resolver"
|
14
11
|
require_relative "progress"
|
15
|
-
|
16
|
-
require "fiber/local"
|
12
|
+
require_relative "config"
|
17
13
|
|
18
14
|
module Console
|
15
|
+
# The standard logger interface with support for log levels and verbosity.
|
16
|
+
#
|
17
|
+
# The log levels are: `debug`, `info`, `warn`, `error`, and `fatal`.
|
19
18
|
class Logger < Filter[debug: 0, info: 1, warn: 2, error: 3, fatal: 4]
|
20
|
-
extend Fiber::Local
|
21
|
-
|
22
19
|
# Set the default log level based on `$DEBUG` and `$VERBOSE`.
|
23
20
|
# You can also specify CONSOLE_LEVEL=debug or CONSOLE_LEVEL=info in environment.
|
24
21
|
# https://mislav.net/2011/06/ruby-verbose-mode/ has more details about how it all fits together.
|
25
|
-
|
22
|
+
#
|
23
|
+
# @parameter env [Hash] The environment to read the log level from.
|
24
|
+
# @parameter verbose [Boolean] The verbose flag.
|
25
|
+
# @parameter debug [Boolean] The debug flag.
|
26
|
+
# @returns [Integer] The default log level.
|
27
|
+
def self.default_log_level(env = ENV, verbose: $VERBOSE, debug: $DEBUG)
|
26
28
|
if level = env["CONSOLE_LEVEL"]
|
27
29
|
LEVELS[level.to_sym] || level.to_i
|
28
|
-
elsif
|
30
|
+
elsif debug
|
29
31
|
DEBUG
|
30
|
-
elsif
|
32
|
+
elsif verbose.nil?
|
31
33
|
WARN
|
32
34
|
else
|
33
35
|
INFO
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
37
|
-
# Controls verbose output using `$VERBOSE`.
|
38
|
-
def self.verbose?(env = ENV)
|
39
|
-
!$VERBOSE.nil? || env["CONSOLE_VERBOSE"]
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.default_logger(output = $stderr, env = ENV, **options)
|
43
|
-
if options[:verbose].nil?
|
44
|
-
options[:verbose] = self.verbose?(env)
|
45
|
-
end
|
46
|
-
|
47
|
-
if options[:level].nil?
|
48
|
-
options[:level] = self.default_log_level(env)
|
49
|
-
end
|
50
|
-
|
51
|
-
output = Output.new(output, env, **options)
|
52
|
-
|
53
|
-
logger = self.new(output, **options)
|
54
|
-
|
55
|
-
Resolver.default_resolver(logger)
|
56
|
-
|
57
|
-
return logger
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.local
|
61
|
-
self.default_logger
|
62
|
-
end
|
63
|
-
|
64
39
|
DEFAULT_LEVEL = 1
|
65
40
|
|
41
|
+
# Create a new logger.
|
42
|
+
#
|
43
|
+
# @parameter output [Console::Output] The output destination.
|
44
|
+
# @parameter options [Hash] Additional options.
|
66
45
|
def initialize(output, **options)
|
67
46
|
# This is the expected default behaviour, but it may be nice to have a way to override it.
|
68
47
|
output = Output::Failure.new(output, **options)
|
@@ -70,6 +49,12 @@ module Console
|
|
70
49
|
super(output, **options)
|
71
50
|
end
|
72
51
|
|
52
|
+
# Create a progress indicator for the given subject.
|
53
|
+
#
|
54
|
+
# @parameter subject [String] The subject of the progress indicator.
|
55
|
+
# @parameter total [Integer] The total number of items to process.
|
56
|
+
# @parameter options [Hash] Additional options passed to {Progress}.
|
57
|
+
# @returns [Progress] The progress indicator.
|
73
58
|
def progress(subject, total, **options)
|
74
59
|
options[:severity] ||= :info
|
75
60
|
|
@@ -9,14 +9,20 @@ require_relative "failure"
|
|
9
9
|
|
10
10
|
module Console
|
11
11
|
module Output
|
12
|
+
# Default output format selection.
|
12
13
|
module Default
|
13
|
-
|
14
|
-
|
14
|
+
# Create a new output format based on the given stream.
|
15
|
+
#
|
16
|
+
# @parameter io [IO] The output stream.
|
17
|
+
# @parameter options [Hash] Additional options to customize the output.
|
18
|
+
# @returns [Console::Output::Terminal | Console::Output::Serialized] The output instance, depending on whether the `io` is a terminal or not.
|
19
|
+
def self.new(stream, **options)
|
20
|
+
stream ||= $stderr
|
15
21
|
|
16
|
-
if
|
17
|
-
output = Terminal.new(
|
22
|
+
if stream.tty?
|
23
|
+
output = Terminal.new(stream, **options)
|
18
24
|
else
|
19
|
-
output = Serialized.new(
|
25
|
+
output = Serialized.new(stream, **options)
|
20
26
|
end
|
21
27
|
|
22
28
|
return output
|
@@ -10,11 +10,18 @@ module Console
|
|
10
10
|
module Output
|
11
11
|
# A wrapper for outputting failure messages, which can include exceptions.
|
12
12
|
class Failure < Wrapper
|
13
|
+
# Create a new failure output wrapper.
|
13
14
|
def initialize(output, **options)
|
14
15
|
super(output, **options)
|
15
16
|
end
|
16
17
|
|
17
18
|
# The exception must be either the last argument or passed as an option.
|
19
|
+
#
|
20
|
+
# @parameter subject [String] The subject of the message.
|
21
|
+
# @parameter arguments [Array] The arguments to output.
|
22
|
+
# @parameter exception [Exception] The exception to output.
|
23
|
+
# @parameter options [Hash] Additional options to pass to the output.
|
24
|
+
# @parameter block [Proc] An optional block to pass to the output.
|
18
25
|
def call(subject = nil, *arguments, exception: nil, **options, &block)
|
19
26
|
if exception.nil?
|
20
27
|
last = arguments.last
|
@@ -28,7 +35,7 @@ module Console
|
|
28
35
|
options[:exception] = exception
|
29
36
|
end
|
30
37
|
|
31
|
-
super(subject, *arguments, **options)
|
38
|
+
super(subject, *arguments, **options, &block)
|
32
39
|
end
|
33
40
|
end
|
34
41
|
end
|
data/lib/console/output/null.rb
CHANGED
@@ -5,16 +5,19 @@
|
|
5
5
|
|
6
6
|
module Console
|
7
7
|
module Output
|
8
|
+
# A null output that does nothing.
|
8
9
|
class Null
|
10
|
+
# Create a new null output.
|
9
11
|
def initialize(...)
|
10
12
|
end
|
11
13
|
|
14
|
+
# The last output is always self.
|
12
15
|
def last_output
|
13
16
|
self
|
14
17
|
end
|
15
18
|
|
19
|
+
# Do nothing.
|
16
20
|
def call(...)
|
17
|
-
# Do nothing.
|
18
21
|
end
|
19
22
|
end
|
20
23
|
end
|
@@ -7,7 +7,9 @@ require_relative "wrapper"
|
|
7
7
|
|
8
8
|
module Console
|
9
9
|
module Output
|
10
|
+
# Redact sensitive information from output.
|
10
11
|
class Sensitive < Wrapper
|
12
|
+
# Default redaction pattern.
|
11
13
|
REDACT = /
|
12
14
|
phone
|
13
15
|
| email
|
@@ -34,28 +36,52 @@ module Console
|
|
34
36
|
| password
|
35
37
|
/xi
|
36
38
|
|
39
|
+
# Create a new sensitive output wrapper.
|
40
|
+
#
|
41
|
+
# @parameter output [Console::Output] The output to wrap.
|
42
|
+
# @parameter redact [Regexp] The pattern to redact.
|
43
|
+
# @parameter options [Hash] Additional options to pass to the output.
|
37
44
|
def initialize(output, redact: REDACT, **options)
|
38
45
|
super(output, **options)
|
39
46
|
|
40
47
|
@redact = redact
|
41
48
|
end
|
42
49
|
|
50
|
+
# Check if the given text should be redacted.
|
51
|
+
#
|
52
|
+
# @parameter text [String] The text to check.
|
53
|
+
# @returns [Boolean] Whether the text should be redacted.
|
43
54
|
def redact?(text)
|
44
55
|
text.match?(@redact)
|
45
56
|
end
|
46
57
|
|
58
|
+
# Redact sensitive information from a hash.
|
59
|
+
#
|
60
|
+
# @parameter arguments [Hash] The hash to redact.
|
61
|
+
# @parameter filter [Proc] An optional filter to apply to redacted text.
|
62
|
+
# @returns [Hash] The redacted hash.
|
47
63
|
def redact_hash(arguments, filter)
|
48
64
|
arguments.transform_values do |value|
|
49
65
|
redact(value, filter)
|
50
66
|
end
|
51
67
|
end
|
52
68
|
|
69
|
+
# Redact sensitive information from an array.
|
70
|
+
#
|
71
|
+
# @parameter array [Array] The array to redact.
|
72
|
+
# @parameter filter [Proc] An optional filter to apply to redacted text.
|
73
|
+
# @returns [Array] The redacted array.
|
53
74
|
def redact_array(array, filter)
|
54
75
|
array.map do |value|
|
55
76
|
redact(value, filter)
|
56
77
|
end
|
57
78
|
end
|
58
79
|
|
80
|
+
# Redact sensitive information from the given argument.
|
81
|
+
#
|
82
|
+
# @parameter argument [String | Array | Hash] The argument to redact.
|
83
|
+
# @parameter filter [Proc] An optional filter to apply to redacted text.
|
84
|
+
# @returns [String | Array | Hash] The redacted argument.
|
59
85
|
def redact(argument, filter)
|
60
86
|
case argument
|
61
87
|
when String
|
@@ -75,17 +101,32 @@ module Console
|
|
75
101
|
end
|
76
102
|
end
|
77
103
|
|
104
|
+
# A simple filter for redacting sensitive information.
|
78
105
|
class Filter
|
106
|
+
# Create a new filter.
|
107
|
+
#
|
108
|
+
# @parameter substitutions [Hash] The substitutions to apply.
|
79
109
|
def initialize(substitutions)
|
80
110
|
@substitutions = substitutions
|
81
111
|
@pattern = Regexp.union(substitutions.keys)
|
82
112
|
end
|
83
113
|
|
114
|
+
# Apply the filter to the given text. This will replace all occurrences of the pattern with the corresponding substitution.
|
115
|
+
#
|
116
|
+
# @parameter text [String] The text to filter.
|
117
|
+
# @returns [String] The filtered text.
|
84
118
|
def call(text)
|
85
119
|
text.gsub(@pattern, @substitutions)
|
86
120
|
end
|
87
121
|
end
|
88
122
|
|
123
|
+
# Write a message to the output, filtering sensitive information if necessary.
|
124
|
+
#
|
125
|
+
# @parameter subject [String] The subject of the message.
|
126
|
+
# @parameter arguments [Array] The arguments to output.
|
127
|
+
# @parameter sensitive [Boolean | Filter | Hash] Whether to filter sensitive information.
|
128
|
+
# @parameter options [Hash] Additional options to pass to the output.
|
129
|
+
# @parameter block [Proc] An optional block to pass to the output.
|
89
130
|
def call(subject = nil, *arguments, sensitive: true, **options, &block)
|
90
131
|
if sensitive
|
91
132
|
if sensitive.respond_to?(:call)
|
@@ -9,9 +9,15 @@ require "fiber/annotation"
|
|
9
9
|
|
10
10
|
module Console
|
11
11
|
module Output
|
12
|
+
# Serialize log messages in a structured format.
|
12
13
|
class Serialized
|
13
|
-
|
14
|
-
|
14
|
+
# Create a new serialized output.
|
15
|
+
#
|
16
|
+
# @parameter io [IO] The output stream.
|
17
|
+
# @parameter format [Console::Format] The format to use for serializing log messages.
|
18
|
+
# @parameter options [Hash] Additional options to customize the output.
|
19
|
+
def initialize(stream, format: Format.default, **options)
|
20
|
+
@stream = stream
|
15
21
|
@format = format
|
16
22
|
end
|
17
23
|
|
@@ -20,13 +26,27 @@ module Console
|
|
20
26
|
self
|
21
27
|
end
|
22
28
|
|
23
|
-
|
29
|
+
# @attribute [IO] The output stream.
|
30
|
+
attr :stream
|
31
|
+
|
32
|
+
# @attribute [Console::Format] The format to use for serializing log messages.
|
24
33
|
attr :format
|
25
34
|
|
35
|
+
# Serialize the given record.
|
36
|
+
#
|
37
|
+
# @parameter record [Hash] The record to serialize.
|
38
|
+
# @returns [String] The serialized record.
|
26
39
|
def dump(record)
|
27
40
|
@format.dump(record)
|
28
41
|
end
|
29
42
|
|
43
|
+
# Output the given log message.
|
44
|
+
#
|
45
|
+
# @parameter subject [String] The subject of the log message.
|
46
|
+
# @parameter arguments [Array] The arguments to log.
|
47
|
+
# @parameter severity [Symbol] The severity of the log message.
|
48
|
+
# @parameter options [Hash] Additional options.
|
49
|
+
# @parameter block [Proc] An optional block used to generate the log message.
|
30
50
|
def call(subject = nil, *arguments, severity: UNKNOWN, **options, &block)
|
31
51
|
record = {
|
32
52
|
time: Time.now.iso8601,
|
@@ -68,10 +88,11 @@ module Console
|
|
68
88
|
|
69
89
|
record.update(options)
|
70
90
|
|
71
|
-
@
|
91
|
+
@stream.write(self.dump(record) << "\n")
|
72
92
|
end
|
73
93
|
end
|
74
94
|
|
95
|
+
# @deprecated This is a legacy constant, please use `Serialized` instead.
|
75
96
|
JSON = Serialized
|
76
97
|
end
|
77
98
|
end
|
data/lib/console/output/split.rb
CHANGED
@@ -5,19 +5,30 @@
|
|
5
5
|
|
6
6
|
module Console
|
7
7
|
module Output
|
8
|
+
# Split output into multiple outputs.
|
8
9
|
class Split
|
10
|
+
# Create a new split output.
|
11
|
+
#
|
12
|
+
# @parameter outputs [Array(Console::Output)] The outputs to split into.
|
9
13
|
def self.[](*outputs)
|
10
14
|
self.new(outputs)
|
11
15
|
end
|
12
16
|
|
17
|
+
# Create a new split output.
|
18
|
+
#
|
19
|
+
# @parameter outputs [Array(Console::Output)] The outputs to split into.
|
13
20
|
def initialize(outputs)
|
14
21
|
@outputs = outputs
|
15
22
|
end
|
16
23
|
|
24
|
+
# Set the verbose flag for all outputs.
|
25
|
+
#
|
26
|
+
# @parameter value [Boolean] The new value.
|
17
27
|
def verbose!(value = true)
|
18
28
|
@outputs.each{|output| output.verbose!(value)}
|
19
29
|
end
|
20
30
|
|
31
|
+
# Invoke the outputs. If a block is used, it may be invoked multiple times.
|
21
32
|
def call(...)
|
22
33
|
@outputs.each do |output|
|
23
34
|
output.call(...)
|
@@ -14,48 +14,65 @@ require "stringio"
|
|
14
14
|
|
15
15
|
module Console
|
16
16
|
module Output
|
17
|
+
# Represents a terminal output, and formats log messages for display.
|
17
18
|
class Terminal
|
19
|
+
# Represents an output buffer that formats lines with a prefix.
|
18
20
|
class Buffer < StringIO
|
21
|
+
# Create a new buffer with the given prefix.
|
22
|
+
#
|
23
|
+
# @parameter prefix [String] The prefix to use for each line.
|
19
24
|
def initialize(prefix = nil)
|
20
25
|
@prefix = prefix
|
21
26
|
|
22
27
|
super()
|
23
28
|
end
|
24
29
|
|
30
|
+
# @attribute [String] The prefix to use for each line.
|
25
31
|
attr :prefix
|
26
32
|
|
27
|
-
|
28
|
-
|
33
|
+
# Write lines using the given prefix.
|
34
|
+
#
|
35
|
+
# @parameter lines [Array] The lines to write.
|
36
|
+
# @parameter prefix [String] The prefix to use for each line.
|
37
|
+
def puts(*lines, prefix: @prefix)
|
38
|
+
lines.each do |line|
|
29
39
|
self.write(prefix) if prefix
|
30
|
-
super(
|
40
|
+
super(line)
|
31
41
|
end
|
32
42
|
end
|
33
43
|
|
34
44
|
alias << puts
|
35
45
|
end
|
36
46
|
|
37
|
-
#
|
47
|
+
# The environment variable used to store the start time of the console terminal output.
|
38
48
|
CONSOLE_START_AT = "CONSOLE_START_AT"
|
39
49
|
|
40
|
-
# Exports
|
41
|
-
def self.start_at!(
|
42
|
-
if time_string =
|
50
|
+
# Exports CONSOLE_START_AT which can be used to synchronize the start times of all child processes when they log using delta time.
|
51
|
+
def self.start_at!(env = ENV)
|
52
|
+
if time_string = env[CONSOLE_START_AT]
|
43
53
|
start_at = Time.parse(time_string) rescue nil
|
44
54
|
end
|
45
55
|
|
46
56
|
unless start_at
|
47
57
|
start_at = Time.now
|
48
|
-
|
58
|
+
env[CONSOLE_START_AT] = start_at.to_s
|
49
59
|
end
|
50
60
|
|
51
61
|
return start_at
|
52
62
|
end
|
53
63
|
|
54
|
-
|
55
|
-
|
64
|
+
# Create a new terminal output.
|
65
|
+
#
|
66
|
+
# @parameter stream [IO] The output stream.
|
67
|
+
# @parameter verbose [Boolean] Whether to print verbose output.
|
68
|
+
# @parameter start_at [Time] The start time of the terminal output.
|
69
|
+
# @parameter format [Console::Terminal::Format] The format to use for terminal output.
|
70
|
+
# @parameter options [Hash] Additional options to customize the output.
|
71
|
+
def initialize(stream, verbose: nil, start_at: Terminal.start_at!, format: nil, **options)
|
72
|
+
@stream = stream
|
56
73
|
@start_at = start_at
|
57
74
|
|
58
|
-
@terminal = format.nil? ? Console::Terminal.for(@
|
75
|
+
@terminal = format.nil? ? Console::Terminal.for(@stream) : format.new(@stream)
|
59
76
|
|
60
77
|
if verbose.nil?
|
61
78
|
@verbose = !@terminal.colors?
|
@@ -78,22 +95,31 @@ module Console
|
|
78
95
|
self.register_formatters
|
79
96
|
end
|
80
97
|
|
81
|
-
# This a final output
|
98
|
+
# This a final output.
|
82
99
|
def last_output
|
83
100
|
self
|
84
101
|
end
|
85
102
|
|
86
|
-
|
103
|
+
# @attribute [IO] The output stream.
|
104
|
+
attr :stream
|
87
105
|
|
106
|
+
# @attribute [Boolean] Whether to print verbose output.
|
88
107
|
attr_accessor :verbose
|
89
108
|
|
109
|
+
# @attribute [Time] The start time of the terminal output.
|
90
110
|
attr :start
|
111
|
+
|
112
|
+
# @attribute [Console::Terminal::Format] The format to use for terminal output.
|
91
113
|
attr :terminal
|
92
114
|
|
115
|
+
# Set the verbose output.
|
116
|
+
#
|
117
|
+
# @parameter value [Boolean] Whether to print verbose output.
|
93
118
|
def verbose!(value = true)
|
94
119
|
@verbose = value
|
95
120
|
end
|
96
121
|
|
122
|
+
# Register all formatters in the given namespace.
|
97
123
|
def register_formatters(namespace = Console::Terminal::Formatter)
|
98
124
|
namespace.constants.each do |name|
|
99
125
|
formatter = namespace.const_get(name)
|
@@ -101,8 +127,20 @@ module Console
|
|
101
127
|
end
|
102
128
|
end
|
103
129
|
|
130
|
+
# The default severity for log messages, if not specified.
|
104
131
|
UNKNOWN = :unknown
|
105
132
|
|
133
|
+
# Log a message with the given severity.
|
134
|
+
#
|
135
|
+
# @parameter subject [String] The subject of the log message.
|
136
|
+
# @parameter arguments [Array] The arguments to log.
|
137
|
+
# @parameter name [String | Nil] The optional name of the log message, used as a prefix, otherwise defaults to the severity name.
|
138
|
+
# @parameter severity [Symbol] The severity of the log message.
|
139
|
+
# @parameter event [Hash] The event to log.
|
140
|
+
# @parameter options [Hash] Additional options.
|
141
|
+
# @yields {|buffer, terminal| ...} An optional block used to generate the log message.
|
142
|
+
# @parameter buffer [Console::Output::Terminal::Buffer] The output buffer.
|
143
|
+
# @parameter terminal [Console::Terminal] The terminal instance.
|
106
144
|
def call(subject = nil, *arguments, name: nil, severity: UNKNOWN, event: nil, **options, &block)
|
107
145
|
width = @terminal.width
|
108
146
|
|
@@ -134,7 +172,7 @@ module Console
|
|
134
172
|
format_options(options, buffer)
|
135
173
|
end
|
136
174
|
|
137
|
-
@
|
175
|
+
@stream.write buffer.string
|
138
176
|
end
|
139
177
|
|
140
178
|
protected
|
@@ -242,13 +280,27 @@ module Console
|
|
242
280
|
end
|
243
281
|
end
|
244
282
|
|
283
|
+
# Terminal text output.
|
245
284
|
module Text
|
285
|
+
# Create a new terminal output.
|
286
|
+
#
|
287
|
+
# @parameter output [IO] The output stream.
|
288
|
+
# @parameter options [Hash] Additional options to customize the output.
|
289
|
+
# @returns [Console::Output::Terminal] The terminal output instance.
|
246
290
|
def self.new(output, **options)
|
247
291
|
Terminal.new(output, format: Console::Terminal::Text, **options)
|
248
292
|
end
|
249
293
|
end
|
250
294
|
|
295
|
+
# Terminal XTerm output.
|
251
296
|
module XTerm
|
297
|
+
# Create a new terminal output.
|
298
|
+
#
|
299
|
+
# You can use this to force XTerm output on a non-TTY output streams that support XTerm escape codes.
|
300
|
+
#
|
301
|
+
# @parameter output [IO] The output stream.
|
302
|
+
# @parameter options [Hash] Additional options to customize the output.
|
303
|
+
# @returns [Console::Output::Terminal] The terminal output instance.
|
252
304
|
def self.new(output, **options)
|
253
305
|
Terminal.new(output, format: Console::Terminal::XTerm, **options)
|
254
306
|
end
|