console 1.29.2 → 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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/console/capture.rb +26 -1
  4. data/lib/console/clock.rb +6 -1
  5. data/lib/console/compatible/logger.rb +30 -1
  6. data/lib/console/config.rb +93 -0
  7. data/lib/console/event/failure.rb +32 -3
  8. data/lib/console/event/generic.rb +14 -0
  9. data/lib/console/event/spawn.rb +38 -6
  10. data/lib/console/event.rb +6 -0
  11. data/lib/console/filter.rb +62 -2
  12. data/lib/console/format/safe.rb +35 -7
  13. data/lib/console/format.rb +3 -0
  14. data/lib/console/interface.rb +18 -10
  15. data/lib/console/logger.rb +22 -37
  16. data/lib/console/output/default.rb +11 -5
  17. data/lib/console/output/failure.rb +9 -2
  18. data/lib/console/output/null.rb +4 -1
  19. data/lib/console/output/sensitive.rb +41 -0
  20. data/lib/console/output/serialized.rb +26 -5
  21. data/lib/console/output/split.rb +11 -0
  22. data/lib/console/output/terminal.rb +66 -14
  23. data/lib/console/output/wrapper.rb +11 -0
  24. data/lib/console/output.rb +11 -0
  25. data/lib/console/progress.rb +55 -8
  26. data/lib/console/resolver.rb +18 -1
  27. data/lib/console/terminal/formatter/failure.rb +17 -5
  28. data/lib/console/terminal/formatter/progress.rb +15 -2
  29. data/lib/console/terminal/formatter/spawn.rb +15 -4
  30. data/lib/console/terminal/formatter.rb +16 -0
  31. data/lib/console/terminal/text.rb +60 -19
  32. data/lib/console/terminal/xterm.rb +16 -1
  33. data/lib/console/terminal.rb +6 -8
  34. data/lib/console/version.rb +1 -1
  35. data/lib/console/warn.rb +1 -1
  36. data/lib/console.rb +1 -0
  37. data/license.md +1 -1
  38. data/readme.md +19 -1
  39. data/releases.md +36 -1
  40. data.tar.gz.sig +0 -0
  41. metadata +5 -8
  42. metadata.gz.sig +0 -0
@@ -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
- def puts(*args, prefix: @prefix)
28
- args.each do |arg|
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(arg)
40
+ super(line)
31
41
  end
32
42
  end
33
43
 
34
44
  alias << puts
35
45
  end
36
46
 
37
- # This, and all related methods, is considered private.
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 CONSOLE_START which can be used to synchronize the start times of all child processes when they log using delta time.
41
- def self.start_at!(environment = ENV)
42
- if time_string = environment[CONSOLE_START_AT]
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
- environment[CONSOLE_START_AT] = start_at.to_s
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
- def initialize(output, verbose: nil, start_at: Terminal.start_at!, format: nil, **options)
55
- @io = output
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(@io) : format.new(@io)
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 that then writes to an IO object.
98
+ # This a final output.
82
99
  def last_output
83
100
  self
84
101
  end
85
102
 
86
- attr :io
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
- @io.write buffer.string
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
@@ -5,21 +5,32 @@
5
5
 
6
6
  module Console
7
7
  module Output
8
+ # A generic wrapper for output handling.
8
9
  class Wrapper
10
+ # Create a new wrapper output.
11
+ #
12
+ # @parameter delegate [Console::Output] The output to delegate to.
13
+ # @parameter options [Hash] Additional options to customize the output.
9
14
  def initialize(delegate, **options)
10
15
  @delegate = delegate
11
16
  end
12
17
 
18
+ # @attribute [Console::Output] The output to delegate to.
13
19
  attr :delegate
14
20
 
21
+ # The last output is the last output of the delegate.
15
22
  def last_output
16
23
  @delegate.last_output
17
24
  end
18
25
 
26
+ # Set the verbose flag for the delegate.
27
+ #
28
+ # @parameter value [Boolean] The new value.
19
29
  def verbose!(value = true)
20
30
  @delegate.verbose!(value)
21
31
  end
22
32
 
33
+ # Invoke the delegate.
23
34
  def call(...)
24
35
  @delegate.call(...)
25
36
  end
@@ -9,7 +9,18 @@ require_relative "output/terminal"
9
9
  require_relative "output/null"
10
10
 
11
11
  module Console
12
+ # Output handling.
12
13
  module Output
14
+ # Create a new output based on the environment.
15
+ #
16
+ # The environment variable `CONSOLE_OUTPUT` can be used to specify a list of output classes to wrap around the output. If not specified the {Default} output is used.
17
+ #
18
+ # The output argument is deliberately unders-specified but can be an IO object or an instance of {Output}.
19
+ #
20
+ # @parameter output [Console::Output] The output to wrap OR an IO object.
21
+ # @parameter env [Hash] The environment to read configuration from.
22
+ # @parameter options [Hash] Additional options to customize the output.
23
+ # @returns [Console::Output] The output instance.
13
24
  def self.new(output = nil, env = ENV, **options)
14
25
  if names = env["CONSOLE_OUTPUT"]
15
26
  names = names.split(",").reverse
@@ -7,16 +7,24 @@
7
7
  require_relative "clock"
8
8
 
9
9
  module Console
10
+ # A simple progress indicator
10
11
  class Progress
12
+ # @deprecated Use {Clock.now} instead.
11
13
  def self.now
12
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
14
+ Clock.now
13
15
  end
14
16
 
17
+ # Create a new progress indicator.
18
+ #
19
+ # @parameter subject [Object] The subject of the progress indicator.
20
+ # @parameter total [Integer] The total number of steps.
21
+ # @parameter minimum_output_duration [Numeric] The minimum duration between outputs.
22
+ # @parameter options [Hash] Additional options to customize the output.
15
23
  def initialize(subject, total = 0, minimum_output_duration: 0.1, **options)
16
24
  @subject = subject
17
25
  @options = options
18
26
 
19
- @start_time = Progress.now
27
+ @start_time = Clock.now
20
28
 
21
29
  @last_output_time = nil
22
30
  @minimum_output_duration = minimum_output_duration
@@ -25,34 +33,53 @@ module Console
25
33
  @total = total
26
34
  end
27
35
 
36
+ # @attribute [Object] The subject of the progress indicator.
28
37
  attr :subject
38
+
39
+ # @attribute [Numeric] The minimum duration between outputs.
40
+ attr :minimum_output_duration
41
+
42
+ # @attribute [Time] The time the progress indicator was started.
43
+ attr :start_time
44
+
45
+ # @attribute [Numeric] The current number of steps completed.
29
46
  attr :current
47
+
48
+ # @attribute [Numeric] The total number of steps.
30
49
  attr :total
31
50
 
51
+ # @returns [Numeric] The duration since the progress indicator was started.
32
52
  def duration
33
- Progress.now - @start_time
53
+ Clock.now - @start_time
34
54
  end
35
55
 
56
+ # @returns [Rational] The ratio of steps completed to total steps.
36
57
  def ratio
37
58
  Rational(@current.to_f, @total.to_f)
38
59
  end
39
60
 
61
+ # @returns [Numeric] The number of steps remaining.
40
62
  def remaining
41
63
  @total - @current
42
64
  end
43
65
 
66
+ # @returns [Numeric | Nil] The average duration per step, or `nil` if no steps have been completed.
44
67
  def average_duration
45
68
  if @current > 0
46
69
  duration / @current
47
70
  end
48
71
  end
49
72
 
73
+ # @returns [Numeric | Nil] The estimated remaining time, or `nil` if no steps have been completed.
50
74
  def estimated_remaining_time
51
75
  if average_duration = self.average_duration
52
76
  average_duration * remaining
53
77
  end
54
78
  end
55
79
 
80
+ # Generate an appropriate event for the progress indicator.
81
+ #
82
+ # @returns [Hash] The progress indicator as a hash.
56
83
  def to_hash
57
84
  Hash.new.tap do |hash|
58
85
  hash[:type] = :progress
@@ -64,30 +91,44 @@ module Console
64
91
  end
65
92
  end
66
93
 
94
+ # Increment the progress indicator by the given amount.
95
+ #
96
+ # @parameter amount [Numeric] The amount to increment by.
97
+ # @returns [Progress] The progress indicator itself.
67
98
  def increment(amount = 1)
68
99
  @current += amount
69
100
 
70
101
  if output?
71
102
  Console.call(@subject, self.to_s, event: self.to_hash, **@options)
72
- @last_output_time = Progress.now
103
+ @last_output_time = Clock.now
73
104
  end
74
105
 
75
106
  return self
76
107
  end
77
108
 
109
+ # Resize the progress indicator to the given total.
110
+ #
111
+ # @parameter total [Numeric] The new total number of steps.
112
+ # @returns [Progress] The progress indicator itself.
78
113
  def resize(total)
79
114
  @total = total
80
115
 
81
116
  Console.call(@subject, self.to_s, event: self.to_hash, **@options)
82
- @last_output_time = Progress.now
117
+ @last_output_time = Clock.now
83
118
 
84
119
  return self
85
120
  end
86
121
 
87
- def mark(*arguments, **options)
88
- Console.call(@subject, *arguments, **options, **@options)
122
+ # Augment the progress indicator with additional information.
123
+ #
124
+ # @parameter *arguments [Array] The arguments to log.
125
+ # @parameter **options [Hash] Additional options to log.
126
+ # @parameter &block [Proc] An optional block used to generate the log message.
127
+ def mark(*arguments, **options, &block)
128
+ Console.call(@subject, *arguments, **options, **@options, &block)
89
129
  end
90
130
 
131
+ # @returns [String] A human-readable representation of the progress indicator.
91
132
  def to_s
92
133
  if estimated_remaining_time = self.estimated_remaining_time
93
134
  "#{@current}/#{@total} completed in #{Clock.formatted_duration(self.duration)}, #{Clock.formatted_duration(estimated_remaining_time)} remaining."
@@ -98,12 +139,18 @@ module Console
98
139
 
99
140
  private
100
141
 
142
+ # Compute a time delta since the last output, used for rate limiting the output.
143
+ #
144
+ # @returns [Numeric | Nil] The duration since the last output.
101
145
  def duration_since_last_output
102
146
  if @last_output_time
103
- Progress.now - @last_output_time
147
+ Clock.now - @last_output_time
104
148
  end
105
149
  end
106
150
 
151
+ # Whether an output should be generated at this time, taking into account the remaining steps, and the duration since the last output.
152
+ #
153
+ # @returns [Boolean] Whether an output should be generated.
107
154
  def output?
108
155
  if remaining.zero?
109
156
  return true
@@ -7,6 +7,7 @@
7
7
  require_relative "filter"
8
8
 
9
9
  module Console
10
+ # Represents a class resolver that can be used to set log levels for different classes as they become available.
10
11
  class Resolver
11
12
  # You can change the log level for different classes using CONSOLE_$LEVEL env vars.
12
13
  #
@@ -16,7 +17,6 @@ module Console
16
17
  #
17
18
  # @parameter logger [Logger] A logger instance to set the logging levels on.
18
19
  # @parameter env [Hash] The environment to read levels from.
19
- #
20
20
  # @returns [Nil] If there were no custom logging levels specified in the environment.
21
21
  # @returns [Resolver] If there were custom logging levels, then the created resolver is returned.
22
22
  def self.default_resolver(logger, env = ENV)
@@ -59,12 +59,21 @@ module Console
59
59
  return resolver
60
60
  end
61
61
 
62
+ # Create a new class resolver.
62
63
  def initialize
63
64
  @names = {}
64
65
 
65
66
  @trace_point = TracePoint.new(:class, &self.method(:resolve))
66
67
  end
67
68
 
69
+ # Bind the given class names to the given block. When the class name is resolved into an actual class, the block will be called with the class as an argument.
70
+ #
71
+ # If the class is already defined, the block will be called immediately.
72
+ #
73
+ # If the class is not defined, the block will be called when the class is defined, using a trace point.
74
+ #
75
+ # @parameter names [Array(String)] The class names to bind.
76
+ # @parameter block [Proc] The block to call when the class is resolved.
68
77
  def bind(names, &block)
69
78
  names.each do |name|
70
79
  if klass = Object.const_get(name) rescue nil
@@ -81,10 +90,18 @@ module Console
81
90
  end
82
91
  end
83
92
 
93
+ # @returns [Boolean] True if the resolver is waiting for classes to be defined.
84
94
  def waiting?
85
95
  @trace_point.enabled?
86
96
  end
87
97
 
98
+ # Invoked by the trace point when a class is defined.
99
+ #
100
+ # This will call the block associated with the class name, if any, and remove it from the list of names to resolve.
101
+ #
102
+ # If the list of names is empty, the trace point will be disabled.
103
+ #
104
+ # @parameter trace_point [TracePoint] The trace point that triggered the event.
88
105
  def resolve(trace_point)
89
106
  if block = @names.delete(trace_point.self.to_s)
90
107
  block.call(trace_point.self)
@@ -6,9 +6,14 @@
6
6
  module Console
7
7
  module Terminal
8
8
  module Formatter
9
+ # Format a failure event, including the exception message and backtrace.
9
10
  class Failure
11
+ # The key used to identify this formatter.
10
12
  KEY = :failure
11
13
 
14
+ # Create a new failure formatter.
15
+ #
16
+ # @param terminal [Terminal::Text] The terminal to use for formatting.
12
17
  def initialize(terminal)
13
18
  @terminal = terminal
14
19
 
@@ -19,7 +24,14 @@ module Console
19
24
  @terminal[:exception_message] ||= @terminal.style(:default)
20
25
  end
21
26
 
22
- def format(event, output, prefix: nil, verbose: false, width: 80)
27
+ # Format the given event.
28
+ #
29
+ # @parameter event [Hash] The event to format.
30
+ # @parameter stream [IO] The stream to write the formatted event to.
31
+ # @parameter prefix [String] The prefix to use before the title.
32
+ # @parameter verbose [Boolean] Whether to include additional information.
33
+ # @parameter options [Hash] Additional options.
34
+ def format(event, stream, prefix: nil, verbose: false, **options)
23
35
  title = event[:class]
24
36
  message = event[:message]
25
37
  backtrace = event[:backtrace]
@@ -27,10 +39,10 @@ module Console
27
39
 
28
40
  lines = message.lines.map(&:chomp)
29
41
 
30
- output.puts " #{prefix}#{@terminal[:exception_title]}#{title}#{@terminal.reset}: #{lines.shift}"
42
+ stream.puts " #{prefix}#{@terminal[:exception_title]}#{title}#{@terminal.reset}: #{lines.shift}"
31
43
 
32
44
  lines.each do |line|
33
- output.puts " #{@terminal[:exception_detail]}#{line}#{@terminal.reset}"
45
+ stream.puts " #{@terminal[:exception_detail]}#{line}#{@terminal.reset}"
34
46
  end
35
47
 
36
48
  root_pattern = /^#{root}\// if root
@@ -44,11 +56,11 @@ module Console
44
56
  style = :exception_backtrace_other
45
57
  end
46
58
 
47
- output.puts " #{index == 0 ? "→" : " "} #{@terminal[style]}#{path}:#{offset}#{@terminal[:exception_message]} #{message}#{@terminal.reset}"
59
+ stream.puts " #{index == 0 ? "→" : " "} #{@terminal[style]}#{path}:#{offset}#{@terminal[:exception_message]} #{message}#{@terminal.reset}"
48
60
  end
49
61
 
50
62
  if cause = event[:cause]
51
- format(cause, output, prefix: "Caused by ", verbose: verbose, width: width)
63
+ format(cause, stream, prefix: "Caused by ", verbose: verbose, **options)
52
64
  end
53
65
  end
54
66
  end
@@ -6,9 +6,12 @@
6
6
  module Console
7
7
  module Terminal
8
8
  module Formatter
9
+ # Format a progress event, including the current progress and total.
9
10
  class Progress
11
+ # The key used to identify this formatter.
10
12
  KEY = :progress
11
13
 
14
+ # The block characters used to render the progress bar.
12
15
  BLOCK = [
13
16
  " ",
14
17
  "▏",
@@ -21,12 +24,21 @@ module Console
21
24
  "█",
22
25
  ]
23
26
 
27
+ # Create a new progress formatter.
28
+ #
29
+ # @param terminal [Terminal::Text] The terminal to use for formatting.
24
30
  def initialize(terminal)
25
31
  @terminal = terminal
26
32
  @terminal[:progress_bar] ||= terminal.style(:blue, :white)
27
33
  end
28
34
 
29
- def format(event, output, verbose: false, width: 80)
35
+ # Format the given event.
36
+ #
37
+ # @parameter event [Hash] The event to format.
38
+ # @parameter stream [IO] The stream to write the formatted event to.
39
+ # @parameter verbose [Boolean] Whether to include additional information.
40
+ # @parameter width [Integer] The width of the progress bar.
41
+ def format(event, stream, verbose: false, width: 80)
30
42
  current = event[:current].to_f
31
43
  total = event[:total].to_f
32
44
  value = current / total
@@ -36,11 +48,12 @@ module Console
36
48
  value = 1.0
37
49
  end
38
50
 
39
- output.puts "#{@terminal[:progress_bar]}#{self.bar(value, width-10)}#{@terminal.reset} #{sprintf('%6.2f', value * 100)}%"
51
+ stream.puts "#{@terminal[:progress_bar]}#{self.bar(value, width-10)}#{@terminal.reset} #{sprintf('%6.2f', value * 100)}%"
40
52
  end
41
53
 
42
54
  private
43
55
 
56
+ # Render a progress bar with the given value and width.
44
57
  def bar(value, width)
45
58
  blocks = width * value
46
59
  full_blocks = blocks.floor
@@ -6,31 +6,42 @@
6
6
  module Console
7
7
  module Terminal
8
8
  module Formatter
9
- # Format spawn events.
9
+ # Format a spawn event, including the command and arguments.
10
10
  class Spawn
11
+ # The key used to identify this formatter.
11
12
  KEY = :spawn
12
13
 
14
+ # Create a new spawn formatter.
15
+ #
16
+ # @param terminal [Terminal::Text] The terminal to use for formatting.
13
17
  def initialize(terminal)
14
18
  @terminal = terminal
15
19
  @terminal[:spawn_command] ||= @terminal.style(:blue, nil, :bold)
16
20
  end
17
21
 
18
- def format(event, output, verbose: false, width: 80)
22
+ # Format the given event.
23
+ #
24
+ # @parameter event [Hash] The event to format.
25
+ # @parameter stream [IO] The stream to write the formatted event to.
26
+ # @parameter verbose [Boolean] Whether to include additional information.
27
+ # @parameter width [Integer] The width of the progress bar.
28
+ def format(event, stream, verbose: false, width: 80)
19
29
  environment, arguments, options = event.values_at(:environment, :arguments, :options)
20
30
 
21
31
  arguments = arguments.flatten.collect(&:to_s)
22
32
 
23
- output.puts "#{@terminal[:spawn_command]}#{arguments.join(' ')}#{@terminal.reset}#{chdir_string(options)}"
33
+ stream.puts "#{@terminal[:spawn_command]}#{arguments.join(' ')}#{@terminal.reset}#{chdir_string(options)}"
24
34
 
25
35
  if verbose and environment
26
36
  environment.each do |key, value|
27
- output.puts "export #{key}=#{value}"
37
+ stream.puts "export #{key}=#{value}"
28
38
  end
29
39
  end
30
40
  end
31
41
 
32
42
  private
33
43
 
44
+ # Generate a string to represent the working directory.
34
45
  def chdir_string(options)
35
46
  if options and chdir = options[:chdir]
36
47
  " in #{chdir}"
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require_relative "formatter/progress"
7
+ require_relative "formatter/failure"
8
+ require_relative "formatter/spawn"
9
+
10
+ module Console
11
+ module Terminal
12
+ # Formatters for various types of events.
13
+ module Formatter
14
+ end
15
+ end
16
+ end