Last active
November 5, 2017 23:39
-
-
Save Demonstrandum/e969488092bde75d8e8e0da0103c810a to your computer and use it in GitHub Desktop.
Different style progress bars in Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'net/http' | |
require 'uri' | |
uri = URI.parse 'http://www.mirrorservice.org/sites/ftp.archlinux.org/iso/2017.11.01/archlinux-2017.11.01-x86_64.iso' | |
uri = URI.parse 'http://ipv4.download.thinkbroadband.com/10MB.zip' | |
download = File.basename uri.path | |
#spin_states = %w{ - \\ | / Done! } # Traditional line spinner | |
#spin_states = %w{ /^v^\\ \\^v^/ \\ovo/ } # Happy bats | |
#spin_states = %w{ ⠁ ⠂ ⠄ ⡀ ⢀ ⠠ ⠐ ⠈ ✓ } # Rectangle trace | |
#spin_states = %w{ ← ↖ ↑ ↗ → ↘ ↓ ↙ ✓ } # Arrows | |
spin_states = %w{ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▇ ▆ ▅ ▄ ▃ ▁ ✓ } # Grow shrink | |
#spin_states = %w{ ▉ ▊ ▋ ▌ ▍ ▎ ▏ ▎ ▍ ▌ ▋ ▊ ▉ ✓ } # Thin and fat | |
#spin_states = %w{ ┤ ┘ ┴ └ ├ ┌ ┬ ┐ ✓ } # Folding lines | |
#spin_states = %w{ ⣾ ⣽ ⣻ ⢿ ⡿ ⣟ ⣯ ⣷ ⣿ } # Braille arranger | |
#spin_states = %w{ ⠖ ⠲ ⠴ ⠦ ⠶ } # Braille spinner | |
update_every = 0.125 | |
spin_speed = 1 # 0 < speed <= 1 (1 is once every update) | |
MiB = 1.049e+6 | |
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 element in bar_offset | |
start = Time.now.to_f | |
open download, 'w' do |io| | |
show_progress = Proc.new do |frequency, preset=nil| | |
Thread.new do | |
while true | |
thread = Thread.current | |
if preset.nil? | |
done = thread[:done] | |
else | |
done = preset | |
end | |
bar_length = %x{ tput cols }.to_i - bar_offset | |
percentage = 100 * done / size | |
bar_ratio = bar_length * done / size | |
print "\r" | |
stats = "'#{download}' — " + ('%.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 += spin_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 update_every | |
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 | |
# Make sure all threads are completly dead | |
puts "\n\n" | |
puts "\n#{download}, downloaded!" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment