/tqdmpp

Simple C++ "port" of Python tqdm terminal progress bar library.

Primary LanguageC++MIT LicenseMIT

tqdm++

tqdm++ is a C++ range/view interface for displaying a progress bar in the terminal. It is a rudimentary equivalent to the Python tqdm library. Wrap a range or view in Tqdm() and it will display a progress bar in the terminal:

#include <tqdm/tqdm.h>

using tqdm::Tqdm;

for (auto&& i : Tqdm(std::views::iota(0, 10000))) {
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

17%│███▍ │ 1730/10000 [00:17<01:24 98.38it/s]

tqdm::Range(N) can be used as a shortcut for the iota above to achieve a timed integer iteration.

Note

This port does not have quite a lot of the functionality of the Python library. This is intentional. It is meant to be lighter weight and to support the majority of use cases (and all of my personal uses).

Building

tqdm++ is a header-only library requiring C++23 or newer. To add it to a CMake project:

FetchContent_Declare(
  tqdmpp
  GIT_REPOSITORY https://github.com/sophec/tqdmpp.git
  GIT_TAG main
)
FetchContent_MakeAvailable(tqdmpp)

target_link_libraries(mytarget PRIVATE tqdmpp)

Usage

The primary interface for the project is the tqdm::Tqdm class. This will wrap any (ish) range/view and display a progress bar:

#include <tqdm/tqdm.h>

using tqdm::Tqdm;

for (auto&& item : Tqdm(my_range)) {
  // ...
}

Additionally, the helper function tqdm::Range() allows you to easily replace a classic for (int i{}; i < N; ++i) loop like so:

// iterates 0..99
for (std::size_t i : tqdm::Range(100)) {}
// iterates 10..109
for (std::size_t i : tqdm::Range(10, 100)) {}

If the range's bound is not known (i.e., not std::ranges::sized_range<R>), the progress bar is not shown. Instead, a running count, elapsed time, and items per second will be shown.

As a shorthand for an iteration counter with unknown upper bound, the tqdm::Iota() function is provided:

// iterates forever, starting from 0
for (std::size_t i : tqdm::Iota()) {
  if (some_condition) {
    break;
  }
}
// iterates forever, starting from 10
for (std::size_t i : tqdm::Iota(10)) {
  if (some_condition) {
    break;
  }
}

Configuration

The constructor for the Tqdm class and the Range/Iota helper overloads accept an optional last argument of type tqdm::Config. This lets you configure some of the behavior of the progress bar. For example:

for (auto&& item : Tqdm(my_range, {
                          .prefix = "doing stuff: ",
                          .unit = "files",
                          .segments = 30,
                          .term_progress = true,
                        })) {
  // ...
}
for (auto&& i : tqdm::Range(100, { .unit = "items" })) {}
for (auto&& i : tqdm::Iota({ .unit = "items" })) {}

Options

Option Type Default Description
prefix string_view "" A prefix for the progress bar (should include a trailing space)
unit string_view "it" Units (displayed as 123.45{unit}/s)
segments size_t 20 Number of segments in the progress bar (should be at least 1)
min_update_ms unsigned 100 Minimum number of milliseconds between consecutive iterations before updating the status bar (improves performance by skipping unecessary writes)
ascii bool false Use ASCII instead of unicode for the bar (uses 0-9 for partial progress and # for full segments)
use_stderr bool false Print the progress bar to stderr instead of stdout
term_progress bool false Use ConEmu Progress Bar sequences (OSC 9;4) to set the terminal progress bar (requires terminal support)