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.2"
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
484 485 486 |
# File 'lib/tty/progressbar.rb', line 484 def clear_line output.print("#{ECMA_CSI}0m#{TTY::Cursor.clear_line}") end |
#complete? ⇒ Boolean
Check if progress is finished
494 495 496 |
# File 'lib/tty/progressbar.rb', line 494 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
521 522 523 |
# File 'lib/tty/progressbar.rb', line 521 def done? @done || @stopped || @paused end |
#finish ⇒ Object
End the progress
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 |
# File 'lib/tty/progressbar.rb', line 419 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
572 573 574 575 576 577 578 579 580 581 582 583 |
# File 'lib/tty/progressbar.rb', line 572 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
546 547 548 549 550 551 552 553 554 555 556 |
# File 'lib/tty/progressbar.rb', line 546 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.
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
# File 'lib/tty/progressbar.rb', line 362 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
533 534 535 536 537 538 |
# File 'lib/tty/progressbar.rb', line 533 def on(name, &callback) synchronize do @callbacks[name] << callback end self end |
#pause ⇒ Object
Pause the progress at the current position
473 474 475 476 477 478 479 |
# File 'lib/tty/progressbar.rb', line 473 def pause synchronize do @paused = true @timer.stop emit(:paused) end end |
#paused? ⇒ Boolean
Check if progress is paused
512 513 514 |
# File 'lib/tty/progressbar.rb', line 512 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.
318 319 320 321 322 323 324 325 326 327 |
# File 'lib/tty/progressbar.rb', line 318 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.
304 305 306 307 |
# File 'lib/tty/progressbar.rb', line 304 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
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
# File 'lib/tty/progressbar.rb', line 332 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
405 406 407 408 409 410 411 412 413 414 |
# File 'lib/tty/progressbar.rb', line 405 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
441 442 443 444 445 446 447 |
# File 'lib/tty/progressbar.rb', line 441 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
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 |
# File 'lib/tty/progressbar.rb', line 452 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
503 504 505 |
# File 'lib/tty/progressbar.rb', line 503 def stopped? @stopped end |
#to_s ⇒ String
Show bar format
563 564 565 |
# File 'lib/tty/progressbar.rb', line 563 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
388 389 390 391 392 393 394 395 396 397 |
# File 'lib/tty/progressbar.rb', line 388 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 |