2 # Ruby/ProgressBar - a text progress bar library
4 # Copyright (C) 2001-2005 Satoru Takabayashi <satoru@namazu.org>
6 # This is free software with ABSOLUTELY NO WARRANTY.
8 # You can redistribute it and/or modify it under the terms
15 def initialize (title
, total
, out
= STDERR)
24 @start_time = Time
.now
25 @previous_time = @start_time
27 @format = "%-#{@title_width}s %3d%% %s %s"
28 @format_arguments = [:title, :percentage, :bar, :stat]
35 attr_accessor
:start_time
39 bar_width
= do_percentage
* @terminal_width / 100
41 @bar_mark * bar_width
,
42 " " * (@terminal_width - bar_width
))
50 if @finished_p then elapsed
else eta
end
53 def fmt_stat_for_file_transfer
55 sprintf("%s %s %s", bytes
, transfer_rate
, elapsed
)
57 sprintf("%s %s %s", bytes
, transfer_rate
, eta
)
62 @title[0,(@title_width - 1)] +
":"
65 def convert_bytes (bytes
)
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)
73 sprintf("%5.1fGB", bytes
.to_f
/ 1024 / 1024 / 1024)
78 bytes_per_second
= @current.to_f
/ (Time
.now
- @start_time)
79 sprintf("%s/s", convert_bytes(bytes_per_second
))
83 convert_bytes(@current)
91 sprintf("%02d:%02d:%02d", hour
, min
, sec
);
94 # ETA stands for Estimated Time of Arrival.
99 elapsed
= Time
.now
- @start_time
100 eta
= elapsed
* @total / @current - elapsed
;
101 sprintf("ETA: %s", format_time(eta
))
106 elapsed
= Time
.now
- @start_time
107 sprintf("Time: %s", format_time(elapsed
))
111 if @finished_p then "\n" else "\r" end
118 @current * 100 / @total
123 # FIXME: I don't know how portable it is.
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
141 arguments
= @format_arguments.map
{|method
|
142 method
= sprintf("fmt_%s", method
)
145 line
= sprintf(@format, *arguments
)
148 if line
.length
== width
- 1
149 @out.print(line + eol
)
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
158 @previous_time = Time
.now
166 cur_percentage
= (@current * 100 / @total).to_i
167 prev_percentage
= (@previous * 100 / @total).to_i
170 # Use "!=" instead of ">" to support negative changes
171 if cur_percentage !
= prev_percentage
||
172 Time
.now
- @previous_time >= 1 || @finished_p
180 @out.print(" " * (get_width
- 1))
194 def file_transfer_mode
195 @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
202 def format_arguments
= (arguments
)
203 @format_arguments = arguments
213 @current = @total if @current > @total
219 if count
< 0 || count
> @total
220 raise "invalid count: #{count} (total: #{@total})"
228 "#<ProgressBar:#{@current}/#{@total}>"
232 class ReversedProgressBar
< ProgressBar