ruby-progressbar 1.4.2 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +52 -24
- data/lib/ruby-progressbar/base.rb +3 -0
- data/lib/ruby-progressbar/components.rb +1 -0
- data/lib/ruby-progressbar/components/progressable.rb +5 -5
- data/lib/ruby-progressbar/components/rate.rb +69 -0
- data/lib/ruby-progressbar/format/molecule.rb +18 -17
- data/lib/ruby-progressbar/formatter.rb +8 -0
- data/lib/ruby-progressbar/version.rb +1 -1
- data/spec/lib/ruby-progressbar/base_spec.rb +231 -86
- data/spec/lib/ruby-progressbar/components/bar_spec.rb +27 -27
- data/spec/lib/ruby-progressbar/components/elapsed_timer_spec.rb +10 -10
- data/spec/lib/ruby-progressbar/components/estimated_timer_spec.rb +21 -19
- data/spec/lib/ruby-progressbar/components/progressable_spec.rb +15 -6
- data/spec/lib/ruby-progressbar/components/throttle_spec.rb +10 -11
- data/spec/lib/ruby-progressbar/format/molecule_spec.rb +4 -4
- data/spec/lib/ruby-progressbar/running_average_calculator_spec.rb +4 -4
- data/spec/lib/ruby-progressbar/time_spec.rb +4 -6
- metadata +59 -44
- data/spec/spec_helper.rb +0 -6
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 35cb162ef6a48d988df23e47ffe815580cb6258a
|
4
|
+
data.tar.gz: bf2ed1a84e032ebde941494682375c05da9117f2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 12c2dfc60bd0339e7b643fc68e67018a5f9281a3bd719a4df0197fd0ec639e31c84d2108ddad0516b9df5eaf6ee8f35a303c65159f59dfc931cbecd97928cf38
|
7
|
+
data.tar.gz: d87e233863403cabd91c47eb73d20ab8e03250048638ba2042d50480ceb89b49a384fdb7c570b948941427785354d0d65b033db579633ea92bdfb6e00fa69c8a
|
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
Ruby/ProgressBar: A Text Progress Bar Library for Ruby
|
2
2
|
================================
|
3
|
+
[![Build Status](https://secure.travis-ci.org/jfelchner/ruby-progressbar.png?branch=master)](http://travis-ci.org/jfelchner/ruby-progressbar) [![Code Climate](https://codeclimate.com/github/jfelchner/ruby-progressbar.png)](https://codeclimate.com/github/jfelchner/ruby-progressbar) [![Code Climate](https://codeclimate.com/github/jfelchner/ruby-progressbar/coverage.png)](https://codeclimate.com/github/jfelchner/ruby-progressbar)
|
3
4
|
|
4
5
|
The **ultimate** text progress bar library for Ruby! It'll **SMASH YOU OVER THE HEAD** with a **PURE RUSH** of progress bar excitement!
|
5
6
|
|
@@ -18,7 +19,7 @@ Supported Rubies
|
|
18
19
|
|
19
20
|
It's Better Than The Other 186,312 Progress Bar Libraries Because...
|
20
21
|
--------------------------------
|
21
|
-
* Full test suite [![
|
22
|
+
* Full test suite [![Code Climate](https://codeclimate.com/github/jfelchner/ruby-progressbar/coverage.png)](https://codeclimate.com/github/jfelchner/ruby-progressbar)
|
22
23
|
* _**ZERO**_ dependencies
|
23
24
|
* Used by tons of other open source projects (which means we find out about bugs quickly)
|
24
25
|
* It's pretty [freakin' sweet](https://www.youtube.com/watch?v=On3IoVhf_GM)
|
@@ -63,7 +64,7 @@ It's simple to get started:
|
|
63
64
|
ProgressBar.create
|
64
65
|
```
|
65
66
|
|
66
|
-
Creates a basic progress bar beginning at `0`, a
|
67
|
+
Creates a basic progress bar beginning at `0`, a maximum capacity of `100` and tells it to start.
|
67
68
|
|
68
69
|
Progress: | |
|
69
70
|
|
@@ -90,7 +91,7 @@ If you would like to customize your prompt, you can pass options when you call `
|
|
90
91
|
ProgressBar.create(:title => "Items", :starting_at => 20, :total => 200)
|
91
92
|
```
|
92
93
|
|
93
|
-
|
94
|
+
This will output:
|
94
95
|
|
95
96
|
Items: |======= |
|
96
97
|
|
@@ -114,7 +115,7 @@ The following are the list of options you can use:
|
|
114
115
|
* `#decrement`: Will retract the bar's progress by `1` unit.
|
115
116
|
* `#progress +=`: Will allow you to increment by a relative amount.
|
116
117
|
* `#progress -=`: Will allow you to decrement by a relative amount.
|
117
|
-
* `#progress=`: Will
|
118
|
+
* `#progress=`: Will set the bar's progress to whatever value you would like. _Note: This will likely mess up your estimated time if you're using it._
|
118
119
|
* `#total=`: Will change the total number of items being processed by the bar. This can be anything (even nil) but cannot be less than the amount of progress already accumulated by the bar.
|
119
120
|
|
120
121
|
### Stopping
|
@@ -123,7 +124,7 @@ The bar can be stopped in four ways:
|
|
123
124
|
|
124
125
|
* `#finish`: Will stop the bar by completing it immediately. The current position will be advanced to the total.
|
125
126
|
* `#stop`: Will stop the bar by immediately cancelling it. The current position will remain where it is.
|
126
|
-
* `#pause`: Will stop the bar
|
127
|
+
* `#pause`: Will stop the bar like `#stop` but will allow it to be restarted from where it previously left off by calling `#resume`. _Note: Elapsed Time and Estimated Time will stop being affected while the bar is paused._
|
127
128
|
* `#reset`: Will stop the bar by resetting all information. The current position of the bar will be reset to where it began when it was created. _(eg if you passed `:starting_at => 5` when you created the bar, it would reset to `5` and not `0`)_
|
128
129
|
|
129
130
|
### Finishing
|
@@ -134,11 +135,11 @@ _Note: The bar will be finished automatically if the current value ever becomes
|
|
134
135
|
|
135
136
|
### Refreshing
|
136
137
|
|
137
|
-
* If you need to
|
138
|
+
* If you need to redisplay the progress bar to give your users a "real-time" feel, you can call `#refresh`. `#refresh` will not affect the current position but will update the elapsed and estimated timers.
|
138
139
|
|
139
140
|
### Unknown Progress
|
140
141
|
|
141
|
-
Sometimes when processing work, you don't know
|
142
|
+
Sometimes when processing work, you don't know exactly how many items you will need to process. This might be because you're downloading a chunked file or because you're processing a set of jobs that hasn't been fully loaded yet.
|
142
143
|
|
143
144
|
In times like these, you can set total to `nil` and continue to increment the bar as usual. The bar will display an 'unknown' animation which will change every time you increment. This will give the appearance (by default) that the bar is processing work even though there is no "progress".
|
144
145
|
|
@@ -174,12 +175,12 @@ And the bar will magically transform into its typical state:
|
|
174
175
|
|
175
176
|
### Logging
|
176
177
|
|
177
|
-
|
178
|
+
While using the progress bar, you may wish to log some output for the user. If you attempt to do this using a standard `puts` statement, you'll find that the text will overwrite the bar. For example if you were to `puts "hello"` after progress has already begun, you may get something like this:
|
178
179
|
|
179
180
|
helloess: |======= |
|
180
181
|
Progress: |======== |
|
181
182
|
|
182
|
-
|
183
|
+
This happens because the ruby-progressbar has to keep redrawing itself every time you change the progress. It's a limitation of terminal output. Using `puts` messes that up because `puts` adds a newline which moves the cursor to the next line, then when ruby-progressbar updates, it does so on the following line.
|
183
184
|
|
184
185
|
To circumvent this, use `#log` instead.
|
185
186
|
|
@@ -192,7 +193,7 @@ progressbar.log 'hello'
|
|
192
193
|
hello
|
193
194
|
Progress: |============= |
|
194
195
|
|
195
|
-
`#log` will automatically clear the bar, print your desired text and then redraw the bar on the following line. Notice that we did not get a bar **above** the logged output. If you consistently use `#log`, you should only
|
196
|
+
`#log` will automatically clear the bar, print your desired text and then redraw the bar on the following line. Notice that we did not get a bar **above** the logged output. If you consistently use `#log`, you should only ever see one bar on the screen at any time.
|
196
197
|
|
197
198
|
Formatting
|
198
199
|
--------------------------------
|
@@ -213,6 +214,8 @@ The flags you can use in the format string are as follows:
|
|
213
214
|
* `%B`: The full progress bar including 'incomplete' space (eg: `========== `)
|
214
215
|
* `%b`: Progress bar only (eg: `==========`)
|
215
216
|
* `%w`: Bar With Integrated Percentage (eg: `==== 75 ====`)
|
217
|
+
* `%r`: Rate of Progress as a whole number (eg: `13`)
|
218
|
+
* `%R`: Rate of Progress as a decimal number (eg: `13.67`)
|
216
219
|
* `%i`: Display the incomplete space of the bar (this string will only contain whitespace eg: ` `)
|
217
220
|
* `%%`: A literal percent sign `%`
|
218
221
|
|
@@ -268,13 +271,13 @@ Becomes **PAC-MAN**!
|
|
268
271
|
|
269
272
|
### Overriding the Length
|
270
273
|
|
271
|
-
By default, the
|
274
|
+
By default, the progress bar will try to be as smart as possible about how wide it can be. Under most Unix systems, it should be as wide as the terminal will allow while still fitting on one line. If you wish to override this behavior, you can pass in the `:length` option when creating the bar:
|
272
275
|
|
273
276
|
```ruby
|
274
277
|
ProgressBar.create(:length => 40)
|
275
278
|
```
|
276
279
|
|
277
|
-
|
280
|
+
If you don't have access to the code calling the progress bar itself (say if you're using a gem like Fuubar), you can set the `RUBY_PROGRESS_BAR_LENGTH` environment variable and it will override any other setting.
|
278
281
|
|
279
282
|
_Note: If the terminal width is less than 20 characters or ruby-progressbar is being used on a non-*nix system, the bar will default to an 80 character width._
|
280
283
|
|
@@ -287,6 +290,27 @@ The following items can be set at any time. Changes cause an immediate bar refr
|
|
287
290
|
* `#title=`: Sets the string used to represent the items the bar is tracking (or I guess whatever else you want it to be).
|
288
291
|
* `#format(format_string)`: If you need to adjust the format that the bar uses when rendering itself, just pass in a string in the same format as describe [above](#formatting).
|
289
292
|
|
293
|
+
### Rate Scaling
|
294
|
+
|
295
|
+
By default the rate shown on the progress bar is shown as the number of items
|
296
|
+
processed per second. Often times, you won't want to display the literal number
|
297
|
+
of items, but rather scale it in some way. For example, if you're displaying
|
298
|
+
the progress of a file being transferred, and you are representing the bar as
|
299
|
+
the number of bytes in the file, by default the `%r` formatter will show the
|
300
|
+
number of bytes per second.
|
301
|
+
|
302
|
+
If instead of the bytes per second you wanted to show the user the number of
|
303
|
+
kilobytes per second, you can do that like so:
|
304
|
+
|
305
|
+
```ruby
|
306
|
+
ProgressBar.create(:format => '%a %B %p%% %r KB/sec',
|
307
|
+
:rate_scale => lambda { |rate| rate / 1024 })
|
308
|
+
```
|
309
|
+
|
310
|
+
Now, when the bar is displayed it will look something like so:
|
311
|
+
|
312
|
+
Time: --:--:-- =============== 40% - 102 KB/sec
|
313
|
+
|
290
314
|
## In The Weeds
|
291
315
|
|
292
316
|
This is some stuff that makes ruby-progressbar extra awesome, but for the most part it "Just Works" and you won't have to even know it's there, but if you're curious like us, here it is.
|
@@ -295,11 +319,11 @@ This is some stuff that makes ruby-progressbar extra awesome, but for the most p
|
|
295
319
|
|
296
320
|
#### Smoothing Out Estimated Time Jitters
|
297
321
|
|
298
|
-
Sometimes when you're tracking progress, you
|
322
|
+
Sometimes when you're tracking progress, you might have some items which take significantly longer than others to complete. When this is the case, the ETA gauge can vary wildly from increment to increment.
|
299
323
|
|
300
324
|
__RUBY PROGRESS BAR TO THE RESCUE!__
|
301
325
|
|
302
|
-
Thanks to [@L2G](https://github.com/L2G) and 'the maths' you can pass the `:smoothing` option when creating a new bar
|
326
|
+
Thanks to [@L2G](https://github.com/L2G) and 'the maths' you can pass the `:smoothing` option when creating a new bar. Your progress bar will then use an exponentially smoothed average rather than a linear one. A value of `0.0` means no smoothing and is equivalent to the classic behavior. A value of `1.0` is the maximum amount of smoothing. Any values between those two are valid. The default value is `0.1`.
|
303
327
|
|
304
328
|
```ruby
|
305
329
|
ProgressBar.create(:smoothing => 0.6)
|
@@ -307,7 +331,7 @@ ProgressBar.create(:smoothing => 0.6)
|
|
307
331
|
|
308
332
|
#### Time Mocking Support
|
309
333
|
|
310
|
-
When mocking time, the concept of when `now` is becomes distorted. You can imagine that because ruby-progressbar tracks elapsed and estimated times, if it used the mocked version of `now` the results would be very undesirable.
|
334
|
+
When mocking time, the concept of when `now` is becomes distorted. You can imagine that because ruby-progressbar tracks elapsed and estimated times, if it used the mocked version of `now` the results would be very undesirable. But, if you use one of our supported Ruby time mocking libraries, your elapsed and estimated times will always appear correctly. Currently supported are:
|
311
335
|
|
312
336
|
* [Timecop](https://github.com/jtrupiano/timecop)
|
313
337
|
* [Delorean](https://github.com/bebanjo/delorean)
|
@@ -316,17 +340,19 @@ When mocking time, the concept of when `now` is becomes distorted. You can imag
|
|
316
340
|
|
317
341
|
When reporting progress of large amounts of very fast operations, whose duration is comparable to the output time of a progress bar, it becomes desirable to throttle output to the console and only perform it once in a set period. ProgressBar supports throttling if given `:throttle_rate` option:
|
318
342
|
|
319
|
-
|
343
|
+
```ruby
|
344
|
+
ProgressBar.create(:throttle_rate => 0.1)
|
345
|
+
```
|
320
346
|
|
321
347
|
The above progress bar will output at most 10 times a second.
|
322
348
|
|
323
|
-
The default throttling rate
|
349
|
+
The default throttling rate is 100 times per second (or 0.01)
|
324
350
|
|
325
351
|
### Custom Unknown Progress Animations
|
326
352
|
|
327
353
|
Following up on [unknown progress](#unknown-progress), you may wish to update the unknown progress animation to suit your specific needs. This can be easily done by passing in the `:unknown_progress_animation_steps` option.
|
328
354
|
|
329
|
-
This item should be an array of strings
|
355
|
+
This item should be an array of strings that represent each step of the animation. The specific step used for a given progress is determined by the current progress of the bar. For example:
|
330
356
|
|
331
357
|
```ruby
|
332
358
|
progressbar = ProgressBar.create(:unknown_progress_animation_steps => ['==>', '>==', '=>='])
|
@@ -340,21 +366,23 @@ Whatever element is chosen is repeated along the entire 'incomplete' portion of
|
|
340
366
|
|
341
367
|
### Non-TTY Output
|
342
368
|
|
343
|
-
|
369
|
+
Normally, when the progress bar is updated, the entire previous bar is 'overwritten' with the updated information. However when the bar is being output on a non-TTY enabled output stream (such as a file or pipe), that standard behavior of outputting the progress bar will not work. This is mainly due to the fact that we can't easily go back and replace the content that the bar had previously written.
|
344
370
|
|
345
|
-
To try to solve this, ruby-progressbar, when it determines that it is being used on a non-TTY device, will override any format which was set in the initializer to something which more closely resembles this:
|
371
|
+
To try to solve this problem, ruby-progressbar, when it determines that it is being used on a non-TTY device, will override any format which was set in the initializer to something which more closely resembles this:
|
346
372
|
|
347
373
|
Progress: |=============
|
348
374
|
|
349
|
-
Notice that there are no dynamically updating segments like counters or ETA. Dynamic segments are
|
375
|
+
Notice that there are no dynamically updating segments like counters or ETA. Dynamic segments are incompatible with non-TTY devices. This is because dynamic segments need to be updated on each refresh of the bar, which is impossible in non-TTY mode.
|
350
376
|
|
351
377
|
Also notice that there is no end cap on the righthand side of the bar. Again, we cannot output something which is past the point at which we next need to output text. If we added an end cap, that would mean that any additional progress text would be placed _after_ the end cap. Definitely not what we want.
|
352
378
|
|
353
|
-
So how does it work?
|
379
|
+
So how does it work?
|
380
|
+
|
381
|
+
First we output the title and the first end cap:
|
354
382
|
|
355
383
|
Progress: |
|
356
384
|
|
357
|
-
Next, every time we increment the bar, we check whether the progress bar has grown. If it has, we output
|
385
|
+
Next, every time we increment the bar, we check whether the progress bar has grown. If it has, we _only output the additional portion_ of the bar to the output.
|
358
386
|
|
359
387
|
For example, given the previous title output, if we increment the bar once, we would get:
|
360
388
|
|
@@ -362,7 +390,7 @@ For example, given the previous title output, if we increment the bar once, we w
|
|
362
390
|
|
363
391
|
But in this case, only one `=` was output. Not the entire `Progress: |=`.
|
364
392
|
|
365
|
-
|
393
|
+
However when the bar is completed:
|
366
394
|
|
367
395
|
Progress: |====================================================================|
|
368
396
|
|
@@ -12,6 +12,7 @@ class ProgressBar
|
|
12
12
|
super(options)
|
13
13
|
|
14
14
|
@bar = Components::Bar.new(options)
|
15
|
+
@rate = Components::Rate.new(options)
|
15
16
|
@estimated_time = Components::EstimatedTimer.new(options)
|
16
17
|
@elapsed_time = Components::ElapsedTimer.new
|
17
18
|
@throttle = Components::Throttle.new(options)
|
@@ -155,11 +156,13 @@ class ProgressBar
|
|
155
156
|
def with_progressables(*args)
|
156
157
|
@bar.send(*args)
|
157
158
|
@estimated_time.send(*args)
|
159
|
+
@rate.send(*args)
|
158
160
|
end
|
159
161
|
|
160
162
|
def with_timers(*args)
|
161
163
|
@estimated_time.send(*args)
|
162
164
|
@elapsed_time.send(*args)
|
165
|
+
@rate.send(*args)
|
163
166
|
end
|
164
167
|
|
165
168
|
def update_progress(*args)
|
@@ -84,6 +84,10 @@ class ProgressBar
|
|
84
84
|
format('%5.2f', (progress.to_f * 100.0 / total * 100.0).floor / 100.0)
|
85
85
|
end
|
86
86
|
|
87
|
+
def progress_made
|
88
|
+
started? ? self.progress - self.starting_position : 0
|
89
|
+
end
|
90
|
+
|
87
91
|
private
|
88
92
|
def validate_total(new_total)
|
89
93
|
(progress.nil? || new_total.nil? || new_total >= progress) || raise(ProgressBar::InvalidProgressError, "You can't set the item's total value to be less than the current progress.")
|
@@ -93,12 +97,8 @@ class ProgressBar
|
|
93
97
|
(total.nil? || new_progress <= total) || raise(ProgressBar::InvalidProgressError, "You can't set the item's current value to be greater than the total.")
|
94
98
|
end
|
95
99
|
|
96
|
-
def progress_made
|
97
|
-
started? ? self.progress - self.starting_position : 0
|
98
|
-
end
|
99
|
-
|
100
100
|
def update_running_average
|
101
|
-
self.running_average = RunningAverageCalculator.calculate(self.running_average, self.
|
101
|
+
self.running_average = RunningAverageCalculator.calculate(self.running_average, self.progress_made, self.smoothing)
|
102
102
|
end
|
103
103
|
end
|
104
104
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class ProgressBar
|
2
|
+
module Components
|
3
|
+
class Rate
|
4
|
+
include Timer
|
5
|
+
include Progressable
|
6
|
+
|
7
|
+
attr_accessor :rate_scale
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
self.rate_scale = options[:rate_scale]
|
11
|
+
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def start(options = {})
|
16
|
+
as(Timer).start
|
17
|
+
as(Progressable).start(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset
|
21
|
+
as(Timer).reset
|
22
|
+
as(Progressable).reset
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s(format_string = "%i")
|
26
|
+
elapsed = elapsed_whole_seconds.to_f
|
27
|
+
return 0 unless elapsed > 0
|
28
|
+
|
29
|
+
base_rate = (progress_made / elapsed)
|
30
|
+
|
31
|
+
if rate_scale
|
32
|
+
scaled_rate = rate_scale.call(base_rate)
|
33
|
+
else
|
34
|
+
scaled_rate = base_rate
|
35
|
+
end
|
36
|
+
|
37
|
+
format_string % scaled_rate
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def as(ancestor, &blk)
|
43
|
+
@__as ||= {}
|
44
|
+
unless r = @__as[ancestor]
|
45
|
+
r = (@__as[ancestor] = As.new(self, ancestor))
|
46
|
+
end
|
47
|
+
r.instance_eval(&blk) if block_given?
|
48
|
+
r
|
49
|
+
end
|
50
|
+
|
51
|
+
class As
|
52
|
+
private *instance_methods.select { |m| m !~ /(^__|^\W|^binding$)/ }
|
53
|
+
|
54
|
+
def initialize(subject, ancestor)
|
55
|
+
@subject = subject
|
56
|
+
@ancestor = ancestor
|
57
|
+
end
|
58
|
+
|
59
|
+
def start(*args, &blk)
|
60
|
+
@ancestor.instance_method(:start).bind(@subject).call(*args,&blk)
|
61
|
+
end
|
62
|
+
|
63
|
+
def method_missing(sym, *args, &blk)
|
64
|
+
@ancestor.instance_method(sym).bind(@subject).call(*args,&blk)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -2,31 +2,32 @@ class ProgressBar
|
|
2
2
|
module Format
|
3
3
|
class Molecule
|
4
4
|
MOLECULES = {
|
5
|
-
:t =>
|
6
|
-
:T =>
|
7
|
-
:c =>
|
8
|
-
:C =>
|
9
|
-
:p =>
|
10
|
-
:P =>
|
11
|
-
:a =>
|
12
|
-
:e =>
|
13
|
-
:E =>
|
14
|
-
:f =>
|
15
|
-
:B =>
|
16
|
-
:b =>
|
17
|
-
:w =>
|
18
|
-
:i =>
|
5
|
+
:t => :title,
|
6
|
+
:T => :title,
|
7
|
+
:c => :progress,
|
8
|
+
:C => :total,
|
9
|
+
:p => :percentage,
|
10
|
+
:P => :percentage_with_precision,
|
11
|
+
:a => :elapsed_time,
|
12
|
+
:e => :estimated_time_with_unknown_oob,
|
13
|
+
:E => :estimated_time_with_friendly_oob,
|
14
|
+
:f => :estimated_time_with_no_oob,
|
15
|
+
:B => :complete_bar,
|
16
|
+
:b => :bar,
|
17
|
+
:w => :bar_with_percentage,
|
18
|
+
:i => :incomplete_space,
|
19
|
+
:r => :rate_of_change,
|
20
|
+
:R => :rate_of_change_with_precision,
|
19
21
|
}
|
20
22
|
|
21
23
|
BAR_MOLECULES = %w{w B b i}
|
22
24
|
|
23
25
|
attr_reader :key
|
24
26
|
attr_reader :method_name
|
25
|
-
attr_reader :method_arguments
|
26
27
|
|
27
28
|
def initialize(letter)
|
28
|
-
@key
|
29
|
-
@
|
29
|
+
@key = letter
|
30
|
+
@method_name = MOLECULES.fetch(@key.to_sym)
|
30
31
|
end
|
31
32
|
|
32
33
|
def bar_molecule?
|
@@ -1,16 +1,17 @@
|
|
1
|
-
require '
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'support/time'
|
2
3
|
require 'stringio'
|
3
4
|
|
4
5
|
describe ProgressBar::Base do
|
5
6
|
let(:output) do
|
6
7
|
StringIO.new('', 'w+').tap do |io|
|
7
|
-
io.
|
8
|
+
allow(io).to receive(:tty?).and_return true
|
8
9
|
end
|
9
10
|
end
|
10
11
|
|
11
12
|
let(:non_tty_output) do
|
12
13
|
StringIO.new('', 'w+').tap do |io|
|
13
|
-
io.
|
14
|
+
allow(io).to receive(:tty?).and_return false
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
@@ -31,7 +32,7 @@ describe ProgressBar::Base do
|
|
31
32
|
progressbar.increment
|
32
33
|
|
33
34
|
output.rewind
|
34
|
-
output.read.
|
35
|
+
expect(output.read).to match /\raaaaaaaaaaaaaaaaaaaaaaaaa \r\s+\raaaaaaaaaaaaaaaaaaaaaaaaa\r\z/
|
35
36
|
end
|
36
37
|
|
37
38
|
context 'and the bar length is calculated' do
|
@@ -41,7 +42,7 @@ describe ProgressBar::Base do
|
|
41
42
|
allow(progressbar).to receive(:terminal_width).
|
42
43
|
and_return 20
|
43
44
|
|
44
|
-
progressbar.to_s('%t%w').
|
45
|
+
expect(progressbar.to_s('%t%w')).to eql '*********************'
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
@@ -52,7 +53,7 @@ describe ProgressBar::Base do
|
|
52
53
|
allow(progressbar).to receive(:terminal_width).
|
53
54
|
and_return 20
|
54
55
|
|
55
|
-
progressbar.to_s('%t%i').
|
56
|
+
expect(progressbar.to_s('%t%i')).to eql '*********************'
|
56
57
|
end
|
57
58
|
|
58
59
|
it 'returns the proper string' do
|
@@ -61,7 +62,7 @@ describe ProgressBar::Base do
|
|
61
62
|
allow(progressbar).to receive(:terminal_width).
|
62
63
|
and_return 20
|
63
64
|
|
64
|
-
progressbar.to_s('%t%i').
|
65
|
+
expect(progressbar.to_s('%t%i')).to eql '*********************'
|
65
66
|
end
|
66
67
|
end
|
67
68
|
|
@@ -72,7 +73,7 @@ describe ProgressBar::Base do
|
|
72
73
|
allow(progressbar).to receive(:terminal_width).
|
73
74
|
and_return 20
|
74
75
|
|
75
|
-
progressbar.to_s('%t%B').
|
76
|
+
expect(progressbar.to_s('%t%B')).to eql '******************* '
|
76
77
|
end
|
77
78
|
|
78
79
|
it 'returns the proper string' do
|
@@ -81,7 +82,7 @@ describe ProgressBar::Base do
|
|
81
82
|
allow(progressbar).to receive(:terminal_width).
|
82
83
|
and_return 20
|
83
84
|
|
84
|
-
progressbar.to_s('%t%w%i').
|
85
|
+
expect(progressbar.to_s('%t%w%i')).to eql '******************* '
|
85
86
|
end
|
86
87
|
end
|
87
88
|
end
|
@@ -92,13 +93,13 @@ describe ProgressBar::Base do
|
|
92
93
|
|
93
94
|
describe '#title' do
|
94
95
|
it 'returns the default title' do
|
95
|
-
progressbar.send(:title).to_s.
|
96
|
+
expect(progressbar.send(:title).to_s).to eql ProgressBar::Base::DEFAULT_TITLE
|
96
97
|
end
|
97
98
|
end
|
98
99
|
|
99
100
|
describe '#output' do
|
100
101
|
it 'returns the default output stream' do
|
101
|
-
progressbar.send(:output).
|
102
|
+
expect(progressbar.send(:output)).to eql ProgressBar::Base::DEFAULT_OUTPUT_STREAM
|
102
103
|
end
|
103
104
|
end
|
104
105
|
|
@@ -109,7 +110,7 @@ describe ProgressBar::Base do
|
|
109
110
|
|
110
111
|
it 'returns the length of the environment variable as an integer' do
|
111
112
|
progressbar = ProgressBar::Base.new
|
112
|
-
progressbar.send(:length).
|
113
|
+
expect(progressbar.send(:length)).to eql 44
|
113
114
|
end
|
114
115
|
end
|
115
116
|
|
@@ -119,21 +120,21 @@ describe ProgressBar::Base do
|
|
119
120
|
context 'but the length option was passed in' do
|
120
121
|
it 'returns the length specified in the option' do
|
121
122
|
progressbar = ProgressBar::Base.new(:length => 88)
|
122
|
-
progressbar.send(:length).
|
123
|
+
expect(progressbar.send(:length)).to eql 88
|
123
124
|
end
|
124
125
|
end
|
125
126
|
|
126
127
|
context 'and no length option was passed in' do
|
127
128
|
it 'returns the width of the terminal if it is a Unix environment' do
|
128
|
-
progressbar.
|
129
|
+
allow(progressbar).to receive(:terminal_width).and_return(99)
|
129
130
|
progressbar.send(:reset_length)
|
130
|
-
progressbar.send(:length).
|
131
|
+
expect(progressbar.send(:length)).to eql 99
|
131
132
|
end
|
132
133
|
|
133
134
|
it 'returns 80 if it is not a Unix environment' do
|
134
|
-
progressbar.
|
135
|
+
allow(progressbar).to receive(:unix?).and_return(false)
|
135
136
|
progressbar.send(:reset_length)
|
136
|
-
progressbar.send(:length).
|
137
|
+
expect(progressbar.send(:length)).to eql 80
|
137
138
|
end
|
138
139
|
end
|
139
140
|
end
|
@@ -145,19 +146,19 @@ describe ProgressBar::Base do
|
|
145
146
|
|
146
147
|
describe '#title' do
|
147
148
|
it 'returns the overridden title' do
|
148
|
-
progressbar.send(:title).to_s.
|
149
|
+
expect(progressbar.send(:title).to_s).to eql 'We All Float'
|
149
150
|
end
|
150
151
|
end
|
151
152
|
|
152
153
|
describe '#output' do
|
153
154
|
it 'returns the overridden output stream' do
|
154
|
-
progressbar.send(:output).
|
155
|
+
expect(progressbar.send(:output)).to eql STDOUT
|
155
156
|
end
|
156
157
|
end
|
157
158
|
|
158
159
|
describe '#length' do
|
159
160
|
it 'returns the overridden length' do
|
160
|
-
progressbar.send(:length).
|
161
|
+
expect(progressbar.send(:length)).to eql 88
|
161
162
|
end
|
162
163
|
end
|
163
164
|
end
|
@@ -185,15 +186,15 @@ describe ProgressBar::Base do
|
|
185
186
|
|
186
187
|
it 'completes the bar' do
|
187
188
|
output.rewind
|
188
|
-
output.read.
|
189
|
+
expect(output.read).to match /Progress: \|#{'=' * 68}\|\n/
|
189
190
|
end
|
190
191
|
|
191
192
|
it 'shows the elapsed time instead of the estimated time since the bar is completed' do
|
192
|
-
progressbar.to_s('%e').
|
193
|
+
expect(progressbar.to_s('%e')).to eql 'Time: 00:02:00'
|
193
194
|
end
|
194
195
|
|
195
196
|
it 'calculates the elapsed time to 00:02:00' do
|
196
|
-
progressbar.to_s('%a').
|
197
|
+
expect(progressbar.to_s('%a')).to eql 'Time: 00:02:00'
|
197
198
|
end
|
198
199
|
end
|
199
200
|
end
|
@@ -216,7 +217,7 @@ describe ProgressBar::Base do
|
|
216
217
|
progressbar.increment
|
217
218
|
|
218
219
|
output.rewind
|
219
|
-
output.read.
|
220
|
+
expect(output.read).to include "#{@color_code}Processing... #{@progress_mark * 3}#{' ' * 3}#{@reset_code}#{@color_code} 50%#{@reset_code}\r#{@color_code}Processing... #{@progress_mark * 3}#{' ' * 3}#{@reset_code}#{@color_code} 66%#{@reset_code}\r#{@color_code}Processing... #{@progress_mark * 4}#{' ' * 2}#{@reset_code}#{@color_code} 83%#{@reset_code}\r"
|
220
221
|
end
|
221
222
|
|
222
223
|
it 'properly calculates the length of the bar by removing the short version of the ANSI codes from the calculated length' do
|
@@ -235,7 +236,7 @@ describe ProgressBar::Base do
|
|
235
236
|
progressbar.increment
|
236
237
|
|
237
238
|
output.rewind
|
238
|
-
output.read.
|
239
|
+
expect(output.read).to include "#{@color_code}Processing... #{@progress_mark * 3}#{' ' * 3}#{@reset_code}#{@color_code} 50%#{@reset_code}\r#{@color_code}Processing... #{@progress_mark * 3}#{' ' * 3}#{@reset_code}#{@color_code} 66%#{@reset_code}\r#{@color_code}Processing... #{@progress_mark * 4}#{' ' * 2}#{@reset_code}#{@color_code} 83%#{@reset_code}\r"
|
239
240
|
end
|
240
241
|
end
|
241
242
|
|
@@ -247,7 +248,7 @@ describe ProgressBar::Base do
|
|
247
248
|
progressbar.increment
|
248
249
|
|
249
250
|
output.rewind
|
250
|
-
output.read.
|
251
|
+
expect(output.read).to include "Progress: |==== |\rProgress: |===== |\r \rWe All Float\nProgress: |===== |\rProgress: |====== |\r"
|
251
252
|
end
|
252
253
|
end
|
253
254
|
|
@@ -260,7 +261,7 @@ describe ProgressBar::Base do
|
|
260
261
|
progressbar.finish
|
261
262
|
|
262
263
|
non_tty_output.rewind
|
263
|
-
non_tty_output.read.
|
264
|
+
expect(non_tty_output.read).to include "We All Float\nProgress: |========|\n"
|
264
265
|
end
|
265
266
|
|
266
267
|
it 'can output the bar properly so that it does not spam the screen' do
|
@@ -269,7 +270,7 @@ describe ProgressBar::Base do
|
|
269
270
|
6.times { progressbar.increment }
|
270
271
|
|
271
272
|
non_tty_output.rewind
|
272
|
-
non_tty_output.read.
|
273
|
+
expect(non_tty_output.read).to eql "\n\nProgress: |========|\n"
|
273
274
|
end
|
274
275
|
|
275
276
|
it 'can output the bar properly if finished in the middle of its progress' do
|
@@ -280,7 +281,7 @@ describe ProgressBar::Base do
|
|
280
281
|
progressbar.finish
|
281
282
|
|
282
283
|
non_tty_output.rewind
|
283
|
-
non_tty_output.read.
|
284
|
+
expect(non_tty_output.read).to eql "\n\nProgress: |========|\n"
|
284
285
|
end
|
285
286
|
|
286
287
|
it 'can output the bar properly if stopped in the middle of its progress' do
|
@@ -291,7 +292,7 @@ describe ProgressBar::Base do
|
|
291
292
|
progressbar.stop
|
292
293
|
|
293
294
|
non_tty_output.rewind
|
294
|
-
non_tty_output.read.
|
295
|
+
expect(non_tty_output.read).to eql "\n\nProgress: |====\n"
|
295
296
|
end
|
296
297
|
end
|
297
298
|
end
|
@@ -303,19 +304,19 @@ describe ProgressBar::Base do
|
|
303
304
|
before { progressbar.increment }
|
304
305
|
|
305
306
|
it 'registers as being "finished"' do
|
306
|
-
progressbar.
|
307
|
+
expect(progressbar).to be_finished
|
307
308
|
end
|
308
309
|
|
309
310
|
it 'prints a new line' do
|
310
311
|
output.rewind
|
311
|
-
output.read.end_with?("\n").
|
312
|
+
expect(output.read.end_with?("\n")).to eql true
|
312
313
|
end
|
313
314
|
|
314
315
|
it 'does not continue to print bars if finish is subsequently called' do
|
315
316
|
progressbar.finish
|
316
317
|
|
317
318
|
output.rewind
|
318
|
-
output.read.
|
319
|
+
expect(output.read).to end_with " \rProgress: |====== |\rProgress: |========|\n"
|
319
320
|
end
|
320
321
|
end
|
321
322
|
end
|
@@ -324,25 +325,25 @@ describe ProgressBar::Base do
|
|
324
325
|
let(:progressbar) { ProgressBar::Base.new(:total => nil, :output => output, :length => 80, :unknown_progress_animation_steps => ['=--', '-=-', '--=']) }
|
325
326
|
|
326
327
|
it 'is represented correctly' do
|
327
|
-
progressbar.to_s('%i').
|
328
|
+
expect(progressbar.to_s('%i')).to eql '=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=-'
|
328
329
|
end
|
329
330
|
|
330
331
|
it 'is represented after being incremented once' do
|
331
332
|
progressbar.increment
|
332
|
-
progressbar.to_s('%i').
|
333
|
+
expect(progressbar.to_s('%i')).to eql '-=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--='
|
333
334
|
end
|
334
335
|
|
335
336
|
it 'is represented after being incremented twice' do
|
336
337
|
progressbar.increment
|
337
338
|
progressbar.increment
|
338
|
-
progressbar.to_s('%i').
|
339
|
+
expect(progressbar.to_s('%i')).to eql '--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--'
|
339
340
|
end
|
340
341
|
|
341
342
|
it 'displays the proper ETA' do
|
342
343
|
progressbar.increment
|
343
344
|
|
344
|
-
progressbar.to_s('%i%e').
|
345
|
-
progressbar.to_s('%i%E').
|
345
|
+
expect(progressbar.to_s('%i%e')).to eql '-=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=- ETA: ??:??:??'
|
346
|
+
expect(progressbar.to_s('%i%E')).to eql '-=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=- ETA: ??:??:??'
|
346
347
|
end
|
347
348
|
end
|
348
349
|
|
@@ -357,7 +358,7 @@ describe ProgressBar::Base do
|
|
357
358
|
progressbar.progress_mark = 'x'
|
358
359
|
|
359
360
|
output.rewind
|
360
|
-
output.read.
|
361
|
+
expect(output.read).to match /\rProgress: \|xxxxxx#{' ' * 62}\|\r\z/
|
361
362
|
end
|
362
363
|
end
|
363
364
|
|
@@ -366,7 +367,7 @@ describe ProgressBar::Base do
|
|
366
367
|
progressbar.remainder_mark = 'x'
|
367
368
|
|
368
369
|
output.rewind
|
369
|
-
output.read.
|
370
|
+
expect(output.read).to match /\rProgress: \|======#{'x' * 62}\|\r\z/
|
370
371
|
end
|
371
372
|
end
|
372
373
|
|
@@ -375,7 +376,7 @@ describe ProgressBar::Base do
|
|
375
376
|
progressbar.title = 'Items'
|
376
377
|
|
377
378
|
output.rewind
|
378
|
-
output.read.
|
379
|
+
expect(output.read).to match /\rItems: \|=======#{' ' * 64}\|\r\z/
|
379
380
|
end
|
380
381
|
end
|
381
382
|
|
@@ -384,7 +385,7 @@ describe ProgressBar::Base do
|
|
384
385
|
|
385
386
|
it 'resets the bar back to the starting value' do
|
386
387
|
output.rewind
|
387
|
-
output.read.
|
388
|
+
expect(output.read).to match /\rProgress: \|#{' ' * 68}\|\r\z/
|
388
389
|
end
|
389
390
|
end
|
390
391
|
|
@@ -393,7 +394,7 @@ describe ProgressBar::Base do
|
|
393
394
|
|
394
395
|
it 'forcibly halts the bar wherever it is and cancels it' do
|
395
396
|
output.rewind
|
396
|
-
output.read.
|
397
|
+
expect(output.read).to match /\rProgress: \|======#{' ' * 62}\|\n\z/
|
397
398
|
end
|
398
399
|
|
399
400
|
it 'does not output the bar multiple times if the bar is already stopped' do
|
@@ -401,7 +402,7 @@ describe ProgressBar::Base do
|
|
401
402
|
progressbar.stop
|
402
403
|
output.rewind
|
403
404
|
|
404
|
-
output.read.
|
405
|
+
expect(output.read).to start_with "#{' ' * 80}"
|
405
406
|
end
|
406
407
|
end
|
407
408
|
|
@@ -411,7 +412,7 @@ describe ProgressBar::Base do
|
|
411
412
|
progressbar.resume
|
412
413
|
output.rewind
|
413
414
|
|
414
|
-
output.read.
|
415
|
+
expect(output.read).to start_with "#{' ' * 80}"
|
415
416
|
end
|
416
417
|
end
|
417
418
|
end
|
@@ -428,7 +429,7 @@ describe ProgressBar::Base do
|
|
428
429
|
|
429
430
|
it 'resets the bar back to the starting value' do
|
430
431
|
output.rewind
|
431
|
-
output.read.
|
432
|
+
expect(output.read).to match /\rProgress: \|==========#{' ' * 90}\|\r\z/
|
432
433
|
end
|
433
434
|
end
|
434
435
|
end
|
@@ -439,7 +440,7 @@ describe ProgressBar::Base do
|
|
439
440
|
progressbar.clear
|
440
441
|
|
441
442
|
output.rewind
|
442
|
-
output.read.
|
443
|
+
expect(output.read).to match /^#{progressbar.send(:clear_string)}/
|
443
444
|
end
|
444
445
|
end
|
445
446
|
|
@@ -448,21 +449,21 @@ describe ProgressBar::Base do
|
|
448
449
|
progressbar.start
|
449
450
|
|
450
451
|
output.rewind
|
451
|
-
output.read.
|
452
|
+
expect(output.read).to match /^#{progressbar.send(:clear_string)}/
|
452
453
|
end
|
453
454
|
|
454
455
|
it 'prints the bar for the first time' do
|
455
456
|
progressbar.start
|
456
457
|
|
457
458
|
output.rewind
|
458
|
-
output.read.
|
459
|
+
expect(output.read).to match /Progress: \| \|\r\z/
|
459
460
|
end
|
460
461
|
|
461
462
|
it 'prints correctly if passed a position to start at' do
|
462
463
|
progressbar.start(:at => 20)
|
463
464
|
|
464
465
|
output.rewind
|
465
|
-
output.read.
|
466
|
+
expect(output.read).to match /Progress: \|============= \|\r\z/
|
466
467
|
end
|
467
468
|
end
|
468
469
|
|
@@ -474,7 +475,7 @@ describe ProgressBar::Base do
|
|
474
475
|
|
475
476
|
it 'displays the bar with the correct formatting' do
|
476
477
|
output.rewind
|
477
|
-
output.read.
|
478
|
+
expect(output.read).to match /Progress: \|== \|\r\z/
|
478
479
|
end
|
479
480
|
end
|
480
481
|
end
|
@@ -487,7 +488,7 @@ describe ProgressBar::Base do
|
|
487
488
|
before { progressbar.format }
|
488
489
|
|
489
490
|
it 'resets the format back to the default' do
|
490
|
-
progressbar.to_s.
|
491
|
+
expect(progressbar.to_s).to match /^Progress: \|\s+\|\z/
|
491
492
|
end
|
492
493
|
end
|
493
494
|
|
@@ -495,116 +496,260 @@ describe ProgressBar::Base do
|
|
495
496
|
before { progressbar.format '%t' }
|
496
497
|
|
497
498
|
it 'sets it as the new format for the bar' do
|
498
|
-
progressbar.to_s.
|
499
|
+
expect(progressbar.to_s).to match /^Progress\z/
|
499
500
|
end
|
500
501
|
end
|
501
502
|
end
|
502
503
|
|
503
504
|
context '#to_s' do
|
505
|
+
context 'when no time has elapsed' do
|
506
|
+
it 'displays zero for the rate' do
|
507
|
+
Timecop.freeze do
|
508
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 0)
|
509
|
+
|
510
|
+
expect(progressbar.to_s('%r')).to match /^0\z/
|
511
|
+
end
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
context 'when any time has elasped' do
|
516
|
+
context 'and the standard rate is applied' do
|
517
|
+
it 'displays zero for %r if no progress has been made' do
|
518
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
519
|
+
|
520
|
+
Timecop.travel(2) do
|
521
|
+
expect(progressbar.to_s('%r')).to match /^0\z/
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
it 'displays zero for %R if no progress has been made' do
|
526
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
527
|
+
|
528
|
+
Timecop.travel(2) do
|
529
|
+
expect(progressbar.to_s('%R')).to match /^0.00\z/
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
it 'takes into account the starting position when calculating %r' do
|
534
|
+
Timecop.freeze do
|
535
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
536
|
+
progressbar.start
|
537
|
+
progressbar.progress += 20
|
538
|
+
|
539
|
+
Timecop.travel(2) do
|
540
|
+
expect(progressbar.to_s('%r')).to match /^10\z/
|
541
|
+
end
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
it 'takes into account the starting position when calculating %R' do
|
546
|
+
Timecop.freeze do
|
547
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
548
|
+
progressbar.start
|
549
|
+
progressbar.progress += 13
|
550
|
+
|
551
|
+
Timecop.travel(2) do
|
552
|
+
expect(progressbar.to_s('%R')).to match /^6.50\z/
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
it 'displays the rate when passed the "%r" format flag' do
|
558
|
+
Timecop.freeze do
|
559
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 0)
|
560
|
+
progressbar.start
|
561
|
+
progressbar.progress += 20
|
562
|
+
|
563
|
+
Timecop.travel(2) do
|
564
|
+
expect(progressbar.to_s('%r')).to match /^10\z/
|
565
|
+
end
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
it 'displays the rate when passed the "%R" format flag' do
|
570
|
+
Timecop.freeze do
|
571
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 0)
|
572
|
+
progressbar.start
|
573
|
+
progressbar.progress += 10
|
574
|
+
|
575
|
+
Timecop.travel(6) do
|
576
|
+
expect(progressbar.to_s('%R')).to match /^1.67\z/
|
577
|
+
end
|
578
|
+
end
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
context 'and the a custom rate is applied' do
|
583
|
+
it 'displays zero for %r if no progress has been made' do
|
584
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20, :rate_scale => lambda { |rate| rate / 2 })
|
585
|
+
|
586
|
+
Timecop.travel(2) do
|
587
|
+
expect(progressbar.to_s('%r')).to match /^0\z/
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
it 'displays zero for %R if no progress has been made' do
|
592
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20, :rate_scale => lambda { |rate| rate / 2 })
|
593
|
+
|
594
|
+
Timecop.travel(2) do
|
595
|
+
expect(progressbar.to_s('%R')).to match /^0.00\z/
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
599
|
+
it 'takes into account the starting position when calculating %r' do
|
600
|
+
Timecop.freeze do
|
601
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20, :rate_scale => lambda { |rate| rate / 2 })
|
602
|
+
progressbar.start
|
603
|
+
progressbar.progress += 20
|
604
|
+
|
605
|
+
Timecop.travel(2) do
|
606
|
+
expect(progressbar.to_s('%r')).to match /^5\z/
|
607
|
+
end
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
it 'takes into account the starting position when calculating %R' do
|
612
|
+
Timecop.freeze do
|
613
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20, :rate_scale => lambda { |rate| rate / 2 })
|
614
|
+
progressbar.start
|
615
|
+
progressbar.progress += 13
|
616
|
+
|
617
|
+
Timecop.travel(2) do
|
618
|
+
expect(progressbar.to_s('%R')).to match /^3.25\z/
|
619
|
+
end
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
it 'displays the rate when passed the "%r" format flag' do
|
624
|
+
Timecop.freeze do
|
625
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 0, :rate_scale => lambda { |rate| rate / 2 })
|
626
|
+
progressbar.start
|
627
|
+
progressbar.progress += 20
|
628
|
+
|
629
|
+
Timecop.travel(2) do
|
630
|
+
expect(progressbar.to_s('%r')).to match /^5\z/
|
631
|
+
end
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
635
|
+
it 'displays the rate when passed the "%R" format flag' do
|
636
|
+
Timecop.freeze do
|
637
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 0, :rate_scale => lambda { |rate| rate / 2 })
|
638
|
+
progressbar.start
|
639
|
+
progressbar.progress += 10
|
640
|
+
|
641
|
+
Timecop.travel(6) do
|
642
|
+
expect(progressbar.to_s('%R')).to match /^0.83\z/
|
643
|
+
end
|
644
|
+
end
|
645
|
+
end
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
504
649
|
it 'displays the title when passed the "%t" format flag' do
|
505
|
-
progressbar.to_s('%t').
|
650
|
+
expect(progressbar.to_s('%t')).to match /^Progress\z/
|
506
651
|
end
|
507
652
|
|
508
653
|
it 'displays the title when passed the "%T" format flag' do
|
509
|
-
progressbar.to_s('%T').
|
654
|
+
expect(progressbar.to_s('%T')).to match /^Progress\z/
|
510
655
|
end
|
511
656
|
|
512
657
|
it 'displays the bar when passed the "%B" format flag (including empty space)' do
|
513
658
|
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
514
|
-
progressbar.to_s('%B').
|
659
|
+
expect(progressbar.to_s('%B')).to match /^#{'=' * 20}#{' ' * 80}\z/
|
515
660
|
end
|
516
661
|
|
517
662
|
it 'displays the bar when passed the combined "%b%i" format flags' do
|
518
663
|
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
519
|
-
progressbar.to_s('%b%i').
|
664
|
+
expect(progressbar.to_s('%b%i')).to match /^#{'=' * 20}#{' ' * 80}\z/
|
520
665
|
end
|
521
666
|
|
522
667
|
it 'displays the bar when passed the "%b" format flag (excluding empty space)' do
|
523
668
|
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
524
|
-
progressbar.to_s('%b').
|
669
|
+
expect(progressbar.to_s('%b')).to match /^#{'=' * 20}\z/
|
525
670
|
end
|
526
671
|
|
527
672
|
it 'displays the incomplete space when passed the "%i" format flag' do
|
528
673
|
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
529
|
-
progressbar.to_s('%i').
|
674
|
+
expect(progressbar.to_s('%i')).to match /^#{' ' * 80}\z/
|
530
675
|
end
|
531
676
|
|
532
677
|
it 'displays the bar when passed the "%w" format flag' do
|
533
678
|
progressbar = ProgressBar::Base.new(:output => output, :length => 100, :starting_at => 0)
|
534
679
|
|
535
|
-
progressbar.to_s('%w').
|
680
|
+
expect(progressbar.to_s('%w')).to match /^\z/
|
536
681
|
4.times { progressbar.increment }
|
537
|
-
progressbar.to_s('%w').
|
682
|
+
expect(progressbar.to_s('%w')).to match /^====\z/
|
538
683
|
progressbar.increment
|
539
|
-
progressbar.to_s('%w').
|
684
|
+
expect(progressbar.to_s('%w')).to match /^= 5 =\z/
|
540
685
|
5.times { progressbar.increment }
|
541
|
-
progressbar.to_s('%w').
|
686
|
+
expect(progressbar.to_s('%w')).to match /^=== 10 ===\z/
|
542
687
|
progressbar.decrement
|
543
|
-
progressbar.to_s('%w').
|
688
|
+
expect(progressbar.to_s('%w')).to match /^=== 9 ===\z/
|
544
689
|
91.times { progressbar.increment }
|
545
|
-
progressbar.to_s('%w').
|
690
|
+
expect(progressbar.to_s('%w')).to match /^#{'=' * 47} 100 #{'=' * 48}\z/
|
546
691
|
end
|
547
692
|
|
548
693
|
it 'calculates the remaining negative space properly with an integrated percentage bar of 0 percent' do
|
549
694
|
progressbar = ProgressBar::Base.new(:output => output, :length => 100, :total => 200, :starting_at => 0)
|
550
695
|
|
551
|
-
progressbar.to_s('%w%i').
|
696
|
+
expect(progressbar.to_s('%w%i')).to match /^\s{100}\z/
|
552
697
|
9.times { progressbar.increment }
|
553
|
-
progressbar.to_s('%w%i').
|
698
|
+
expect(progressbar.to_s('%w%i')).to match /^====\s{96}\z/
|
554
699
|
progressbar.increment
|
555
|
-
progressbar.to_s('%w%i').
|
700
|
+
expect(progressbar.to_s('%w%i')).to match /^= 5 =\s{95}\z/
|
556
701
|
end
|
557
702
|
|
558
703
|
it 'displays the current capacity when passed the "%c" format flag' do
|
559
704
|
progressbar = ProgressBar::Base.new(:output => output, :starting_at => 0)
|
560
705
|
|
561
|
-
progressbar.to_s('%c').
|
706
|
+
expect(progressbar.to_s('%c')).to match /^0\z/
|
562
707
|
progressbar.increment
|
563
|
-
progressbar.to_s('%c').
|
708
|
+
expect(progressbar.to_s('%c')).to match /^1\z/
|
564
709
|
progressbar.decrement
|
565
|
-
progressbar.to_s('%c').
|
710
|
+
expect(progressbar.to_s('%c')).to match /^0\z/
|
566
711
|
end
|
567
712
|
|
568
713
|
it 'displays the total capacity when passed the "%C" format flag' do
|
569
714
|
progressbar = ProgressBar::Base.new(:total => 100)
|
570
715
|
|
571
|
-
progressbar.to_s('%C').
|
716
|
+
expect(progressbar.to_s('%C')).to match /^100\z/
|
572
717
|
end
|
573
718
|
|
574
719
|
it 'displays the percentage complete when passed the "%p" format flag' do
|
575
720
|
progressbar = ProgressBar::Base.new(:starting_at => 33, :total => 200)
|
576
721
|
|
577
|
-
progressbar.to_s('%p').
|
722
|
+
expect(progressbar.to_s('%p')).to match /^16\z/
|
578
723
|
end
|
579
724
|
|
580
725
|
it 'displays the percentage complete when passed the "%P" format flag' do
|
581
726
|
progressbar = ProgressBar::Base.new(:starting_at => 33, :total => 200)
|
582
727
|
|
583
|
-
progressbar.to_s('%P').
|
728
|
+
expect(progressbar.to_s('%P')).to match /^16.50\z/
|
584
729
|
end
|
585
730
|
|
586
731
|
it 'displays only up to 2 decimal places when using the "%P" flag' do
|
587
732
|
progressbar = ProgressBar::Base.new(:starting_at => 66, :total => 99)
|
588
733
|
|
589
|
-
progressbar.to_s('%P').
|
734
|
+
expect(progressbar.to_s('%P')).to match /^66.66\z/
|
590
735
|
end
|
591
736
|
|
592
737
|
it 'displays a literal percent sign when using the "%%" flag' do
|
593
738
|
progressbar = ProgressBar::Base.new(:starting_at => 66, :total => 99)
|
594
739
|
|
595
|
-
progressbar.to_s('%%').
|
740
|
+
expect(progressbar.to_s('%%')).to match /^%\z/
|
596
741
|
end
|
597
742
|
|
598
743
|
it 'displays a literal percent sign when using the "%%" flag' do
|
599
744
|
progressbar = ProgressBar::Base.new(:starting_at => 66, :total => 99)
|
600
745
|
|
601
|
-
progressbar.to_s('%%').
|
746
|
+
expect(progressbar.to_s('%%')).to match /^%\z/
|
602
747
|
end
|
603
748
|
|
604
749
|
# Autostarting for now. This will be applicable later.
|
605
750
|
# context "when called before #start" do
|
606
751
|
# it "displays unknown time elapsed when using the %a flag" do
|
607
|
-
|
752
|
+
# expect(progressbar.to_s('%a')).to match /^Time: --:--:--\z/
|
608
753
|
# end
|
609
754
|
# end
|
610
755
|
|
@@ -619,19 +764,19 @@ describe ProgressBar::Base do
|
|
619
764
|
before { progressbar.reset }
|
620
765
|
|
621
766
|
it 'displays "??:??:??" until finished when passed the %e flag' do
|
622
|
-
progressbar.to_s('%a').
|
767
|
+
expect(progressbar.to_s('%a')).to match /^Time: --:--:--\z/
|
623
768
|
end
|
624
769
|
end
|
625
770
|
|
626
771
|
it 'displays the time elapsed when using the "%a" flag' do
|
627
|
-
progressbar.to_s('%a').
|
772
|
+
expect(progressbar.to_s('%a')).to match /^Time: 01:02:03\z/
|
628
773
|
end
|
629
774
|
end
|
630
775
|
|
631
776
|
context 'when called before #start' do
|
632
777
|
it 'displays unknown time until finished when passed the "%e" flag' do
|
633
778
|
progressbar = ProgressBar::Base.new
|
634
|
-
progressbar.to_s('%e').
|
779
|
+
expect(progressbar.to_s('%e')).to match /^ ETA: \?\?:\?\?:\?\?\z/
|
635
780
|
end
|
636
781
|
end
|
637
782
|
|
@@ -649,12 +794,12 @@ describe ProgressBar::Base do
|
|
649
794
|
before { progressbar.reset }
|
650
795
|
|
651
796
|
it 'displays "??:??:??" until finished when passed the "%e" flag' do
|
652
|
-
progressbar.to_s('%e').
|
797
|
+
expect(progressbar.to_s('%e')).to match /^ ETA: \?\?:\?\?:\?\?\z/
|
653
798
|
end
|
654
799
|
end
|
655
800
|
|
656
801
|
it 'displays the estimated time remaining when using the "%e" flag' do
|
657
|
-
progressbar.to_s('%e').
|
802
|
+
expect(progressbar.to_s('%e')).to match /^ ETA: 01:02:03\z/
|
658
803
|
end
|
659
804
|
end
|
660
805
|
|
@@ -669,15 +814,15 @@ describe ProgressBar::Base do
|
|
669
814
|
end
|
670
815
|
|
671
816
|
it 'displays "> 4 Days" until finished when passed the "%E" flag' do
|
672
|
-
progressbar.to_s('%E').
|
817
|
+
expect(progressbar.to_s('%E')).to match /^ ETA: > 4 Days\z/
|
673
818
|
end
|
674
819
|
|
675
820
|
it 'displays "??:??:??" until finished when passed the "%e" flag' do
|
676
|
-
progressbar.to_s('%e').
|
821
|
+
expect(progressbar.to_s('%e')).to match /^ ETA: \?\?:\?\?:\?\?\z/
|
677
822
|
end
|
678
823
|
|
679
824
|
it 'displays the exact estimated time until finished when passed the "%f" flag' do
|
680
|
-
progressbar.to_s('%f').
|
825
|
+
expect(progressbar.to_s('%f')).to match /^ ETA: 100:00:00\z/
|
681
826
|
end
|
682
827
|
end
|
683
828
|
end
|