lib/progress_bar.rb in progress_bar-0.1.0 vs lib/progress_bar.rb in progress_bar-0.2.0

- old
+ new

@@ -1,72 +1,156 @@ require 'options' require 'highline' -require File.join(File.dirname(__FILE__), 'progress_bar', 'time_formatter') -require File.join(File.dirname(__FILE__), 'progress_bar', 'meter') -require File.join(File.dirname(__FILE__), 'progress_bar', 'meters') - class ProgressBar - attr_accessor :count, :max, :start + attr_accessor :count, :max, :start, :meters - def initialize *args, &block - args, options = Options.parse args + def initialize(max = 100, meters = :all) - @count = options[:count] || 0 - @max = options[:max] || 100 - @start = Time.now + @count = 0 + @max = max + @start = Time.now + if meters == :all + @meters = [:bar, :counter, :percentage, :elapsed, :eta, :rate] + else + @meters = meters + end + @hl = HighLine.new end - def increment! - self.count = count.succ + def increment!(count = 1) + self.count += count write end def write clear! print to_s end - def bar(width = terminal_width) - Bar.new(count, max, width) + def remaining + max - count end - def counter - Counter.new(count, max) + def ratio + count.to_f / max end def percentage - Percentage.new(count, max) + ratio * 100 end def elapsed - Elapsed.new(start) + Time.now - start end + def rate + if count > 0 + count / elapsed + else + 0 + end + end + def eta - ETA.new(start, count, max) + remaining / rate end def to_s - width = terminal_width - - (counter.width + 1) - - (percentage.width + 1) - - (elapsed.width + 1) - - (eta.width + 1) - "#{bar(width)} #{counter} #{percentage} #{elapsed} #{eta}" + meters.inject("") do |text, meter| + text << render(meter) + " " + end.strip end protected def clear! print "\r" end + def render(meter) + send(:"render_#{meter}") + end + + def width_of(meter) + send(:"#{meter}_width") + end + + def render_bar + "[" + + "#" * (ratio * (bar_width - 2)).ceil + + " " * ((1-ratio) * (bar_width - 2)).floor + + "]" + end + + def render_counter + "[%#{max.to_s.length}i/%i]" % [count, max] + end + + def render_percentage + format = (max % 10 == 0 ? "%3i" : "%6.2f") + "[#{format}%%]" % percentage + end + + def render_elapsed + "[#{format_interval(elapsed)}]" + end + + def render_eta + "[#{format_interval(eta)}]" + end + + def render_rate + "[%.2f/s]" % rate + end + def terminal_width @hl.output_cols.to_i + end + + def bar_width + terminal_width - non_bar_width + end + + def non_bar_width + meters.reject { |m| m == :bar }.inject(0) do |width, meter| + width += width_of(meter) + 1 + end + end + + def counter_width # [ 1/100] + max.to_s.length * 2 + 3 + end + + def percentage_width + if max == 100 # [ 24%] + 6 + else # [ 24.0%] + 8 + end + end + + def elapsed_width + format_interval(elapsed).length + 2 + end + + def eta_width + format_interval(eta).length + 2 + end + + def rate_width # [ 23.45/s] + render_rate.length + end + + def format_interval(interval) + if interval > 3600 + "%02i:%02i:%02i" % [interval/3600, interval%3600/60, interval%60] + else + "%02i:%02i" % [interval/60, interval%60] + end end end