TTY::ProgressBar

repository·master·Indexed 19 days ago

https://github.com/piotrmurach/tty-progressbar

A flexible and extensible progress bar component for terminal applications, part of the TTY toolkit. It supports custom formatting, multiple parallel bars via TTY::ProgressBar::Multi, and indeterminate progress modes. Features include lifecycle control (start, finish, stop, pause, resume, reset), dynamic configuration updates, event callbacks, and a wide array of predefined bar formats and tokens for detailed progress tracking.

Tokens
7.8K
Snippets
41
Records
46
Agent score
61%

What's inside tty-progressbar

  1. How TTY::ProgressBar::Multi works

    master

    The TTY::ProgressBar::Multi class allows you to display multiple progress bars in parallel. You first create a top-level Multi instance (which acts as a container) and then register child bars using the register method. Calling start on the multi-bar instance begins the timers for all registered bars.

    # Declare a top level bar and then register child bars
    bars = TTY::ProgressBar::Multi.new("main [:bar] :percent")
    
    bar1 = bars.register("one [:bar] :percent", total: 15)
    bar2 = bars.register("two [:bar] :percent", total: 15)
    
    # starts all registered bars timers
    bars.start
    
    # Progress child bars in parallel (e.g., using threads)
    th1 = Thread.new { 15.times { sleep(0.1); bar1.advance } }
    th2 = Thread.new { 15.times { sleep(0.1); bar2.advance } }
    
    [th1, th2].each { |t| t.join }
  2. Manage multiple progress bars with TTY::ProgressBar::Multi

    master

    Use TTY::ProgressBar::Multi to manage a group of progress bars.

    • Creation: Use TTY::ProgressBar::Multi.new for a simple group, or TTY::ProgressBar::Multi.new("format") to create a top-level bar that tracks the aggregate progress of all registered bars.
    • Registration: Use multibar.register("format", total: n) to add a bar to the group. This returns a standard TTY::ProgressBar instance.
    • Execution: Bars can be advanced synchronously or asynchronously (e.g., in separate threads). The multi-bar handles synchronization and rendering.
    • Control: Use start, finish, stop, pause, and resume to control the lifecycle of all bars in the group.
    • Status: Check state using complete?, paused?, or stopped?.
    multibar = TTY::ProgressBar::Multi.new
    bar1 = multibar.register("one [:bar]", total: 20)
    bar2 = multibar.register("two [:bar]", total: 30)
    
    th1 = Thread.new { 20.times { sleep(0.1); bar1.advance } }
    th2 = Thread.new { 30.times { sleep(0.1); bar2.advance } }
    
    [th1, th2].each { |t| t.join }
  3. Configure progress bar format strings and tokens

    master

    Every TTY::ProgressBar instance requires a format string. You can use special tokens within this string to display dynamic information. In indeterminate mode (where the total is unknown), tokens like :total, :percent, and :eta will display as -.

    "downloading [:bar] :elapsed :percent"
  4. How indeterminate progress works

    master

    If the total number of steps is unknown, set the total configuration option to nil. This switches the progress bar to an indeterminate mode, which displays a moving animation instead of a percentage-based bar.

    # downloading [       <=>                    ]
    bar = TTY::ProgressBar.new("downloading [:bar]", total: nil)
  5. Configure TTY::ProgressBar options

    master

    You can configure a TTY::ProgressBar instance using a hash of options during initialization, via a configuration block, or by updating it at runtime.

    Initialization via Hash:

    bar = TTY::ProgressBar.new("[:bar]", total: 30, frequency: 10)

    Initialization via Block:

    bar = TTY::ProgressBar.new("[:bar]") do |config|
      config.total = 30
      config.frequency = 10
      config.clear = true
    end

    Runtime Configuration: Use configure to change settings (new values take precedence) or update for quick property changes.

    # Using configure
    bar.configure do |config|
      config.total = 100
      config.frequency = 20
    end
    
    # Using update
    bar.update(total: 100, frequency: 20)
  6. Create custom formatters for new tokens

    master

    If the built-in tokens are insufficient, you can create a custom formatter class. To do this:

    1. Include TTY::ProgressBar::Formatter[/:your_token/i] in your class.
    2. Implement a call(value) method that uses value.gsub(matcher, replacement) to substitute the token with your custom logic.
    3. Inside call, you can access the progress bar instance via progress to read internal data like start_time or configuration options.
    4. Register the formatter using bar.use YourFormatter.
    class TimeFormatter
      include TTY::ProgressBar::Formatter[/:time/i]
    
      def call(value)
        # access current progress bar instance to read start time
        elapsed = (Time.now - progress.start_time).to_s
        value.gsub(matcher, elapsed)
      end
    end
    
    bar = TTY::ProgressBar.new(":time", total: 30)
    bar.use TimeFormatter
    bar.advance
  7. Install TTY::ProgressBar

    master

    You can install tty-progressbar using Bundler by adding it to your Gemfile, or by installing the gem directly via the command line.

    # Add to Gemfile
    gem "tty-progressbar"
    # Or install via gem
    $ gem install tty-progressbar
  8. Basic Usage of TTY::ProgressBar

    master

    To create a basic progress bar, initialize TTY::ProgressBar.new with a format string containing the :bar token and a total number of steps. Use the advance method to increment progress. By default, advance increases the progress by 1 step.

    bar = TTY::ProgressBar.new("downloading [:bar]", total: 30)
    
    30.times do
      sleep(0.1)
      bar.advance  # by default increases by 1
    end
  9. Use Unicode characters in progress bars

    master

    You can use non-monospaced Unicode characters in the format string or in configuration options like complete, head, incomplete, and unknown.

    # Using Unicode in configuration
    bar = TTY::ProgressBar.new("Unicode [:bar]", total: 30, complete: "あ")
    
    # Using Unicode in the format string
    bar = TTY::ProgressBar.new("あめかんむり[:bar]", total: 20)
  10. Colorize progress bars with Pastel

    master

    You can colorize the complete and incomplete characters by passing colored strings (e.g., from the pastel gem) into the TTY::ProgressBar constructor.

    require "pastel"
    
    pastel = Pastel.new
    green  = pastel.on_green(" ")
    red    = pastel.on_red(" ")
    
    bar = TTY::ProgressBar.new("|:bar|",
      total: 30,
      complete: green,
      incomplete: red
    )
  11. Check bar state with status methods

    master

    Use these predicate methods to check the current state of the progress bar:

    • complete?: Returns true if the bar finished successfully.
    • paused?: Returns true if the bar is currently paused.
    • stopped?: Returns true if the bar is currently stopped.
    • indeterminate?: Returns true if the bar is in an indeterminate state (when :total is nil).
    bar.complete?   # => false
    bar.paused?     # => true
    bar.stopped?    # => true
    bar.indeterminate? # => false
  12. Define custom tokens via advance()

    master

    For lightweight content replacement that doesn't depend on internal progress data (like titles), you can pass a hash of name: value pairs to the advance method. These names must be present in your initial format string.

    bar = TTY::ProgressBar.new("(:current) :title", total: 4)
    bar.advance(title: "Hello Piotr!")
    bar.advance(3, title: "Bye Piotr!")