#!/usr/bin/env ruby

##
# A small application to change the title of an xterm to a meter with the
# current CPU usage (works only on Linux with a properly configured
# /proc)
#

##
# Get the cpu info for the cpu with the given name.  "cpu" is for all
# cpus, or cpu0 for the first cpu, etc.  Returns:
# [ name, total_user, total_nice, total_system, total_idle ]
def get_cpuinfo(name = "cpu")
  stats = File.readlines('/proc/stat')
  begin
    cpustat = stats[0].split(/\s+/)
  end while cpustat[0] != name
  return [ cpustat[0], *(cpustat[1..-1].map { |x| x.to_i }) ]
end

##
# Given two return value from get_cpuinfo, return the difference between
# them.  Returns:
# [ diff_user, diff_nice, diff_system, diff_idle ]
def cpudiff(oldcpuinfo, cpuinfo)
  diff = []
  (1..4).each do |idx|
    diff.push(cpuinfo[idx] - oldcpuinfo[idx])
  end
  return diff
end

##
# Run a loop that yields the difference in cpu usage since the last
# yield every interval seconds.
def cpu_stat_loop(name = "cpu", interval = 1)
  oldcpuinfo = get_cpuinfo(name)
  loop do
    sleep interval
    cpuinfo = get_cpuinfo(name)
    diff = cpudiff(oldcpuinfo, cpuinfo)
    yield diff
    oldcpuinfo = cpuinfo
  end
end

##
# Return a string holding an ascii representation of a meter.
def ascii_meter(percent, total_bar_size)
  bar_size = (total_bar_size * percent)
  not_bar_size = (total_bar_size - bar_size)
  return ('I' * bar_size) + (':' * (not_bar_size))
end

##
# Set the title of an xterm.
def set_xterm_title(x)
  $stdout.print "\033]0;#{x}\007"
  $stdout.flush
end

# Main
TOTAL_BAR_SIZE = 20
cpu_stat_loop do |diff|
  total = (diff[0] + diff[1] + diff[2] + diff[3])
  idle_percent = diff[3].to_f / total
  set_xterm_title(
      ascii_meter(1.0 - idle_percent, TOTAL_BAR_SIZE) +
      ' ' +
      ("%2.1f" % (100.0 * (1.0 - idle_percent))))
end

