Skip to content

Instantly share code, notes, and snippets.

@ja-k-e
Last active May 11, 2017 16:38
Show Gist options
  • Save ja-k-e/d9703e575be85a56588c5fac9d982eca to your computer and use it in GitHub Desktop.
Save ja-k-e/d9703e575be85a56588c5fac9d982eca to your computer and use it in GitHub Desktop.
Stopwatch: Timing tasks in a pretty way.

Stopwatch

Timing things in a pretty way

  • instantiate
  • mark events at points in time
  • generate a report
stopwatch = Stopwatch.new('StopWatch Test')
stopwatch.mark 'Hello, World'
stopwatch.mark 'Gonna sleep for 1 second'
sleep 1
stopwatch.mark 'Gonna sleep for 2 seconds'
sleep 2
stopwatch.mark 'Phew! Done.'
stopwatch.report

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment