module ProgressDownload

Constants

MiB
SPINNERS
VERSIONS

Public Class Methods

add_spinner(name, states) click to toggle source
# File lib/progress_download/spinners.rb, line 27
def self.add_spinner name, states
  @@custom_spinners[name.to_sym] = states
  SPINNERS.replace spinner_hash
end
download(address, location: Dir.getwd, spinner: :dots, speed: 1, refresh: 0.125) click to toggle source
# File lib/progress_download/bar.rb, line 7
def self.download address, location: Dir.getwd, spinner: :dots, speed: 1, refresh: 0.125
  uri = URI.parse address
  download_location = "#{File.expand_path location}/#{File.basename uri.path}"
  spin_states = SPINNERS[spinner.to_sym]

  Net::HTTP.start uri.host, uri.port do |http|
    request = Net::HTTP::Get.new uri.request_uri

    http.request request do |response|
      size = response['Content-Length'].to_i

      done = state = 0
      bar_offset = 10 + spin_states.max_by(&:size).size
        # There are 10 extra chars next to the progress bar,
        #   adding on the widest spinner element in bar_offset

      start = Time.now.to_f
      open download_location, 'w' do |io|
        show_progress = Proc.new do |frequency, preset=nil|
          Thread.new do
            loop do
              thread = Thread.current

              done = if preset.nil?
                thread[:done]
              else
                preset
              end

              bar_length = %x{ tput cols }.to_i - bar_offset
              percentage = 100 * done / size
              bar_ratio  = bar_length * done / size

              print "\r"
              stats = "‘#{File.basename uri.path}’ — " + ('%.2f' % (done / MiB)).rjust((size / MiB).round(2).to_s.size, ' ') +
              ' / ' + (size / MiB).round(2).to_s + ' MiB' +
              ' at ' + ('%.2f MiB/s' % ((done / MiB) / (Time.now.to_f - start)).round(2)) +
              ' in %.2fs' % (Time.now.to_f - start)

              short_stats = stats.slice 0..(bar_length + bar_offset - 4)
              print short_stats, stats.size == short_stats.size ? '' : '...', "\n"
              # 3 dots and -1 for index correction
              print "\r#{percentage == 100 ? spin_states[-1] : spin_states[state.to_i]} [ #{'█' * bar_ratio}#{'▒' * (bar_length - bar_ratio)} ] #{percentage.to_s.rjust 3, ' '}%"
              print "\033[F"

              state += speed
              state = 0 if state >= spin_states.size - 1
              Thread.stop if percentage == 100
              sleep frequency
            end
          end
        end

        done = 0
        thread = nil
        first_response = true
        response.read_body do |chunk|
          io.write chunk

          if first_response
            thread = show_progress.call refresh
          end

          done += chunk.size
          thread[:done] = done unless thread.nil?
          first_response = false
        end

        thread = show_progress.call 0, preset=size
        # Make sure the progress bar finishes
      end
    end
  end
  sleep 0.3
  print "\n\n"
end
spinner_hash() click to toggle source
# File lib/progress_download/spinners.rb, line 4
def self.spinner_hash
  types = %w{ classic bats tracer arrows pump breathe fold sorter dots }.map(&:to_sym)
  types.push *@@custom_spinners.keys

  flat = Array.new
  flat << %w{ - \\ | / Done! }  # Traditional line spinner
  flat << %w{ /^v^\\ \\^v^/ \\ovo/ } # Happy bats, old DOS spinner.
  flat << %w{ ⠁ ⠂ ⠄ ⡀ ⢀ ⠠ ⠐ ⠈ · } # Rectangle trace
  flat << %w{ ← ↖ ↑ ↗ → ↘ ↓ ↙ ↔ } # Arrows
  flat << %w{ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▇ ▆ ▅ ▄ ▃ ▁ █ } # Grow shrink
  flat << %w{ ▉ ▊ ▋ ▌ ▍ ▎ ▏ ▎ ▍ ▌ ▋ ▊ ▉ ▉ } # Thin and fat
  flat << %w{ ┤ ┘ ┴ └ ├ ┌ ┬ ┐ ✓ } # Folding lines
  flat << %w{ ⣾ ⣽ ⣻ ⢿ ⡿ ⣟ ⣯ ⣷ ⣿ } # Braille arranger
  flat << %w{ ⠖ ⠲ ⠴ ⠦ ⠶ } # Braille spinner
  flat.push *@@custom_spinners.values

  spinners = Hash.new
  types.each.with_index { |type, i| spinners[type] = flat[i] }
  spinners
end
version(*args) click to toggle source
# File lib/progress_download.rb, line 6
def self.version *args
  VERSIONS.flatten.select.with_index { |_, i| i.odd? }.join '.'
end