Module: ProgressDownload

Defined in:
lib/progress_download.rb,
lib/progress_download/bar.rb,
lib/progress_download/spinners.rb

Constant Summary collapse

VERSIONS =
{ :major => 0, :minor => 1, :tiny => 0 }.freeze
MiB =
1.049e+6
SPINNERS =
spinner_hash
@@custom_spinners =
Hash.new

Class Method Summary collapse

Class Method Details

.add_spinner(name, states) ⇒ Object



27
28
29
30
# 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) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 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_hashObject



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 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) ⇒ Object



6
7
8
# File 'lib/progress_download.rb', line 6

def self.version *args
  VERSIONS.flatten.select.with_index { |_, i| i.odd? }.join '.'
end