Text-based progress bar in Ruby for command line programs

When I’m running tests and tools, I frequently want to know how far through I am. I’d built a class to help with this a while back, but Corey Goldberg’s recent post on a python version prompted me to post this Ruby version.

First, you’ll need to save this to progress_bar.rb:

class Progress_bar

  attr_accessor :items_to_do, :items_done

  def initialize(items_to_do, items_done=0)
    reset(items_to_do, items_done)
  end

  def percent_complete
    return (@items_complete*1.0/@items_to_do*1.0)*100
  end

  def advance(steps_to_advance=1)
    @items_complete+=steps_to_advance
  end

  def reset(items_to_do, items_done=0)
    @items_to_do=items_to_do
    @items_complete=items_done
  end

  def report
    $stderr.print "\r#{progress_bar} #{@items_complete} of #{@items_to_do} done"
  end

  def progress_bar
    complete_bar=(percent_complete/2.0).floor
    incomplete_bar=((100-percent_complete)/2.0).ceil
    return "[#{"*"*complete_bar}#{"-"*incomplete_bar}]"
  end
end

You can then mix this in to so that when you iterate through collections, you can report on your progress. Handy for data-driven tests:

require 'progress_bar.rb'

module Enumerable
  def each_with_progress
    progress=Progress_bar.new(self.size)

    self.each do |item |
      progress.advance
      yield item
      progress.report
    end
  end
end

# Examples:

b={1=>"a",2=>"b"}

puts "Iterating through hash"
b.each_with_progress do | val |
  # do stuff
  sleep 2
end

puts
puts "Iterating through array"
c=[1,2,3,4]
c.each_with_progress do | val |
  # do stuff
  sleep 2
end

puts "Manual control..."
pb=Progress_bar.new(40,20)
5.times do
  pb.advance
  pb.report
  sleep 1
end

5.times do
  pb.advance(2)
  sleep 1
  pb.report
end

If you run from the command line, your output will look something like this:

[*******************************************——-] 35 of 40 done

This should all appear on a single line, although anything sent to standard output will force this to go to a new line. I never managed to get ANSI terminal display libraries working.

Enjoy!

2 comments on “Text-based progress bar in Ruby for command line programs”

  1. John Conery says:

    Nice! Thank you…..

  2. Exactly what I needed! Awsome implementation! Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *