~ubuntu-branches/ubuntu/precise/ruby-progressbar/precise

« back to all changes in this revision

Viewing changes to progressbar.rb

  • Committer: Bazaar Package Importer
  • Author(s): Antonio Terceiro
  • Date: 2011-08-26 16:03:30 UTC
  • Revision ID: james.westby@ubuntu.com-20110826160330-lkjbp6i3avq0btao
Tags: upstream-0.9
ImportĀ upstreamĀ versionĀ 0.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 = data.unpack("SSSS")
 
130
        if cols >= 0 then cols else default_width end
 
131
      else
 
132
        default_width
 
133
      end
 
134
    rescue Exception
 
135
      default_width
 
136
    end
 
137
  end
 
138
 
 
139
  def show
 
140
    arguments = @format_arguments.map {|method| 
 
141
      method = sprintf("fmt_%s", method)
 
142
      send(method)
 
143
    }
 
144
    line = sprintf(@format, *arguments)
 
145
 
 
146
    width = get_width
 
147
    if line.length == width - 1 
 
148
      @out.print(line + eol)
 
149
      @out.flush
 
150
    elsif line.length >= width
 
151
      @terminal_width = [@terminal_width - (line.length - width + 1), 0].max
 
152
      if @terminal_width == 0 then @out.print(line + eol) else show end
 
153
    else # line.length < width - 1
 
154
      @terminal_width += width - line.length + 1
 
155
      show
 
156
    end
 
157
    @previous_time = Time.now
 
158
  end
 
159
 
 
160
  def show_if_needed
 
161
    if @total.zero?
 
162
      cur_percentage = 100
 
163
      prev_percentage = 0
 
164
    else
 
165
      cur_percentage  = (@current  * 100 / @total).to_i
 
166
      prev_percentage = (@previous * 100 / @total).to_i
 
167
    end
 
168
 
 
169
    # Use "!=" instead of ">" to support negative changes
 
170
    if cur_percentage != prev_percentage || 
 
171
        Time.now - @previous_time >= 1 || @finished_p
 
172
      show
 
173
    end
 
174
  end
 
175
 
 
176
  public
 
177
  def clear
 
178
    @out.print "\r"
 
179
    @out.print(" " * (get_width - 1))
 
180
    @out.print "\r"
 
181
  end
 
182
 
 
183
  def finish
 
184
    @current = @total
 
185
    @finished_p = true
 
186
    show
 
187
  end
 
188
 
 
189
  def finished?
 
190
    @finished_p
 
191
  end
 
192
 
 
193
  def file_transfer_mode
 
194
    @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
 
195
  end
 
196
 
 
197
  def format= (format)
 
198
    @format = format
 
199
  end
 
200
 
 
201
  def format_arguments= (arguments)
 
202
    @format_arguments = arguments
 
203
  end
 
204
 
 
205
  def halt
 
206
    @finished_p = true
 
207
    show
 
208
  end
 
209
 
 
210
  def inc (step = 1)
 
211
    @current += step
 
212
    @current = @total if @current > @total
 
213
    show_if_needed
 
214
    @previous = @current
 
215
  end
 
216
 
 
217
  def set (count)
 
218
    if count < 0 || count > @total
 
219
      raise "invalid count: #{count} (total: #{@total})"
 
220
    end
 
221
    @current = count
 
222
    show_if_needed
 
223
    @previous = @current
 
224
  end
 
225
 
 
226
  def inspect
 
227
    "#<ProgressBar:#{@current}/#{@total}>"
 
228
  end
 
229
end
 
230
 
 
231
class ReversedProgressBar < ProgressBar
 
232
  def do_percentage
 
233
    100 - super
 
234
  end
 
235
end
 
236