|
class Stopwatch |
|
def initialize(name = 'Stopwatch', line_max = 80) |
|
@line_max = line_max |
|
@marks = [] |
|
@name = name |
|
end |
|
|
|
def mark(label) |
|
@marks << [label, Time.current.localtime] |
|
spit_mark "#{magenta @name} #{gray label}" |
|
end |
|
|
|
def report |
|
header |
|
|
|
line |
|
time_header |
|
line |
|
breakline |
|
line |
|
|
|
marks_report |
|
|
|
line |
|
total_report |
|
line |
|
|
|
footer |
|
end |
|
|
|
private |
|
|
|
def time_header |
|
start = @marks.first[1].strftime(time_strf) |
|
finish = @marks.last[1].strftime(time_strf) |
|
|
|
spit append(@name, brown("#{start} to #{finish}")) |
|
end |
|
|
|
def marks_report |
|
cleanup_marks |
|
|
|
@marks.each_with_index do |time, i| |
|
next if i.zero? |
|
prev = @marks[i - 1] |
|
t = distance(time[1], prev[1]) |
|
spit append( |
|
"#{indent}#{gray(prev[0])}", |
|
"#{time[2]}#{indent}#{cyan t}", |
|
gray('─'), |
|
gray('◑'), |
|
gray('◐') |
|
) |
|
end |
|
end |
|
|
|
def cleanup_marks |
|
longest = @marks.map { |t| t[0] }.group_by(&:size).max.last.last.length |
|
@marks = @marks.map do |time| |
|
diff = longest - time[0].length |
|
spaces = (' ' * diff) |
|
time[2] = time[0] + spaces |
|
time[0] = spaces + time[0] |
|
time |
|
end |
|
end |
|
|
|
def total_report |
|
spit append('', green('Total: ' + distance(@marks.last[1], @marks.first[1]))) |
|
end |
|
|
|
def append(beginning = '', ending = '', delimiter = ' ', start = nil, cap = nil) |
|
begin_length = beginning.gsub(/\e\[\d+m/, '').length |
|
end_length = ending.gsub(/\e\[\d+m/, '').length |
|
spaces = (@line_max - 4) - begin_length - end_length - 2 |
|
spaces -= 2 |
|
start ||= delimiter |
|
cap ||= delimiter |
|
"#{beginning} #{start}#{delimiter * [spaces, 0].max}#{cap} #{ending}" |
|
end |
|
|
|
def indent |
|
' ' |
|
end |
|
|
|
def line |
|
logger.debug gray("┃#{' ' * (@line_max - 2)}┃") |
|
end |
|
|
|
def breakline |
|
logger.debug gray("┣#{'━' * (@line_max - 2)}┫") |
|
end |
|
|
|
def header |
|
logger.debug '' |
|
logger.debug gray("┏#{'━' * (@line_max - 2)}┓") |
|
end |
|
|
|
def footer |
|
logger.debug gray("┗#{'━' * (@line_max - 2)}┛") |
|
logger.debug '' |
|
end |
|
|
|
def spit(a) |
|
length = a.gsub(/\e\[\d+m/, '').length |
|
times = @line_max - length - 4 |
|
spaces = times > 0 ? ' ' * times : '' |
|
logger.debug "#{gray('┃')} #{a}#{spaces} #{gray('┃')}" |
|
end |
|
|
|
def spit_mark(a) |
|
logger.debug gray("#{gray('┃')} #{a}") |
|
end |
|
|
|
def logger |
|
return @logger if @logger |
|
@logger = Logger.new(STDOUT) |
|
@logger.formatter = proc do |_severity, _datetime, _progname, msg| |
|
"#{msg}\n" |
|
end |
|
@logger |
|
end |
|
|
|
def strf |
|
@strf ||= '%H:%M:%S.%3N' |
|
end |
|
|
|
def time_strf |
|
@time_strf ||= '%I:%M %p' |
|
end |
|
|
|
def underline(txt) |
|
"\e[4m#{txt}\e[24m" |
|
end |
|
|
|
def bold(txt) |
|
"\e[1m#{txt}\e[22m" |
|
end |
|
|
|
def italic(txt) |
|
"\e[3m#{txt}\e[23m" |
|
end |
|
|
|
def brown(txt) |
|
color(33, txt) |
|
end |
|
|
|
def green(txt) |
|
color(32, txt) |
|
end |
|
|
|
def gray(txt) |
|
color(37, txt) |
|
end |
|
|
|
def magenta(txt) |
|
color(35, txt) |
|
end |
|
|
|
def cyan(txt) |
|
color(36, txt) |
|
end |
|
|
|
def color(int, txt) |
|
"\e[#{int}m#{txt}\e[0m" |
|
end |
|
|
|
def bg(txt) |
|
"\e[40m#{txt}\e[0m" |
|
end |
|
|
|
def distance(a, b) |
|
Time.at(a - b).utc.strftime(strf) |
|
end |
|
end |