progress 3.0.2 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.rubocop.yml +65 -0
- data/.travis.yml +13 -2
- data/Gemfile +1 -1
- data/README.markdown +6 -2
- data/lib/progress.rb +12 -221
- data/lib/progress/active_record.rb +3 -5
- data/lib/progress/beeper.rb +1 -0
- data/lib/progress/class_methods.rb +214 -0
- data/lib/progress/enumerable.rb +3 -1
- data/lib/progress/eta.rb +20 -22
- data/lib/progress/integer.rb +1 -0
- data/lib/progress/kernel.rb +9 -0
- data/lib/progress/with_progress.rb +91 -43
- data/progress.gemspec +5 -2
- data/spec/progress_spec.rb +246 -179
- data/spec/test.csv +8 -0
- metadata +25 -6
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YmExNzc5ZGQ5Mzc1ZGQzY2Y4Zjg0N2ExNGMyZGNlNzQ0NDhmZTIyYQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MThiNTU2Yzc1MTAzMGI3ZDY5M2UwNDBhZmZhOTM1ZWI0YzMyNDEyNg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MjIxMGI1Y2Q3OGI1MzJhZDZmMzJmNTllZDFjMTE1ODhjZTM0OTliZWQwODhm
|
10
|
+
MDdmOWM1NWU5NGM2Y2I1OTFkMjJkYjdhZTE5ZmRlOThmZGNhZDdjYzRhYTJj
|
11
|
+
NGNjOTM2YmNkMjdiOThlYWE1ZDNhM2EyZWRhMTgyYTVjMjJlMGU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZmE3MDVkNDgxOTY4NmUxMGY1MjAzMjMwMzEwNTkwYmFhYzA3ZmExYjExZGZm
|
14
|
+
YjYyZDRiMzc4MDBjOGQ1ZWRiYWZjNDA2NzkwNDk4NjU5NTM0NjljNTE0MjM4
|
15
|
+
OTcxOGRlY2U4NjhmZWQzZDUyZDNlNzFkNDljZWIwOWQzYWVkZTI=
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- '*.gemspec'
|
4
|
+
|
5
|
+
Lint/EndAlignment:
|
6
|
+
AlignWith: variable
|
7
|
+
|
8
|
+
Metrics/AbcSize:
|
9
|
+
Max: 30
|
10
|
+
|
11
|
+
Metrics/ClassLength:
|
12
|
+
Max: 150
|
13
|
+
|
14
|
+
Metrics/CyclomaticComplexity:
|
15
|
+
Max: 10
|
16
|
+
|
17
|
+
Metrics/MethodLength:
|
18
|
+
Max: 20
|
19
|
+
|
20
|
+
Metrics/PerceivedComplexity:
|
21
|
+
Max: 10
|
22
|
+
|
23
|
+
Style/AccessModifierIndentation:
|
24
|
+
EnforcedStyle: outdent
|
25
|
+
|
26
|
+
Style/BracesAroundHashParameters:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
Style/CaseIndentation:
|
30
|
+
IndentWhenRelativeTo: end
|
31
|
+
|
32
|
+
Style/DotPosition:
|
33
|
+
EnforcedStyle: trailing
|
34
|
+
|
35
|
+
Style/DoubleNegation:
|
36
|
+
Enabled: false
|
37
|
+
|
38
|
+
Style/Encoding:
|
39
|
+
EnforcedStyle: when_needed
|
40
|
+
|
41
|
+
Style/HashSyntax:
|
42
|
+
EnforcedStyle: hash_rockets
|
43
|
+
|
44
|
+
Style/IfUnlessModifier:
|
45
|
+
MaxLineLength: 40
|
46
|
+
|
47
|
+
Style/IndentHash:
|
48
|
+
EnforcedStyle: consistent
|
49
|
+
|
50
|
+
Style/PercentLiteralDelimiters:
|
51
|
+
PreferredDelimiters:
|
52
|
+
'%w': '[]'
|
53
|
+
'%W': '[]'
|
54
|
+
|
55
|
+
Style/Semicolon:
|
56
|
+
AllowAsExpressionSeparator: true
|
57
|
+
|
58
|
+
Style/SpaceBeforeBlockBraces:
|
59
|
+
EnforcedStyle: no_space
|
60
|
+
|
61
|
+
Style/SpaceInsideHashLiteralBraces:
|
62
|
+
EnforcedStyle: no_space
|
63
|
+
|
64
|
+
Style/TrailingComma:
|
65
|
+
EnforcedStyleForMultiline: comma
|
data/.travis.yml
CHANGED
@@ -3,8 +3,19 @@ rvm:
|
|
3
3
|
- 1.8.7
|
4
4
|
- 1.9.2
|
5
5
|
- 1.9.3
|
6
|
-
- 2.0
|
6
|
+
- '2.0'
|
7
|
+
- '2.1'
|
7
8
|
- jruby-18mode
|
8
9
|
- jruby-19mode
|
9
10
|
- ree
|
10
|
-
script:
|
11
|
+
script:
|
12
|
+
if [ -z "$RUBOCOP" ]; then
|
13
|
+
bundle exec rspec
|
14
|
+
; else
|
15
|
+
bundle exec rubocop
|
16
|
+
; fi
|
17
|
+
matrix:
|
18
|
+
fast_finish: true
|
19
|
+
include:
|
20
|
+
- env: RUBOCOP=true
|
21
|
+
rvm: default
|
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
[![Gem Version](https://img.shields.io/gem/v/progress.svg?style=flat)](https://rubygems.org/gems/progress)
|
2
|
+
[![Build Status](https://img.shields.io/travis/toy/progress/master.svg?style=flat)](https://travis-ci.org/toy/progress)
|
3
|
+
[![Code Climate](https://img.shields.io/codeclimate/github/toy/progress.svg?style=flat)](https://codeclimate.com/github/toy/progress)
|
4
|
+
[![Dependency Status](https://img.shields.io/gemnasium/toy/progress.svg?style=flat)](https://gemnasium.com/toy/progress)
|
5
|
+
[![Inch CI](http://inch-ci.org/github/toy/progress.svg?branch=master&style=flat)](http://inch-ci.org/github/toy/progress)
|
6
|
+
|
1
7
|
# progress
|
2
8
|
|
3
9
|
Show progress during console script run.
|
4
10
|
|
5
|
-
[![Build Status](https://travis-ci.org/toy/progress.png?branch=master)](https://travis-ci.org/toy/progress)
|
6
|
-
|
7
11
|
## Installation
|
8
12
|
|
9
13
|
gem install progress
|
data/lib/progress.rb
CHANGED
@@ -3,6 +3,15 @@
|
|
3
3
|
require 'singleton'
|
4
4
|
require 'thread'
|
5
5
|
|
6
|
+
require 'progress/class_methods'
|
7
|
+
require 'progress/beeper'
|
8
|
+
require 'progress/eta'
|
9
|
+
|
10
|
+
require 'progress/kernel'
|
11
|
+
require 'progress/enumerable'
|
12
|
+
require 'progress/integer'
|
13
|
+
require 'progress/active_record' if defined?(ActiveRecord::Base)
|
14
|
+
|
6
15
|
# ==== Procedural example
|
7
16
|
# Progress.start('Test', 1000)
|
8
17
|
# 1000.times do
|
@@ -36,13 +45,14 @@ require 'thread'
|
|
36
45
|
# end
|
37
46
|
class Progress
|
38
47
|
include Singleton
|
48
|
+
extend ClassMethods
|
39
49
|
|
40
50
|
attr_reader :total
|
41
51
|
attr_reader :current
|
42
52
|
attr_reader :title
|
43
53
|
attr_accessor :note
|
44
54
|
def initialize(total, title)
|
45
|
-
if !total.
|
55
|
+
if !total.is_a?(Numeric) && (title.nil? || title.is_a?(Numeric))
|
46
56
|
total, title = title, total
|
47
57
|
end
|
48
58
|
total = total && total != 0 ? Float(total) : 1.0
|
@@ -59,7 +69,7 @@ class Progress
|
|
59
69
|
end
|
60
70
|
|
61
71
|
def step(step, note)
|
62
|
-
|
72
|
+
unless step.is_a?(Numeric)
|
63
73
|
step, note = nil, step
|
64
74
|
end
|
65
75
|
step = 1 if step.nil?
|
@@ -82,223 +92,4 @@ class Progress
|
|
82
92
|
end
|
83
93
|
ret
|
84
94
|
end
|
85
|
-
|
86
|
-
@lock = Mutex.new
|
87
|
-
class << self
|
88
|
-
|
89
|
-
# start progress indication
|
90
|
-
def start(total = nil, title = nil)
|
91
|
-
lock do
|
92
|
-
if running?
|
93
|
-
unless @started_in == Thread.current
|
94
|
-
warn 'Can\'t start inner progress in different thread'
|
95
|
-
if block_given?
|
96
|
-
return yield
|
97
|
-
else
|
98
|
-
return
|
99
|
-
end
|
100
|
-
end
|
101
|
-
else
|
102
|
-
@started_in = Thread.current
|
103
|
-
@eta = Eta.new
|
104
|
-
start_beeper
|
105
|
-
end
|
106
|
-
@levels ||= []
|
107
|
-
@levels.push new(total, title)
|
108
|
-
end
|
109
|
-
print_message :force => true
|
110
|
-
if block_given?
|
111
|
-
begin
|
112
|
-
yield
|
113
|
-
ensure
|
114
|
-
stop
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# step current progress
|
120
|
-
def step(step = nil, note = nil, &block)
|
121
|
-
if running?
|
122
|
-
ret = @levels.last.step(step, note, &block)
|
123
|
-
print_message
|
124
|
-
ret
|
125
|
-
elsif block
|
126
|
-
block.call
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
# set value of current progress
|
131
|
-
def set(new_current, note = nil, &block)
|
132
|
-
if running?
|
133
|
-
ret = @levels.last.set(new_current, note, &block)
|
134
|
-
print_message
|
135
|
-
ret
|
136
|
-
elsif block
|
137
|
-
block.call
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
# stop progress
|
142
|
-
def stop
|
143
|
-
if running?
|
144
|
-
if @levels.length == 1
|
145
|
-
print_message :force => true, :finish => true
|
146
|
-
stop_beeper
|
147
|
-
end
|
148
|
-
@levels.pop
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
# check if progress was started
|
153
|
-
def running?
|
154
|
-
@levels && !@levels.empty?
|
155
|
-
end
|
156
|
-
|
157
|
-
# set note
|
158
|
-
def note=(note)
|
159
|
-
if running?
|
160
|
-
@levels.last.note = note
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
# stay on one line
|
165
|
-
def stay_on_line?
|
166
|
-
@stay_on_line.nil? ? io_tty? : @stay_on_line
|
167
|
-
end
|
168
|
-
|
169
|
-
# explicitly set staying on one line [true/false/nil]
|
170
|
-
def stay_on_line=(value)
|
171
|
-
@stay_on_line = true && value
|
172
|
-
end
|
173
|
-
|
174
|
-
# highlight output using control characters
|
175
|
-
def highlight?
|
176
|
-
@highlight.nil? ? io_tty? : @highlight
|
177
|
-
end
|
178
|
-
|
179
|
-
# explicitly set highlighting [true/false/nil]
|
180
|
-
def highlight=(value)
|
181
|
-
@highlight = true && value
|
182
|
-
end
|
183
|
-
|
184
|
-
# show progerss in terminal title
|
185
|
-
def set_terminal_title?
|
186
|
-
@set_terminal_title.nil? ? io_tty? : @set_terminal_title
|
187
|
-
end
|
188
|
-
|
189
|
-
# explicitly set showing progress in terminal title [true/false/nil]
|
190
|
-
def set_terminal_title=(value)
|
191
|
-
@set_terminal_title = true && value
|
192
|
-
end
|
193
|
-
|
194
|
-
private
|
195
|
-
|
196
|
-
def lock(force = true)
|
197
|
-
if force ? @lock.lock : @lock.try_lock
|
198
|
-
begin
|
199
|
-
yield
|
200
|
-
ensure
|
201
|
-
@lock.unlock
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def io
|
207
|
-
@io || $stderr
|
208
|
-
end
|
209
|
-
|
210
|
-
def io_tty?
|
211
|
-
io.tty? || ENV['PROGRESS_TTY']
|
212
|
-
end
|
213
|
-
|
214
|
-
def start_beeper
|
215
|
-
@beeper = Beeper.new(10) do
|
216
|
-
print_message
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
def stop_beeper
|
221
|
-
@beeper.stop if @beeper
|
222
|
-
end
|
223
|
-
|
224
|
-
def restart_beeper
|
225
|
-
@beeper.restart if @beeper
|
226
|
-
end
|
227
|
-
|
228
|
-
def time_to_print?
|
229
|
-
!@next_time_to_print || @next_time_to_print <= Time.now
|
230
|
-
end
|
231
|
-
|
232
|
-
def eta(current)
|
233
|
-
@eta.left(current)
|
234
|
-
end
|
235
|
-
|
236
|
-
def elapsed
|
237
|
-
@eta.elapsed
|
238
|
-
end
|
239
|
-
|
240
|
-
def print_message(options = {})
|
241
|
-
force = options[:force]
|
242
|
-
lock force do
|
243
|
-
if force || time_to_print?
|
244
|
-
@next_time_to_print = Time.now + 0.3
|
245
|
-
restart_beeper
|
246
|
-
|
247
|
-
current = 0
|
248
|
-
parts = []
|
249
|
-
title_parts = []
|
250
|
-
@levels.reverse.each do |level|
|
251
|
-
current = level.to_f(current)
|
252
|
-
|
253
|
-
percent = current == 0 ? '......' : "#{'%5.1f' % (current * 100.0)}%"
|
254
|
-
title = level.title && "#{level.title}: "
|
255
|
-
if !highlight? || percent == '100.0%'
|
256
|
-
parts << "#{title}#{percent}"
|
257
|
-
else
|
258
|
-
parts << "#{title}\e[1m#{percent}\e[0m"
|
259
|
-
end
|
260
|
-
title_parts << "#{title}#{percent}"
|
261
|
-
end
|
262
|
-
|
263
|
-
timing = if options[:finish]
|
264
|
-
" (elapsed: #{elapsed})"
|
265
|
-
elsif eta_ = eta(current)
|
266
|
-
" (ETA: #{eta_})"
|
267
|
-
end
|
268
|
-
|
269
|
-
message = "#{parts.reverse * ' > '}#{timing}"
|
270
|
-
text_message = "#{title_parts.reverse * ' > '}#{timing}"
|
271
|
-
|
272
|
-
if note = running? && @levels.last.note
|
273
|
-
message << " - #{note}"
|
274
|
-
text_message << " - #{note}"
|
275
|
-
end
|
276
|
-
|
277
|
-
message = "\r#{message}\e[K" if stay_on_line?
|
278
|
-
message << "\n" if !stay_on_line? || options[:finish]
|
279
|
-
io << message
|
280
|
-
|
281
|
-
if set_terminal_title?
|
282
|
-
title = options[:finish] ? nil : text_message.to_s.gsub("\a", '␇')
|
283
|
-
io << "\e]0;#{title}\a"
|
284
|
-
end
|
285
|
-
end
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
require 'progress/beeper'
|
293
|
-
require 'progress/eta'
|
294
|
-
|
295
|
-
require 'progress/enumerable'
|
296
|
-
require 'progress/integer'
|
297
|
-
require 'progress/active_record' if defined?(ActiveRecord::Base)
|
298
|
-
|
299
|
-
module Kernel
|
300
|
-
def Progress(*args, &block)
|
301
|
-
Progress.start(*args, &block)
|
302
|
-
end
|
303
|
-
private :Progress
|
304
95
|
end
|
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'progress'
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
-
|
4
|
+
# Add find_each_with_progress and find_in_batches_with_progress method to
|
5
|
+
# ActiveRecord::Base
|
6
|
+
class Base
|
5
7
|
# run `find_each` with progress
|
6
8
|
def find_each_with_progress(options = {})
|
7
9
|
Progress.start(name.tableize, count(options)) do
|
@@ -24,8 +26,4 @@ module ActiveRecord
|
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
27
|
-
|
28
|
-
class Base
|
29
|
-
extend BatchesWithProgress
|
30
|
-
end
|
31
29
|
end
|
data/lib/progress/beeper.rb
CHANGED
@@ -0,0 +1,214 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
class Progress
|
4
|
+
# Class methods of Progress
|
5
|
+
module ClassMethods
|
6
|
+
def self.extended(klass)
|
7
|
+
klass.instance_variable_set(:@lock, Mutex.new)
|
8
|
+
end
|
9
|
+
|
10
|
+
# start progress indication
|
11
|
+
def start(total = nil, title = nil)
|
12
|
+
init(total, title)
|
13
|
+
print_message :force => true
|
14
|
+
return unless block_given?
|
15
|
+
begin
|
16
|
+
yield
|
17
|
+
ensure
|
18
|
+
stop
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# step current progress
|
23
|
+
def step(step = nil, note = nil, &block)
|
24
|
+
if running?
|
25
|
+
ret = @levels.last.step(step, note, &block)
|
26
|
+
print_message
|
27
|
+
ret
|
28
|
+
elsif block
|
29
|
+
block.call
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# set value of current progress
|
34
|
+
def set(new_current, note = nil, &block)
|
35
|
+
if running?
|
36
|
+
ret = @levels.last.set(new_current, note, &block)
|
37
|
+
print_message
|
38
|
+
ret
|
39
|
+
elsif block
|
40
|
+
block.call
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# stop progress
|
45
|
+
def stop
|
46
|
+
return unless running?
|
47
|
+
if @levels.length == 1
|
48
|
+
print_message :force => true, :finish => true
|
49
|
+
stop_beeper
|
50
|
+
end
|
51
|
+
@levels.pop
|
52
|
+
end
|
53
|
+
|
54
|
+
# check if progress was started
|
55
|
+
def running?
|
56
|
+
@levels && !@levels.empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
# set note
|
60
|
+
def note=(note)
|
61
|
+
return unless running?
|
62
|
+
@levels.last.note = note
|
63
|
+
end
|
64
|
+
|
65
|
+
# stay on one line
|
66
|
+
def stay_on_line?
|
67
|
+
@stay_on_line.nil? ? io_tty? : @stay_on_line
|
68
|
+
end
|
69
|
+
|
70
|
+
# explicitly set staying on one line [true/false/nil]
|
71
|
+
def stay_on_line=(value)
|
72
|
+
@stay_on_line = true && value
|
73
|
+
end
|
74
|
+
|
75
|
+
# highlight output using control characters
|
76
|
+
def highlight?
|
77
|
+
@highlight.nil? ? io_tty? : @highlight
|
78
|
+
end
|
79
|
+
|
80
|
+
# explicitly set highlighting [true/false/nil]
|
81
|
+
def highlight=(value)
|
82
|
+
@highlight = true && value
|
83
|
+
end
|
84
|
+
|
85
|
+
# show progerss in terminal title
|
86
|
+
def terminal_title?
|
87
|
+
@terminal_title.nil? ? io_tty? : @terminal_title
|
88
|
+
end
|
89
|
+
|
90
|
+
# explicitly set showing progress in terminal title [true/false/nil]
|
91
|
+
def terminal_title=(value)
|
92
|
+
@terminal_title = true && value
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
attr_reader :eta
|
98
|
+
|
99
|
+
def init(total = nil, title = nil)
|
100
|
+
lock do
|
101
|
+
if running?
|
102
|
+
unless @started_in == Thread.current
|
103
|
+
warn 'Can\'t start inner progress in different thread'
|
104
|
+
return block_given? ? yield : nil
|
105
|
+
end
|
106
|
+
else
|
107
|
+
@started_in = Thread.current
|
108
|
+
@eta = Eta.new
|
109
|
+
start_beeper
|
110
|
+
end
|
111
|
+
@levels ||= []
|
112
|
+
@levels.push new(total, title)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def lock(force = true)
|
117
|
+
if force
|
118
|
+
@lock.lock
|
119
|
+
else
|
120
|
+
return unless @lock.try_lock
|
121
|
+
end
|
122
|
+
|
123
|
+
begin
|
124
|
+
yield
|
125
|
+
ensure
|
126
|
+
@lock.unlock
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def io
|
131
|
+
@io || $stderr
|
132
|
+
end
|
133
|
+
|
134
|
+
def io_tty?
|
135
|
+
io.tty? || ENV['PROGRESS_TTY']
|
136
|
+
end
|
137
|
+
|
138
|
+
def start_beeper
|
139
|
+
@beeper = Beeper.new(10) do
|
140
|
+
print_message
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def stop_beeper
|
145
|
+
@beeper.stop if @beeper
|
146
|
+
end
|
147
|
+
|
148
|
+
def restart_beeper
|
149
|
+
@beeper.restart if @beeper
|
150
|
+
end
|
151
|
+
|
152
|
+
def time_to_print?
|
153
|
+
!@next_time_to_print || @next_time_to_print <= Time.now
|
154
|
+
end
|
155
|
+
|
156
|
+
def print_message(options = {})
|
157
|
+
force = options[:force]
|
158
|
+
lock force do
|
159
|
+
if force || time_to_print?
|
160
|
+
@next_time_to_print = Time.now + 0.3
|
161
|
+
restart_beeper
|
162
|
+
io << message_for_output(options)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def message_for_output(options)
|
168
|
+
message = build_message(options)
|
169
|
+
|
170
|
+
out = ''
|
171
|
+
out << "\r" if stay_on_line?
|
172
|
+
out << message
|
173
|
+
out << "\e[K" if stay_on_line?
|
174
|
+
out << "\n" if !stay_on_line? || options[:finish]
|
175
|
+
|
176
|
+
if terminal_title?
|
177
|
+
out << "\e]0;"
|
178
|
+
unless options[:finish]
|
179
|
+
out << message.gsub(/\e\[\dm/, '').gsub("\a", '␇')
|
180
|
+
end
|
181
|
+
out << "\a"
|
182
|
+
end
|
183
|
+
|
184
|
+
out
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_message(options)
|
188
|
+
current = 0
|
189
|
+
message = @levels.reverse.map do |level|
|
190
|
+
current = level.to_f(current)
|
191
|
+
|
192
|
+
part = current.zero? ? '......' : format('%5.1f%%', current * 100.0)
|
193
|
+
|
194
|
+
if highlight? && part != '100.0%'
|
195
|
+
part = "\e[1m#{part}\e[0m"
|
196
|
+
end
|
197
|
+
|
198
|
+
level.title ? "#{level.title}: #{part}" : part
|
199
|
+
end.reverse * ' > '
|
200
|
+
|
201
|
+
if options[:finish]
|
202
|
+
message << " (elapsed: #{eta.elapsed})"
|
203
|
+
elsif (left = eta.left(current))
|
204
|
+
message << " (ETA: #{left})"
|
205
|
+
end
|
206
|
+
|
207
|
+
if running? && (note = @levels.last.note)
|
208
|
+
message << " - #{note}"
|
209
|
+
end
|
210
|
+
|
211
|
+
message
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|