Skip to content

Commit

Permalink
Separate out logging from formatting.
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Apr 30, 2024
1 parent 24b0923 commit 1584fc2
Show file tree
Hide file tree
Showing 17 changed files with 354 additions and 300 deletions.
25 changes: 0 additions & 25 deletions lib/console/buffer.rb

This file was deleted.

1 change: 1 addition & 0 deletions lib/console/compatible/logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

module Console
module Compatible
# A compatible interface for {::Logger} which can be used with {Console}.
class Logger < ::Logger
class LogDevice
def initialize(subject, output)
Expand Down
78 changes: 26 additions & 52 deletions lib/console/event/failure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,80 +4,54 @@
# Copyright, 2019-2022, by Samuel Williams.
# Copyright, 2021, by Robert Schulze.

require_relative 'generic'

module Console
module Event
class Failure < Generic
def self.current_working_directory
# Represents a failure event.
#
# ```ruby
# Console.error(self, **Console::Event::Failure.for(exception))
# ````
class Failure
def self.default_root
Dir.getwd
rescue # e.g. Errno::EMFILE
nil
end

def self.for(exception)
self.new(exception, self.current_working_directory)
self.new(exception, self.default_root)
end

def initialize(exception, root = nil)
def initialize(exception, root)
@exception = exception
@root = root
end

attr :exception
attr :root

def self.register(terminal)
terminal[:exception_title] ||= terminal.style(:red, nil, :bold)
terminal[:exception_detail] ||= terminal.style(:yellow)
terminal[:exception_backtrace] ||= terminal.style(:red)
terminal[:exception_backtrace_other] ||= terminal.style(:red, nil, :faint)
terminal[:exception_message] ||= terminal.style(:default)
end

def to_h
{exception: @exception, root: @root}
end

def format(output, terminal, verbose)
format_exception(@exception, nil, output, terminal, verbose)
end

if Exception.method_defined?(:detailed_message)
def detailed_message(exception)
exception.detailed_message
end
else
def detailed_message(exception)
exception.message
def to_hash
Hash.new.tap do |hash|
hash[:event] = :failure
hash[:root] = @root if @root
extract(@exception, hash)
end
end

def format_exception(exception, prefix, output, terminal, verbose)
lines = detailed_message(exception).lines.map(&:chomp)
output.puts " #{prefix}#{terminal[:exception_title]}#{exception.class}#{terminal.reset}: #{lines.shift}"
private

def extract(exception, hash)
hash[:title] = exception.class

lines.each do |line|
output.puts " #{terminal[:exception_detail]}#{line}#{terminal.reset}"
if exception.respond_to?(:detailed_message)
hash[:message] = exception.detailed_message
else
hash[:message] = exception.message
end

root_pattern = /^#{@root}\// if @root
hash[:backtrace] = exception.backtrace

exception.backtrace&.each_with_index do |line, index|
path, offset, message = line.split(":", 3)
style = :exception_backtrace

# Make the path a bit more readable
if root_pattern and path.sub!(root_pattern, "").nil?
style = :exception_backtrace_other
if cause = exception.cause
hash[:cause] = Hash.new.tap do |cause_hash|
extract(cause, cause_hash)
end

output.puts " #{index == 0 ? "→" : " "} #{terminal[style]}#{path}:#{offset}#{terminal[:exception_message]} #{message}#{terminal.reset}"
end

if exception.cause
format_exception(exception.cause, "Caused by ", output, terminal, verbose)
end
end
end
Expand Down
23 changes: 0 additions & 23 deletions lib/console/event/generic.rb

This file was deleted.

125 changes: 91 additions & 34 deletions lib/console/event/progress.rb
Original file line number Diff line number Diff line change
@@ -1,59 +1,116 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2020-2022, by Samuel Williams.
# Copyright, 2020-2023, by Samuel Williams.
# Copyright, 2022, by Anton Sozontov.

require_relative 'generic'
require_relative '../clock'

module Console
module Event
class Progress < Generic
BLOCK = [
" ",
"▏",
"▎",
"▍",
"▌",
"▋",
"▊",
"▉",
"█",
]

def initialize(current, total)
@current = current
class Progress
def self.now
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end

def initialize(output, subject, total = 0, minimum_output_duration: 0.1, **options)
@output = output
@subject = subject
@options = options

@start_time = Progress.now

@last_output_time = nil
@minimum_output_duration = minimum_output_duration

@current = 0
@total = total
end

attr :subject
attr :current
attr :total

def value
@current.to_f / @total.to_f
def duration
Progress.now - @start_time
end

def ratio
Rational(@current.to_f, @total.to_f)
end

def bar(value = self.value, width = 70)
blocks = width * value
full_blocks = blocks.floor
partial_block = ((blocks - full_blocks) * BLOCK.size).floor
def remaining
@total - @current
end

def average_duration
if @current > 0
duration / @current
end
end

def estimated_remaining_time
if average_duration = self.average_duration
average_duration * remaining
end
end

def to_hash
Hash.new.tap do |hash|
hash[:event] = :progress
hash[:current] = @current
hash[:total] = @total
end
end

def increment(amount = 1)
@current += amount

if partial_block.zero?
BLOCK.last * full_blocks
else
"#{BLOCK.last * full_blocks}#{BLOCK[partial_block]}"
end.ljust(width)
if output?
@output.info(@subject, self.to_s, **@options, **self)
@last_output_time = Progress.now
end

return self
end

def self.register(terminal)
terminal[:progress_bar] ||= terminal.style(:blue, :white)
def resize(total)
@total = total

@output.call(@subject, self.to_s, **@options, **self)
@last_output_time = Progress.now

return self
end

def to_h
{current: @current, total: @total}
def mark(...)
@output.call(@subject, ...)
end

def format(output, terminal, verbose)
output.puts "#{terminal[:progress_bar]}#{self.bar}#{terminal.reset} #{sprintf('%6.2f', self.value * 100)}%"
def to_s
if estimated_remaining_time = self.estimated_remaining_time
"#{@current}/#{@total} completed in #{Clock.formatted_duration(self.duration)}, #{Clock.formatted_duration(estimated_remaining_time)} remaining."
else
"#{@current}/#{@total} completed, waiting for estimate..."
end
end

private

def duration_since_last_output
if @last_output_time
Progress.now - @last_output_time
end
end

def output?
if remaining.zero?
return true
elsif duration = duration_since_last_output
return duration > @minimum_output_duration
else
return true
end
end
end
end
Expand Down
41 changes: 8 additions & 33 deletions lib/console/event/spawn.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
# Released under the MIT License.
# Copyright, 2019-2022, by Samuel Williams.

require_relative 'generic'

module Console
module Event
class Spawn < Generic
# Represents a spawn event.
#
# ```ruby
# Console.info(self, **Console::Event::Spawn.for("ls", "-l"))
# ```
class Spawn
def self.for(*arguments, **options)
# Extract out the command environment:
if arguments.first.is_a?(Hash)
Expand All @@ -24,42 +27,14 @@ def initialize(environment, arguments, options)
@options = options
end

attr :environment
attr :arguments
attr :options

def chdir_string(options)
if options and chdir = options[:chdir]
" in #{chdir}"
end
end

def self.register(terminal)
terminal[:shell_command] ||= terminal.style(:blue, nil, :bold)
end

def to_h
def to_hash
Hash.new.tap do |hash|
hash[:event] = :spawn
hash[:environment] = @environment if @environment&.any?
hash[:arguments] = @arguments if @arguments&.any?
hash[:options] = @options if @options&.any?
end
end

def format(output, terminal, verbose)
arguments = @arguments.flatten.collect(&:to_s)

output.puts " #{terminal[:shell_command]}#{arguments.join(' ')}#{terminal.reset}#{chdir_string(options)}"

if verbose and @environment
@environment.each do |key, value|
output.puts " export #{key}=#{value}"
end
end
end
end
end

# Deprecated.
Shell = Event::Spawn
end
2 changes: 0 additions & 2 deletions lib/console/filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
# Copyright, 2020, by Michael Adams.
# Copyright, 2021, by Robert Schulze.

require_relative 'buffer'

module Console
UNKNOWN = 'unknown'

Expand Down
Loading

0 comments on commit 1584fc2

Please sign in to comment.