Class: TTY::ProgressBar
- Inherits:
-
Object
- Object
- TTY::ProgressBar
- Extended by:
- Forwardable
- Includes:
- MonitorMixin
- Defined in:
- lib/tty/progressbar.rb,
lib/tty/progressbar/meter.rb,
lib/tty/progressbar/multi.rb,
lib/tty/progressbar/timer.rb,
lib/tty/progressbar/formats.rb,
lib/tty/progressbar/version.rb,
lib/tty/progressbar/pipeline.rb,
lib/tty/progressbar/converter.rb,
lib/tty/progressbar/formatter.rb,
lib/tty/progressbar/formatters.rb,
lib/tty/progressbar/configuration.rb,
lib/tty/progressbar/formatter/bar.rb,
lib/tty/progressbar/formatter/rate.rb,
lib/tty/progressbar/formatter/total.rb,
lib/tty/progressbar/formatter/current.rb,
lib/tty/progressbar/formatter/elapsed.rb,
lib/tty/progressbar/formatter/percent.rb,
lib/tty/progressbar/formatter/byte_rate.rb,
lib/tty/progressbar/formatter/estimated.rb,
lib/tty/progressbar/formatter/mean_byte.rb,
lib/tty/progressbar/formatter/mean_rate.rb,
lib/tty/progressbar/formatter/total_byte.rb,
lib/tty/progressbar/formatter/current_byte.rb,
lib/tty/progressbar/formatter/estimated_time.rb
Overview
Used for creating terminal progress bar
Defined Under Namespace
Modules: Converter, Formats Classes: BarFormatter, ByteFormatter, ByteRateFormatter, Configuration, CurrentFormatter, ElapsedFormatter, EstimatedFormatter, EstimatedTimeFormatter, Formatter, Formatters, MeanByteFormatter, MeanRateFormatter, Meter, Multi, PercentFormatter, Pipeline, RateFormatter, Timer, TotalByteFormatter, TotalFormatter
Constant Summary collapse
- ECMA_CSI =
"\e["
- NEWLINE =
"\n"
- CURSOR_LOCK =
Monitor.new
- VERSION =
"0.18.3"
Instance Attribute Summary collapse
Class Method Summary collapse
-
.display_columns(value) ⇒ Integer
Determine the monospace display width of a string.
-
.max_columns ⇒ Integer
Determine terminal width.
Instance Method Summary collapse
-
#advance(progress = 1, tokens = {}) ⇒ Object
Advance the progress bar.
-
#attach_to(multibar) ⇒ Object
private
Attach this bar to multi bar.
-
#clear_line ⇒ Object
Clear current line.
-
#complete? ⇒ Boolean
Check if progress is finished.
-
#configure {|@configuration| ... } ⇒ Object
Access instance configuration.
-
#done? ⇒ Boolean
Check if progress is finished, stopped or paused.
-
#finish ⇒ Object
End the progress.
-
#indeterminate? ⇒ Boolean
Check if progress can be determined or not.
-
#initialize(format, options = {}) {|@configuration| ... } ⇒ ProgressBar
constructor
Create progress bar.
-
#inspect ⇒ String
Inspect bar properties.
-
#iterate(collection, progress = 1, &block) ⇒ Enumerator
Iterate over collection either yielding computation to block or provided Enumerator.
-
#log(message) ⇒ Object
Log message above the current progress bar.
-
#move_to_row ⇒ Object
private
Move cursor to a row of the current bar if the bar is rendered under a multibar.
-
#on(name, &callback) ⇒ self
Register callback with this bar.
-
#pause ⇒ Object
Pause the progress at the current position.
-
#paused? ⇒ Boolean
Check if progress is paused.
-
#ratio ⇒ Float
Ratio of completed over total steps.
-
#ratio=(value) ⇒ Object
Advance the progress bar to an exact ratio.
-
#render ⇒ Object
private
Render progress to the output.
-
#reset ⇒ Object
Reset progress to default configuration.
-
#resize(new_width = nil) ⇒ Object
Resize progress bar with new configuration.
-
#resume ⇒ Object
Resume rendering when bar is done, stopped or paused.
-
#start ⇒ Object
Start progression by drawing bar and setting time.
-
#stop ⇒ Object
Stop and cancel the progress at the current position.
-
#stopped? ⇒ Boolean
Check if progress is stopped.
-
#to_s ⇒ String
Show bar format.
-
#update(options = {}) ⇒ Object
Update configuration options for this bar.
-
#use(formatter_class) ⇒ Object
Use custom token formatter.
-
#write(data, clear_first = false) ⇒ Object
private
Write out to the output.
Constructor Details
#initialize(format, options = {}) {|@configuration| ... } ⇒ ProgressBar
Create progress bar
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/tty/progressbar.rb', line 106 def initialize(format, = {}) super() @format = format if format.is_a?(Hash) raise ArgumentError, "Expected bar formatting string, " \ "got `#{format}` instead." end @configuration = TTY::ProgressBar::Configuration.new() yield @configuration if block_given? @formatters = TTY::ProgressBar::Formatters.new @meter = TTY::ProgressBar::Meter.new(interval) @timer = TTY::ProgressBar::Timer.new @callbacks = Hash.new { |h, k| h[k] = [] } @formatters.load(self) reset @first_render = true @multibar = nil @row = nil end |
Instance Attribute Details
#current ⇒ Object
33 34 35 |
# File 'lib/tty/progressbar.rb', line 33 def current @current end |
#format ⇒ Object
31 32 33 |
# File 'lib/tty/progressbar.rb', line 31 def format @format end |
#row ⇒ Object (readonly)
35 36 37 |
# File 'lib/tty/progressbar.rb', line 35 def row @row end |
Class Method Details
.display_columns(value) ⇒ Integer
Determine the monospace display width of a string
62 63 64 |
# File 'lib/tty/progressbar.rb', line 62 def self.display_columns(value) Unicode::DisplayWidth.of(Strings::ANSI.sanitize(value)) end |
.max_columns ⇒ Integer
Determine terminal width
50 51 52 |
# File 'lib/tty/progressbar.rb', line 50 def self.max_columns TTY::Screen.width end |
Instance Method Details
#advance(progress = 1, tokens = {}) ⇒ Object
Advance the progress bar
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/tty/progressbar.rb', line 205 def advance(progress = 1, tokens = {}) return if done? synchronize do emit(:progress, progress) if progress.respond_to?(:to_hash) tokens, progress = progress, 1 end @timer.start @current += progress # When progress is unknown increase by 2% up to max 200%, after # that reset back to 0% @unknown += 2 if indeterminate? @unknown = 0 if @unknown > 199 @tokens = tokens @meter.sample(Time.now, progress) if !indeterminate? && @current >= total finish && return end return if (Time.now - @last_render_time) < @render_period render end end |
#attach_to(multibar) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Attach this bar to multi bar
170 171 172 |
# File 'lib/tty/progressbar.rb', line 170 def attach_to() @multibar = end |
#clear_line ⇒ Object
Clear current line
489 490 491 |
# File 'lib/tty/progressbar.rb', line 489 def clear_line output.print("#{ECMA_CSI}0m#{TTY::Cursor.clear_line}") end |
#complete? ⇒ Boolean
Check if progress is finished
499 500 501 |
# File 'lib/tty/progressbar.rb', line 499 def complete? @done end |
#configure {|@configuration| ... } ⇒ Object
Access instance configuration
151 152 153 |
# File 'lib/tty/progressbar.rb', line 151 def configure yield @configuration end |
#done? ⇒ Boolean
Check if progress is finished, stopped or paused
526 527 528 |
# File 'lib/tty/progressbar.rb', line 526 def done? @done || @stopped || @paused end |
#finish ⇒ Object
End the progress
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 |
# File 'lib/tty/progressbar.rb', line 424 def finish return if done? @current = total unless indeterminate? render clear ? clear_line : write(NEWLINE, false) ensure @meter.clear @done = true @timer.stop # reenable cursor if it is turned off if hide_cursor && @last_render_width != 0 write(TTY::Cursor.show, false) end emit(:done) end |
#indeterminate? ⇒ Boolean
Check if progress can be determined or not
160 161 162 |
# File 'lib/tty/progressbar.rb', line 160 def indeterminate? total.nil? end |
#inspect ⇒ String
Inspect bar properties
577 578 579 580 581 582 583 584 585 586 587 588 |
# File 'lib/tty/progressbar.rb', line 577 def inspect "#<#{self.class.name} " \ "@format=\"#{@format}\", " \ "@current=\"#{@current}\", " \ "@total=\"#{total}\", " \ "@width=\"#{width}\", " \ "@complete=\"#{complete}\", " \ "@head=\"#{head}\", " \ "@incomplete=\"#{incomplete}\", " \ "@unknown=\"#{unknown}\", " \ "@interval=\"#{interval}\">" end |
#iterate(collection, progress = 1, &block) ⇒ Enumerator
If ‘total` is set, iteration will NOT stop after this number of iterations, only when provided Enumerable is finished. It may be convenient in “unsure number of iterations” situations (like downloading in chunks, when server may eventually send more chunks than predicted), but be careful to not pass infinite enumerators without previously doing `.take(some_finite_number)` on them.
Iterate over collection either yielding computation to block or provided Enumerator. If the bar’s ‘total` was not set, it would be taken from `collection.count`, otherwise previously set `total` would be used. This allows using the progressbar with infinite, lazy, or slowly-calculated enumerators.
259 260 261 262 263 264 265 266 267 268 |
# File 'lib/tty/progressbar.rb', line 259 def iterate(collection, progress = 1, &block) update(total: collection.count * progress) unless total progress_enum = Enumerator.new do |iter| collection.each do |elem| advance(progress) iter.yield(elem) end end block_given? ? progress_enum.each(&block) : progress_enum end |
#log(message) ⇒ Object
Log message above the current progress bar
551 552 553 554 555 556 557 558 559 560 561 |
# File 'lib/tty/progressbar.rb', line 551 def log() = .gsub(/\r|\n/, " ") if done? write("#{}#{NEWLINE}", false) return end = padout() write("#{}#{NEWLINE}", true) render end |
#move_to_row ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Move cursor to a row of the current bar if the bar is rendered under a multibar. Otherwise, do not move and yield on current row.
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 |
# File 'lib/tty/progressbar.rb', line 367 def move_to_row if @multibar CURSOR_LOCK.synchronize do if @first_render @row = @multibar.next_row yield if block_given? output.print NEWLINE @first_render = false else lines_up = (@multibar.rows + 1) - @row output.print TTY::Cursor.save output.print TTY::Cursor.up(lines_up) yield if block_given? output.print TTY::Cursor.restore end end else yield if block_given? end end |
#on(name, &callback) ⇒ self
Register callback with this bar
538 539 540 541 542 543 |
# File 'lib/tty/progressbar.rb', line 538 def on(name, &callback) synchronize do @callbacks[name] << callback end self end |
#pause ⇒ Object
Pause the progress at the current position
478 479 480 481 482 483 484 |
# File 'lib/tty/progressbar.rb', line 478 def pause synchronize do @paused = true @timer.stop emit(:paused) end end |
#paused? ⇒ Boolean
Check if progress is paused
517 518 519 |
# File 'lib/tty/progressbar.rb', line 517 def paused? @paused end |
#ratio ⇒ Float
Ratio of completed over total steps
When the total is unknown the progress ratio oscillates by going up from 0 to 1 and then down from 1 to 0 and up again to infinity.
323 324 325 326 327 328 329 330 331 332 |
# File 'lib/tty/progressbar.rb', line 323 def ratio synchronize do proportion = if total total > 0 ? (@current.to_f / total) : 0 else (@unknown > 100 ? 200 - @unknown : @unknown).to_f / 100 end [[proportion, 0].max, 1].min end end |
#ratio=(value) ⇒ Object
Advance the progress bar to an exact ratio. The target value is set to the closest available value.
309 310 311 312 |
# File 'lib/tty/progressbar.rb', line 309 def ratio=(value) target = (value * total).floor advance(target - @current) end |
#render ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Render progress to the output
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File 'lib/tty/progressbar.rb', line 337 def render return if done? if hide_cursor && @last_render_width == 0 && (indeterminate? || @current < total) write(TTY::Cursor.hide) end if @multibar characters_in = @multibar.line_inset(self) update(inset: self.class.display_columns(characters_in)) end formatted = @formatters.decorate(@format) @tokens.each do |token, val| formatted = formatted.gsub(":#{token}", val) end padded = padout(formatted) write(padded, true) @last_render_time = Time.now @last_render_width = self.class.display_columns(formatted) end |
#reset ⇒ Object
Reset progress to default configuration
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/tty/progressbar.rb', line 132 def reset @width = 0 if indeterminate? @render_period = frequency == 0 ? 0 : 1.0 / frequency @current = 0 @unknown = 0 @last_render_time = Time.now @last_render_width = 0 @done = false @stopped = false @paused = false @tokens = {} @meter.clear @timer.reset end |
#resize(new_width = nil) ⇒ Object
Resize progress bar with new configuration
410 411 412 413 414 415 416 417 418 419 |
# File 'lib/tty/progressbar.rb', line 410 def resize(new_width = nil) return if done? synchronize do clear_line if new_width self.width = new_width end end end |
#resume ⇒ Object
Resume rendering when bar is done, stopped or paused
446 447 448 449 450 451 452 |
# File 'lib/tty/progressbar.rb', line 446 def resume synchronize do @done = false @stopped = false @paused = false end end |
#start ⇒ Object
Start progression by drawing bar and setting time
191 192 193 194 195 196 197 198 |
# File 'lib/tty/progressbar.rb', line 191 def start synchronize do @timer.start @meter.start end advance(0) end |
#stop ⇒ Object
Stop and cancel the progress at the current position
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
# File 'lib/tty/progressbar.rb', line 457 def stop return if done? render clear ? clear_line : write(NEWLINE, false) ensure @meter.clear @stopped = true @timer.stop # reenable cursor if it is turned off if hide_cursor && @last_render_width != 0 write(TTY::Cursor.show, false) end emit(:stopped) end |
#stopped? ⇒ Boolean
Check if progress is stopped
508 509 510 |
# File 'lib/tty/progressbar.rb', line 508 def stopped? @stopped end |
#to_s ⇒ String
Show bar format
568 569 570 |
# File 'lib/tty/progressbar.rb', line 568 def to_s @format.to_s end |
#update(options = {}) ⇒ Object
Update configuration options for this bar
276 277 278 279 280 281 282 283 284 |
# File 'lib/tty/progressbar.rb', line 276 def update( = {}) synchronize do .each do |name, val| if @configuration.respond_to?("#{name}=") @configuration.public_send("#{name}=", val) end end end end |
#use(formatter_class) ⇒ Object
Use custom token formatter
180 181 182 183 184 185 186 |
# File 'lib/tty/progressbar.rb', line 180 def use(formatter_class) unless formatter_class.is_a?(Class) raise ArgumentError, "Formatter needs to be a class" end @formatters.use(formatter_class.new(self)) end |
#write(data, clear_first = false) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Write out to the output
393 394 395 396 397 398 399 400 401 402 |
# File 'lib/tty/progressbar.rb', line 393 def write(data, clear_first = false) return unless tty? # write only to terminal move_to_row do output.print(TTY::Cursor.column(1)) if clear_first characters_in = @multibar.line_inset(self) if @multibar output.print("#{characters_in}#{data}") output.flush end end |