<commit_before>require 'ruby-progressbar/length_calculator'

class ProgressBar
  class Base
    DEFAULT_OUTPUT_STREAM = $stdout
    DEFAULT_FORMAT_STRING         = '%t: |%B|'
    DEFAULT_NON_TTY_FORMAT_STRING = '%t: |%b|'
    DEFAULT_TITLE                 = 'Progress'

    def initialize(options = {})
      self.output       = options[:output] || DEFAULT_OUTPUT_STREAM
      autostart         = options.fetch(:autostart, true)

      @format_string     = nil
      self.format_string = options[:format] || DEFAULT_FORMAT_STRING
      @title             = options[:title]  || DEFAULT_TITLE

      @timer            = Components::Timer.new(options)
      @progressable     = Components::Progressable.new(options)
      @length_calc      = LengthCalculator.new(options)
      @bar              = Components::Bar.new(options.merge(:progress => @progressable))
      @rate             = Components::Rate.new(options.merge(:timer => @timer, :progress => @progressable))
      @estimated_time   = Components::EstimatedTimer.new(options.merge(:timer => @timer, :progress => @progressable))
      @elapsed_time     = Components::ElapsedTimer.new({:timer => @timer})
      @throttle         = Components::Throttle.new(options.merge(:timer => @timer))

      start :at => options[:starting_at] if autostart
    end

    ###
    # Starting The Bar
    #
    def start(options = {})
      clear

      with_update do
        with_progressables(:start, options)
        with_timers(:start)
      end
    end

    ###
    # Updating The Bar's Progress
    #
    def decrement
      update_progress(:decrement)
    end

    def increment
      update_progress(:increment)
    end

    def progress=(new_progress)
      update_progress(:progress=, new_progress)
    end

    def total=(new_total)
      update_progress(:total=, new_total)
    end

    ###
    # Stopping The Bar
    #
    def finish
      with_update { with_progressables(:finish); with_timers(:stop) } unless finished?
    end

    def pause
      with_update { with_timers(:pause) } unless paused?
    end

    def stop
      with_update { with_timers(:stop) } unless stopped?
    end

    def resume
      with_update { with_timers(:resume) } if stopped?
    end

    def reset
      with_update do
        @progressable.reset
        with_timers(:reset)
      end
    end

    def stopped?
      @timer.stopped? || finished?
    end

    alias :paused? :stopped?

    def finished?
      @progressable.finished?
    end

    def started?
      @timer.started? && @progressable.started?
    end

    ###
    # UI Updates
    #
    def progress_mark=(mark)
      with_update { @bar.progress_mark = mark }
    end

    def remainder_mark=(mark)
      with_update { @bar.remainder_mark = mark }
    end

    def title=(title)
      if output.tty?
        with_update { @title = title }
      end
    end

    def format(new_format_string = DEFAULT_FORMAT_STRING)
      self.format_string = new_format_string
      @format.process(self)
    end

    def progress
      @progressable.progress
    end

    def total
      @progressable.total
    end

    ###
    # Output
    #
    def clear
      self.last_update_length = 0

      if output.tty?
        output.print clear_string
        output.print "\r"
      else
        output.print "\n"
      end
    end

    def refresh
      update
    end

    def log(string)
      clear
      output.puts string

      update(:force => true) unless stopped?
    end

    def to_s(format_string = nil)
      format_string ||= @format_string

      format(format_string)
    end

    def inspect
      "#<ProgressBar:#{progress}/#{total || 'unknown'}>"
    end

  protected

    attr_accessor :output,
                  :last_update_length

  private

    def clear_string
      "#{" " * @length_calc.length}"
    end

    def last_update_length
      @last_update_length ||= 0
    end

    def with_progressables(*args)
      @progressable.send(*args)
    end

    def with_timers(*args)
      @timer.send(*args)
    end

    def update_progress(*args)
      with_update do
        with_progressables(*args)
        with_timers(:stop) if finished?
      end
    end

    def with_update
      yield
      update
    end

    def update(options = {})
      if @length_calc.length_changed?
        clear
        @length_calc.reset_length
      end

      @throttle.choke( stopped? || options[:force] ) do
        if output.tty?
          formatted_string = self.to_s
          output_string    = formatted_string
        else
          formatted_string = self.to_s(DEFAULT_NON_TTY_FORMAT_STRING)
          formatted_string = formatted_string[0...-1] unless finished?

          output_string    = formatted_string[last_update_length..-1]
        end<commit_msg>Refactor: Remove 'with_timers' and 'with_progressables'<commit_after>require 'ruby-progressbar/length_calculator'

class ProgressBar
  class Base
    DEFAULT_OUTPUT_STREAM = $stdout
    DEFAULT_FORMAT_STRING         = '%t: |%B|'
    DEFAULT_NON_TTY_FORMAT_STRING = '%t: |%b|'
    DEFAULT_TITLE                 = 'Progress'

    def initialize(options = {})
      self.output       = options[:output] || DEFAULT_OUTPUT_STREAM
      autostart         = options.fetch(:autostart, true)

      @format_string     = nil
      self.format_string = options[:format] || DEFAULT_FORMAT_STRING
      @title             = options[:title]  || DEFAULT_TITLE

      @timer            = Components::Timer.new(options)
      @progressable     = Components::Progressable.new(options)
      @length_calc      = LengthCalculator.new(options)
      @bar              = Components::Bar.new(options.merge(:progress => @progressable))
      @rate             = Components::Rate.new(options.merge(:timer => @timer, :progress => @progressable))
      @estimated_time   = Components::EstimatedTimer.new(options.merge(:timer => @timer, :progress => @progressable))
      @elapsed_time     = Components::ElapsedTimer.new({:timer => @timer})
      @throttle         = Components::Throttle.new(options.merge(:timer => @timer))

      start :at => options[:starting_at] if autostart
    end

    ###
    # Starting The Bar
    #
    def start(options = {})
      clear

      with_update do
        @progressable.start(options)
        @timer.start
      end
    end

    ###
    # Updating The Bar's Progress
    #
    def decrement
      update_progress(:decrement)
    end

    def increment
      update_progress(:increment)
    end

    def progress=(new_progress)
      update_progress(:progress=, new_progress)
    end

    def total=(new_total)
      update_progress(:total=, new_total)
    end

    ###
    # Stopping The Bar
    #
    def finish
      with_update { @progressable.finish; @timer.stop } unless finished?
    end

    def pause
      with_update { @timer.pause } unless paused?
    end

    def stop
      with_update { @timer.stop } unless stopped?
    end

    def resume
      with_update { @timer.resume } if stopped?
    end

    def reset
      with_update do
        @progressable.reset
        @timer.reset
      end
    end

    def stopped?
      @timer.stopped? || finished?
    end

    alias :paused? :stopped?

    def finished?
      @progressable.finished?
    end

    def started?
      @timer.started? && @progressable.started?
    end

    ###
    # UI Updates
    #
    def progress_mark=(mark)
      with_update { @bar.progress_mark = mark }
    end

    def remainder_mark=(mark)
      with_update { @bar.remainder_mark = mark }
    end

    def title=(title)
      if output.tty?
        with_update { @title = title }
      end
    end

    def format(new_format_string = DEFAULT_FORMAT_STRING)
      self.format_string = new_format_string
      @format.process(self)
    end

    def progress
      @progressable.progress
    end

    def total
      @progressable.total
    end

    ###
    # Output
    #
    def clear
      self.last_update_length = 0

      if output.tty?
        output.print clear_string
        output.print "\r"
      else
        output.print "\n"
      end
    end

    def refresh
      update
    end

    def log(string)
      clear
      output.puts string

      update(:force => true) unless stopped?
    end

    def to_s(format_string = nil)
      format_string ||= @format_string

      format(format_string)
    end

    def inspect
      "#<ProgressBar:#{progress}/#{total || 'unknown'}>"
    end

  protected

    attr_accessor :output,
                  :last_update_length

  private

    def clear_string
      "#{" " * @length_calc.length}"
    end

    def last_update_length
      @last_update_length ||= 0
    end

    def update_progress(*args)
      with_update do
        @progressable.send(*args)
        @timer.stop if finished?
      end
    end

    def with_update
      yield
      update
    end

    def update(options = {})
      if @length_calc.length_changed?
        clear
        @length_calc.reset_length
      end

      @throttle.choke( stopped? || options[:force] ) do
        if output.tty?
          formatted_string = self.to_s
          output_string    = formatted_string
        else
          formatted_string = self.to_s(DEFAULT_NON_TTY_FORMAT_STRING)
          formatted_string = formatted_string[0...-1] unless finished?

          output_string    = formatted_string[last_update_length..-1]
        end
{'fraction_non_alphanumeric': 0.09547738693467336, 'fraction_numerical': 0.0010691756655618518, 'mean_word_length': 2.1580013504388926, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1754985', 'n_tokens_mistral': 2874, 'n_tokens_neox': 2767, 'n_words': 592}