lib/progress.rb in progress-0.0.9.3 vs lib/progress.rb in progress-0.1.0.0

- old
+ new

@@ -4,149 +4,127 @@ require 'singleton' class Progress include Singleton - # 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 - # Progress.start('Test', 10) do - # (1..10).to_a.each_slice do |slice| - # Progress.step(slice.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 self.start(title, total = 1, options = {}) - levels << new(title, total, levels.length, options) - print_message - if block_given? - result = yield - stop - result + module InstanceMethods # :nodoc: + attr_accessor :title, :current, :total + def initialize(title, total) + @title, @current, @total = title, 0, total.to_f end - end - attr_reader :message, :options - def initialize(title, total, level, options) # :nodoc: - @title = title + ': %s' - @total = total - @level = level - @options = options - @current = 0 - start - end + def step_if_blank + self.current = 1 if current == 0 && total == 1 + end - def start # :nodoc: - self.message = '.' * 6 + def to_f(inner) + (current + [inner, 1].min) / total + end end + include InstanceMethods - def step(steps) # :nodoc: - @current += steps - self.message = percent - end + 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, total = 1) + levels << new(title, total) + print_message + if block_given? + result = yield + stop + result + end + end - def stop # :nodoc: - self.message = percent - end - -protected - - def percent - '%5.1f%%' % (@current * 100.0 / @total) - end - - def message=(s) - formatted = s.ljust(6)[0, 6] - @message = @title % formatted - end - - module ClassMethods def step(steps = 1) - levels[-1].step(steps) + levels.last.current += steps print_message end + def set(value) + levels.last.current = value + print_message + end + def stop - levels.pop.stop - @io.puts if levels.empty? + print_message if levels.last.step_if_blank + levels.pop + io.puts if levels.empty? end + attr_writer :io, :lines, :highlight # :nodoc: + + private + + def levels + @levels ||= [] + end + def io @io ||= $stderr + @io.sync = true + @io end def io_tty? - ENV['PROGRESS_TTY'] || io.tty? + io.tty? || ENV['PROGRESS_TTY'] end - def io=(io) - @io = io - end - - def lines=(value) - @lines = value - end def lines? - if @lines.nil? - @lines = !io_tty? - end - @lines + @lines.nil? ? !io_tty? : @lines end - def highlight=(value) - @highlight = value - end def highlight? - if @highlight.nil? - @highlight = io_tty? - end - @highlight + @highlight.nil? ? io_tty? : @highlight end - protected - def print_message - message = levels.map{ |level| level.message } * ' > ' - io.sync = true + messages = [] + inner = 0 + levels.reverse.each do |l| + current = l.to_f(inner) + messages << "#{l.title}: #{(current == 0 ? '......' : '%5.1f%%' % (current * 100.0))[0, 6]}" + inner = current + end + message = messages.reverse * ' > ' unless lines? previous_length = @previous_length || 0 @previous_length = message.length message = message.ljust(previous_length, ' ') + "\r" end - if highlight? - message.gsub!(/\d+\.\d+/){ |s| s == '100.0' ? s : "\e[1m#{s}\e[0m" } - end + message.gsub!(/\d+\.\d+/){ |s| s == '100.0' ? s : "\e[1m#{s}\e[0m" } if highlight? - unless lines? - io.print message - else - io.puts message - end + lines? ? io.puts(message) : io.print(message) end - - def levels - @levels ||= [] - end end - extend ClassMethods end require 'progress/with_progress' require 'progress/enumerable'