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.
Files changed (41) 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 +17 -9
  15. data/lib/console/logger.rb +22 -37
  16. data/lib/console/output/default.rb +11 -5
  17. data/lib/console/output/failure.rb +8 -1
  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 +25 -4
  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/readme.md +7 -1
  38. data/releases.md +24 -1
  39. data.tar.gz.sig +0 -0
  40. metadata +4 -2
  41. metadata.gz.sig +0 -0
@@ -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
@@ -8,75 +8,116 @@ require "io/console"
8
8
  module Console
9
9
  # Styled terminal output.
10
10
  module Terminal
11
+ # A simple text-based terminal output.
11
12
  class Text
12
- def initialize(output)
13
- @output = output
13
+ # Create a new text terminal output.
14
+ #
15
+ # @parameter stream [IO] The stream to write to.
16
+ def initialize(stream)
17
+ @stream = stream
14
18
  @styles = {reset: self.reset}
15
19
  end
16
20
 
21
+ # @attribute [IO] The stream to write to.
22
+ attr :stream
23
+
24
+ # Get the style associated with the given key.
25
+ #
26
+ # @parameter key [Symbol] The key to look up.
27
+ # @returns [String] The style associated with the key.
17
28
  def [] key
18
29
  @styles[key]
19
30
  end
20
31
 
32
+ # Set the style associated with the given key.
33
+ #
34
+ # @parameter key [Symbol] The key to associate the style with.
35
+ # @parameter value [String] The style to associate with the key.
21
36
  def []= key, value
22
37
  @styles[key] = value
23
38
  end
24
39
 
40
+ # @returns [Boolean] Whether the terminal supports colors.
25
41
  def colors?
26
42
  false
27
43
  end
28
44
 
45
+ # @returns [Tuple(Integer, Integer)] The size of the terminal, or a default value of [24, 80].
46
+ def size
47
+ [24, 80]
48
+ end
49
+
50
+ # @returns [Integer] The width of the terminal.
29
51
  def width
30
- 80
52
+ self.size.last
31
53
  end
32
54
 
55
+ # Generate a style string for the given foreground, background, and attributes.
56
+ #
57
+ # @returns [String | Nil] The style string if colors are supported, otherwise nil.
33
58
  def style(foreground, background = nil, *attributes)
34
59
  end
35
60
 
61
+ # Generate a reset sequence.
62
+ #
63
+ # @returns [String | Nil] The reset sequence if colors are supported, otherwise nil.
36
64
  def reset
37
65
  end
38
66
 
67
+ # Write the given arguments to the output stream using the given style. The reset sequence is automatically appended.
68
+ #
69
+ # @parameter arguments [Array] The arguments to write.
70
+ # @parameter style [Symbol] The style to apply.
39
71
  def write(*arguments, style: nil)
40
72
  if style and prefix = self[style]
41
- @output.write(prefix)
42
- @output.write(*arguments)
43
- @output.write(self.reset)
73
+ @stream.write(prefix)
74
+ @stream.write(*arguments)
75
+ @stream.write(self.reset)
44
76
  else
45
- @output.write(*arguments)
77
+ @stream.write(*arguments)
46
78
  end
47
79
  end
48
80
 
81
+ # Write the given arguments to the output stream using the given style. The reset sequence is automatically appended.
82
+ #
83
+ # @parameter arguments [Array] The arguments to write, each on a new line.
84
+ # @parameter style [Symbol] The style to apply.
49
85
  def puts(*arguments, style: nil)
50
86
  if style and prefix = self[style]
51
- @output.write(prefix)
52
- @output.puts(*arguments)
53
- @output.write(self.reset)
87
+ @stream.write(prefix)
88
+ @stream.puts(*arguments)
89
+ @stream.write(self.reset)
54
90
  else
55
- @output.puts(*arguments)
91
+ @stream.puts(*arguments)
56
92
  end
57
93
  end
58
94
 
59
- # Print out the given arguments.
60
- # When the argument is a symbol, look up the style and inject it into the output stream.
61
- # When the argument is a proc/lambda, call it with self as the argument.
62
- # When the argument is anything else, write it directly to the output.
95
+ # Print rich text to the output stream.
96
+ #
97
+ # - When the argument is a symbol, look up the style and inject it into the output stream.
98
+ # - When the argument is a proc/lambda, call it with self as the argument.
99
+ # - When the argument is anything else, write it directly to the output.
100
+ #
101
+ # @parameter arguments [Array] The arguments to print.
63
102
  def print(*arguments)
64
103
  arguments.each do |argument|
65
104
  case argument
66
105
  when Symbol
67
- @output.write(self[argument])
106
+ @stream.write(self[argument])
68
107
  when Proc
69
108
  argument.call(self)
70
109
  else
71
- @output.write(argument)
110
+ @stream.write(argument)
72
111
  end
73
112
  end
74
113
  end
75
114
 
76
- # Print out the arguments as per {#print}, followed by the reset sequence and a newline.
115
+ # Print rich text to the output stream, followed by the reset sequence and a newline.
116
+ #
117
+ # @parameter arguments [Array] The arguments to print.
77
118
  def print_line(*arguments)
78
119
  print(*arguments)
79
- @output.puts(self.reset)
120
+ @stream.puts(self.reset)
80
121
  end
81
122
  end
82
123
  end
@@ -10,7 +10,9 @@ require_relative "text"
10
10
  module Console
11
11
  # Styled terminal output.
12
12
  module Terminal
13
+ # XTerm style terminal output.
13
14
  class XTerm < Text
15
+ # XTerm color codes.
14
16
  COLORS = {
15
17
  black: 0,
16
18
  red: 1,
@@ -23,6 +25,7 @@ module Console
23
25
  default: 9,
24
26
  }.freeze
25
27
 
28
+ # XTerm attribute codes.
26
29
  ATTRIBUTES = {
27
30
  normal: 0,
28
31
  bold: 1,
@@ -35,21 +38,30 @@ module Console
35
38
  hidden: 8,
36
39
  }.freeze
37
40
 
41
+ # Whether the terminal supports colors.
38
42
  def colors?
39
43
  true
40
44
  end
41
45
 
46
+ # The size of the terminal.
42
47
  def size
43
- @output.winsize
48
+ @stream.winsize
44
49
  rescue Errno::ENOTTY
45
50
  # Fake it...
46
51
  [24, 80]
47
52
  end
48
53
 
54
+ # The width of the terminal.
49
55
  def width
50
56
  size.last
51
57
  end
52
58
 
59
+ # Apply the given style to the output.
60
+ #
61
+ # @parameter foreground [Symbol] The foreground color.
62
+ # @parameter background [Symbol] The background color.
63
+ # @parameter attributes [Array(Symbol)] The attributes to apply.
64
+ # @returns [String] The style code.
53
65
  def style(foreground, background = nil, *attributes)
54
66
  tokens = []
55
67
 
@@ -68,6 +80,9 @@ module Console
68
80
  return "\e[#{tokens.join(';')}m"
69
81
  end
70
82
 
83
+ # Reset the style.
84
+ #
85
+ # @returns [String] The reset code.
71
86
  def reset
72
87
  "\e[0m"
73
88
  end
@@ -5,18 +5,16 @@
5
5
 
6
6
  require_relative "terminal/text"
7
7
  require_relative "terminal/xterm"
8
-
9
- require_relative "terminal/formatter/progress"
10
- require_relative "terminal/formatter/failure"
11
- require_relative "terminal/formatter/spawn"
8
+ require_relative "terminal/formatter"
12
9
 
13
10
  module Console
14
11
  module Terminal
15
- def self.for(io)
16
- if io.tty?
17
- XTerm.new(io)
12
+ # Create a new terminal output for the given stream.
13
+ def self.for(stream)
14
+ if stream.tty?
15
+ XTerm.new(stream)
18
16
  else
19
- Text.new(io)
17
+ Text.new(stream)
20
18
  end
21
19
  end
22
20
  end
@@ -4,5 +4,5 @@
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
6
  module Console
7
- VERSION = "1.29.3"
7
+ VERSION = "1.30.0"
8
8
  end
data/lib/console/warn.rb CHANGED
@@ -22,7 +22,7 @@ module Console
22
22
  fiber.console_warn = true
23
23
  message.chomp!
24
24
 
25
- Console::Logger.instance.warn(message, **options)
25
+ Console::Interface.instance.warn(message, **options)
26
26
  ensure
27
27
  fiber.console_warn = false
28
28
  end
data/lib/console.rb CHANGED
@@ -9,6 +9,7 @@
9
9
  require_relative "console/version"
10
10
  require_relative "console/interface"
11
11
 
12
+ # @namespace
12
13
  module Console
13
14
  Console.extend(Interface)
14
15
  end