lib/progress.rb in progress-1.1.1 vs lib/progress.rb in progress-1.1.2

- old
+ new

@@ -1,100 +1,95 @@ require 'singleton' +# ==== Procedural example +# Progress.start('Test', 1000) +# 1000.times{ Progress.step } +# Progress.stop +# ==== Block example +# Progress.start('Test', 1000) do +# 1000.times{ Progress.step } +# end +# ==== Step must not always be one +# symbols = [] +# Progress.start('Input 100 symbols', 100) do +# while symbols.length < 100 +# input = gets.scan(/\S/) +# symbols += input +# Progress.step input.length +# end +# end +# ==== Enclosed block example +# [1, 2, 3].each_with_progress('1 2 3') do |one_of_1_2_3| +# 10.times_with_progress('10') do |one_of_10| +# sleep(0.001) +# end +# end class Progress include Singleton - module InstanceMethods # :nodoc: - attr_accessor :title, :current, :total, :note - attr_reader :current_step - def initialize(title, total) - if title.is_a?(Numeric) && total.nil? - title, total = nil, title - elsif total.nil? - total = 1 - end - @title = title - @current = 0.0 - @total = total == 0.0 ? 1.0 : Float(total) + attr_accessor :title, :current, :total, :note + attr_reader :current_step + def initialize(title, total) + if title.is_a?(Numeric) && total.nil? + title, total = nil, title + elsif total.nil? + total = 1 end + @title = title + @current = 0.0 + @total = total == 0.0 ? 1.0 : Float(total) + end - def step_if_blank - if current == 0.0 && total == 1.0 - self.current = 1.0 - end + def step_if_blank + if current == 0.0 && total == 1.0 + self.current = 1.0 end + end - def to_f(inner) - inner = [inner, 1.0].min - if current_step - inner *= current_step - end - (current + inner) / total + def to_f(inner) + inner = [inner, 1.0].min + if current_step + inner *= current_step end + (current + inner) / total + end - def step(steps) - @current_step = steps - yield - ensure - @current_step = nil - end + def step(steps) + @current_step = steps + yield + ensure + @current_step = nil end - include InstanceMethods class << self # start progress indication - # ==== Procedural example - # Progress.start('Test', 1000) - # 1000.times{ Progress.step } - # Progress.stop - # ==== Block example - # Progress.start('Test', 1000) do - # 1000.times{ Progress.step } - # end - # ==== Step must not always be one - # symbols = [] - # Progress.start('Input 100 symbols', 100) do - # while symbols.length < 100 - # input = gets.scan(/\S/) - # symbols += input - # Progress.step input.length - # end - # end - # ==== Enclosed block example - # [1, 2, 3].each_with_progress('1 2 3') do |one_of_1_2_3| - # 10.times_with_progress('10') do |one_of_10| - # sleep(0.001) - # end - # end - # ==== To output progress as lines (not trying to stay on line) - # Progress.lines = true - # ==== To force highlight - # Progress.highlight = true def start(title = nil, total = nil) if levels.empty? @started_at = Time.now @eta = nil end levels << new(title, total) - print_message(true) + print_message true if block_given? begin yield ensure stop end end end + # step current progress by `num / den` def step(num = 1, den = 1, &block) if levels.last set(levels.last.current + Float(num) / den, &block) elsif block block.call end end + # set current progress to `value` def set(value, &block) if levels.last ret = if block levels.last.step(value - levels.last.current, &block) end @@ -107,31 +102,39 @@ elsif block block.call end end + # stop progress def stop if levels.last if levels.last.step_if_blank || levels.length == 1 - print_message(true) - set_title(nil) + print_message true + set_title nil end levels.pop if levels.empty? io.puts end end end + # set note (will be shown after progress message) def note=(s) if levels.last levels.last.note = s end end - attr_writer :lines, :highlight # :nodoc: + # output progress as lines (not trying to stay on line) + # Progress.lines = true + attr_writer :lines + # force highlight + # Progress.highlight = true + attr_writer :highlight + private def levels @levels ||= [] end @@ -185,30 +188,27 @@ end end def set_title(title) if io_tty? - io.print("\e]0;#{title}\a") + io.print "\e]0;#{title}\a" end end def print_message(force = false) if force || time_to_print? inner = 0 - parts = [] - parts_cl = [] - levels.reverse.each do |l| - current = l.to_f(inner) - value = current == 0 ? '......' : "#{'%5.1f' % (current * 100.0)}%" - inner = current + parts, parts_cl = [], [] + levels.reverse.each do |level| + inner = current = level.to_f(inner) + value = current.zero? ? '......' : "#{'%5.1f' % (current * 100.0)}%" - title = l.title ? "#{l.title}: " : '' - highlighted = "\e[1m#{value}\e[0m" + title = level.title ? "#{level.title}: " : nil if !highlight? || value == '100.0%' parts << "#{title}#{value}" else - parts << "#{title}#{highlighted}" + parts << "#{title}\e[1m#{value}\e[0m" end parts_cl << "#{title}#{value}" end eta_string = eta(inner) @@ -218,17 +218,16 @@ if note = levels.last && levels.last.note message << " - #{note}" message_cl << " - #{note}" end - unless lines? - previous_length = @previous_length || 0 - @previous_length = message_cl.length - message << "#{' ' * [previous_length - message_cl.length, 0].max}\r" + if lines? + io.puts message + else + io << message << "\e[K\r" end - lines? ? io.puts(message) : io.print(message) - set_title(message_cl) + set_title message_cl end end end end