31 Commits
v1.3 ... v1.4

Author SHA1 Message Date
Pranav
ba604b7dd6 Update README.md 2019-12-17 22:04:36 -06:00
Pranav
2853aba409 Update README.md 2019-12-17 22:03:28 -06:00
Pranav Srinivas Kumar
2719604ba9 Updated README 2019-12-17 22:02:40 -06:00
Pranav
a80e4af117 Update README.md 2019-12-17 21:59:29 -06:00
Pranav Srinivas Kumar
d862ccde37 Updated FID 2019-12-17 21:59:17 -06:00
Pranav Srinivas Kumar
63ea50103a Merge branch 'master' of github.com:p-ranav/indicators 2019-12-17 21:56:41 -06:00
Pranav Srinivas Kumar
d9aa064380 Updated GIF 2019-12-17 21:56:36 -06:00
Pranav
5449ad0629 Update README.md 2019-12-17 21:49:37 -06:00
Pranav
c5969eefe4 Update README.md 2019-12-17 21:41:44 -06:00
Pranav Srinivas Kumar
34813c8642 Added progress_bar.tick GIF 2019-12-17 21:40:05 -06:00
Pranav Srinivas Kumar
c2832a5412 Updated GIF 2019-12-17 21:36:13 -06:00
Pranav Srinivas Kumar
67663b9d7d Updated GIF 2019-12-17 21:33:34 -06:00
Pranav
45ad6da847 Update README.md 2019-12-17 21:33:22 -06:00
Pranav Srinivas Kumar
5eb8cc5f91 Merge branch 'master' of github.com:p-ranav/indicators 2019-12-17 21:30:49 -06:00
Pranav Srinivas Kumar
99a14b5563 Updated GIF 2019-12-17 21:30:37 -06:00
Pranav
3bc140f90f Update README.md 2019-12-17 21:26:55 -06:00
Pranav
3f21b1d901 Update README.md 2019-12-17 21:15:47 -06:00
Pranav
7eb31cf24b Update README.md 2019-12-17 21:12:13 -06:00
Pranav
b726255bfd Merge pull request #12 from p-ranav/feature/multi_progress
Feature/multi progress
2019-12-17 21:11:07 -06:00
Pranav Srinivas Kumar
082b7a69e9 Updated README GIF 2019-12-17 21:05:14 -06:00
Pranav Srinivas Kumar
39922dbf80 Updated README 2019-12-17 20:59:50 -06:00
Pranav Srinivas Kumar
4f0cd06969 Minor update 2019-12-17 20:57:28 -06:00
Pranav Srinivas Kumar
70f843ce01 Minor update to API 2019-12-17 20:56:17 -06:00
Pranav Srinivas Kumar
4e5e5cfa19 Added missing includes 2019-12-17 20:40:44 -06:00
Pranav
36e77a64e9 Update README.md 2019-12-17 20:36:39 -06:00
Pranav
b542bedf5b Update README.md 2019-12-17 20:28:18 -06:00
Pranav Srinivas Kumar
8e41f2712e Added sample showing MultiProgress with BlockProgressBar 2019-12-17 20:21:33 -06:00
Pranav Srinivas Kumar
03000c8493 Changed MultiProgress into a template container class 2019-12-17 20:14:05 -06:00
Pranav Srinivas Kumar
92725d6cb2 Draft implementation of MultiProgress for progress bars 2019-12-17 20:06:50 -06:00
Pranav Srinivas Kumar
01966b8239 First attempt at MultiProgress 2019-12-17 19:10:52 -06:00
Pranav
788f6c9e1e Update README.md 2019-12-17 15:41:42 -06:00
14 changed files with 468 additions and 146 deletions

272
README.md
View File

@@ -9,7 +9,7 @@
<a href="https://github.com/p-ranav/indicators/blob/master/LICENSE">
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="license"/>
</a>
<img src="https://img.shields.io/badge/version-1.2-blue.svg?cacheSeconds=2592000" alt="version"/>
<img src="https://img.shields.io/badge/version-1.4-blue.svg?cacheSeconds=2592000" alt="version"/>
</p>
<p align="center">
@@ -23,33 +23,18 @@
* Source for the above GIF can be found [here](demo/demo.cpp)
* MIT License
# Table of Contents
* [Progress Bar](#progress-bar)
* [Block Progress Bar](#block-progress-bar)
* [Multi Progress](#multiprogress)
* [Progress Spinner](#progress-spinner)
* [Contributing](#contributing)
* [License](#license)
# Progress bar
To introduce a progress bar in your application, include `indicators/progress_bar.hpp` and create a `ProgressBar` object.
```cpp
#include <indicators/progress_bar.hpp>
int main() {
indicators::ProgressBar bar;
// Configure the bar
bar.set_bar_width(50);
bar.start_bar_with("[");
bar.fill_bar_progress_with("=");
bar.lead_bar_progress_with(">");
bar.fill_bar_remainder_with(" ");
bar.end_bar_with("]");
bar.set_postfix_text("Getting started");
bar.set_foreground_color(indicators::Color::GREEN);
// Update bar state
return 0;
}
```
Here's the general structure of a progress bar:
To introduce a progress bar in your application, include `indicators/progress_bar.hpp` and create a `ProgressBar` object. Here's the general structure of a progress bar:
```
{prefix} {start} {fill} {lead} {remaining} {end} {percentage} [{elapsed}<{remaining}] {postfix}
@@ -64,6 +49,10 @@ From application-level code, there are two ways in which you can update this pro
You can update the progress bar using `bar.tick()` which increments progress by exactly `1%`.
<p align="center">
<img src="img/progress_bar_tick.gif"/>
</p>
```cpp
#include <indicators/progress_bar.hpp>
#include <thread>
@@ -79,7 +68,7 @@ int main() {
bar.lead_bar_progress_with(">");
bar.fill_bar_remainder_with(" ");
bar.end_bar_with("]");
bar.set_postfix_text("Getting started");
bar.set_postfix_text("Extracting Archive");
bar.set_foreground_color(indicators::Color::GREEN);
// Update bar state
@@ -100,110 +89,61 @@ The above code will print a progress bar that goes from 0 to 100% at the rate of
If you'd rather control progress of the bar in discrete steps, consider using `bar.set_progress(value)`. Example:
<p align="center">
<img src="img/progress_bar_set_progress.gif"/>
</p>
```cpp
#include <chrono>
#include <indicators/progress_bar.hpp>
#include <thread>
#include <chrono>
int main() {
// Hide cursor
std::cout << "\e[?25l";
indicators::ProgressBar bar;
// Configure the bar
bar.set_bar_width(50);
bar.start_bar_with("[");
bar.fill_bar_progress_with("=");
bar.lead_bar_progress_with(">");
bar.fill_bar_remainder_with(" ");
bar.end_bar_with("]");
bar.set_postfix_text("Getting started");
bar.set_foreground_color(indicators::Color::GREEN);
// Update bar state
bar.set_progress(10); // 10% done
// do some work
std::this_thread::sleep_for(std::chrono::milliseconds(100));
bar.set_progress(30); // 30% done
// do some more work
std::this_thread::sleep_for(std::chrono::milliseconds(600));
bar.set_progress(65); // 65% done
// do final bit of work
std::this_thread::sleep_for(std::chrono::milliseconds(300));
bar.set_progress(100); // all done
return 0;
}
```
## Multi-threaded Example
```cpp
#include <indicators/progress_bar.hpp>
#include <vector>
int main() {
indicators::ProgressBar bar;
bar.set_bar_width(50);
bar.start_bar_with("[");
bar.fill_bar_progress_with("");
bar.lead_bar_progress_with("");
bar.fill_bar_remainder_with("-");
bar.end_bar_with(" ]");
bar.set_foreground_color(indicators::Color::YELLOW);
bar.set_postfix_text("Loading dependency 1/4");
bar.set_foreground_color(indicators::Color::CYAN);
// As configured, the bar will look like this:
//
// [■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■-------------] 70%
//
//
// Update bar state
bar.set_progress(10); // 10% done
std::atomic<size_t> index{0};
std::vector<std::string> status_text =
{
"Rocket.exe is not responding",
"Finding a replacement engineer",
"Buying more snacks",
"Assimilating the modding community",
"Crossing fingers",
"Porting KSP to a Nokia 3310"
};
// do some work
std::this_thread::sleep_for(std::chrono::milliseconds(800));
// Let's say you want to append some status text to the right of the progress bar
// You can use bar.set_postfix_text(...) to append text to the right
//
// [■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■-------------] 70% Finding a replacement engineer
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
//
bar.set_postfix_text("Loading dependency 2/4");
auto job = [&bar, &index, &status_text]() {
while (true) {
if (bar.is_completed()) {
break;
}
bar.set_postfix_text(status_text[index % status_text.size()]);
bar.tick();
index += 1;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
};
bar.set_progress(30); // 30% done
std::thread first_job(job);
std::thread second_job(job);
std::thread third_job(job);
std::thread last_job(job);
// do some more work
std::this_thread::sleep_for(std::chrono::milliseconds(700));
first_job.join();
second_job.join();
third_job.join();
last_job.join();
bar.set_postfix_text("Loading dependency 3/4");
bar.set_progress(65); // 65% done
// do final bit of work
std::this_thread::sleep_for(std::chrono::milliseconds(900));
bar.set_postfix_text("Loaded dependencies!");
bar.set_progress(100); // all done
bar.mark_as_completed();
// Show cursor
std::cout << "\e[?25h";
return 0;
}
@@ -297,29 +237,113 @@ int main() {
}
```
# Progress Spinner
# MultiProgress
To introduce a progress spinner in your application, include `indicators/progress_spinner.hpp` and create a `ProgressSpinner` object.
`indicators` supports management of multiple progress bars with the `MultiProgress` class.
`template <typename Indicator, size_t count> class MultiProgress` is a class template that holds references to multiple progress bars and provides a safe interface to update the state of each bar. `MultiProgress` works with both `ProgressBar` and `BlockProgressBar` classes.
Below is an example `MultiProgress` object that manages three `ProgressBar` objects.
<p align="center">
<img src="img/multi_progress.gif"/>
</p>
```cpp
#include <indicators/progress_spinner.hpp>
#include <indicators/multi_progress.hpp>
#include <indicators/progress_bar.hpp>
int main() {
indicators::ProgressSpinner spinner;
// Configure the spinner
spinner.set_prefix_text(" ");
spinner.set_postfix_text("Checking credentials");
spinner.set_foreground_color(indicators::Color::YELLOW);
spinner.set_spinner_states({"", "", "", "", "", "", "", ""});
// Configure first progress bar
indicators::ProgressBar bar1;
bar1.set_bar_width(50);
bar1.start_bar_with("[");
bar1.fill_bar_progress_with("");
bar1.lead_bar_progress_with("");
bar1.fill_bar_remainder_with(" ");
bar1.end_bar_with(" ]");
bar1.set_foreground_color(indicators::Color::YELLOW);
bar1.show_elapsed_time();
bar1.show_remaining_time();
bar1.set_prefix_text("Progress Bar #1 ");
// Update spinner state
// Configure second progress bar
indicators::ProgressBar bar2;
bar2.set_bar_width(50);
bar2.start_bar_with("[");
bar2.fill_bar_progress_with("=");
bar2.lead_bar_progress_with(">");
bar2.fill_bar_remainder_with(" ");
bar2.end_bar_with(" ]");
bar2.set_foreground_color(indicators::Color::CYAN);
bar2.show_elapsed_time();
bar2.show_remaining_time();
bar2.set_prefix_text("Progress Bar #2 ");
// Configure third progress bar
indicators::ProgressBar bar3;
bar3.set_bar_width(50);
bar3.start_bar_with("[");
bar3.fill_bar_progress_with("#");
bar3.lead_bar_progress_with("#");
bar3.fill_bar_remainder_with(" ");
bar3.end_bar_with(" ]");
bar3.set_foreground_color(indicators::Color::RED);
bar3.show_elapsed_time();
bar3.show_remaining_time();
bar3.set_prefix_text("Progress Bar #3 ");
// Construct MultiProgress object
indicators::MultiProgress<indicators::ProgressBar, 3> bars;
bars.insert<0>(bar1);
bars.insert<1>(bar2);
bars.insert<2>(bar3);
std::cout << "Multiple Progress Bars:\n";
auto job1 = [&bars]() {
while (true) {
bars.tick<0>();
if (bars.is_completed<0>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
};
auto job2 = [&bars]() {
while (true) {
bars.tick<1>();
if (bars.is_completed<1>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
};
auto job3 = [&bars]() {
while (true) {
bars.tick<2>();
if (bars.is_completed<2>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(60));
}
};
std::thread first_job(job1);
std::thread second_job(job2);
std::thread third_job(job3);
first_job.join();
second_job.join();
third_job.join();
return 0;
}
```
Here's the general structure of a progress spinner:
# Progress Spinner
To introduce a progress spinner in your application, include `indicators/progress_spinner.hpp` and create a `ProgressSpinner` object. Here's the general structure of a progress spinner:
```
{prefix} {spinner} {percentage} [{elapsed}<{remaining}] {postfix}
@@ -327,6 +351,10 @@ Here's the general structure of a progress spinner:
ProgressSpinner has a vector of strings: `spinner_states`. At each update, the spinner will pick the next string from this sequence to print to the console. The spinner state can be updated similarly to ProgressBars: Using either `tick()` or `set_progress(value)`.
<p align="center">
<img src="img/progress_spinner.gif"/>
</p>
```cpp
#include <indicators/progress_spinner.hpp>

BIN
img/multi_progress.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
img/progress_bar_tick.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 146 KiB

View File

@@ -131,7 +131,10 @@ private:
std::atomic<bool> _saved_start_time{false};
std::chrono::time_point<std::chrono::high_resolution_clock> _start_time_point;
std::mutex _mutex;
Color _foreground_color;
Color _foreground_color{indicators::Color::WHITE};
template <typename Indicator, size_t count> friend class MultiProgress;
std::atomic<bool> _multi_progress_mode{false};
std::ostream &_print_duration(std::ostream &os, std::chrono::nanoseconds ns) {
using namespace std;
@@ -162,7 +165,13 @@ private:
}
}
void _print_progress() {
void _print_progress(bool from_multi_progress = false) {
if (_multi_progress_mode && !from_multi_progress) {
if (_progress > 100.0) {
_completed = true;
}
return;
}
std::unique_lock<std::mutex> lock{_mutex};
auto now = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(now - _start_time_point);
@@ -231,6 +240,9 @@ private:
auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
_print_duration(std::cout, remaining);
std::cout << "]";
} else {
if (_show_elapsed_time)
std::cout << "]";
}
if (_max_postfix_text_length == 0)
@@ -240,7 +252,7 @@ private:
if (_progress > 100.0) {
_completed = true;
}
if (_completed)
if (_completed && !from_multi_progress) // Don't std::endl if calling from MultiProgress
std::cout << termcolor::reset << std::endl;
}
};

View File

@@ -0,0 +1,92 @@
/*
Activity Indicators for Modern C++
https://github.com/p-ranav/indicators
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <atomic>
#include <functional>
#include <indicators/color.hpp>
#include <iostream>
#include <mutex>
#include <vector>
namespace indicators {
template <typename Indicator, size_t count> class MultiProgress {
public:
MultiProgress() { _bars.reserve(count); }
template <size_t index>
typename std::enable_if<(index < count), void>::type insert(Indicator &bar) {
_bars.insert(_bars.begin() + index, 1, bar);
bar._multi_progress_mode = true;
}
template <size_t index>
typename std::enable_if<(index < count), void>::type set_progress(float value) {
if (!_bars[index].get().is_completed())
_bars[index].get().set_progress(value);
_print_progress();
}
template <size_t index> typename std::enable_if<(index < count), void>::type tick() {
if (!_bars[index].get().is_completed())
_bars[index].get().tick();
_print_progress();
}
template <size_t index>
typename std::enable_if<(index < count), bool>::type is_completed() const {
return _bars[index].get().is_completed();
}
private:
std::atomic<bool> _started{false};
std::mutex _mutex;
std::vector<std::reference_wrapper<Indicator>> _bars;
bool _all_completed() {
bool result{true};
for (size_t i = 0; i < count; ++i)
result &= _bars[i].get().is_completed();
return result;
}
void _print_progress() {
std::unique_lock<std::mutex> lock{_mutex};
if (_started)
for (size_t i = 0; i < count; ++i)
std::cout << "\x1b[A";
for (auto &bar : _bars) {
bar.get()._print_progress(true);
std::cout << "\n";
}
std::cout << termcolor::reset;
if (!_started)
_started = true;
}
};
} // namespace indicators

View File

@@ -145,7 +145,10 @@ private:
std::atomic<bool> _saved_start_time{false};
std::chrono::time_point<std::chrono::high_resolution_clock> _start_time_point;
std::mutex _mutex;
Color _foreground_color;
Color _foreground_color{indicators::Color::WHITE};
template <typename Indicator, size_t count> friend class MultiProgress;
std::atomic<bool> _multi_progress_mode{false};
std::ostream &_print_duration(std::ostream &os, std::chrono::nanoseconds ns) {
using namespace std;
@@ -176,7 +179,13 @@ private:
}
}
void _print_progress() {
void _print_progress(bool from_multi_progress = false) {
if (_multi_progress_mode && !from_multi_progress) {
if (_progress > 100.0) {
_completed = true;
}
return;
}
std::unique_lock<std::mutex> lock{_mutex};
auto now = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(now - _start_time_point);
@@ -239,6 +248,9 @@ private:
auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
_print_duration(std::cout, remaining);
std::cout << "]";
} else {
if (_show_elapsed_time)
std::cout << "]";
}
if (_max_postfix_text_length == 0)
@@ -248,7 +260,7 @@ private:
if (_progress > 100.0) {
_completed = true;
}
if (_completed)
if (_completed && !from_multi_progress) // Don't std::endl if calling from MultiProgress
std::cout << termcolor::reset << std::endl;
}
};

View File

@@ -207,6 +207,9 @@ private:
auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
_print_duration(std::cout, remaining);
std::cout << "]";
} else {
if (_show_elapsed_time)
std::cout << "]";
}
if (_max_postfix_text_length == 0)

View File

@@ -16,3 +16,9 @@ target_link_libraries(progress_spinner PRIVATE indica::indica)
add_executable(time_meter time_meter.cpp)
target_link_libraries(time_meter PRIVATE indica::indica)
add_executable(multi_progress_bar multi_progress_bar.cpp)
target_link_libraries(multi_progress_bar PRIVATE indica::indica)
add_executable(multi_block_progress_bar multi_block_progress_bar.cpp)
target_link_libraries(multi_block_progress_bar PRIVATE indica::indica)

View File

@@ -0,0 +1,70 @@
#include <indicators/block_progress_bar.hpp>
#include <indicators/multi_progress.hpp>
int main() {
indicators::BlockProgressBar bar1;
bar1.set_bar_width(50);
bar1.set_foreground_color(indicators::Color::YELLOW);
bar1.show_elapsed_time();
bar1.show_remaining_time();
bar1.set_prefix_text("Progress Bar #1 ");
indicators::BlockProgressBar bar2;
bar2.set_bar_width(50);
bar2.set_foreground_color(indicators::Color::CYAN);
bar2.show_elapsed_time();
bar2.show_remaining_time();
bar2.set_prefix_text("Progress Bar #2 ");
indicators::BlockProgressBar bar3;
bar3.set_bar_width(50);
bar3.set_foreground_color(indicators::Color::RED);
bar3.show_elapsed_time();
bar3.show_remaining_time();
bar3.set_prefix_text("Progress Bar #3 ");
indicators::MultiProgress<indicators::BlockProgressBar, 3> bars;
bars.insert<0>(bar1);
bars.insert<1>(bar2);
bars.insert<2>(bar3);
std::cout << "Multiple Progress Bars:\n";
auto job1 = [&bars]() {
while (true) {
bars.tick<0>();
if (bars.is_completed<0>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
};
auto job2 = [&bars]() {
while (true) {
bars.tick<1>();
if (bars.is_completed<1>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
};
auto job3 = [&bars]() {
while (true) {
bars.tick<2>();
if (bars.is_completed<2>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(60));
}
};
std::thread first_job(job1);
std::thread second_job(job2);
std::thread third_job(job3);
first_job.join();
second_job.join();
third_job.join();
return 0;
}

View File

@@ -0,0 +1,85 @@
#include <indicators/multi_progress.hpp>
#include <indicators/progress_bar.hpp>
int main() {
indicators::ProgressBar bar1;
bar1.set_bar_width(50);
bar1.start_bar_with("[");
bar1.fill_bar_progress_with("");
bar1.lead_bar_progress_with("");
bar1.fill_bar_remainder_with(" ");
bar1.end_bar_with(" ]");
bar1.set_foreground_color(indicators::Color::YELLOW);
bar1.show_elapsed_time();
bar1.show_remaining_time();
bar1.set_prefix_text("Progress Bar #1 ");
indicators::ProgressBar bar2;
bar2.set_bar_width(50);
bar2.start_bar_with("[");
bar2.fill_bar_progress_with("=");
bar2.lead_bar_progress_with(">");
bar2.fill_bar_remainder_with(" ");
bar2.end_bar_with(" ]");
bar2.set_foreground_color(indicators::Color::CYAN);
bar2.show_elapsed_time();
bar2.show_remaining_time();
bar2.set_prefix_text("Progress Bar #2 ");
indicators::ProgressBar bar3;
bar3.set_bar_width(50);
bar3.start_bar_with("[");
bar3.fill_bar_progress_with("#");
bar3.lead_bar_progress_with("#");
bar3.fill_bar_remainder_with(" ");
bar3.end_bar_with(" ]");
bar3.set_foreground_color(indicators::Color::RED);
bar3.show_elapsed_time();
bar3.show_remaining_time();
bar3.set_prefix_text("Progress Bar #3 ");
indicators::MultiProgress<indicators::ProgressBar, 3> bars;
bars.insert<0>(bar1);
bars.insert<1>(bar2);
bars.insert<2>(bar3);
std::cout << "Multiple Progress Bars:\n";
auto job1 = [&bars]() {
while (true) {
bars.tick<0>();
if (bars.is_completed<0>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
};
auto job2 = [&bars]() {
while (true) {
bars.tick<1>();
if (bars.is_completed<1>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
};
auto job3 = [&bars]() {
while (true) {
bars.tick<2>();
if (bars.is_completed<2>())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(60));
}
};
std::thread first_job(job1);
std::thread second_job(job2);
std::thread third_job(job3);
first_job.join();
second_job.join();
third_job.join();
return 0;
}

View File

@@ -3,36 +3,50 @@
#include <thread>
int main() {
// Hide cursor
std::cout << "\e[?25l";
indicators::ProgressBar bar;
// Configure the bar
bar.set_bar_width(50);
bar.start_bar_with("[");
bar.fill_bar_progress_with("=");
bar.lead_bar_progress_with(">");
bar.fill_bar_remainder_with(" ");
bar.fill_bar_progress_with("");
bar.lead_bar_progress_with("");
bar.fill_bar_remainder_with("-");
bar.end_bar_with(" ]");
bar.set_postfix_text("Getting started");
bar.set_foreground_color(indicators::Color::GREEN);
bar.set_postfix_text("Loading dependency 1/4");
bar.set_foreground_color(indicators::Color::CYAN);
// Update bar state
bar.set_progress(10); // 10% done
// do some work
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(800));
bar.set_postfix_text("Loading dependency 2/4");
bar.set_progress(30); // 30% done
// do some more work
std::this_thread::sleep_for(std::chrono::milliseconds(600));
std::this_thread::sleep_for(std::chrono::milliseconds(700));
bar.set_postfix_text("Loading dependency 3/4");
bar.set_progress(65); // 65% done
// do final bit of work
std::this_thread::sleep_for(std::chrono::milliseconds(300));
std::this_thread::sleep_for(std::chrono::milliseconds(900));
bar.set_postfix_text("Loaded dependencies!");
bar.set_progress(100); // all done
bar.mark_as_completed();
// Show cursor
std::cout << "\e[?25h";
return 0;
}