]> gitweb.michael.orlitzky.com - dead/whatever-dl.git/blob - lib/vendor/ruby-progressbar/progressbar.rb
Update the makefile to build/install a gem.
[dead/whatever-dl.git] / lib / vendor / ruby-progressbar / progressbar.rb
1 #
2 # Ruby/ProgressBar - a text progress bar library
3 #
4 # Copyright (C) 2001-2005 Satoru Takabayashi <satoru@namazu.org>
5 # All rights reserved.
6 # This is free software with ABSOLUTELY NO WARRANTY.
7 #
8 # You can redistribute it and/or modify it under the terms
9 # of Ruby's license.
10 #
11
12 class ProgressBar
13 VERSION = "0.9"
14
15 def initialize (title, total, out = STDERR)
16 @title = title
17 @total = total
18 @out = out
19 @terminal_width = 80
20 @bar_mark = "o"
21 @current = 0
22 @previous = 0
23 @finished_p = false
24 @start_time = Time.now
25 @previous_time = @start_time
26 @title_width = 14
27 @format = "%-#{@title_width}s %3d%% %s %s"
28 @format_arguments = [:title, :percentage, :bar, :stat]
29 clear
30 show
31 end
32 attr_reader :title
33 attr_reader :current
34 attr_reader :total
35 attr_accessor :start_time
36
37 private
38 def fmt_bar
39 bar_width = do_percentage * @terminal_width / 100
40 sprintf("|%s%s|",
41 @bar_mark * bar_width,
42 " " * (@terminal_width - bar_width))
43 end
44
45 def fmt_percentage
46 do_percentage
47 end
48
49 def fmt_stat
50 if @finished_p then elapsed else eta end
51 end
52
53 def fmt_stat_for_file_transfer
54 if @finished_p then
55 sprintf("%s %s %s", bytes, transfer_rate, elapsed)
56 else
57 sprintf("%s %s %s", bytes, transfer_rate, eta)
58 end
59 end
60
61 def fmt_title
62 @title[0,(@title_width - 1)] + ":"
63 end
64
65 def convert_bytes (bytes)
66 if bytes < 1024
67 sprintf("%6dB", bytes)
68 elsif bytes < 1024 * 1000 # 1000kb
69 sprintf("%5.1fKB", bytes.to_f / 1024)
70 elsif bytes < 1024 * 1024 * 1000 # 1000mb
71 sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
72 else
73 sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
74 end
75 end
76
77 def transfer_rate
78 bytes_per_second = @current.to_f / (Time.now - @start_time)
79 sprintf("%s/s", convert_bytes(bytes_per_second))
80 end
81
82 def bytes
83 convert_bytes(@current)
84 end
85
86 def format_time (t)
87 t = t.to_i
88 sec = t % 60
89 min = (t / 60) % 60
90 hour = t / 3600
91 sprintf("%02d:%02d:%02d", hour, min, sec);
92 end
93
94 # ETA stands for Estimated Time of Arrival.
95 def eta
96 if @current == 0
97 "ETA: --:--:--"
98 else
99 elapsed = Time.now - @start_time
100 eta = elapsed * @total / @current - elapsed;
101 sprintf("ETA: %s", format_time(eta))
102 end
103 end
104
105 def elapsed
106 elapsed = Time.now - @start_time
107 sprintf("Time: %s", format_time(elapsed))
108 end
109
110 def eol
111 if @finished_p then "\n" else "\r" end
112 end
113
114 def do_percentage
115 if @total.zero?
116 100
117 else
118 @current * 100 / @total
119 end
120 end
121
122 def get_width
123 # FIXME: I don't know how portable it is.
124 default_width = 80
125 begin
126 tiocgwinsz = 0x5413
127 data = [0, 0, 0, 0].pack("SSSS")
128 if @out.ioctl(tiocgwinsz, data) >= 0 then
129 # rows,cols,xpixels,ypixels
130 cols = data.unpack("SSSS")[1]
131 if cols >= 0 then cols else default_width end
132 else
133 default_width
134 end
135 rescue Exception
136 default_width
137 end
138 end
139
140 def show
141 arguments = @format_arguments.map {|method|
142 method = sprintf("fmt_%s", method)
143 send(method)
144 }
145 line = sprintf(@format, *arguments)
146
147 width = get_width
148 if line.length == width - 1
149 @out.print(line + eol)
150 @out.flush
151 elsif line.length >= width
152 @terminal_width = [@terminal_width - (line.length - width + 1), 0].max
153 if @terminal_width == 0 then @out.print(line + eol) else show end
154 else # line.length < width - 1
155 @terminal_width += width - line.length + 1
156 show
157 end
158 @previous_time = Time.now
159 end
160
161 def show_if_needed
162 if @total.zero?
163 cur_percentage = 100
164 prev_percentage = 0
165 else
166 cur_percentage = (@current * 100 / @total).to_i
167 prev_percentage = (@previous * 100 / @total).to_i
168 end
169
170 # Use "!=" instead of ">" to support negative changes
171 if cur_percentage != prev_percentage ||
172 Time.now - @previous_time >= 1 || @finished_p
173 show
174 end
175 end
176
177 public
178 def clear
179 @out.print "\r"
180 @out.print(" " * (get_width - 1))
181 @out.print "\r"
182 end
183
184 def finish
185 @current = @total
186 @finished_p = true
187 show
188 end
189
190 def finished?
191 @finished_p
192 end
193
194 def file_transfer_mode
195 @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
196 end
197
198 def format= (format)
199 @format = format
200 end
201
202 def format_arguments= (arguments)
203 @format_arguments = arguments
204 end
205
206 def halt
207 @finished_p = true
208 show
209 end
210
211 def inc (step = 1)
212 @current += step
213 @current = @total if @current > @total
214 show_if_needed
215 @previous = @current
216 end
217
218 def set (count)
219 if count < 0 || count > @total
220 raise "invalid count: #{count} (total: #{@total})"
221 end
222 @current = count
223 show_if_needed
224 @previous = @current
225 end
226
227 def inspect
228 "#<ProgressBar:#{@current}/#{@total}>"
229 end
230 end
231
232 class ReversedProgressBar < ProgressBar
233 def do_percentage
234 100 - super
235 end
236 end
237