# $Id: progress.rb,v 1.1 2002/09/28 12:26:56 sdalu Exp $ # # Copyrigth (C) 2002 Stephane D'Alu # Code is under GPL v2 (see http://www.gnu.org/licenses/gpl.txt) # # WWW: http://www.sdalu.com/software/ # module TTY class ProgressBar EraseEndLine = "\033[K" HideCursor = "\033[?25l" ShowCursor = "\033[?25h" ProgressBarSize = 37 DisplayNoFinalStatus = 0x1 def initialize(output, precision, display = 0) @output = output @precision = precision @display = display end def start(length, totalrsize = 0) @length = length @starttime = @lasttime = Time.now @totaltime = 0 @totalsize = 0 @totalrsize = totalrsize @tick = 0 update_barstr unless @output.nil? @output.print HideCursor @output.print @barstr end end def processed(size) @totalsize += size; @totalrsize += size nowtime = Time.now @deltatime = nowtime - @lasttime if @deltatime > @precision @totaltime = @lasttime == @starttime \ ? 0.0 : nowtime - @starttime @lasttime = nowtime update_barstr unless @output.nil? @output.print "\r", @barstr, EraseEndLine @output.flush end @tick += 1 end @barstr.dup end def done(filename) filename = filename.slice(0,52) + ":" if @totaltime == 0.0 @barstr = sprintf "%-53s %10d [ --.--#{unit}]", filename, @totalsize else speed = @totalrsize.to_f / @totaltime @barstr = sprintf "%-53s %10d [%7.2f#{unit}]", filename, @totalsize, unit_cvt(speed) end if (@display & DisplayNoFinalStatus) != 0 str = "\r#{EraseEndLine}" else str = "\r#{@barstr}#{EraseEndLine}\n" end unless @output.nil? @output.print str @output.flush end @barstr.dup end def failed(filename) filename = filename.slice(0,52) + ":" @barstr = sprintf "%-53s Failed", filename if (@display & DisplayNoFinalStatus) != 0 str = "\r#{EraseEndLine}" else str = "\r#{@barstr}#{EraseEndLine}\n" end unless @output.nil? @output.print str @output.flush end @barstr.dup end def finish @output.print ShowCursor unless @output.nil? end def to_s @barstr.dup end #-- [protected] --------------------------------------------- protected def unit ; "K/s" ; end def unit_cvt(value) ; value/1024 ; end def update_barstr speed = @totaltime == 0.0 ? -1.0 : @totalrsize / @totaltime speed_str = if speed < 0.0 then "--.--#{unit}" else "%7.2f#{unit}" % (unit_cvt(speed)) end totalsizestr = @totalsize.to_s.reverse! totalsizestr.gsub!(/(...)/, '\1,') totalsizestr.reverse! totalsizestr.gsub!(/^,/, '') if @length > 0 then pct = 100 * @totalsize / @length rmt = speed < 0.0 ? -1 : ((@length-@totalrsize) / speed).to_i str = pct == 100 ? "100%%" : "%2d%% " % pct str << sprintf("[%-#{ProgressBarSize}.#{ProgressBarSize}s]", "=" * (ProgressBarSize * pct / 100) + ">") str << sprintf(" %-11s", totalsizestr) str << sprintf(" %10s", speed_str) str << sprintf(" %12s", "ETA %s" % sec_to_timestr(rmt)) else ind = @tick % (ProgressBarSize * 2 - 6) if ind < ProgressBarSize - 2 pos = ind + 1; else pos = ProgressBarSize - (ind - ProgressBarSize + 5) end bar = (" " * ProgressBarSize) bar[pos-1,3] = '<=>' str = sprintf " [%s] %-11s %10s", bar, totalsizestr, speed_str end @barstr = str end #-- [private] ----------------------------------------------- private def sec_to_timestr(sec) return "--:--" if sec < 0 hrs = sec / 3600; sec %= 3600; min = sec / 60; sec %= 60; if (hrs > 0) return sprintf("%2d:%02d:%02d", hrs, min, sec) else return sprintf("%2d:%02d", min, sec) end end end end