TTY::ProgressBar
A flexible progress bars drawing in terminal emulators.
TTY::ProgressBar provides independent progress bars component for TTY toolkit.
Features
- Fully configurable
- Extremly flexible progress display formatting
- Ability to define your custom format tokens
- Works on all ECMA-48 compatible terminals
Installation
Add this line to your application's Gemfile:
gem 'tty-progressbar'
And then execute:
$ bundle
Or install it yourself as:
$ gem install tty-progressbar
Contents
1. Usage
TTY::ProgressBar requires only format string and total number of steps to completion. Once initialized, use advance
method to indicated the progress like so:
= TTY::ProgressBar.new("downloading [:bar]", total: 30)
30.times do
sleep(0.1)
.advance(1)
end
This would produce animation in your terminal:
downloading [======================= ]
1.1 advance
Once you have TTY::ProgressBar instance, you can progress the display by calling advance
method. By default it will increase by 1
but you can pass any number of steps, for instance, when used to advance number of bytes of downloaded file.
.advance(1000)
You can also pass negative steps if you wish to backtrack the progress:
.advance(-1)
Note: If a progress bar has already finished then negative steps will not set it back to desired value.
1.2 current=
TTY::ProgressBar allows you to set progress to a given value by calling current=
method.
.current = 50
Note: If a progress bar has already finished then negative steps will not set it back to desired value.
1.3 ratio=
In order to update overall completion of a progress bar as an exact percentage use the ratio=
method. The method accepts values between 0
and 1
inclusive. For example, a ratio of 0.5 will attempt to set the progress bar halfway:
.ratio = 0.5
1.4 start
By default the timer for internal time esitamation is started automatically when the advance
method is called. However, if you require control on when the progression timer is started use start
call:
.start # => sets timer and draws initial progress bar
1.5 finish
In order to immediately stop and finish the progress call finish
. This will finish drawing the progress and return to new line.
.finish
1.6 complete?
During progresion you can check if bar is finished or not by calling complete?
.
.complete? # => false
1.7 reset
In order to reset currently running or finished progress bar to its original configuration and initial position use reset
like so:
.reset
1.8 resize
If you wish for a progress bar to change it's current width, you can use resize
by passing in a new desired length:
.resize(50) # => will resize bar proportionately from this point onwards
2. Configuration
There are number of configuration options that can be provided:
total
total number of steps to completionwidth
for the bars display including formatting options defaulting to totalcomplete
completion character by default=
incomplete
incomplete character by default single spaceoutput
the output stream defaulting tostderr
frequency
used to throttle the output, by default0
(see Frequency)interval
used to measure the speed, by default1 sec
(see Interval)hide_cursor
to hide display cursor defaulting tofalse
clear
to clear the finished bar defaulting tofalse
All the above options can be passed in as hash options or block parameters:
TTY::ProgressBar.new "[:bar]" do |config|
config.total = 30
config.frequency = 10
config.clear = true
end
2.1 Frequency
Each time the advance
is called it causes the progress bar to repaint. In cases when there is a huge number of updates per second, you may need to limit the rendering process by using the frequency
option.
The frequency
option accepts integer
representing number of Hz
units, for instance, frequency of 2 will mean that the progress will be updated maximum 2 times per second.
TTY::ProgressBar.new("[:bar]", total: 30, frequency: 10) # 10 Hz
2.2 Interval
For every call of advance
method the ProgressBar takes a sample for speed measurement. By default the samples are grouped per second but you can change that by passing the interval
option.
The interval
option is an integer
that represents the number of seconds, for example, interval of 60
would mean that speed is measured per 1 minute.
TTY::ProgressBar.new(":rate/minute", total: 100, interval: 60) # 1 minute
TTY::ProgressBar.new(":rate/hour", total: 100, interval: 3600) # 1 hour
3. Formatting
Every TTY::ProgressBar instance requires a format string, which apart from regular characters accepts special tokens to display dynamic information. For instance, a format to measure download progress could be:
"downloading [:bar] :elapsed :percent"
3.1 Tokens
These are the tokens that are currently supported:
:bar
the progress bar:current
the current progress number:current_byte
the current progress in bytes:total
the total progress number:total_byte
the total progress in bytes:percent
the completion percentage:elapsed
the elapsed time in seconds:eta
the esitmated time to completion in seconds:rate
the current rate of progression per second:byte_rate
the current rate of pregression in bytes per second:mean_rate
the averaged rate of progression per second:mean_byte
the averaged rate of progression in bytes per second
3.2 Custom Formatters
If the provided tokens do not meet your needs, you can write your own formatter and instrument formatting pipeline to use a formatter you prefer. This option is preferred if you are going to rely on progress bar internal data such as rate
, current
etc. which will all be available on the passed in progress bar instance.
For example, begin by creating custom formatter called TimeFormatter
that will dynamicly update :time
token in format string. The methods that you need to specify are initialize
, matches?
and format
like follows:
class TimeFormatter
def initialize(progress)
@progress = progress # current progress bar instance
end
def matches?(value) # specify condition to match for in display string
value.to_s =~ /:time/
end
def format(value) # specify how display string is formatted
transformed = (Time.now - @progress.start_at).to_s
value.gsub(/:time/, transformed) # => :time token replacement
end
end
Notice that you have access to all the configuration options inside the formatter by simply invoking them on the @progress
instance.
Create TTY::ProgressBar instance with new token:
= TTY::ProgressBar.new(":time", total: 30)
Then add TimeFormatter
to the pipeline like so:
.use TimeFormatter
and then invoke progression:
.advance
3.3 Custom Tokens
You can define custom tokens by passing pairs name: value
to advance
method in order to dynamically update formatted bar. This option is useful for lightweight content replacement such as titles that doesn't depend on the internal data of progressbar. For example:
= TTY::ProgressBar.new("(:current) :title", total: 4)
.advance(title: 'Hello Piotr!')
.advance(3, title: 'Bye Piotr!')
which outputs:
(1) Hello Piotr!
(4) Bye Piotr!
4. Logging
If you want to print messages out to terminal along with the progress bar use the log
method. The messages will appear above the progress bar and will continue scrolling up as more are logged out.
.log('Piotrrrrr')
.advance
will result in:
Piotrrrrr
downloading [======================= ]
5. Examples
This section demonstrates some of the possible uses for the TTY::ProgressBar, for more please see examples folder in the source directory.
5.1 Colors
Creating a progress bar that displays in color is as simple as coloring the :complete
and :incomplete
character options. In order to help with coloring you can use pastel library like so:
require 'pastel'
pastel = Pastel.new
green = pastel.on_green(" ")
red = pastel.on_red(" ")
And then pass in the colored strings as options to TTY::ProgressBar:
= TTY::ProgressBar.new("|:bar|",
total: 30,
complete: green,
incomplete: red
)
To see how a progress bar is reported in terminal you can do:
30.times do
sleep(0.1)
.advance
end
5.2 Speed
Commonly a progress bar is utilized to measure download speed per second. This can be done like so:
TTY::ProgressBar.new("[:bar] :byte_rate/s") do |config|
config.total = 300000
config.interval = 1 # => 1 sec
end
This will result in output similar to:
downloading [======================= ] 4.12MB/s
Contributing
- Fork it ( https://github.com/peter-murach/tty-progressbar/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
Copyright
Copyright (c) 2014-2016 Piotr Murach. See LICENSE for further details.