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,19 @@
1
+ require 'progress_bar/depreciable'
2
+ require 'progress_bar/length_calculator'
3
+ require 'progress_bar/running_average_calculator'
4
+ require 'progress_bar/formatter'
5
+ require 'progress_bar/components'
6
+ require 'progress_bar/format'
7
+ require 'progress_bar/base'
8
+
9
+ class ProgressBar
10
+ def self.new(*args)
11
+ puts "DEPRECATION WARNING: Calling `ProgressBar.new` is deprecated and will be removed on or after #{ProgressBar::Depreciable::DEPRECATION_DATE}. Please use `ProgressBar.create` instead."
12
+
13
+ create *args
14
+ end
15
+
16
+ def self.create(*args)
17
+ ProgressBar::Base.new *args
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "progress_bar/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.rubygems_version = '1.3.5'
7
+
8
+ s.name = 'ruby-progressbar'
9
+ s.rubyforge_project = 'ruby-progressbar'
10
+
11
+ s.version = ProgressBar::VERSION
12
+ s.platform = Gem::Platform::RUBY
13
+
14
+ s.authors = ["thekompanee", "jfelchner"]
15
+ s.email = 'support@thekompanee.com'
16
+ s.date = Date.today
17
+ s.homepage = 'https://github.com/jfelchner/ruby-progressbar'
18
+
19
+ s.summary = 'Ruby/ProgressBar is a flexible text progress bar library for Ruby.'
20
+ s.description = <<-THEDOCTOR
21
+ Ruby/ProgressBar is an extremely flexible text progress bar library for Ruby.
22
+ The output can be customized with a flexible formatting system including:
23
+ percentage, bars of various formats, elapsed time and estimated time remaining.
24
+ THEDOCTOR
25
+
26
+ s.rdoc_options = ["--charset = UTF-8"]
27
+ s.extra_rdoc_files = %w[README.md LICENSE]
28
+
29
+ #= Manifest =#
30
+ # s.default_executable = 'nothing'
31
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
32
+ s.files = `git ls-files`.split("\n")
33
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
34
+ s.require_paths = ["lib"]
35
+ #= Manifest =#
36
+
37
+ s.add_development_dependency('bundler', '~> 1.0')
38
+ s.add_development_dependency('rspec', '~> 2.8')
39
+ s.add_development_dependency('timecop', '~> 0.3.5')
40
+ s.add_development_dependency('simplecov', '~> 0.5')
41
+ s.add_development_dependency('guard', '~> 1.0')
42
+ s.add_development_dependency('guard-rspec', '~> 0.6')
43
+ end
44
+
@@ -0,0 +1,434 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+ require 'timecop'
4
+
5
+ describe ProgressBar::Base do
6
+ before do
7
+ @output = StringIO.new('', 'w+')
8
+ @progressbar = ProgressBar::Base.new(:output => @output, :length => 80)
9
+ end
10
+
11
+ context 'when a new bar is created' do
12
+ context 'and no options are passed' do
13
+ before { @progressbar = ProgressBar::Base.new }
14
+
15
+ describe '#title' do
16
+ it 'returns the default title' do
17
+ @progressbar.send(:title).to_s.should eql ProgressBar::Base::DEFAULT_TITLE
18
+ end
19
+ end
20
+
21
+ describe '#output' do
22
+ it 'returns the default output stream' do
23
+ @progressbar.send(:output).should eql ProgressBar::Base::DEFAULT_OUTPUT_STREAM
24
+ end
25
+ end
26
+
27
+ describe '#length' do
28
+ it 'returns the width of the terminal if it is a Unix environment' do
29
+ @progressbar.stub(:terminal_width).and_return(99)
30
+ @progressbar.send(:reset_length) # This should be changed to use #any_instance
31
+ @progressbar.send(:length).should eql 99
32
+ end
33
+ end
34
+
35
+ describe '#length' do
36
+ it 'returns 80 if it is not a Unix environment' do
37
+ @progressbar.stub(:unix?).and_return(false)
38
+ @progressbar.send(:reset_length) # This should be changed to use #any_instance
39
+ @progressbar.send(:length).should eql 80
40
+ end
41
+ end
42
+ end
43
+
44
+ context 'and options are passed' do
45
+ before { @progressbar = ProgressBar::Base.new(:title => 'We All Float', :total => 12, :output => STDOUT, :progress_mark => 'x', :length => 88, :starting_at => 5) }
46
+
47
+ describe '#title' do
48
+ it 'returns the overridden title' do
49
+ @progressbar.send(:title).to_s.should eql 'We All Float'
50
+ end
51
+ end
52
+
53
+ describe '#output' do
54
+ it 'returns the overridden output stream' do
55
+ @progressbar.send(:output).should eql STDOUT
56
+ end
57
+ end
58
+
59
+ describe '#length' do
60
+ it 'returns the overridden length' do
61
+ @progressbar.send(:length).should eql 88
62
+ end
63
+ end
64
+ end
65
+
66
+ context 'if the bar was started 4 minutes ago' do
67
+ before do
68
+ Timecop.travel(-240) do
69
+ @progressbar.start
70
+ end
71
+ end
72
+
73
+ context 'and within 2 minutes it was halfway done' do
74
+ before do
75
+ Timecop.travel(-120) do
76
+ 50.times { @progressbar.increment }
77
+ end
78
+ end
79
+
80
+ describe '#finish' do
81
+ before do
82
+ Timecop.travel(-120) do
83
+ @progressbar.finish
84
+ end
85
+ end
86
+
87
+ it 'completes the bar' do
88
+ @output.rewind
89
+ @output.read.should match /Progress: \|#{'=' * 68}\|\n/
90
+ end
91
+
92
+ it 'shows the elapsed time instead of the estimated time since the bar is completed' do
93
+ @progressbar.to_s('%e').should eql 'Time: 00:02:00'
94
+ end
95
+
96
+ it 'calculates the elapsed time to 00:02:00' do
97
+ @progressbar.to_s('%a').should eql 'Time: 00:02:00'
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ context 'when a bar is about to be completed' do
105
+ before do
106
+ @progressbar = ProgressBar::Base.new(:starting_at => 99, :total => 100, :output => @output, :length => 80)
107
+ end
108
+
109
+ context 'and it is incremented' do
110
+ before { @progressbar.increment }
111
+
112
+ it 'registers as being "finished"' do
113
+ @progressbar.should be_finished
114
+ end
115
+
116
+ it 'prints a new line' do
117
+ @output.rewind
118
+ @output.read.end_with?("\n").should be_true
119
+ end
120
+ end
121
+ end
122
+
123
+ context 'when a bar is started' do
124
+ before do
125
+ @progressbar = ProgressBar::Base.new(:starting_at => 0, :total => 100, :output => @output, :length => 80)
126
+ end
127
+
128
+ context 'and it is incremented any number of times' do
129
+ before { 10.times { @progressbar.increment } }
130
+
131
+ describe '#progress_mark=' do
132
+ it 'changes the mark used to represent progress and updates the output' do
133
+ @progressbar.progress_mark = 'x'
134
+
135
+ @output.rewind
136
+ @output.read.should match /\rProgress: \|xxxxxx#{' ' * 62}\|\r\z/
137
+ end
138
+ end
139
+
140
+ describe '#title=' do
141
+ it 'changes the title used to represent the items being progressed and updates the output' do
142
+ @progressbar.title = 'Items'
143
+
144
+ @output.rewind
145
+ @output.read.should match /\rItems: \|=======#{' ' * 64}\|\r\z/
146
+ end
147
+ end
148
+
149
+ describe '#reset' do
150
+ before { @progressbar.reset }
151
+
152
+ it 'resets the bar back to the starting value' do
153
+ @output.rewind
154
+ @output.read.should match /\rProgress: \|#{' ' * 68}\|\r\z/
155
+ end
156
+ end
157
+
158
+ describe '#stop' do
159
+ before { @progressbar.stop }
160
+
161
+ it 'forcibly halts the bar wherever it is and cancels it' do
162
+ @output.rewind
163
+ @output.read.should match /\rProgress: \|======#{' ' * 62}\|\n\z/
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ context 'when a bar is started from 10/100' do
170
+ before do
171
+ @progressbar = ProgressBar::Base.new(:starting_at => 10, :total => 100, :output => @output, :length => 112)
172
+ end
173
+
174
+ context 'and it is incremented any number of times' do
175
+ before { 10.times { @progressbar.increment } }
176
+
177
+ describe '#reset' do
178
+ before { @progressbar.reset }
179
+
180
+ it 'resets the bar back to the starting value' do
181
+ @output.rewind
182
+ @output.read.should match /\rProgress: \|==========#{' ' * 90}\|\r\z/
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ describe '#clear' do
189
+ it 'clears the current terminal line and/or bar text' do
190
+ @progressbar.clear
191
+
192
+ @output.rewind
193
+ @output.read.should match /^#{@progressbar.send(:clear_string)}/
194
+ end
195
+ end
196
+
197
+ describe '#start' do
198
+ it 'clears the current terminal line' do
199
+ @progressbar.start
200
+
201
+ @output.rewind
202
+ @output.read.should match /^#{@progressbar.send(:clear_string)}/
203
+ end
204
+
205
+ it 'prints the bar for the first time' do
206
+ @progressbar.start
207
+
208
+ @output.rewind
209
+ @output.read.should match /Progress: \| \|\r\z/
210
+ end
211
+
212
+ it 'prints correctly if passed a position to start at' do
213
+ @progressbar.start(:at => 20)
214
+
215
+ @output.rewind
216
+ @output.read.should match /Progress: \|============= \|\r\z/
217
+ end
218
+ end
219
+
220
+ context 'when the bar has not been completed' do
221
+ before { @progressbar = ProgressBar::Base.new(:length => 112, :starting_at => 0, :total => 50, :output => @output) }
222
+
223
+ describe '#increment' do
224
+ before { @progressbar.increment }
225
+
226
+ it 'displays the bar with the correct formatting' do
227
+ @output.rewind
228
+ @output.read.should match /Progress: \|== \|\r\z/
229
+ end
230
+ end
231
+ end
232
+
233
+ context 'when a new bar is created with a specific format' do
234
+ context '#format' do
235
+ before { @progressbar = ProgressBar::Base.new(:format => '%B %p%%') }
236
+
237
+ context 'if called with no arguments' do
238
+ before { @progressbar.format }
239
+
240
+ it 'resets the format back to the default' do
241
+ @progressbar.to_s.should match /^Progress: \|\s+\|\z/
242
+ end
243
+ end
244
+
245
+ context 'if called with a specific format string' do
246
+ before { @progressbar.format '%t' }
247
+
248
+ it 'sets it as the new format for the bar' do
249
+ @progressbar.to_s.should match /^Progress\z/
250
+ end
251
+ end
252
+ end
253
+
254
+ context '#to_s' do
255
+ it 'displays the title when passed the "%t" format flag' do
256
+ @progressbar.to_s('%t').should match /^Progress\z/
257
+ end
258
+
259
+ it 'displays the title when passed the "%T" format flag' do
260
+ @progressbar.to_s('%T').should match /^Progress\z/
261
+ end
262
+
263
+ it 'displays the bar when passed the "%B" format flag (including empty space)' do
264
+ @progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
265
+ @progressbar.to_s('%B').should match /^#{'=' * 20}#{' ' * 80}\z/
266
+ end
267
+
268
+ it 'displays the bar when passed the combined "%b%i" format flags' do
269
+ @progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
270
+ @progressbar.to_s('%b%i').should match /^#{'=' * 20}#{' ' * 80}\z/
271
+ end
272
+
273
+ it 'displays the bar when passed the "%b" format flag (excluding empty space)' do
274
+ @progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
275
+ @progressbar.to_s('%b').should match /^#{'=' * 20}\z/
276
+ end
277
+
278
+ it 'displays the incomplete space when passed the "%i" format flag' do
279
+ @progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
280
+ @progressbar.to_s('%i').should match /^#{' ' * 80}\z/
281
+ end
282
+
283
+ it 'displays the bar when passed the "%w" format flag' do
284
+ @progressbar = ProgressBar::Base.new(:output => @output, :length => 100, :starting_at => 0)
285
+
286
+ @progressbar.to_s('%w').should match /^\z/
287
+ 4.times { @progressbar.increment }
288
+ @progressbar.to_s('%w').should match /^====\z/
289
+ @progressbar.increment
290
+ @progressbar.to_s('%w').should match /^= 5 =\z/
291
+ 5.times { @progressbar.increment }
292
+ @progressbar.to_s('%w').should match /^=== 10 ===\z/
293
+ @progressbar.decrement
294
+ @progressbar.to_s('%w').should match /^=== 9 ===\z/
295
+ 91.times { @progressbar.increment }
296
+ @progressbar.to_s('%w').should match /^#{'=' * 47} 100 #{'=' * 48}\z/
297
+ end
298
+
299
+ it 'calculates the remaining negative space properly with an integrated percentage bar of 0 percent' do
300
+ @progressbar = ProgressBar::Base.new(:output => @output, :length => 100, :total => 200, :starting_at => 0)
301
+
302
+ @progressbar.to_s('%w%i').should match /^\s{100}\z/
303
+ 9.times { @progressbar.increment }
304
+ @progressbar.to_s('%w%i').should match /^====\s{96}\z/
305
+ @progressbar.increment
306
+ @progressbar.to_s('%w%i').should match /^= 5 =\s{95}\z/
307
+ end
308
+
309
+ it 'displays the current capacity when passed the "%c" format flag' do
310
+ @progressbar = ProgressBar::Base.new(:output => @output, :starting_at => 0)
311
+
312
+ @progressbar.to_s('%c').should match /^0\z/
313
+ @progressbar.increment
314
+ @progressbar.to_s('%c').should match /^1\z/
315
+ @progressbar.decrement
316
+ @progressbar.to_s('%c').should match /^0\z/
317
+ end
318
+
319
+ it 'displays the total capacity when passed the "%C" format flag' do
320
+ @progressbar = ProgressBar::Base.new(:total => 100)
321
+
322
+ @progressbar.to_s('%C').should match /^100\z/
323
+ end
324
+
325
+ it 'displays the percentage complete when passed the "%p" format flag' do
326
+ @progressbar = ProgressBar::Base.new(:starting_at => 33, :total => 200)
327
+
328
+ @progressbar.to_s('%p').should match /^16\z/
329
+ end
330
+
331
+ it 'displays the percentage complete when passed the "%P" format flag' do
332
+ @progressbar = ProgressBar::Base.new(:starting_at => 33, :total => 200)
333
+
334
+ @progressbar.to_s('%P').should match /^16.50\z/
335
+ end
336
+
337
+ it 'displays only up to 2 decimal places when using the "%P" flag' do
338
+ @progressbar = ProgressBar::Base.new(:starting_at => 66, :total => 99)
339
+
340
+ @progressbar.to_s('%P').should match /^66.66\z/
341
+ end
342
+
343
+ it 'displays a literal percent sign when using the "%%" flag' do
344
+ @progressbar = ProgressBar::Base.new(:starting_at => 66, :total => 99)
345
+
346
+ @progressbar.to_s('%%').should match /^%\z/
347
+ end
348
+
349
+ it 'displays a literal percent sign when using the "%%" flag' do
350
+ @progressbar = ProgressBar::Base.new(:starting_at => 66, :total => 99)
351
+
352
+ @progressbar.to_s('%%').should match /^%\z/
353
+ end
354
+
355
+ # Autostarting for now. This will be applicable later.
356
+ # context "when called before #start" do
357
+ # it "displays unknown time elapsed when using the %a flag" do
358
+ # @progressbar.to_s('%a').should match /^Time: --:--:--\z/
359
+ # end
360
+ # end
361
+
362
+ context 'when called after #start' do
363
+ before do
364
+ Timecop.travel(-3723) do
365
+ @progressbar.start
366
+ end
367
+ end
368
+
369
+ context 'and the bar is reset' do
370
+ before { @progressbar.reset }
371
+
372
+ it 'displays "??:??:??" until finished when passed the %e flag' do
373
+ @progressbar.to_s('%a').should match /^Time: --:--:--\z/
374
+ end
375
+ end
376
+
377
+ it 'displays the time elapsed when using the "%a" flag' do
378
+ @progressbar.to_s('%a').should match /^Time: 01:02:03\z/
379
+ end
380
+ end
381
+
382
+ context 'when called before #start' do
383
+ it 'displays unknown time until finished when passed the "%e" flag' do
384
+ @progressbar = ProgressBar::Base.new
385
+ @progressbar.to_s('%e').should match /^ ETA: \?\?:\?\?:\?\?\z/
386
+ end
387
+ end
388
+
389
+ context 'when called after #start' do
390
+ before do
391
+ Timecop.travel(-3723) do
392
+ @progressbar = ProgressBar::Base.new(:starting_at => 0, :output => @output, :smoothing => 0.0)
393
+ @progressbar.start
394
+ @progressbar.progress = 50
395
+ end
396
+ end
397
+
398
+ context 'and the bar is reset' do
399
+ before { @progressbar.reset }
400
+
401
+ it 'displays "??:??:??" until finished when passed the "%e" flag' do
402
+ @progressbar.to_s('%e').should match /^ ETA: \?\?:\?\?:\?\?\z/
403
+ end
404
+ end
405
+
406
+ it 'displays the estimated time remaining when using the "%e" flag' do
407
+ @progressbar.to_s('%e').should match /^ ETA: 01:02:02\z/
408
+ end
409
+ end
410
+
411
+ context 'when it could take 100 hours or longer to finish' do
412
+ before do
413
+ Timecop.travel(-120000) do
414
+ @progressbar = ProgressBar::Base.new(:starting_at => 0, :total => 100, :output => @output, :smoothing => 0.0)
415
+ @progressbar.start
416
+ @progressbar.progress = 25
417
+ end
418
+ end
419
+
420
+ it 'displays "> 4 Days" until finished when passed the "%E" flag' do
421
+ @progressbar.to_s('%E').should match /^ ETA: > 4 Days\z/
422
+ end
423
+
424
+ it 'displays "??:??:??" until finished when passed the "%e" flag' do
425
+ @progressbar.to_s('%e').should match /^ ETA: \?\?:\?\?:\?\?\z/
426
+ end
427
+
428
+ it 'displays the exact estimated time until finished when passed the "%f" flag' do
429
+ @progressbar.to_s('%f').should match /^ ETA: 100:00:00\z/
430
+ end
431
+ end
432
+ end
433
+ end
434
+ end