tty-progressbar 0.17.0 → 0.18.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/LICENSE.txt +1 -1
- data/README.md +492 -126
- data/lib/tty-progressbar.rb +2 -2
- data/lib/tty/progressbar.rb +168 -68
- data/lib/tty/progressbar/configuration.rb +121 -27
- data/lib/tty/progressbar/converter.rb +16 -19
- data/lib/tty/progressbar/formats.rb +120 -0
- data/lib/tty/progressbar/formatter.rb +33 -38
- data/lib/tty/progressbar/formatter/bar.rb +74 -27
- data/lib/tty/progressbar/formatter/byte_rate.rb +6 -20
- data/lib/tty/progressbar/formatter/current.rb +4 -19
- data/lib/tty/progressbar/formatter/current_byte.rb +9 -17
- data/lib/tty/progressbar/formatter/elapsed.rb +9 -18
- data/lib/tty/progressbar/formatter/estimated.rb +14 -18
- data/lib/tty/progressbar/formatter/estimated_time.rb +37 -0
- data/lib/tty/progressbar/formatter/mean_byte.rb +6 -20
- data/lib/tty/progressbar/formatter/mean_rate.rb +6 -20
- data/lib/tty/progressbar/formatter/percent.rb +10 -16
- data/lib/tty/progressbar/formatter/rate.rb +5 -19
- data/lib/tty/progressbar/formatter/total.rb +10 -16
- data/lib/tty/progressbar/formatter/total_byte.rb +14 -18
- data/lib/tty/progressbar/formatters.rb +53 -0
- data/lib/tty/progressbar/meter.rb +2 -2
- data/lib/tty/progressbar/multi.rb +61 -21
- data/lib/tty/progressbar/pipeline.rb +13 -6
- data/lib/tty/progressbar/timer.rb +89 -0
- data/lib/tty/progressbar/version.rb +1 -1
- metadata +44 -103
- data/Rakefile +0 -8
- data/examples/color.rb +0 -18
- data/examples/failure.rb +0 -12
- data/examples/iterator.rb +0 -5
- data/examples/lazy.rb +0 -6
- data/examples/multi/main_bar.rb +0 -13
- data/examples/multi/simple.rb +0 -13
- data/examples/multi/width.rb +0 -13
- data/examples/simple.rb +0 -7
- data/examples/slow_process.rb +0 -29
- data/examples/speed.rb +0 -11
- data/examples/threaded.rb +0 -14
- data/examples/tokens.rb +0 -12
- data/examples/unicode.rb +0 -7
- data/spec/spec_helper.rb +0 -53
- data/spec/unit/advance_spec.rb +0 -25
- data/spec/unit/clear_spec.rb +0 -17
- data/spec/unit/complete_spec.rb +0 -16
- data/spec/unit/converter/to_bytes_spec.rb +0 -47
- data/spec/unit/converter/to_seconds_spec.rb +0 -15
- data/spec/unit/converter/to_time_spec.rb +0 -19
- data/spec/unit/custom_formatter_spec.rb +0 -26
- data/spec/unit/custom_token_spec.rb +0 -14
- data/spec/unit/events_spec.rb +0 -33
- data/spec/unit/finish_spec.rb +0 -15
- data/spec/unit/formatter/bar_spec.rb +0 -33
- data/spec/unit/formatter/byte_rate_spec.rb +0 -32
- data/spec/unit/formatter/current_byte_spec.rb +0 -16
- data/spec/unit/formatter/current_spec.rb +0 -14
- data/spec/unit/formatter/elapsed_spec.rb +0 -58
- data/spec/unit/formatter/estimated_spec.rb +0 -27
- data/spec/unit/formatter/mean_byte_spec.rb +0 -32
- data/spec/unit/formatter/mean_rate_spec.rb +0 -31
- data/spec/unit/formatter/percent_spec.rb +0 -16
- data/spec/unit/formatter/rate_spec.rb +0 -31
- data/spec/unit/formatter/total_byte_spec.rb +0 -16
- data/spec/unit/formatter/total_spec.rb +0 -16
- data/spec/unit/frequency_spec.rb +0 -27
- data/spec/unit/head_spec.rb +0 -32
- data/spec/unit/hide_cursor_spec.rb +0 -27
- data/spec/unit/inspect_spec.rb +0 -11
- data/spec/unit/iterate_spec.rb +0 -79
- data/spec/unit/log_spec.rb +0 -29
- data/spec/unit/meter_spec.rb +0 -70
- data/spec/unit/multi/advance_spec.rb +0 -123
- data/spec/unit/multi/events_spec.rb +0 -115
- data/spec/unit/multi/finish_spec.rb +0 -41
- data/spec/unit/multi/line_inset_spec.rb +0 -65
- data/spec/unit/multi/register_spec.rb +0 -35
- data/spec/unit/multi/reset_spec.rb +0 -28
- data/spec/unit/multi/stop_spec.rb +0 -15
- data/spec/unit/multi/width_spec.rb +0 -118
- data/spec/unit/new_spec.rb +0 -76
- data/spec/unit/pipeline_spec.rb +0 -19
- data/spec/unit/ratio_spec.rb +0 -31
- data/spec/unit/render_spec.rb +0 -25
- data/spec/unit/reset_spec.rb +0 -31
- data/spec/unit/resize_spec.rb +0 -35
- data/spec/unit/set_current_spec.rb +0 -43
- data/spec/unit/start_spec.rb +0 -14
- data/spec/unit/stop_spec.rb +0 -19
- data/spec/unit/update_spec.rb +0 -22
- data/spec/unit/width_spec.rb +0 -86
- data/tasks/console.rake +0 -9
- data/tasks/coverage.rake +0 -9
- data/tasks/spec.rake +0 -27
- data/tty-progressbar.gemspec +0 -32
data/lib/tty-progressbar.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative
|
1
|
+
require_relative "tty/progressbar"
|
2
|
+
require_relative "tty/progressbar/multi"
|
data/lib/tty/progressbar.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
|
11
|
-
require_relative
|
12
|
-
require_relative
|
13
|
-
require_relative
|
14
|
-
require_relative
|
3
|
+
require "io/console"
|
4
|
+
require "forwardable"
|
5
|
+
require "monitor"
|
6
|
+
require "tty-cursor"
|
7
|
+
require "tty-screen"
|
8
|
+
require "strings-ansi"
|
9
|
+
require "unicode/display_width"
|
10
|
+
|
11
|
+
require_relative "progressbar/timer"
|
12
|
+
require_relative "progressbar/configuration"
|
13
|
+
require_relative "progressbar/formatters"
|
14
|
+
require_relative "progressbar/meter"
|
15
|
+
require_relative "progressbar/version"
|
15
16
|
|
16
17
|
module TTY
|
17
18
|
# Used for creating terminal progress bar
|
@@ -21,7 +22,9 @@ module TTY
|
|
21
22
|
extend Forwardable
|
22
23
|
include MonitorMixin
|
23
24
|
|
24
|
-
ECMA_CSI = "\e["
|
25
|
+
ECMA_CSI = "\e["
|
26
|
+
|
27
|
+
NEWLINE = "\n"
|
25
28
|
|
26
29
|
CURSOR_LOCK = Monitor.new
|
27
30
|
|
@@ -29,17 +32,15 @@ module TTY
|
|
29
32
|
|
30
33
|
attr_reader :current
|
31
34
|
|
32
|
-
attr_reader :start_at
|
33
|
-
|
34
35
|
attr_reader :row
|
35
36
|
|
36
|
-
def_delegators :@configuration, :total, :width, :
|
37
|
-
:
|
38
|
-
:
|
37
|
+
def_delegators :@configuration, :total, :width, :complete, :incomplete,
|
38
|
+
:head, :clear_head, :hide_cursor, :clear, :output,
|
39
|
+
:frequency, :interval, :inset, :width=, :unknown, :bar_format
|
39
40
|
|
40
41
|
def_delegators :@meter, :rate, :mean_rate
|
41
42
|
|
42
|
-
|
43
|
+
def_delegators :@timer, :elapsed_time, :start_time
|
43
44
|
|
44
45
|
# Determine terminal width
|
45
46
|
#
|
@@ -64,6 +65,12 @@ module TTY
|
|
64
65
|
|
65
66
|
# Create progress bar
|
66
67
|
#
|
68
|
+
# @example
|
69
|
+
# bar = TTY::Progressbar.new
|
70
|
+
# bar.configure do |config|
|
71
|
+
# config.total = 20
|
72
|
+
# end
|
73
|
+
#
|
67
74
|
# @param [String] format
|
68
75
|
# the tokenized string that displays the output
|
69
76
|
#
|
@@ -71,20 +78,29 @@ module TTY
|
|
71
78
|
# @option options [Numeric] :total
|
72
79
|
# the total number of steps to completion
|
73
80
|
# @option options [Numeric] :width
|
74
|
-
# the maximum width for the
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
81
|
+
# the maximum width for the progress bar except all formatting tokens
|
82
|
+
# @option option [String] :complete
|
83
|
+
# the complete character in progress animation
|
84
|
+
# @option options [String] :incomplete
|
85
|
+
# the incomplete character in progress animation
|
86
|
+
# @option options [String] :head
|
87
|
+
# the head character, defaults to complete
|
88
|
+
# @option options [String] :unknown
|
89
|
+
# the unknown character for indeterminate progress animation
|
90
|
+
# @option options [Boolean] :bar_format
|
91
|
+
# the preconfigured bar format name, defaults to :classic
|
82
92
|
# @option options [Object] :output
|
83
|
-
# the object that responds to print call
|
93
|
+
# the object that responds to print call, defaults to stderr
|
84
94
|
# @option options [Number] :frequency
|
85
|
-
# the frequency with which to display
|
95
|
+
# the frequency with which to display a progress bar per second
|
86
96
|
# @option options [Number] :interval
|
87
|
-
# the
|
97
|
+
# the time interval for sampling of speed measurement, defaults to 1 second
|
98
|
+
# @option options [Boolean] :hide_cursor
|
99
|
+
# whether or not to hide the cursor, defaults to false
|
100
|
+
# @option options [Boolean] :clear
|
101
|
+
# whether or not to clear the progress line, defaults to false
|
102
|
+
# @option options [Boolean] :clear_head
|
103
|
+
# whether or not to replace head character with complete, defaults to false
|
88
104
|
#
|
89
105
|
# @api public
|
90
106
|
def initialize(format, options = {})
|
@@ -97,34 +113,52 @@ module TTY
|
|
97
113
|
@configuration = TTY::ProgressBar::Configuration.new(options)
|
98
114
|
yield @configuration if block_given?
|
99
115
|
|
100
|
-
@
|
101
|
-
@meter
|
116
|
+
@formatters = TTY::ProgressBar::Formatters.new
|
117
|
+
@meter = TTY::ProgressBar::Meter.new(interval)
|
118
|
+
@timer = TTY::ProgressBar::Timer.new
|
102
119
|
@callbacks = Hash.new { |h, k| h[k] = [] }
|
103
120
|
|
104
|
-
@
|
121
|
+
@formatters.load(self)
|
105
122
|
reset
|
106
123
|
|
107
124
|
@first_render = true
|
108
|
-
@multibar
|
109
|
-
@row
|
125
|
+
@multibar = nil
|
126
|
+
@row = nil
|
110
127
|
end
|
111
128
|
|
112
129
|
# Reset progress to default configuration
|
113
130
|
#
|
114
131
|
# @api public
|
115
132
|
def reset
|
116
|
-
@width = 0 if
|
133
|
+
@width = 0 if indeterminate?
|
117
134
|
@render_period = frequency == 0 ? 0 : 1.0 / frequency
|
118
135
|
@current = 0
|
136
|
+
@unknown = 0
|
119
137
|
@last_render_time = Time.now
|
120
138
|
@last_render_width = 0
|
121
139
|
@done = false
|
122
140
|
@stopped = false
|
123
|
-
@
|
124
|
-
@started = false
|
141
|
+
@paused = false
|
125
142
|
@tokens = {}
|
126
143
|
|
127
144
|
@meter.clear
|
145
|
+
@timer.reset
|
146
|
+
end
|
147
|
+
|
148
|
+
# Access instance configuration
|
149
|
+
#
|
150
|
+
# @api public
|
151
|
+
def configure
|
152
|
+
yield @configuration
|
153
|
+
end
|
154
|
+
|
155
|
+
# Check if progress can be determined or not
|
156
|
+
#
|
157
|
+
# @return [Boolean]
|
158
|
+
#
|
159
|
+
# @api public
|
160
|
+
def indeterminate?
|
161
|
+
total.nil?
|
128
162
|
end
|
129
163
|
|
130
164
|
# Attach this bar to multi bar
|
@@ -137,13 +171,26 @@ module TTY
|
|
137
171
|
@multibar = multibar
|
138
172
|
end
|
139
173
|
|
174
|
+
# Use custom token formatter
|
175
|
+
#
|
176
|
+
# @param [Object] formatter_class
|
177
|
+
# the formatter class to add to formatting pipeline
|
178
|
+
#
|
179
|
+
# @api public
|
180
|
+
def use(formatter_class)
|
181
|
+
unless formatter_class.is_a?(Class)
|
182
|
+
raise ArgumentError, "Formatter needs to be a class"
|
183
|
+
end
|
184
|
+
|
185
|
+
@formatters.use(formatter_class.new(self))
|
186
|
+
end
|
187
|
+
|
140
188
|
# Start progression by drawing bar and setting time
|
141
189
|
#
|
142
190
|
# @api public
|
143
191
|
def start
|
144
192
|
synchronize do
|
145
|
-
@
|
146
|
-
@start_at = Time.now
|
193
|
+
@timer.start
|
147
194
|
@meter.start
|
148
195
|
end
|
149
196
|
|
@@ -163,17 +210,21 @@ module TTY
|
|
163
210
|
if progress.respond_to?(:to_hash)
|
164
211
|
tokens, progress = progress, 1
|
165
212
|
end
|
166
|
-
@
|
167
|
-
@current
|
168
|
-
|
213
|
+
@timer.start
|
214
|
+
@current += progress
|
215
|
+
# When progress is unknown increase by 2% up to max 200%, after
|
216
|
+
# that reset back to 0%
|
217
|
+
@unknown += 2 if indeterminate?
|
218
|
+
@unknown = 0 if @unknown > 199
|
219
|
+
@tokens = tokens
|
169
220
|
@meter.sample(Time.now, progress)
|
170
221
|
|
171
|
-
if !
|
222
|
+
if !indeterminate? && @current >= total
|
172
223
|
finish && return
|
173
224
|
end
|
174
225
|
|
175
|
-
|
176
|
-
|
226
|
+
return if (Time.now - @last_render_time) < @render_period
|
227
|
+
|
177
228
|
render
|
178
229
|
end
|
179
230
|
end
|
@@ -190,7 +241,7 @@ module TTY
|
|
190
241
|
# be convenient in "unsure number of iterations" situations
|
191
242
|
# (like downloading in chunks, when server may eventually send
|
192
243
|
# more chunks than predicted), but be careful to not pass infinite
|
193
|
-
# enumerators without
|
244
|
+
# enumerators without previously doing `.take(some_finite_number)`
|
194
245
|
# on them.
|
195
246
|
#
|
196
247
|
# @example
|
@@ -257,12 +308,20 @@ module TTY
|
|
257
308
|
|
258
309
|
# Ratio of completed over total steps
|
259
310
|
#
|
311
|
+
# When the total is unknown the progress ratio oscillates
|
312
|
+
# by going up from 0 to 1 and then down from 1 to 0 and
|
313
|
+
# up again to infinity.
|
314
|
+
#
|
260
315
|
# @return [Float]
|
261
316
|
#
|
262
317
|
# @api public
|
263
318
|
def ratio
|
264
319
|
synchronize do
|
265
|
-
proportion =
|
320
|
+
proportion = if total
|
321
|
+
total > 0 ? (@current.to_f / total) : 0
|
322
|
+
else
|
323
|
+
(@unknown > 100 ? 200 - @unknown : @unknown).to_f / 100
|
324
|
+
end
|
266
325
|
[[proportion, 0].max, 1].min
|
267
326
|
end
|
268
327
|
end
|
@@ -272,7 +331,9 @@ module TTY
|
|
272
331
|
# @api private
|
273
332
|
def render
|
274
333
|
return if done?
|
275
|
-
|
334
|
+
|
335
|
+
if hide_cursor && @last_render_width == 0 &&
|
336
|
+
(indeterminate? || @current < total)
|
276
337
|
write(TTY::Cursor.hide)
|
277
338
|
end
|
278
339
|
|
@@ -281,7 +342,7 @@ module TTY
|
|
281
342
|
update(inset: self.class.display_columns(characters_in))
|
282
343
|
end
|
283
344
|
|
284
|
-
formatted = @
|
345
|
+
formatted = @formatters.decorate(@format)
|
285
346
|
@tokens.each do |token, val|
|
286
347
|
formatted = formatted.gsub(":#{token}", val)
|
287
348
|
end
|
@@ -304,7 +365,7 @@ module TTY
|
|
304
365
|
if @first_render
|
305
366
|
@row = @multibar.next_row
|
306
367
|
yield if block_given?
|
307
|
-
output.print
|
368
|
+
output.print NEWLINE
|
308
369
|
@first_render = false
|
309
370
|
else
|
310
371
|
lines_up = (@multibar.rows + 1) - @row
|
@@ -343,6 +404,7 @@ module TTY
|
|
343
404
|
# @api public
|
344
405
|
def resize(new_width = nil)
|
345
406
|
return if done?
|
407
|
+
|
346
408
|
synchronize do
|
347
409
|
clear_line
|
348
410
|
if new_width
|
@@ -356,12 +418,14 @@ module TTY
|
|
356
418
|
# @api public
|
357
419
|
def finish
|
358
420
|
return if done?
|
359
|
-
|
421
|
+
|
422
|
+
@current = total unless indeterminate?
|
360
423
|
render
|
361
|
-
clear ? clear_line : write(
|
424
|
+
clear ? clear_line : write(NEWLINE, false)
|
362
425
|
ensure
|
363
426
|
@meter.clear
|
364
427
|
@done = true
|
428
|
+
@timer.stop
|
365
429
|
|
366
430
|
# reenable cursor if it is turned off
|
367
431
|
if hide_cursor && @last_render_width != 0
|
@@ -371,31 +435,57 @@ module TTY
|
|
371
435
|
emit(:done)
|
372
436
|
end
|
373
437
|
|
438
|
+
# Resume rendering when bar is done, stopped or paused
|
439
|
+
#
|
440
|
+
# @api public
|
441
|
+
def resume
|
442
|
+
synchronize do
|
443
|
+
@done = false
|
444
|
+
@stopped = false
|
445
|
+
@paused = false
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
374
449
|
# Stop and cancel the progress at the current position
|
375
450
|
#
|
376
451
|
# @api public
|
377
452
|
def stop
|
378
|
-
# reenable cursor if it is turned off
|
379
|
-
if hide_cursor && @last_render_width != 0
|
380
|
-
write(TTY::Cursor.show, false)
|
381
|
-
end
|
382
453
|
return if done?
|
454
|
+
|
383
455
|
render
|
384
|
-
clear ? clear_line : write(
|
456
|
+
clear ? clear_line : write(NEWLINE, false)
|
385
457
|
ensure
|
386
458
|
@meter.clear
|
387
459
|
@stopped = true
|
460
|
+
@timer.stop
|
461
|
+
|
462
|
+
# reenable cursor if it is turned off
|
463
|
+
if hide_cursor && @last_render_width != 0
|
464
|
+
write(TTY::Cursor.show, false)
|
465
|
+
end
|
466
|
+
|
388
467
|
emit(:stopped)
|
389
468
|
end
|
390
469
|
|
470
|
+
# Pause the progress at the current position
|
471
|
+
#
|
472
|
+
# @api public
|
473
|
+
def pause
|
474
|
+
synchronize do
|
475
|
+
@paused = true
|
476
|
+
@timer.stop
|
477
|
+
emit(:paused)
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
391
481
|
# Clear current line
|
392
482
|
#
|
393
483
|
# @api public
|
394
484
|
def clear_line
|
395
|
-
output.print(ECMA_CSI
|
485
|
+
output.print("#{ECMA_CSI}0m#{TTY::Cursor.clear_line}")
|
396
486
|
end
|
397
487
|
|
398
|
-
# Check if progress is
|
488
|
+
# Check if progress is finished
|
399
489
|
#
|
400
490
|
# @return [Boolean]
|
401
491
|
# true when progress finished, false otherwise
|
@@ -414,13 +504,22 @@ module TTY
|
|
414
504
|
@stopped
|
415
505
|
end
|
416
506
|
|
417
|
-
# Check if progress is
|
507
|
+
# Check if progress is paused
|
508
|
+
#
|
509
|
+
# @return [Boolean]
|
510
|
+
#
|
511
|
+
# @api public
|
512
|
+
def paused?
|
513
|
+
@paused
|
514
|
+
end
|
515
|
+
|
516
|
+
# Check if progress is finished, stopped or paused
|
418
517
|
#
|
419
518
|
# @return [Boolean]
|
420
519
|
#
|
421
520
|
# @api public
|
422
521
|
def done?
|
423
|
-
@done || @stopped
|
522
|
+
@done || @stopped || @paused
|
424
523
|
end
|
425
524
|
|
426
525
|
# Register callback with this bar
|
@@ -445,14 +544,14 @@ module TTY
|
|
445
544
|
#
|
446
545
|
# @api public
|
447
546
|
def log(message)
|
448
|
-
sanitized_message = message.gsub(/\r|\n/,
|
547
|
+
sanitized_message = message.gsub(/\r|\n/, " ")
|
449
548
|
if done?
|
450
|
-
write(sanitized_message
|
549
|
+
write("#{sanitized_message}#{NEWLINE}", false)
|
451
550
|
return
|
452
551
|
end
|
453
552
|
sanitized_message = padout(sanitized_message)
|
454
553
|
|
455
|
-
write(sanitized_message
|
554
|
+
write("#{sanitized_message}#{NEWLINE}", true)
|
456
555
|
render
|
457
556
|
end
|
458
557
|
|
@@ -472,13 +571,14 @@ module TTY
|
|
472
571
|
# @api public
|
473
572
|
def inspect
|
474
573
|
"#<#{self.class.name} " \
|
475
|
-
"@format=\"#{format}\", " \
|
574
|
+
"@format=\"#{@format}\", " \
|
476
575
|
"@current=\"#{@current}\", " \
|
477
576
|
"@total=\"#{total}\", " \
|
478
577
|
"@width=\"#{width}\", " \
|
479
578
|
"@complete=\"#{complete}\", " \
|
480
579
|
"@head=\"#{head}\", " \
|
481
580
|
"@incomplete=\"#{incomplete}\", " \
|
581
|
+
"@unknown=\"#{unknown}\", " \
|
482
582
|
"@interval=\"#{interval}\">"
|
483
583
|
end
|
484
584
|
|
@@ -492,7 +592,7 @@ module TTY
|
|
492
592
|
|
493
593
|
if @last_render_width > message_length
|
494
594
|
remaining_width = @last_render_width - message_length
|
495
|
-
message +=
|
595
|
+
message += " " * remaining_width
|
496
596
|
end
|
497
597
|
message
|
498
598
|
end
|
@@ -505,7 +605,7 @@ module TTY
|
|
505
605
|
# @api private
|
506
606
|
def emit(name, *args)
|
507
607
|
@callbacks[name].each do |callback|
|
508
|
-
callback.
|
608
|
+
callback.(*args)
|
509
609
|
end
|
510
610
|
end
|
511
611
|
|