1 #!/usr/bin/env ruby
 2 
 3 ##
 4 # A small application to change the title of an xterm to a meter with the
 5 # current CPU usage (works only on Linux with a properly configured
 6 # /proc)
 7 #
 8 
 9 ##
10 # Get the cpu info for the cpu with the given name.  "cpu" is for all
11 # cpus, or cpu0 for the first cpu, etc.  Returns:
12 # [ name, total_user, total_nice, total_system, total_idle ]
13 def get_cpuinfo(name = "cpu")
14   stats = File.readlines('/proc/stat')
15   begin
16     cpustat = stats[0].split(/\s+/)
17   end while cpustat[0] != name
18   return [ cpustat[0], *(cpustat[1..-1].map { |x| x.to_i }) ]
19 end
20 
21 ##
22 # Given two return value from get_cpuinfo, return the difference between
23 # them.  Returns:
24 # [ diff_user, diff_nice, diff_system, diff_idle ]
25 def cpudiff(oldcpuinfo, cpuinfo)
26   diff = []
27   (1..4).each do |idx|
28     diff.push(cpuinfo[idx] - oldcpuinfo[idx])
29   end
30   return diff
31 end
32 
33 ##
34 # Run a loop that yields the difference in cpu usage since the last
35 # yield every interval seconds.
36 def cpu_stat_loop(name = "cpu", interval = 1)
37   oldcpuinfo = get_cpuinfo(name)
38   loop do
39     sleep interval
40     cpuinfo = get_cpuinfo(name)
41     diff = cpudiff(oldcpuinfo, cpuinfo)
42     yield diff
43     oldcpuinfo = cpuinfo
44   end
45 end
46 
47 ##
48 # Return a string holding an ascii representation of a meter.
49 def ascii_meter(percent, total_bar_size)
50   bar_size = (total_bar_size * percent)
51   not_bar_size = (total_bar_size - bar_size)
52   return ('I' * bar_size) + (':' * (not_bar_size))
53 end
54 
55 ##
56 # Set the title of an xterm.
57 def set_xterm_title(x)
58   $stdout.print "\033]0;#{x}\007"
59   $stdout.flush
60 end
61 
62 # Main
63 TOTAL_BAR_SIZE = 20
64 cpu_stat_loop do |diff|
65   total = (diff[0] + diff[1] + diff[2] + diff[3])
66   idle_percent = diff[3].to_f / total
67   set_xterm_title(
68       ascii_meter(1.0 - idle_percent, TOTAL_BAR_SIZE) +
69       ' ' +
70       ("%2.1f" % (100.0 * (1.0 - idle_percent))))
71 end