ruby-progressbar 0.11.0 → 1.0.0rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. data/.gitignore +5 -0
  2. data/.rspec +1 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +42 -0
  7. data/Guardfile +6 -0
  8. data/LICENSE +22 -0
  9. data/README.md +229 -63
  10. data/lib/progress_bar/base.rb +166 -0
  11. data/lib/progress_bar/components.rb +5 -0
  12. data/lib/progress_bar/components/bar.rb +44 -0
  13. data/lib/progress_bar/components/elapsed_timer.rb +20 -0
  14. data/lib/progress_bar/components/estimated_timer.rb +88 -0
  15. data/lib/progress_bar/components/progressable.rb +92 -0
  16. data/lib/progress_bar/components/timer.rb +64 -0
  17. data/lib/progress_bar/depreciable.rb +121 -0
  18. data/lib/progress_bar/format.rb +2 -0
  19. data/lib/progress_bar/format/base.rb +30 -0
  20. data/lib/progress_bar/format/molecule.rb +37 -0
  21. data/lib/progress_bar/formatter.rb +109 -0
  22. data/lib/progress_bar/length_calculator.rb +53 -0
  23. data/lib/progress_bar/running_average_calculator.rb +7 -0
  24. data/lib/progress_bar/time.rb +22 -0
  25. data/lib/progress_bar/version.rb +3 -0
  26. data/lib/progressbar.rb +8 -295
  27. data/lib/ruby-progressbar.rb +19 -0
  28. data/ruby-progressbar.gemspec +44 -0
  29. data/spec/progress_bar/base_spec.rb +434 -0
  30. data/spec/progress_bar/components/bar_spec.rb +198 -0
  31. data/spec/progress_bar/components/elapsed_timer_spec.rb +79 -0
  32. data/spec/progress_bar/components/estimated_timer_spec.rb +173 -0
  33. data/spec/progress_bar/components/progressable_spec.rb +30 -0
  34. data/spec/progress_bar/format/molecule_spec.rb +22 -0
  35. data/spec/progress_bar/running_average_calculator_spec.rb +11 -0
  36. data/spec/progress_bar/time_spec.rb +51 -0
  37. data/spec/spec_helper.rb +13 -0
  38. data/spec/support/focused.rb +7 -0
  39. data/spec/support/timecop.rb +19 -0
  40. metadata +170 -19
  41. data/GPL_LICENSE +0 -340
  42. data/RUBY_LICENSE +0 -53
  43. data/test.rb +0 -247
@@ -0,0 +1,37 @@
1
+ class ProgressBar
2
+ module Format
3
+ class Molecule
4
+ MOLECULES = {
5
+ :t => [:left_justified_title, :title],
6
+ :T => [:right_justified_title, :title],
7
+ :c => [:current_progress, :progress],
8
+ :C => [:total_capacity, :total],
9
+ :p => [:percentage_complete_as_integer, :percentage],
10
+ :P => [:percentage_complete_as_float, :percentage_with_precision],
11
+ :a => [:elapsed_time, :elapsed_time],
12
+ :e => [:estimated_time_with_unknown, :estimated_time_with_unknown_oob],
13
+ :E => [:estimated_time_with_greater_than, :estimated_time_with_friendly_oob],
14
+ :f => [:force_estimated_time, :estimated_time_with_no_oob],
15
+ :B => [:complete_bar, :complete_bar],
16
+ :b => [:bar, :bar],
17
+ :w => [:bar_with_percentage, :bar_with_percentage],
18
+ :i => [:incomplete_space, :incomplete_space]
19
+ }
20
+
21
+ BAR_MOLECULES = %w{w B b i}
22
+
23
+ attr_reader :key
24
+ attr_reader :method_name
25
+ attr_reader :method_arguments
26
+
27
+ def initialize(letter)
28
+ @key = letter
29
+ @description, @method_name, @method_arguments = MOLECULES.fetch(@key.to_sym)
30
+ end
31
+
32
+ def bar_molecule?
33
+ BAR_MOLECULES.include? @key
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,109 @@
1
+ class ProgressBar
2
+ module Formatter
3
+ DEFAULT_FORMAT_STRING = '%t: |%B|'
4
+ DEFAULT_TITLE = 'Progress'
5
+
6
+ def initialize(options)
7
+ @format_string = options[:format] || DEFAULT_FORMAT_STRING
8
+ @title = options[:title] || DEFAULT_TITLE
9
+
10
+ super(options)
11
+ end
12
+
13
+ def format(format_string = DEFAULT_FORMAT_STRING)
14
+ @format_string = format_string
15
+ @format = ProgressBar::Format::Base.new(format_string)
16
+
17
+ process
18
+ end
19
+
20
+ def title=(title)
21
+ @title = title
22
+ end
23
+
24
+ def progress
25
+ @bar.progress
26
+ end
27
+
28
+ def total
29
+ @bar.total
30
+ end
31
+
32
+ private
33
+ def process
34
+ @format_string.dup.tap do |processed_string|
35
+ @format.non_bar_molecules.each do |molecule|
36
+ processed_string.gsub!("%#{molecule.key}", self.send(molecule.method_name).to_s)
37
+ end
38
+
39
+ remaining_molecule_match_data = processed_string.scan(/%[a-zA-Z]/) || []
40
+ remaining_molecules = remaining_molecule_match_data.size
41
+ placeholder_length = remaining_molecules * 2
42
+
43
+ processed_string.gsub! '%%', '%'
44
+
45
+ leftover_bar_length = length - processed_string.length + placeholder_length
46
+
47
+ @format.bar_molecules.each do |molecule|
48
+ processed_string.gsub!("%#{molecule.key}", self.send(molecule.method_name, leftover_bar_length).to_s)
49
+ end
50
+ end
51
+ end
52
+
53
+ # Format Methods
54
+ def title
55
+ @title
56
+ end
57
+
58
+ def percentage
59
+ @bar.percentage_completed
60
+ end
61
+
62
+ def percentage_with_precision
63
+ @bar.percentage_completed_with_precision
64
+ end
65
+
66
+ def elapsed_time
67
+ @elapsed_time
68
+ end
69
+
70
+ def estimated_time_with_no_oob
71
+ @estimated_time.out_of_bounds_time_format = nil
72
+ estimated_time
73
+ end
74
+
75
+ def estimated_time_with_unknown_oob
76
+ @estimated_time.out_of_bounds_time_format = :unknown
77
+ estimated_time
78
+ end
79
+
80
+ def estimated_time_with_friendly_oob
81
+ @estimated_time.out_of_bounds_time_format = :friendly
82
+ estimated_time
83
+ end
84
+
85
+ def bar(length)
86
+ @bar.length = length
87
+ @bar.standard_complete_string
88
+ end
89
+
90
+ def complete_bar(length)
91
+ @bar.length = length
92
+ @bar.to_s
93
+ end
94
+
95
+ def incomplete_space(length)
96
+ @bar.length = length
97
+ @bar.empty_string
98
+ end
99
+
100
+ def bar_with_percentage(length)
101
+ @bar.length = length
102
+ @bar.integrated_percentage_complete_string
103
+ end
104
+
105
+ def estimated_time
106
+ finished? ? @elapsed_time : @estimated_time
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,53 @@
1
+ class ProgressBar
2
+ module LengthCalculator
3
+ def initialize(options)
4
+ @length_override = ENV['RUBY_PROGRESS_BAR_LENGTH'] || options[:length]
5
+
6
+ super()
7
+ end
8
+
9
+ private
10
+ def length
11
+ @current_length || reset_length
12
+ end
13
+
14
+ def length_changed?
15
+ @current_length != calculate_length
16
+ end
17
+
18
+ def calculate_length
19
+ @length_override || terminal_width || 80
20
+ end
21
+
22
+ def reset_length
23
+ @current_length = calculate_length
24
+ end
25
+
26
+ # This code was copied and modified from Rake, available under MIT-LICENSE
27
+ # Copyright (c) 2003, 2004 Jim Weirich
28
+ def terminal_width
29
+ return 80 unless unix?
30
+
31
+ result = dynamic_width
32
+ (result < 20) ? 80 : result
33
+ rescue
34
+ 80
35
+ end
36
+
37
+ def dynamic_width
38
+ dynamic_width_stty.nonzero? || dynamic_width_tput
39
+ end
40
+
41
+ def dynamic_width_stty
42
+ %x{stty size 2>/dev/null}.split[1].to_i
43
+ end
44
+
45
+ def dynamic_width_tput
46
+ %x{tput cols 2>/dev/null}.to_i
47
+ end
48
+
49
+ def unix?
50
+ RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,7 @@
1
+ class ProgressBar
2
+ class RunningAverageCalculator
3
+ def self.calculate(current_average, new_value_to_average, smoothing_factor)
4
+ new_value_to_average * (1.0 - smoothing_factor) + current_average * smoothing_factor
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ class ProgressBar
2
+ class Time
3
+ def self.now(time = ::Time)
4
+ @@time = time
5
+
6
+ @@time.send unmocked_time_method
7
+ end
8
+
9
+ private
10
+ def self.unmocked_time_method
11
+ time_mocking_library_mapping.values.find { |method| @@time.respond_to? method }
12
+ end
13
+
14
+ def self.time_mocking_library_mapping
15
+ {
16
+ :timecop => :now_without_mock_time,
17
+ :delorean => :now_without_delorean,
18
+ :actual => :now
19
+ }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ class ProgressBar
2
+ VERSION = '1.0.0rc1'
3
+ end
@@ -1,297 +1,10 @@
1
+ require 'progress_bar/depreciable'
2
+
3
+ # This file is provided for standardization purposes only.
1
4
  #
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.
5
+ # This gem didn't follow standard Ruby naming conventions and therefore, both `ruby-progressbar.rb` and `progressbar.rb` are needed.
6
+ # `ruby-progressbar.rb` because the gem name should match the filename under `lib` and `progressbar.rb` because this gem was copied
7
+ # directly from another gem and wasn't properly modified. There are other applications which require this file.
10
8
  #
11
-
12
- class ProgressBar
13
- VERSION = "0.0.10"
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
- @format_arguments = [:title, :percentage, :bar, :stat]
27
- @smoothing = 0.9
28
- @running_average = 0
29
- clear
30
- show
31
- end
32
- attr_reader :title
33
- attr_reader :current
34
- attr_reader :total
35
- attr_accessor :start_time
36
- attr_writer :bar_mark
37
- attr_writer :title_width
38
-
39
- def title_width
40
- @title_width ||= 14
41
- end
42
-
43
- def format
44
- @format || "%-#{title_width}s %3d%% %s %s"
45
- end
46
-
47
- # Exponential smoothing helps keep jitter out of the time-remaining estimate.
48
- # The value may be anything from 0.0 to 1.0. Contrary to intuition, LOWER
49
- # values make the average smoother, and 1.0 is equivalent to no smoothing
50
- # whatsoever (the classic behavior). Default value is 0.9.
51
- attr_accessor :smoothing
52
-
53
- private
54
- def fmt_bar
55
- sprintf("|%s%s|",
56
- @bar_mark * bar_width,
57
- " " * (@terminal_width - bar_width))
58
- end
59
-
60
- def fmt_percentage
61
- do_percentage
62
- end
63
-
64
- def fmt_stat
65
- if @finished_p then elapsed else eta end
66
- end
67
-
68
- def fmt_stat_for_file_transfer
69
- if @finished_p then
70
- sprintf("%s %s %s", bytes, transfer_rate, elapsed)
71
- else
72
- sprintf("%s %s %s", bytes, transfer_rate, eta)
73
- end
74
- end
75
-
76
- def fmt_title
77
- @title[0,(title_width - 1)] + ":"
78
- end
79
-
80
- def bar_width
81
- do_percentage * @terminal_width / 100
82
- end
83
-
84
- def convert_bytes (bytes)
85
- if bytes < 1024
86
- sprintf("%6dB", bytes)
87
- elsif bytes < 1024 * 1000 # 1000kb
88
- sprintf("%5.1fKB", bytes.to_f / 1024)
89
- elsif bytes < 1024 * 1024 * 1000 # 1000mb
90
- sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
91
- else
92
- sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
93
- end
94
- end
95
-
96
- def transfer_rate
97
- bytes_per_second = @current.to_f / (time_now - @start_time)
98
- sprintf("%s/s", convert_bytes(bytes_per_second))
99
- end
100
-
101
- def bytes
102
- convert_bytes(@current)
103
- end
104
-
105
- def format_time (t)
106
- if t < 0 or t.infinite? or t.nan? # "not a number"
107
- '--:--:--'
108
- else
109
- t = t.to_i
110
- sec = t % 60
111
- min = (t / 60) % 60
112
- hour = t / 3600
113
- sprintf("%02d:%02d:%02d", hour, min, sec);
114
- end
115
- end
116
-
117
- # ETA stands for Estimated Time of Arrival.
118
- def eta
119
- elapsed = time_now - @start_time
120
- eta = elapsed * @total / @running_average - elapsed;
121
- sprintf("ETA: %s", format_time(eta))
122
- end
123
-
124
- def elapsed
125
- elapsed = time_now - @start_time
126
- sprintf("Time: %s", format_time(elapsed))
127
- end
128
-
129
- def eol
130
- if @finished_p then "\n" else "\r" end
131
- end
132
-
133
- def do_percentage
134
- if @total.zero?
135
- 100
136
- else
137
- @current * 100 / @total
138
- end
139
- end
140
-
141
- def get_width
142
- # FIXME: I don't know how portable it is.
143
- default_width = 80
144
- begin
145
- tiocgwinsz = 0x5413
146
- data = [0, 0, 0, 0].pack("SSSS")
147
- if @out.ioctl(tiocgwinsz, data) >= 0 then
148
- rows, cols, xpixels, ypixels = data.unpack("SSSS")
149
- cols > 0 ? cols : default_width
150
- else
151
- default_width
152
- end
153
- rescue Exception
154
- default_width
155
- end
156
- end
157
-
158
- def show
159
- tty? ? show_tty : show_no_tty
160
- @previous_time = time_now
161
- end
162
-
163
- # Print output to a tty device.
164
- def show_tty
165
- arguments = @format_arguments.map {|method|
166
- method = sprintf("fmt_%s", method)
167
- send(method)
168
- }
169
- line = sprintf(format, *arguments)
170
-
171
- width = get_width
172
- if line.length == width - 1
173
- @out.write(line + eol)
174
- elsif line.length >= width
175
- @terminal_width = [@terminal_width - (line.length - width + 1), 0].max
176
- if @terminal_width == 0 then @out.write(line + eol) else show end
177
- else # line.length < width - 1
178
- @terminal_width += width - line.length + 1
179
- show
180
- end
181
- end
182
-
183
- # Print output to a non-terminal device, such as a log file.
184
- # The terminal width is set to 80 columns.
185
- def show_no_tty
186
- @out.print("| " + elapsed + eol) and return if finished?
187
-
188
- # Draw title the first time
189
- if @last_bar_width.nil?
190
- @last_bar_width = 0
191
- @terminal_width = @terminal_width - fmt_title.size - elapsed.size - 4
192
- @out.print(fmt_title + " |")
193
- else
194
- bar_width_change = bar_width - @last_bar_width
195
- if bar_width_change > 0
196
- @out.print(@bar_mark * bar_width_change)
197
- @last_bar_width = bar_width
198
- end
199
- end
200
- end
201
-
202
- def show_if_needed
203
- if @total.zero?
204
- cur_percentage = 100
205
- prev_percentage = 0
206
- else
207
- cur_percentage = (@current * 100 / @total).to_i
208
- prev_percentage = (@previous * 100 / @total).to_i
209
- end
210
-
211
- # Use "!=" instead of ">" to support negative changes
212
- if cur_percentage != prev_percentage ||
213
- time_now - @previous_time >= 1 || @finished_p
214
- show
215
- end
216
- end
217
-
218
- def time_now
219
- # Ignore Timecop time mocking
220
- if Time.respond_to?(:now_without_mock_time)
221
- Time.now_without_mock_time
222
- # Ignore Delorean time mocking
223
- elsif Time.respond_to?(:now_without_delorean)
224
- Time.now_without_delorean
225
- else
226
- Time.now
227
- end
228
- end
229
-
230
- def tty?
231
- @out.tty?
232
- end
233
-
234
- public
235
- def clear
236
- return unless tty?
237
- @out.print "\r"
238
- @out.print(" " * (get_width - 1))
239
- @out.print "\r"
240
- end
241
-
242
- def finish
243
- @current = @previous = @running_average = @total
244
- @finished_p = true
245
- show
246
- end
247
-
248
- def finished?
249
- @finished_p
250
- end
251
-
252
- def file_transfer_mode
253
- @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
254
- end
255
-
256
- def format= (format)
257
- @format = format
258
- end
259
-
260
- def format_arguments= (arguments)
261
- @format_arguments = arguments
262
- end
263
-
264
- def halt
265
- @finished_p = true
266
- show
267
- end
268
-
269
- def inc (step = 1)
270
- set(@current + step)
271
- end
272
-
273
- def set (count)
274
- # Constrain input to 0 <= count <= 100
275
- @current = [ [count, @total].min, 0 ].max
276
-
277
- # Update the exponentially-smoothed average
278
- @running_average = @previous * @smoothing +
279
- @running_average * (1.0 - @smoothing)
280
-
281
- # If this makes the percentage change by a tick or more, show it
282
- show_if_needed
283
-
284
- # Update for the next iteration
285
- @previous = @current
286
- end
287
-
288
- def inspect
289
- "#<ProgressBar:#{@current}/#{@total}>"
290
- end
291
- end
292
-
293
- class ReversedProgressBar < ProgressBar
294
- def do_percentage
295
- 100 - super
296
- end
297
- end
9
+ puts "DEPRECATION WARNING: Requiring ruby-progressbar using `require progressbar` or `gem progressbar` has been deprecated and will be disabled on or after #{ProgressBar::Depreciable::DEPRECATION_DATE}. Please use `require ruby-progressbar` or `gem ruby-progressbar` instead"
10
+ require File.join(File.dirname(__FILE__), 'ruby-progressbar')