89 Commits
v1.8 ... v2.3

Author SHA1 Message Date
Pranav Srinivas Kumar
26d39ad8fb Bumped to version v2.3 2023-02-15 07:17:27 -08:00
Pranav Srinivas Kumar
bfe95fee17 Updated single_include to support mbstowcs_s Windows impl 2023-02-15 07:11:53 -08:00
Pranav
11c60675d5 Merge pull request #119 from jsttzsf/bugfix/mbstowcs_deprecation
Replaced mbstowcs with mbstowcs_s
2023-02-15 09:09:54 -06:00
Julian Schiedel
98f6e50af9 Added preprocesser fork to account for missing mbstowcs_s on linux 2023-02-15 15:48:37 +01:00
Julian Schiedel
dcfaebf9d9 Replaced mbstowcs with mbstowcs_s to fix fix compiler warning about deprecation 2023-02-15 10:36:38 +01:00
Pranav
f03feacc0b Merge pull request #118 from p-ranav/bugfix/codecvt
Removed deprecated codecvt
2023-02-14 10:10:32 -06:00
Pranav Srinivas Kumar
15c180b113 Removed unused vector header 2023-02-14 08:09:46 -08:00
Pranav Srinivas Kumar
80b822c576 Removed deprecated codecvt 2023-02-14 08:07:50 -08:00
Pranav
f38bf229eb Merge pull request #115 from aengusjiang/master
fix the bug of has_include error with g++4.8.5
2023-01-12 07:56:57 -06:00
Aengus.Jiang
0cce8d7326 fix the bug of has_include error with g++4.8.5 2023-01-12 17:34:05 +08:00
Pranav
a5bc05f32a Merge pull request #103 from SheepGoMeh/master
Fix Windows support for DynamicProgress
2021-10-28 18:43:20 -05:00
Dragon
40b99f6b04 Generate single header 2021-10-28 23:55:59 +03:00
Dragon
9f3b0247f5 Fix Windows support for DynamicProgress 2021-10-28 23:47:55 +03:00
Pranav
cdcff01339 Merge pull request #101 from Chuvi-w/Fix_Windows_h_min_max
Fix #define min/max problem from Windows.h
2021-07-12 10:17:20 -05:00
Chuvi
28a81289a6 Fix #define min/max problem from Windows.h 2021-07-12 09:56:08 +03:00
Pranav Srinivas Kumar
e34840ab0d Closes #93 - Defined _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING to remove codecvt warning 2021-05-03 17:34:59 -05:00
Pranav Srinivas Kumar
6432875ef4 Bumped to v2.2 2021-05-03 09:38:25 -05:00
Pranav Srinivas Kumar
276d476d4d Fixed the NOMINMAX issue for Windows build with latest termcolor #76, replaced #pragma once with #ifndef-define pairs 2021-05-03 09:37:44 -05:00
Pranav Srinivas Kumar
c338b5b280 Updated termcolor to v2.0. Bumped indicators to v2.1, closes #94 2021-05-02 23:17:24 -05:00
Pranav
91ceb5c7cf Merge pull request #92 from turuslan/fix/terminal_size
Uninitialized local variable in terminal_size
2021-03-18 08:36:30 -05:00
turuslan
96a2053d5b initialize local variable 2021-03-18 12:23:58 +03:00
Pranav Srinivas Kumar
4790bfddca Added carriage return before prefix text 2021-03-13 10:48:45 -06:00
Pranav
23b2364f2a Merge pull request #88 from usama-makhzoum/master
Fix some source file permissions
2021-02-18 07:28:53 -06:00
usama makhzoum
0cb5e11636 Fix some source file permissions 2021-02-17 21:43:01 +03:00
Pranav Srinivas Kumar
eb04b594dc Bumped version 2021-01-07 06:47:43 -08:00
Pranav Srinivas Kumar
b85eadb47c Closes #80 2020-12-08 09:15:05 -06:00
Pranav
312c49bf9f Merge pull request #78 from csparker247/77-time-remaining-overflow
Mitigate overflow when calculating ETA
2020-11-16 12:27:33 -06:00
Seth Parker
d11ffd91c6 Round time estimate up to nearest nanosecond 2020-11-16 11:27:16 -05:00
Seth Parker
e01c2950f2 Use floats for remaining time math 2020-11-16 10:54:05 -05:00
Seth Parker
c3ff1fbd91 Mitigate overflow when calculating eta 2020-11-12 13:21:42 -05:00
Pranav Srinivas Kumar
af7c004832 Updated single_include after changing percent calculation in progress spinner 2020-10-26 07:59:48 -05:00
Pranav Srinivas Kumar
77d910d0cf Fixed percentage calculation for progress spinner for user-defined option::MaxProgress 2020-10-26 07:56:44 -05:00
Pranav Srinivas Kumar
f126fde1b4 Fixed missing endif in single header version 2020-09-16 20:06:05 -05:00
Pranav
a7a3f08370 Merge pull request #73 from jcnoronha/bugfix/terminate_def
Terminate def in termcolor
2020-09-16 05:35:47 -05:00
j.noronha
05955650d6 Terminate def in termcolor 2020-09-16 21:16:45 +12:00
Pranav Srinivas Kumar
3d48e2bd25 Closes #72 2020-09-15 08:54:21 -05:00
Pranav
41650d005a Merge pull request #69 from duncanmcn/mingw_compilation
Change include guard to win32
2020-07-22 05:14:10 -05:00
duncanmcn
430a73b7b6 Change include guard to win32 2020-07-22 14:53:47 +12:00
Pranav Srinivas Kumar
f87de6ccbd Fixed missing include for termcolor in dynamic progress and multi progress 2020-07-21 10:20:07 -05:00
Pranav Srinivas Kumar
04fddb9014 Removed redundant includes of termcolor.hpp and updated single include. Closes #68 2020-07-21 10:14:52 -05:00
Pranav
1e622293aa Update indicators.hpp 2020-07-05 13:32:06 -05:00
Pranav
755900d524 Update terminal_size.hpp
Closes #67
2020-07-05 13:31:45 -05:00
Pranav
b43da291f6 Update README.md 2020-06-21 11:53:00 -05:00
Pranav
d9a5219d09 Merge pull request #66 from godbyk/bugfix/nested-namespace
Elevate #includes from being nested in the namespace.
2020-06-17 08:35:52 -05:00
Pranav
51e3460ad0 Merge pull request #65 from godbyk/feature/workaround-missing-codecvt
Support older compilers with missing <codecvt> header.
2020-06-17 08:35:13 -05:00
Kevin M. Godby
74c36cbb93 Support older compilers with missing <codecvt> header. 2020-06-16 13:29:02 -05:00
Kevin M. Godby
3cef73d30d Elevate #includes from being nested in the namespace. 2020-06-16 13:23:45 -05:00
Pranav Srinivas Kumar
50f89e150d Updated single header file version with fix for #63 2020-06-01 08:04:13 -05:00
Pranav Srinivas Kumar
ccd9c5d99d Closes 63 2020-06-01 08:03:40 -05:00
Pranav Srinivas Kumar
a776a52c98 Using \033 instead of \e for ISO-standards compliance #62 2020-05-25 13:06:08 -05:00
Pranav Srinivas Kumar
79dda6dbae Bumped version to v1.9
* Fixed build issues in g++ caused by missing header #54
* Using terminal width to fill the remainder of the progress bar with empty spaces #56
* Previously this was hard-coded to 10 spaces
* Fixed multiple definitions in helper functions, e.g., cursor control #58
* Implemented option::ProgressType which can be incremental or decremental - Provides an easy interface to implement decremental progress (a regressing bar) #59
* Updated to latest version of termcolor #60
2020-05-25 10:24:03 -05:00
Pranav
be24a3ab48 Merge pull request #61 from p-ranav/bugfix/56
Bugfix/56
2020-05-25 10:02:28 -05:00
Pranav Srinivas Kumar
8e39967c1e Removed unused variables 2020-05-25 09:53:56 -05:00
Pranav Srinivas Kumar
20b1d1f69f Updated single include version 2020-05-25 09:51:02 -05:00
Pranav Srinivas Kumar
f6cef6161d Removed sleep 2020-05-25 09:47:48 -05:00
Pranav Srinivas Kumar
6be9c8005f Added terminal size checks in indeterminate progress bar 2020-05-25 09:35:29 -05:00
Pranav Srinivas Kumar
0973cde3d3 Using terminal size in block progress bar 2020-05-25 09:29:32 -05:00
Pranav Srinivas Kumar
958228f55d Removed code duplication in prefix/postfix length calculation 2020-05-25 09:25:22 -05:00
Pranav Srinivas Kumar
7c1d7d6367 Added dynamic postfix text sample based on #56 2020-05-25 09:14:23 -05:00
Pranav Srinivas Kumar
63bb0d8946 Progress bar now uses terminal size to figure out how many spaces to use to fill up the remainder of the terminal row 2020-05-25 08:51:34 -05:00
Pranav Srinivas Kumar
c738215419 Updated single include version w/ latest termcolor 2020-05-25 08:22:46 -05:00
Pranav
664278a432 Merge pull request #60 from data-man/termcolor_latest
Update termcolor to latest
2020-05-25 08:22:14 -05:00
data-man
5660eee6d9 Update termcolor to latest 2020-05-25 09:13:01 +05:00
Pranav Srinivas Kumar
4bf1433c21 Updated single include version 2020-05-24 23:12:20 -05:00
Pranav
fb7b4f7221 Update README.md 2020-05-24 23:07:30 -05:00
Pranav Srinivas Kumar
bd586bbb88 Updated countdown progress bar sample 2020-05-24 23:07:02 -05:00
Pranav
970490c111 Update README.md 2020-05-24 23:06:40 -05:00
Pranav
e1eeaf1bb7 Update README.md 2020-05-24 23:05:54 -05:00
Pranav Srinivas Kumar
728c4f7f7f Added countdown progress bar sample 2020-05-24 23:03:39 -05:00
Pranav Srinivas Kumar
a2e11d4707 Clang format 2020-05-24 22:56:57 -05:00
Pranav
e5cc05a62d Merge pull request #59 from p-ranav/feature/countdown_progress_bar
Feature/countdown progress bar
2020-05-24 22:56:04 -05:00
Pranav Srinivas Kumar
885748d4c2 Reverted minor changes to stream helper w.r.t checking if fill, lead and remainder are empty 2020-05-24 22:47:18 -05:00
Pranav Srinivas Kumar
d0562438d5 Added ProgressType enum and updated single include 2020-05-24 22:43:53 -05:00
Pranav Srinivas Kumar
4dff4e7c5b Restored decremental progress demo 2020-05-24 22:43:11 -05:00
Pranav Srinivas Kumar
120f922326 Added progress_type option to indicate incremental/decremental progress 2020-05-24 22:37:58 -05:00
Pranav
2d9bd0c4a0 Update README.md 2020-05-23 17:24:48 -05:00
Pranav
b27888e523 Update README.md 2020-05-23 17:23:46 -05:00
Pranav Srinivas Kumar
ac5e759794 Minor updates 2020-05-23 17:21:58 -05:00
Pranav
545113c00d Update README.md 2020-05-23 17:21:50 -05:00
Pranav
a553ec6d83 Update README.md 2020-05-23 17:20:57 -05:00
Pranav Srinivas Kumar
16eb028686 Improved support for unicode including indeterminate progress bar. Updated unicode sample 2020-05-23 17:15:18 -05:00
Pranav Srinivas Kumar
cf1f888a0f Better support for displaying unicode characters in the progress bar, while respecting bar_width 2020-05-23 17:00:13 -05:00
Pranav Srinivas Kumar
27f4ad1f59 Made cursor control/movement functions static inline #58 2020-05-23 12:40:17 -05:00
Pranav
a5fb2bbcaf Update README.md 2020-05-22 17:14:18 -05:00
Pranav Srinivas Kumar
f4f1402b66 Updated single header version with missing include 2020-05-22 17:10:15 -05:00
Pranav
3515cb5bde Merge pull request #57 from dawidpilarski/master
[issue-54] added missing header
2020-05-22 17:08:21 -05:00
Dawid Pilarski
b66930b173 [issue-54] added missing header 2020-05-23 01:22:49 +02:00
Pranav
9a1e58a836 Fixes travis CI to correctly build indicators samples and demos 2020-05-19 15:09:10 -05:00
Pranav Srinivas Kumar
078ef915a3 Fixed messed up includes in demo. Closes #54 2020-05-18 18:41:18 -05:00
42 changed files with 4308 additions and 1932 deletions

View File

@@ -61,5 +61,5 @@ matrix:
script: script:
- if [[ "$CXX" == clang* ]]; then export CXXFLAGS="-stdlib=libc++"; fi - if [[ "$CXX" == clang* ]]; then export CXXFLAGS="-stdlib=libc++"; fi
- mkdir build && cd build - mkdir build && cd build
- cmake -DDEMO=ON -DSAMPLES=ON .. - cmake -DINDICATORS_DEMO=ON -DINDICATORS_SAMPLES=ON ..
- make - make

View File

@@ -5,14 +5,14 @@ if(DEFINED PROJECT_NAME)
endif() endif()
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.12") if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.12")
project(indicators VERSION 1.8.0 LANGUAGES CXX project(indicators VERSION 2.3.0 LANGUAGES CXX
HOMEPAGE_URL "https://github.com/p-ranav/indicators" HOMEPAGE_URL "https://github.com/p-ranav/indicators"
DESCRIPTION "Activity Indicators for Modern C++") DESCRIPTION "Activity Indicators for Modern C++")
elseif(CMAKE_VERSION VERSION_GREATER_EQUAL "3.9") elseif(CMAKE_VERSION VERSION_GREATER_EQUAL "3.9")
project(indicators VERSION 1.8.0 LANGUAGES CXX project(indicators VERSION 2.3.0 LANGUAGES CXX
DESCRIPTION "Activity Indicators for Modern C++") DESCRIPTION "Activity Indicators for Modern C++")
else() else()
project(indicators VERSION 1.8.0 LANGUAGES CXX) project(indicators VERSION 2.3.0 LANGUAGES CXX)
endif() endif()
if(EXISTS "${CMAKE_BINARY_DIR}/conanbuildinfo.cmake") if(EXISTS "${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")

261
README.md
View File

@@ -12,9 +12,10 @@
<a href="https://github.com/p-ranav/indicators/blob/master/LICENSE"> <a href="https://github.com/p-ranav/indicators/blob/master/LICENSE">
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="license"/> <img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="license"/>
</a> </a>
<img src="https://img.shields.io/badge/version-1.8-blue.svg?cacheSeconds=2592000" alt="version"/> <img src="https://img.shields.io/badge/version-2.3-blue.svg?cacheSeconds=2592000" alt="version"/>
</p> </p>
<p align="center"> <p align="center">
<img src="img/demo.gif"/> <img src="img/demo.gif"/>
</p> </p>
@@ -36,7 +37,10 @@
* [Multi Progress](#multiprogress) * [Multi Progress](#multiprogress)
* [Dynamic Progress](#dynamicprogress) * [Dynamic Progress](#dynamicprogress)
* [Progress Spinner](#progress-spinner) * [Progress Spinner](#progress-spinner)
* [Working with Iterables](#working-with-iterables) * Additional Samples
* [Decremental Progress](#decremental-progress)
* [Working with Iterables](#working-with-iterables)
* [Unicode Support](#unicode-support)
* [Building Samples](#building-samples) * [Building Samples](#building-samples)
* [Generating Single Header](#generating-single-header) * [Generating Single Header](#generating-single-header)
* [Contributing](#contributing) * [Contributing](#contributing)
@@ -625,6 +629,48 @@ int main() {
} }
``` ```
## Decremental Progress
`indicators` allows you to easily control the progress direction, i.e., incremental or decremental progress by using `option::ProgressType`. To program a countdown progress bar, use `option::ProgressType::decremental`
<p align="center">
<img src="img/progress_bar_countdown.gif"/>
</p>
```cpp
#include <chrono>
#include <indicators/progress_bar.hpp>
#include <thread>
using namespace indicators;
int main() {
ProgressBar bar{option::BarWidth{50},
option::ProgressType{ProgressType::decremental},
option::Start{"["},
option::Fill{""},
option::Lead{""},
option::Remainder{"-"},
option::End{"]"},
option::PostfixText{"Reverting System Restore"},
option::ForegroundColor{Color::yellow},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout << termcolor::bold << termcolor::white
<< "Task Failed Successfully\n" << termcolor::reset;
return 0;
}
```
## Working with Iterables ## Working with Iterables
If you'd like to use progress bars to indicate progress while iterating over iterables, e.g., a list of numbers, this If you'd like to use progress bars to indicate progress while iterating over iterables, e.g., a list of numbers, this
@@ -687,6 +733,207 @@ int main() {
} }
``` ```
## Unicode Support
`indicators` supports multi-byte unicode characters in progress bars.
If the `option::BarWidth` is set, the library aims to respect this setting. When filling the bar, if the next `Fill` string has a display width that would exceed the bar width, then the library will fill the remainder of the bar with `' '` space characters instead.
See below an example of some progress bars, each with a bar width of 50, displaying different unicode characters:
<p align="center">
<img src="img/unicode.gif"/>
</p>
```cpp
#include <chrono>
#include <indicators/progress_bar.hpp>
#include <indicators/indeterminate_progress_bar.hpp>
#include <indicators/cursor_control.hpp>
#include <thread>
int main() {
indicators::show_console_cursor(false);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
{
// Plain old ASCII
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"="},
indicators::option::Lead{">"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Plain-old ASCII"},
indicators::option::ForegroundColor{indicators::Color::green},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Unicode
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"驚くばかり"},
indicators::option::Lead{">"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Japanese"},
indicators::option::ForegroundColor{indicators::Color::yellow},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Russian
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"Потрясающие"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Russian"},
indicators::option::ForegroundColor{indicators::Color::red},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Greek
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"Φοβερός"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Greek"},
indicators::option::ForegroundColor{indicators::Color::cyan},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Chinese
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"太棒了"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Chinese"},
indicators::option::ForegroundColor{indicators::Color::green},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Emojis
indicators::ProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"🔥"},
indicators::option::Lead{"🔥"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Emojis"},
indicators::option::ForegroundColor{indicators::Color::white},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Indeterminate progress bar
indicators::IndeterminateProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{""},
indicators::option::Lead{"載入中"},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Loading Progress Bar"},
indicators::option::ForegroundColor{indicators::Color::yellow},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
auto job = [&bar]() {
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
bar.mark_as_completed();
};
std::thread job_completion_thread(job);
// Update bar state
while (!bar.is_completed()) {
bar.tick();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
job_completion_thread.join();
}
indicators::show_console_cursor(true);
return 0;
}
```
## Building Samples ## Building Samples
```bash ```bash
@@ -697,6 +944,16 @@ cmake -DINDICATORS_SAMPLES=ON -DINDICATORS_DEMO=ON ..
make make
``` ```
### WinLibs + MinGW
For Windows, if you use WinLibs like I do, the cmake command would look like this:
```console
foo@bar:~$ mkdir build && cd build
foo@bar:~$ cmake -G "MinGW Makefiles" -DCMAKE_CXX_COMPILER="C:/WinLibs/mingw64/bin/g++.exe" -DINDICATORS_SAMPLES=ON -DINDICATORS_DEMO=ON ..
foo@bar:~$ make -j4
```
## Generating Single Header ## Generating Single Header
```bash ```bash

View File

@@ -1,4 +1,6 @@
#include "indicators.hpp" #include <indicators/cursor_control.hpp>
#include <indicators/progress_bar.hpp>
#include <indicators/progress_spinner.hpp>
#include <vector> #include <vector>
int main() { int main() {
@@ -11,15 +13,15 @@ int main() {
// //
// PROGRESS BAR 1 // PROGRESS BAR 1
// //
indicators::ProgressBar p{option::BarWidth{50}, indicators::ProgressBar p{
option::Start{"["}, option::BarWidth{50},
option::Fill{""}, option::Start{"["},
option::Lead{""}, option::Fill{""},
option::Remainder{" "}, option::Lead{""},
option::End{" ]"}, option::Remainder{" "},
option::ForegroundColor{indicators::Color::yellow}, option::End{" ]"},
option::FontStyles{ option::ForegroundColor{indicators::Color::yellow},
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
std::atomic<size_t> index{0}; std::atomic<size_t> index{0};
std::vector<std::string> status_text = {"Rocket.exe is not responding", std::vector<std::string> status_text = {"Rocket.exe is not responding",
@@ -51,7 +53,7 @@ int main() {
// PROGRESS BAR 2 // PROGRESS BAR 2
// //
indicators::ProgressBar p; indicators::ProgressBar p;
p.set_option(option::BarWidth{40}); p.set_option(option::BarWidth{0});
p.set_option(option::PrefixText{"Reading package list... "}); p.set_option(option::PrefixText{"Reading package list... "});
p.set_option(option::Start{""}); p.set_option(option::Start{""});
p.set_option(option::Fill{""}); p.set_option(option::Fill{""});
@@ -60,7 +62,8 @@ int main() {
p.set_option(option::End{""}); p.set_option(option::End{""});
p.set_option(option::ForegroundColor{indicators::Color::white}); p.set_option(option::ForegroundColor{indicators::Color::white});
p.set_option(option::ShowPercentage{false}); p.set_option(option::ShowPercentage{false});
p.set_option(option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}); p.set_option(
option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});
auto job = [&p]() { auto job = [&p]() {
while (true) { while (true) {
p.set_option( p.set_option(
@@ -91,7 +94,8 @@ int main() {
p.set_option(option::End{"]"}); p.set_option(option::End{"]"});
p.set_option(option::PostfixText{"Getting started"}); p.set_option(option::PostfixText{"Getting started"});
p.set_option(option::ForegroundColor{indicators::Color::green}); p.set_option(option::ForegroundColor{indicators::Color::green});
p.set_option(option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}); p.set_option(
option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});
auto job = [&p]() { auto job = [&p]() {
while (true) { while (true) {
auto ticks = p.current(); auto ticks = p.current();
@@ -128,7 +132,8 @@ int main() {
p4.set_option(option::ForegroundColor{indicators::Color::cyan}); p4.set_option(option::ForegroundColor{indicators::Color::cyan});
p4.set_option(option::PostfixText{"Restoring system state"}); p4.set_option(option::PostfixText{"Restoring system state"});
p4.set_option(option::ShowPercentage{false}); p4.set_option(option::ShowPercentage{false});
p4.set_option(option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}); p4.set_option(
option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}});
std::atomic<size_t> index4{0}; std::atomic<size_t> index4{0};
auto job4 = [&p4, &index4, &lead_spinner]() { auto job4 = [&p4, &index4, &lead_spinner]() {
while (true) { while (true) {
@@ -139,6 +144,7 @@ int main() {
std::cout << std::endl; std::cout << std::endl;
p4.set_option(option::ForegroundColor{indicators::Color::red}); p4.set_option(option::ForegroundColor{indicators::Color::red});
p4.set_option(option::PrefixText{"{ ERROR }"}); p4.set_option(option::PrefixText{"{ ERROR }"});
p4.set_option(option::BarWidth{0});
p4.set_option(option::Start{}); p4.set_option(option::Start{});
p4.set_option(option::Fill{}); p4.set_option(option::Fill{});
p4.set_option(option::Lead{}); p4.set_option(option::Lead{});
@@ -156,6 +162,35 @@ int main() {
thread4.join(); thread4.join();
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
{
//
// GOING BACKWARDS
//
indicators::ProgressBar p{
option::BarWidth{50},
option::ProgressType{ProgressType::decremental},
option::Start{"["},
option::Fill{""},
option::Lead{""},
option::Remainder{"-"},
option::End{"]"},
option::ForegroundColor{indicators::Color::white},
option::PostfixText{"Reverting system restore"},
option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
auto job = [&p]() {
while (true) {
p.tick();
if (p.is_completed()) {
p.set_option(option::PostfixText{"Revert complete!"});
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(60));
}
};
std::thread thread(job);
thread.join();
}
} }
{ {
@@ -193,8 +228,10 @@ int main() {
// PROGRESS BAR 6 // PROGRESS BAR 6
// //
indicators::ProgressSpinner p{ indicators::ProgressSpinner p{
option::PrefixText{" - "}, option::PostfixText{"Searching for the Moon"}, option::PrefixText{" - "},
option::ForegroundColor{indicators::Color::white}, option::ShowPercentage{false}, option::PostfixText{"Searching for the Moon"},
option::ForegroundColor{indicators::Color::white},
option::ShowPercentage{false},
option::SpinnerStates{std::vector<std::string>{"", "", "", ""}}, option::SpinnerStates{std::vector<std::string>{"", "", "", ""}},
option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
auto job = [&p]() { auto job = [&p]() {
@@ -232,17 +269,17 @@ int main() {
// //
// NESTED PROGRESS BAR // NESTED PROGRESS BAR
// //
indicators::ProgressBar p2{option::BarWidth{30}, indicators::ProgressBar p2{
option::PrefixText{" - "}, option::BarWidth{30},
option::Start{"🌎"}, option::PrefixText{" - "},
option::Fill{"·"}, option::Start{"🌎"},
option::Lead{"🚀"}, option::Fill{"·"},
option::Remainder{" "}, option::Lead{"🚀"},
option::End{"🌑"}, option::Remainder{" "},
option::PostfixText{"Achieved low-Earth orbit"}, option::End{"🌑"},
option::ForegroundColor{indicators::Color::white}, option::PostfixText{"Achieved low-Earth orbit"},
option::FontStyles{ option::ForegroundColor{indicators::Color::white},
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
std::vector<std::string> ship_trail{"", "", "", "", "", "", "", ""}; std::vector<std::string> ship_trail{"", "", "", "", "", "", "", ""};
std::atomic<int> ship_trail_index{0}; std::atomic<int> ship_trail_index{0};
auto job2 = [&p2, &ship_trail_index, &ship_trail]() { auto job2 = [&p2, &ship_trail_index, &ship_trail]() {

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

BIN
img/unicode.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 MiB

View File

@@ -1,4 +1,6 @@
#pragma once
#ifndef INDICATORS_BLOCK_PROGRESS_BAR
#define INDICATORS_BLOCK_PROGRESS_BAR
#include <indicators/color.hpp> #include <indicators/color.hpp>
#include <indicators/details/stream_helper.hpp> #include <indicators/details/stream_helper.hpp>
@@ -7,12 +9,15 @@
#include <atomic> #include <atomic>
#include <chrono> #include <chrono>
#include <indicators/setting.hpp> #include <indicators/setting.hpp>
#include <indicators/terminal_size.hpp>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <sstream>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <thread> #include <thread>
#include <tuple> #include <tuple>
#include <utility>
namespace indicators { namespace indicators {
@@ -55,11 +60,10 @@ public:
option::MaxPostfixTextLen{0}, std::forward<Args>(args)...), option::MaxPostfixTextLen{0}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::font_styles>( details::get<details::ProgressBarOption::font_styles>(
option::FontStyles{std::vector<FontStyle>{}}, std::forward<Args>(args)...), option::FontStyles{std::vector<FontStyle>{}}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::max_progress>(option::MaxProgress{100}, details::get<details::ProgressBarOption::max_progress>(
std::forward<Args>(args)...), option::MaxProgress{100}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::stream>( details::get<details::ProgressBarOption::stream>(option::Stream{std::cout},
option::Stream{std::cout}, std::forward<Args>(args)...) std::forward<Args>(args)...)) {}
) {}
template <typename T, details::ProgressBarOption id> template <typename T, details::ProgressBarOption id>
void set_option(details::Setting<T, id> &&setting) { void set_option(details::Setting<T, id> &&setting) {
@@ -118,7 +122,8 @@ public:
size_t current() { size_t current() {
std::lock_guard<std::mutex> lock{mutex_}; std::lock_guard<std::mutex> lock{mutex_};
return std::min(static_cast<size_t>(progress_), size_t(get_value<details::ProgressBarOption::max_progress>())); return (std::min)(static_cast<size_t>(progress_),
size_t(get_value<details::ProgressBarOption::max_progress>()));
} }
bool is_completed() const { return get_value<details::ProgressBarOption::completed>(); } bool is_completed() const { return get_value<details::ProgressBarOption::completed>(); }
@@ -159,39 +164,23 @@ private:
} }
} }
public: std::pair<std::string, size_t> get_prefix_text() {
void print_progress(bool from_multi_progress = false) { std::stringstream os;
std::lock_guard<std::mutex> lock{mutex_}; os << get_value<details::ProgressBarOption::prefix_text>();
const auto result = os.str();
auto& os = get_value<details::ProgressBarOption::stream>(); const auto result_size = unicode::display_width(result);
return {result, result_size};
}
std::pair<std::string, size_t> get_postfix_text() {
std::stringstream os;
const auto max_progress = get_value<details::ProgressBarOption::max_progress>(); const auto max_progress = get_value<details::ProgressBarOption::max_progress>();
if (multi_progress_mode_ && !from_multi_progress) {
if (progress_ > max_progress) {
get_value<details::ProgressBarOption::completed>() = true;
}
return;
}
auto now = std::chrono::high_resolution_clock::now(); auto now = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(now - start_time_point_); auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(now - start_time_point_);
if (get_value<details::ProgressBarOption::foreground_color>() != Color::unspecified)
details::set_stream_color(os, get_value<details::ProgressBarOption::foreground_color>());
for (auto &style : get_value<details::ProgressBarOption::font_styles>())
details::set_font_style(os, style);
os << get_value<details::ProgressBarOption::prefix_text>();
os << get_value<details::ProgressBarOption::start>();
details::BlockProgressScaleWriter writer{os,
get_value<details::ProgressBarOption::bar_width>()};
writer.write(progress_ / max_progress * 100);
os << get_value<details::ProgressBarOption::end>();
if (get_value<details::ProgressBarOption::show_percentage>()) { if (get_value<details::ProgressBarOption::show_percentage>()) {
os << " " << std::min(static_cast<size_t>(progress_ / max_progress * 100.0), size_t(100)) << "%"; os << " " << (std::min)(static_cast<size_t>(progress_ / max_progress * 100.0), size_t(100))
<< "%";
} }
auto &saved_start_time = get_value<details::ProgressBarOption::saved_start_time>(); auto &saved_start_time = get_value<details::ProgressBarOption::saved_start_time>();
@@ -212,7 +201,10 @@ public:
if (saved_start_time) { if (saved_start_time) {
auto eta = std::chrono::nanoseconds( auto eta = std::chrono::nanoseconds(
progress_ > 0 ? static_cast<long long>(elapsed.count() * max_progress / progress_) : 0); progress_ > 0
? static_cast<long long>(std::ceil(float(elapsed.count()) *
max_progress / progress_))
: 0);
auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
details::write_duration(os, remaining); details::write_duration(os, remaining);
} else { } else {
@@ -225,12 +217,65 @@ public:
os << "]"; os << "]";
} }
if (get_value<details::ProgressBarOption::max_postfix_text_len>() == 0) os << " " << get_value<details::ProgressBarOption::postfix_text>();
get_value<details::ProgressBarOption::max_postfix_text_len>() = 10;
os << " " << get_value<details::ProgressBarOption::postfix_text>() const auto result = os.str();
<< std::string(get_value<details::ProgressBarOption::max_postfix_text_len>(), ' ') const auto result_size = unicode::display_width(result);
<< "\r"; return {result, result_size};
}
public:
void print_progress(bool from_multi_progress = false) {
std::lock_guard<std::mutex> lock{mutex_};
auto &os = get_value<details::ProgressBarOption::stream>();
const auto max_progress = get_value<details::ProgressBarOption::max_progress>();
if (multi_progress_mode_ && !from_multi_progress) {
if (progress_ > max_progress) {
get_value<details::ProgressBarOption::completed>() = true;
}
return;
}
if (get_value<details::ProgressBarOption::foreground_color>() != Color::unspecified)
details::set_stream_color(os, get_value<details::ProgressBarOption::foreground_color>());
for (auto &style : get_value<details::ProgressBarOption::font_styles>())
details::set_font_style(os, style);
const auto prefix_pair = get_prefix_text();
const auto prefix_text = prefix_pair.first;
const auto prefix_length = prefix_pair.second;
os << "\r" << prefix_text;
os << get_value<details::ProgressBarOption::start>();
details::BlockProgressScaleWriter writer{os,
get_value<details::ProgressBarOption::bar_width>()};
writer.write(progress_ / max_progress * 100);
os << get_value<details::ProgressBarOption::end>();
const auto postfix_pair = get_postfix_text();
const auto postfix_text = postfix_pair.first;
const auto postfix_length = postfix_pair.second;
os << postfix_text;
// Get length of prefix text and postfix text
const auto start_length = get_value<details::ProgressBarOption::start>().size();
const auto bar_width = get_value<details::ProgressBarOption::bar_width>();
const auto end_length = get_value<details::ProgressBarOption::end>().size();
const auto terminal_width = terminal_size().second;
// prefix + bar_width + postfix should be <= terminal_width
const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length);
if (remaining > 0) {
os << std::string(remaining, ' ') << "\r";
} else if (remaining < 0) {
// Do nothing. Maybe in the future truncate postfix with ...
}
os.flush(); os.flush();
if (progress_ > max_progress) { if (progress_ > max_progress) {
get_value<details::ProgressBarOption::completed>() = true; get_value<details::ProgressBarOption::completed>() = true;
} }
@@ -241,3 +286,5 @@ public:
}; };
} // namespace indicators } // namespace indicators
#endif

View File

@@ -1,6 +1,9 @@
#pragma once
#include <indicators/termcolor.hpp> #ifndef INDICATORS_COLOR
#define INDICATORS_COLOR
namespace indicators { namespace indicators {
enum class Color { grey, red, green, yellow, blue, magenta, cyan, white, unspecified }; enum class Color { grey, red, green, yellow, blue, magenta, cyan, white, unspecified };
} }
#endif

39
include/indicators/cursor_control.hpp Executable file → Normal file
View File

@@ -1,4 +1,6 @@
#pragma once
#ifndef INDICATORS_CURSOR_CONTROL
#define INDICATORS_CURSOR_CONTROL
#if defined(_MSC_VER) #if defined(_MSC_VER)
#if !defined(NOMINMAX) #if !defined(NOMINMAX)
@@ -14,7 +16,7 @@ namespace indicators {
#if defined(_MSC_VER) #if defined(_MSC_VER)
void show_console_cursor(bool const show) { static inline void show_console_cursor(bool const show) {
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursorInfo; CONSOLE_CURSOR_INFO cursorInfo;
@@ -24,12 +26,41 @@ void show_console_cursor(bool const show) {
SetConsoleCursorInfo(out, &cursorInfo); SetConsoleCursorInfo(out, &cursorInfo);
} }
static inline void erase_line() {
auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (!hStdout)
return;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
COORD cursor;
cursor.X = 0;
cursor.Y = csbiInfo.dwCursorPosition.Y;
DWORD count = 0;
FillConsoleOutputCharacterA(hStdout, ' ', csbiInfo.dwSize.X, cursor, &count);
FillConsoleOutputAttribute(hStdout, csbiInfo.wAttributes, csbiInfo.dwSize.X,
cursor, &count);
SetConsoleCursorPosition(hStdout, cursor);
}
#else #else
void show_console_cursor(bool const show) { static inline void show_console_cursor(bool const show) {
std::fputs(show ? "\e[?25h" : "\e[?25l", stdout); std::fputs(show ? "\033[?25h" : "\033[?25l", stdout);
}
static inline void erase_line() {
std::fputs("\r\033[K", stdout);
} }
#endif #endif
} // namespace indicators } // namespace indicators
#endif

24
include/indicators/cursor_movement.hpp Executable file → Normal file
View File

@@ -1,4 +1,6 @@
#pragma once
#ifndef INDICATORS_CURSOR_MOVEMENT
#define INDICATORS_CURSOR_MOVEMENT
#if defined(_MSC_VER) #if defined(_MSC_VER)
#if !defined(NOMINMAX) #if !defined(NOMINMAX)
@@ -14,7 +16,7 @@ namespace indicators {
#ifdef _MSC_VER #ifdef _MSC_VER
void move(int x, int y) { static inline void move(int x, int y) {
auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE); auto hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (!hStdout) if (!hStdout)
return; return;
@@ -29,18 +31,20 @@ void move(int x, int y) {
SetConsoleCursorPosition(hStdout, cursor); SetConsoleCursorPosition(hStdout, cursor);
} }
void move_up(int lines) { move(0, -lines); } static inline void move_up(int lines) { move(0, -lines); }
void move_down(int lines) { move(0, -lines); } static inline void move_down(int lines) { move(0, -lines); }
void move_right(int cols) { move(cols, 0); } static inline void move_right(int cols) { move(cols, 0); }
void move_left(int cols) { move(-cols, 0); } static inline void move_left(int cols) { move(-cols, 0); }
#else #else
void move_up(int lines) { std::cout << "\033[" << lines << "A"; } static inline void move_up(int lines) { std::cout << "\033[" << lines << "A"; }
void move_down(int lines) { std::cout << "\033[" << lines << "B"; } static inline void move_down(int lines) { std::cout << "\033[" << lines << "B"; }
void move_right(int cols) { std::cout << "\033[" << cols << "C"; } static inline void move_right(int cols) { std::cout << "\033[" << cols << "C"; }
void move_left(int cols) { std::cout << "\033[" << cols << "D"; } static inline void move_left(int cols) { std::cout << "\033[" << cols << "D"; }
#endif #endif
} // namespace indicators } // namespace indicators
#endif

View File

@@ -1,5 +1,8 @@
#pragma once
#ifndef INDICATORS_STREAM_HELPER
#define INDICATORS_STREAM_HELPER
#include <indicators/display_width.hpp>
#include <indicators/setting.hpp> #include <indicators/setting.hpp>
#include <indicators/termcolor.hpp> #include <indicators/termcolor.hpp>
@@ -107,7 +110,7 @@ public:
std::ostream &write(float progress) { std::ostream &write(float progress) {
std::string fill_text{""}; std::string fill_text{""};
std::vector<std::string> lead_characters{" ", "", "", "", "", "", "", ""}; std::vector<std::string> lead_characters{" ", "", "", "", "", "", "", ""};
auto value = std::min(1.0f, std::max(0.0f, progress / 100.0f)); auto value = (std::min)(1.0f, (std::max)(0.0f, progress / 100.0f));
auto whole_width = std::floor(value * bar_width); auto whole_width = std::floor(value * bar_width);
auto remainder_width = fmod((value * bar_width), 1.0f); auto remainder_width = fmod((value * bar_width), 1.0f);
auto part_width = std::floor(remainder_width * lead_characters.size()); auto part_width = std::floor(remainder_width * lead_characters.size());
@@ -135,13 +138,30 @@ public:
std::ostream &write(float progress) { std::ostream &write(float progress) {
auto pos = static_cast<size_t>(progress * bar_width / 100.0); auto pos = static_cast<size_t>(progress * bar_width / 100.0);
for (size_t i = 0; i < bar_width; ++i) { for (size_t i = 0, current_display_width = 0; i < bar_width;) {
if (i < pos) std::string next;
os << fill;
else if (i == pos) if (i < pos) {
os << lead; next = fill;
else current_display_width = unicode::display_width(fill);
os << remainder; } else if (i == pos) {
next = lead;
current_display_width = unicode::display_width(lead);
} else {
next = remainder;
current_display_width = unicode::display_width(remainder);
}
i += current_display_width;
if (i > bar_width) {
// `next` is larger than the allowed bar width
// fill with empty space instead
os << std::string((bar_width - (i - current_display_width)), ' ');
break;
}
os << next;
} }
return os; return os;
} }
@@ -157,17 +177,35 @@ private:
class IndeterminateProgressScaleWriter { class IndeterminateProgressScaleWriter {
public: public:
IndeterminateProgressScaleWriter(std::ostream &os, size_t bar_width, const std::string &fill, IndeterminateProgressScaleWriter(std::ostream &os, size_t bar_width, const std::string &fill,
const std::string &lead) const std::string &lead)
: os(os), bar_width(bar_width), fill(fill), lead(lead) {} : os(os), bar_width(bar_width), fill(fill), lead(lead) {}
std::ostream &write(size_t progress) { std::ostream &write(size_t progress) {
for (size_t i = 0; i < bar_width; ++i) { for (size_t i = 0; i < bar_width;) {
if (i < progress) std::string next;
os << fill; size_t current_display_width = 0;
else if (i == progress)
os << lead; if (i < progress) {
else next = fill;
os << fill; current_display_width = unicode::display_width(fill);
} else if (i == progress) {
next = lead;
current_display_width = unicode::display_width(lead);
} else {
next = fill;
current_display_width = unicode::display_width(fill);
}
i += current_display_width;
if (i > bar_width) {
// `next` is larger than the allowed bar width
// fill with empty space instead
os << std::string((bar_width - (i - current_display_width)), ' ');
break;
}
os << next;
} }
return os; return os;
} }
@@ -181,3 +219,5 @@ private:
} // namespace details } // namespace details
} // namespace indicators } // namespace indicators
#endif

View File

@@ -0,0 +1,353 @@
#ifndef INDICATORS_DISPLAY_WIDTH
#define INDICATORS_DISPLAY_WIDTH
#include <clocale>
#include <cstdlib>
#include <locale>
#include <string>
#include <wchar.h>
namespace unicode {
namespace details {
/*
* This is an implementation of wcwidth() and wcswidth() (defined in
* IEEE Std 1002.1-2001) for Unicode.
*
* http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
* http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
*
* In fixed-width output devices, Latin characters all occupy a single
* "cell" position of equal width, whereas ideographic CJK characters
* occupy two such cells. Interoperability between terminal-line
* applications and (teletype-style) character terminals using the
* UTF-8 encoding requires agreement on which character should advance
* the cursor by how many cell positions. No established formal
* standards exist at present on which Unicode character shall occupy
* how many cell positions on character terminals. These routines are
* a first attempt of defining such behavior based on simple rules
* applied to data provided by the Unicode Consortium.
*
* For some graphical characters, the Unicode standard explicitly
* defines a character-cell width via the definition of the East Asian
* FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
* In all these cases, there is no ambiguity about which width a
* terminal shall use. For characters in the East Asian Ambiguous (A)
* class, the width choice depends purely on a preference of backward
* compatibility with either historic CJK or Western practice.
* Choosing single-width for these characters is easy to justify as
* the appropriate long-term solution, as the CJK practice of
* displaying these characters as double-width comes from historic
* implementation simplicity (8-bit encoded characters were displayed
* single-width and 16-bit ones double-width, even for Greek,
* Cyrillic, etc.) and not any typographic considerations.
*
* Much less clear is the choice of width for the Not East Asian
* (Neutral) class. Existing practice does not dictate a width for any
* of these characters. It would nevertheless make sense
* typographically to allocate two character cells to characters such
* as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
* represented adequately with a single-width glyph. The following
* routines at present merely assign a single-cell width to all
* neutral characters, in the interest of simplicity. This is not
* entirely satisfactory and should be reconsidered before
* establishing a formal standard in this area. At the moment, the
* decision which Not East Asian (Neutral) characters should be
* represented by double-width glyphs cannot yet be answered by
* applying a simple rule from the Unicode database content. Setting
* up a proper standard for the behavior of UTF-8 character terminals
* will require a careful analysis not only of each Unicode character,
* but also of each presentation form, something the author of these
* routines has avoided to do so far.
*
* http://www.unicode.org/unicode/reports/tr11/
*
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
*
* Permission to use, copy, modify, and distribute this software
* for any purpose and without fee is hereby granted. The author
* disclaims all warranties with regard to this software.
*
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
*/
struct interval {
int first;
int last;
};
/* auxiliary function for binary search in interval table */
static inline int bisearch(wchar_t ucs, const struct interval *table, int max) {
int min = 0;
int mid;
if (ucs < table[0].first || ucs > table[max].last)
return 0;
while (max >= min) {
mid = (min + max) / 2;
if (ucs > table[mid].last)
min = mid + 1;
else if (ucs < table[mid].first)
max = mid - 1;
else
return 1;
}
return 0;
}
/* The following two functions define the column width of an ISO 10646
* character as follows:
*
* - The null character (U+0000) has a column width of 0.
*
* - Other C0/C1 control characters and DEL will lead to a return
* value of -1.
*
* - Non-spacing and enclosing combining characters (general
* category code Mn or Me in the Unicode database) have a
* column width of 0.
*
* - SOFT HYPHEN (U+00AD) has a column width of 1.
*
* - Other format characters (general category code Cf in the Unicode
* database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
*
* - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
* have a column width of 0.
*
* - Spacing characters in the East Asian Wide (W) or East Asian
* Full-width (F) category as defined in Unicode Technical
* Report #11 have a column width of 2.
*
* - All remaining characters (including all printable
* ISO 8859-1 and WGL4 characters, Unicode control characters,
* etc.) have a column width of 1.
*
* This implementation assumes that wchar_t characters are encoded
* in ISO 10646.
*/
static inline int mk_wcwidth(wchar_t ucs) {
/* sorted list of non-overlapping intervals of non-spacing characters */
/* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
static const struct interval combining[] = {
{0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489},
{0x0591, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2},
{0x05C4, 0x05C5}, {0x05C7, 0x05C7}, {0x0600, 0x0603},
{0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670},
{0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED},
{0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A},
{0x07A6, 0x07B0}, {0x07EB, 0x07F3}, {0x0901, 0x0902},
{0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D},
{0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981},
{0x09BC, 0x09BC}, {0x09C1, 0x09C4}, {0x09CD, 0x09CD},
{0x09E2, 0x09E3}, {0x0A01, 0x0A02}, {0x0A3C, 0x0A3C},
{0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D},
{0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC},
{0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD},
{0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, {0x0B3C, 0x0B3C},
{0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D},
{0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0},
{0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48},
{0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0CBC, 0x0CBC},
{0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD},
{0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D},
{0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6},
{0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E},
{0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC},
{0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35},
{0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F71, 0x0F7E},
{0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F90, 0x0F97},
{0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030},
{0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039},
{0x1058, 0x1059}, {0x1160, 0x11FF}, {0x135F, 0x135F},
{0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753},
{0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD},
{0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD},
{0x180B, 0x180D}, {0x18A9, 0x18A9}, {0x1920, 0x1922},
{0x1927, 0x1928}, {0x1932, 0x1932}, {0x1939, 0x193B},
{0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34},
{0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42},
{0x1B6B, 0x1B73}, {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF},
{0x200B, 0x200F}, {0x202A, 0x202E}, {0x2060, 0x2063},
{0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F},
{0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B},
{0xA825, 0xA826}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F},
{0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB},
{0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F},
{0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169},
{0x1D173, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD},
{0x1D242, 0x1D244}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F},
{0xE0100, 0xE01EF}};
/* test for 8-bit control characters */
if (ucs == 0)
return 0;
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
return -1;
/* binary search in table of non-spacing characters */
if (bisearch(ucs, combining, sizeof(combining) / sizeof(struct interval) - 1))
return 0;
/* if we arrive here, ucs is not a combining or C0/C1 control character */
return 1 +
(ucs >= 0x1100 &&
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
ucs == 0x2329 || ucs == 0x232a ||
(ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) || /* CJK ... Yi */
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
(ucs >= 0xf900 &&
ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
(ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
(ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
(ucs >= 0x30000 && ucs <= 0x3fffd)));
}
static inline int mk_wcswidth(const wchar_t *pwcs, size_t n) {
int w, width = 0;
for (; *pwcs && n-- > 0; pwcs++)
if ((w = mk_wcwidth(*pwcs)) < 0)
return -1;
else
width += w;
return width;
}
/*
* The following functions are the same as mk_wcwidth() and
* mk_wcswidth(), except that spacing characters in the East Asian
* Ambiguous (A) category as defined in Unicode Technical Report #11
* have a column width of 2. This variant might be useful for users of
* CJK legacy encodings who want to migrate to UCS without changing
* the traditional terminal character-width behaviour. It is not
* otherwise recommended for general use.
*/
static inline int mk_wcwidth_cjk(wchar_t ucs) {
/* sorted list of non-overlapping intervals of East Asian Ambiguous
* characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
static const struct interval ambiguous[] = {
{0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8},
{0x00AA, 0x00AA}, {0x00AE, 0x00AE}, {0x00B0, 0x00B4},
{0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6},
{0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1},
{0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED},
{0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA},
{0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101},
{0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B},
{0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133},
{0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144},
{0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153},
{0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE},
{0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4},
{0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA},
{0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261},
{0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB},
{0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB},
{0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0391, 0x03A1},
{0x03A3, 0x03A9}, {0x03B1, 0x03C1}, {0x03C3, 0x03C9},
{0x0401, 0x0401}, {0x0410, 0x044F}, {0x0451, 0x0451},
{0x2010, 0x2010}, {0x2013, 0x2016}, {0x2018, 0x2019},
{0x201C, 0x201D}, {0x2020, 0x2022}, {0x2024, 0x2027},
{0x2030, 0x2030}, {0x2032, 0x2033}, {0x2035, 0x2035},
{0x203B, 0x203B}, {0x203E, 0x203E}, {0x2074, 0x2074},
{0x207F, 0x207F}, {0x2081, 0x2084}, {0x20AC, 0x20AC},
{0x2103, 0x2103}, {0x2105, 0x2105}, {0x2109, 0x2109},
{0x2113, 0x2113}, {0x2116, 0x2116}, {0x2121, 0x2122},
{0x2126, 0x2126}, {0x212B, 0x212B}, {0x2153, 0x2154},
{0x215B, 0x215E}, {0x2160, 0x216B}, {0x2170, 0x2179},
{0x2190, 0x2199}, {0x21B8, 0x21B9}, {0x21D2, 0x21D2},
{0x21D4, 0x21D4}, {0x21E7, 0x21E7}, {0x2200, 0x2200},
{0x2202, 0x2203}, {0x2207, 0x2208}, {0x220B, 0x220B},
{0x220F, 0x220F}, {0x2211, 0x2211}, {0x2215, 0x2215},
{0x221A, 0x221A}, {0x221D, 0x2220}, {0x2223, 0x2223},
{0x2225, 0x2225}, {0x2227, 0x222C}, {0x222E, 0x222E},
{0x2234, 0x2237}, {0x223C, 0x223D}, {0x2248, 0x2248},
{0x224C, 0x224C}, {0x2252, 0x2252}, {0x2260, 0x2261},
{0x2264, 0x2267}, {0x226A, 0x226B}, {0x226E, 0x226F},
{0x2282, 0x2283}, {0x2286, 0x2287}, {0x2295, 0x2295},
{0x2299, 0x2299}, {0x22A5, 0x22A5}, {0x22BF, 0x22BF},
{0x2312, 0x2312}, {0x2460, 0x24E9}, {0x24EB, 0x254B},
{0x2550, 0x2573}, {0x2580, 0x258F}, {0x2592, 0x2595},
{0x25A0, 0x25A1}, {0x25A3, 0x25A9}, {0x25B2, 0x25B3},
{0x25B6, 0x25B7}, {0x25BC, 0x25BD}, {0x25C0, 0x25C1},
{0x25C6, 0x25C8}, {0x25CB, 0x25CB}, {0x25CE, 0x25D1},
{0x25E2, 0x25E5}, {0x25EF, 0x25EF}, {0x2605, 0x2606},
{0x2609, 0x2609}, {0x260E, 0x260F}, {0x2614, 0x2615},
{0x261C, 0x261C}, {0x261E, 0x261E}, {0x2640, 0x2640},
{0x2642, 0x2642}, {0x2660, 0x2661}, {0x2663, 0x2665},
{0x2667, 0x266A}, {0x266C, 0x266D}, {0x266F, 0x266F},
{0x273D, 0x273D}, {0x2776, 0x277F}, {0xE000, 0xF8FF},
{0xFFFD, 0xFFFD}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}};
/* binary search in table of non-spacing characters */
if (bisearch(ucs, ambiguous, sizeof(ambiguous) / sizeof(struct interval) - 1))
return 2;
return mk_wcwidth(ucs);
}
static inline int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n) {
int w, width = 0;
for (; *pwcs && n-- > 0; pwcs++)
if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
return -1;
else
width += w;
return width;
}
// convert UTF-8 string to wstring
#ifdef _MSC_VER
static inline std::wstring utf8_decode(const std::string& s) {
std::string curLocale = setlocale(LC_ALL, "");
const char* _Source = s.c_str();
size_t _Dsize = std::strlen(_Source) + 1;
wchar_t* _Dest = new wchar_t[_Dsize];
size_t _Osize;
mbstowcs_s(&_Osize, _Dest, _Dsize, _Source, _Dsize);
std::wstring result = _Dest;
delete[] _Dest;
setlocale(LC_ALL, curLocale.c_str());
return result;
}
#else
static inline std::wstring utf8_decode(const std::string& s) {
std::string curLocale = setlocale(LC_ALL, "");
const char* _Source = s.c_str();
size_t _Dsize = mbstowcs(NULL, _Source, 0) + 1;
wchar_t* _Dest = new wchar_t[_Dsize];
wmemset(_Dest, 0, _Dsize);
mbstowcs(_Dest, _Source, _Dsize);
std::wstring result = _Dest;
delete[] _Dest;
setlocale(LC_ALL, curLocale.c_str());
return result;
}
#endif
} // namespace details
static inline int display_width(const std::string &input) {
using namespace unicode::details;
return mk_wcswidth(utf8_decode(input).c_str(), input.size());
}
static inline int display_width(const std::wstring &input) {
return details::mk_wcswidth(input.c_str(), input.size());
}
} // namespace unicode
#endif

View File

@@ -1,8 +1,14 @@
#pragma once
#ifndef INDICATORS_DYNAMIC_PROGRESS
#define INDICATORS_DYNAMIC_PROGRESS
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <indicators/color.hpp> #include <indicators/color.hpp>
#include <indicators/setting.hpp> #include <indicators/setting.hpp>
#include <indicators/cursor_control.hpp>
#include <indicators/cursor_movement.hpp>
#include <indicators/details/stream_helper.hpp>
#include <iostream> #include <iostream>
#include <mutex> #include <mutex>
#include <vector> #include <vector>
@@ -79,8 +85,11 @@ public:
if (hide_bar_when_complete) { if (hide_bar_when_complete) {
// Hide completed bars // Hide completed bars
if (started_) { if (started_) {
for (size_t i = 0; i < incomplete_count_; ++i) for (size_t i = 0; i < incomplete_count_; ++i) {
std::cout << "\033[A\r\033[K" << std::flush; move_up(1);
erase_line();
std::cout << std::flush;
}
} }
incomplete_count_ = 0; incomplete_count_ = 0;
for (auto &bar : bars_) { for (auto &bar : bars_) {
@@ -94,10 +103,8 @@ public:
started_ = true; started_ = true;
} else { } else {
// Don't hide any bars // Don't hide any bars
if (started_) { if (started_)
for (size_t i = 0; i < total_count_; ++i) move_up(static_cast<int>(total_count_));
std::cout << "\x1b[A";
}
for (auto &bar : bars_) { for (auto &bar : bars_) {
bar.get().print_progress(true); bar.get().print_progress(true);
std::cout << "\n"; std::cout << "\n";
@@ -111,3 +118,5 @@ public:
}; };
} // namespace indicators } // namespace indicators
#endif

View File

@@ -1,7 +1,9 @@
#pragma once
#ifndef INDICATORS_FONT_STYLE
#define INDICATORS_FONT_STYLE
namespace indicators { namespace indicators {
enum class FontStyle { bold, dark, italic, underline, blink, reverse, concealed, crossed }; enum class FontStyle { bold, dark, italic, underline, blink, reverse, concealed, crossed };
} }
#endif

View File

@@ -1,4 +1,6 @@
#pragma once
#ifndef INDICATORS_INDETERMINATE_PROGRESS_BAR
#define INDICATORS_INDETERMINATE_PROGRESS_BAR
#include <indicators/details/stream_helper.hpp> #include <indicators/details/stream_helper.hpp>
@@ -8,6 +10,7 @@
#include <cmath> #include <cmath>
#include <indicators/color.hpp> #include <indicators/color.hpp>
#include <indicators/setting.hpp> #include <indicators/setting.hpp>
#include <indicators/terminal_size.hpp>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <mutex> #include <mutex>
@@ -15,20 +18,18 @@
#include <thread> #include <thread>
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include <sstream>
#include <utility>
namespace indicators { namespace indicators {
class IndeterminateProgressBar { class IndeterminateProgressBar {
using Settings = using Settings =
std::tuple<option::BarWidth, option::PrefixText, option::PostfixText, option::Start, std::tuple<option::BarWidth, option::PrefixText, option::PostfixText, option::Start,
option::End, option::Fill, option::Lead, option::End, option::Fill, option::Lead, option::MaxPostfixTextLen,
option::MaxPostfixTextLen, option::Completed, option::Completed, option::ForegroundColor, option::FontStyles, option::Stream>;
option::ForegroundColor, option::FontStyles, option::Stream>;
enum class Direction { enum class Direction { forward, backward };
forward,
backward
};
Direction direction_{Direction::forward}; Direction direction_{Direction::forward};
@@ -60,8 +61,8 @@ public:
option::ForegroundColor{Color::unspecified}, std::forward<Args>(args)...), option::ForegroundColor{Color::unspecified}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::font_styles>( details::get<details::ProgressBarOption::font_styles>(
option::FontStyles{std::vector<FontStyle>{}}, std::forward<Args>(args)...), option::FontStyles{std::vector<FontStyle>{}}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::stream>( details::get<details::ProgressBarOption::stream>(option::Stream{std::cout},
option::Stream{std::cout}, std::forward<Args>(args)...)) { std::forward<Args>(args)...)) {
// starts with [<==>...........] // starts with [<==>...........]
// progress_ = 0 // progress_ = 0
@@ -70,10 +71,10 @@ public:
// ^^^^^^^^^^^^ (bar_width - len(lead)) // ^^^^^^^^^^^^ (bar_width - len(lead))
// progress_ = bar_width - len(lead) // progress_ = bar_width - len(lead)
progress_ = 0; progress_ = 0;
max_progress_ = get_value<details::ProgressBarOption::bar_width>() max_progress_ = get_value<details::ProgressBarOption::bar_width>() -
- get_value<details::ProgressBarOption::lead>().size() get_value<details::ProgressBarOption::lead>().size() +
+ get_value<details::ProgressBarOption::start>().size() get_value<details::ProgressBarOption::start>().size() +
+ get_value<details::ProgressBarOption::end>().size(); get_value<details::ProgressBarOption::end>().size();
} }
template <typename T, details::ProgressBarOption id> template <typename T, details::ProgressBarOption id>
@@ -130,9 +131,7 @@ public:
print_progress(); print_progress();
} }
bool is_completed() { bool is_completed() { return get_value<details::ProgressBarOption::completed>(); }
return get_value<details::ProgressBarOption::completed>();
}
void mark_as_completed() { void mark_as_completed() {
get_value<details::ProgressBarOption::completed>() = true; get_value<details::ProgressBarOption::completed>() = true;
@@ -161,11 +160,28 @@ private:
template <typename Indicator> friend class DynamicProgress; template <typename Indicator> friend class DynamicProgress;
std::atomic<bool> multi_progress_mode_{false}; std::atomic<bool> multi_progress_mode_{false};
std::pair<std::string, size_t> get_prefix_text() {
std::stringstream os;
os << get_value<details::ProgressBarOption::prefix_text>();
const auto result = os.str();
const auto result_size = unicode::display_width(result);
return {result, result_size};
}
std::pair<std::string, size_t> get_postfix_text() {
std::stringstream os;
os << " " << get_value<details::ProgressBarOption::postfix_text>();
const auto result = os.str();
const auto result_size = unicode::display_width(result);
return {result, result_size};
}
public: public:
void print_progress(bool from_multi_progress = false) { void print_progress(bool from_multi_progress = false) {
std::lock_guard<std::mutex> lock{mutex_}; std::lock_guard<std::mutex> lock{mutex_};
auto& os = get_value<details::ProgressBarOption::stream>(); auto &os = get_value<details::ProgressBarOption::stream>();
if (multi_progress_mode_ && !from_multi_progress) { if (multi_progress_mode_ && !from_multi_progress) {
return; return;
@@ -176,24 +192,40 @@ public:
for (auto &style : get_value<details::ProgressBarOption::font_styles>()) for (auto &style : get_value<details::ProgressBarOption::font_styles>())
details::set_font_style(os, style); details::set_font_style(os, style);
os << get_value<details::ProgressBarOption::prefix_text>(); const auto prefix_pair = get_prefix_text();
const auto prefix_text = prefix_pair.first;
const auto prefix_length = prefix_pair.second;
os << "\r" << prefix_text;
os << get_value<details::ProgressBarOption::start>(); os << get_value<details::ProgressBarOption::start>();
details::IndeterminateProgressScaleWriter writer{os, details::IndeterminateProgressScaleWriter writer{
get_value<details::ProgressBarOption::bar_width>(), os, get_value<details::ProgressBarOption::bar_width>(),
get_value<details::ProgressBarOption::fill>(), get_value<details::ProgressBarOption::fill>(),
get_value<details::ProgressBarOption::lead>()}; get_value<details::ProgressBarOption::lead>()};
writer.write(progress_); writer.write(progress_);
os << get_value<details::ProgressBarOption::end>(); os << get_value<details::ProgressBarOption::end>();
if (get_value<details::ProgressBarOption::max_postfix_text_len>() == 0) const auto postfix_pair = get_postfix_text();
get_value<details::ProgressBarOption::max_postfix_text_len>() = 10; const auto postfix_text = postfix_pair.first;
os << " " << get_value<details::ProgressBarOption::postfix_text>() const auto postfix_length = postfix_pair.second;
<< std::string(get_value<details::ProgressBarOption::max_postfix_text_len>(), ' ') os << postfix_text;
<< "\r";
// Get length of prefix text and postfix text
const auto start_length = get_value<details::ProgressBarOption::start>().size();
const auto bar_width = get_value<details::ProgressBarOption::bar_width>();
const auto end_length = get_value<details::ProgressBarOption::end>().size();
const auto terminal_width = terminal_size().second;
// prefix + bar_width + postfix should be <= terminal_width
const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length);
if (remaining > 0) {
os << std::string(remaining, ' ') << "\r";
} else if (remaining < 0) {
// Do nothing. Maybe in the future truncate postfix with ...
}
os.flush(); os.flush();
if (get_value<details::ProgressBarOption::completed>() && if (get_value<details::ProgressBarOption::completed>() &&
!from_multi_progress) // Don't std::endl if calling from MultiProgress !from_multi_progress) // Don't std::endl if calling from MultiProgress
os << termcolor::reset << std::endl; os << termcolor::reset << std::endl;
@@ -201,3 +233,5 @@ public:
}; };
} // namespace indicators } // namespace indicators
#endif

View File

@@ -1,12 +1,15 @@
#pragma once
#ifndef INDICATORS_MULTI_PROGRESS
#define INDICATORS_MULTI_PROGRESS
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <iostream> #include <iostream>
#include <mutex> #include <mutex>
#include <vector> #include <vector>
#include <indicators/cursor_movement.hpp>
#include <indicators/color.hpp> #include <indicators/color.hpp>
#include <indicators/cursor_movement.hpp>
#include <indicators/details/stream_helper.hpp>
namespace indicators { namespace indicators {
@@ -75,3 +78,5 @@ public:
}; };
} // namespace indicators } // namespace indicators
#endif

View File

@@ -1,4 +1,6 @@
#pragma once
#ifndef INDICATORS_PROGRESS_BAR
#define INDICATORS_PROGRESS_BAR
#include <indicators/details/stream_helper.hpp> #include <indicators/details/stream_helper.hpp>
@@ -8,101 +10,134 @@
#include <cmath> #include <cmath>
#include <indicators/color.hpp> #include <indicators/color.hpp>
#include <indicators/setting.hpp> #include <indicators/setting.hpp>
#include <indicators/terminal_size.hpp>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <sstream>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <thread> #include <thread>
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include <utility>
namespace indicators { namespace indicators {
class ProgressBar { class ProgressBar {
using Settings = using Settings =
std::tuple<option::BarWidth, option::PrefixText, option::PostfixText, option::Start, std::tuple<option::BarWidth, option::PrefixText, option::PostfixText,
option::End, option::Fill, option::Lead, option::Remainder, option::Start, option::End, option::Fill, option::Lead,
option::MaxPostfixTextLen, option::Completed, option::ShowPercentage, option::Remainder, option::MaxPostfixTextLen,
option::ShowElapsedTime, option::ShowRemainingTime, option::SavedStartTime, option::Completed, option::ShowPercentage,
option::ForegroundColor, option::FontStyles, option::MaxProgress, option::Stream>; option::ShowElapsedTime, option::ShowRemainingTime,
option::SavedStartTime, option::ForegroundColor,
option::FontStyles, option::MinProgress, option::MaxProgress,
option::ProgressType, option::Stream>;
public: public:
template <typename... Args, template <typename... Args,
typename std::enable_if<details::are_settings_from_tuple< typename std::enable_if<
Settings, typename std::decay<Args>::type...>::value, details::are_settings_from_tuple<
void *>::type = nullptr> Settings, typename std::decay<Args>::type...>::value,
void *>::type = nullptr>
explicit ProgressBar(Args &&... args) explicit ProgressBar(Args &&... args)
: settings_(details::get<details::ProgressBarOption::bar_width>(option::BarWidth{100}, : settings_(
std::forward<Args>(args)...), details::get<details::ProgressBarOption::bar_width>(
details::get<details::ProgressBarOption::prefix_text>( option::BarWidth{100}, std::forward<Args>(args)...),
option::PrefixText{}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::prefix_text>(
details::get<details::ProgressBarOption::postfix_text>( option::PrefixText{}, std::forward<Args>(args)...),
option::PostfixText{}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::postfix_text>(
details::get<details::ProgressBarOption::start>(option::Start{"["}, option::PostfixText{}, std::forward<Args>(args)...),
std::forward<Args>(args)...), details::get<details::ProgressBarOption::start>(
details::get<details::ProgressBarOption::end>(option::End{"]"}, option::Start{"["}, std::forward<Args>(args)...),
std::forward<Args>(args)...), details::get<details::ProgressBarOption::end>(
details::get<details::ProgressBarOption::fill>(option::Fill{"="}, option::End{"]"}, std::forward<Args>(args)...),
std::forward<Args>(args)...), details::get<details::ProgressBarOption::fill>(
details::get<details::ProgressBarOption::lead>(option::Lead{">"}, option::Fill{"="}, std::forward<Args>(args)...),
std::forward<Args>(args)...), details::get<details::ProgressBarOption::lead>(
details::get<details::ProgressBarOption::remainder>(option::Remainder{" "}, option::Lead{">"}, std::forward<Args>(args)...),
std::forward<Args>(args)...), details::get<details::ProgressBarOption::remainder>(
details::get<details::ProgressBarOption::max_postfix_text_len>( option::Remainder{" "}, std::forward<Args>(args)...),
option::MaxPostfixTextLen{0}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::max_postfix_text_len>(
details::get<details::ProgressBarOption::completed>(option::Completed{false}, option::MaxPostfixTextLen{0}, std::forward<Args>(args)...),
std::forward<Args>(args)...), details::get<details::ProgressBarOption::completed>(
details::get<details::ProgressBarOption::show_percentage>( option::Completed{false}, std::forward<Args>(args)...),
option::ShowPercentage{false}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::show_percentage>(
details::get<details::ProgressBarOption::show_elapsed_time>( option::ShowPercentage{false}, std::forward<Args>(args)...),
option::ShowElapsedTime{false}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::show_elapsed_time>(
details::get<details::ProgressBarOption::show_remaining_time>( option::ShowElapsedTime{false}, std::forward<Args>(args)...),
option::ShowRemainingTime{false}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::show_remaining_time>(
details::get<details::ProgressBarOption::saved_start_time>( option::ShowRemainingTime{false}, std::forward<Args>(args)...),
option::SavedStartTime{false}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::saved_start_time>(
details::get<details::ProgressBarOption::foreground_color>( option::SavedStartTime{false}, std::forward<Args>(args)...),
option::ForegroundColor{Color::unspecified}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::foreground_color>(
details::get<details::ProgressBarOption::font_styles>( option::ForegroundColor{Color::unspecified},
option::FontStyles{std::vector<FontStyle>{}}, std::forward<Args>(args)...), std::forward<Args>(args)...),
details::get<details::ProgressBarOption::max_progress>( details::get<details::ProgressBarOption::font_styles>(
option::MaxProgress{100}, std::forward<Args>(args)...), option::FontStyles{std::vector<FontStyle>{}},
details::get<details::ProgressBarOption::stream>( std::forward<Args>(args)...),
option::Stream{std::cout}, std::forward<Args>(args)...)) {} details::get<details::ProgressBarOption::min_progress>(
option::MinProgress{0}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::max_progress>(
option::MaxProgress{100}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::progress_type>(
option::ProgressType{ProgressType::incremental},
std::forward<Args>(args)...),
details::get<details::ProgressBarOption::stream>(
option::Stream{std::cout}, std::forward<Args>(args)...)) {
// if progress is incremental, start from min_progress
// else start from max_progress
const auto type = get_value<details::ProgressBarOption::progress_type>();
if (type == ProgressType::incremental)
progress_ = get_value<details::ProgressBarOption::min_progress>();
else
progress_ = get_value<details::ProgressBarOption::max_progress>();
}
template <typename T, details::ProgressBarOption id> template <typename T, details::ProgressBarOption id>
void set_option(details::Setting<T, id> &&setting) { void set_option(details::Setting<T, id> &&setting) {
static_assert(!std::is_same<T, typename std::decay<decltype(details::get_value<id>( static_assert(
std::declval<Settings>()))>::type>::value, !std::is_same<T, typename std::decay<decltype(details::get_value<id>(
"Setting has wrong type!"); std::declval<Settings>()))>::type>::value,
"Setting has wrong type!");
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
get_value<id>() = std::move(setting).value; get_value<id>() = std::move(setting).value;
} }
template <typename T, details::ProgressBarOption id> template <typename T, details::ProgressBarOption id>
void set_option(const details::Setting<T, id> &setting) { void set_option(const details::Setting<T, id> &setting) {
static_assert(!std::is_same<T, typename std::decay<decltype(details::get_value<id>( static_assert(
std::declval<Settings>()))>::type>::value, !std::is_same<T, typename std::decay<decltype(details::get_value<id>(
"Setting has wrong type!"); std::declval<Settings>()))>::type>::value,
"Setting has wrong type!");
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
get_value<id>() = setting.value; get_value<id>() = setting.value;
} }
void set_option( void
const details::Setting<std::string, details::ProgressBarOption::postfix_text> &setting) { set_option(const details::Setting<
std::string, details::ProgressBarOption::postfix_text> &setting) {
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
get_value<details::ProgressBarOption::postfix_text>() = setting.value; get_value<details::ProgressBarOption::postfix_text>() = setting.value;
if (setting.value.length() > get_value<details::ProgressBarOption::max_postfix_text_len>()) { if (setting.value.length() >
get_value<details::ProgressBarOption::max_postfix_text_len>() = setting.value.length(); get_value<details::ProgressBarOption::max_postfix_text_len>()) {
get_value<details::ProgressBarOption::max_postfix_text_len>() =
setting.value.length();
} }
} }
void void set_option(
set_option(details::Setting<std::string, details::ProgressBarOption::postfix_text> &&setting) { details::Setting<std::string, details::ProgressBarOption::postfix_text>
&&setting) {
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
get_value<details::ProgressBarOption::postfix_text>() = std::move(setting).value; get_value<details::ProgressBarOption::postfix_text>() =
std::move(setting).value;
auto &new_value = get_value<details::ProgressBarOption::postfix_text>(); auto &new_value = get_value<details::ProgressBarOption::postfix_text>();
if (new_value.length() > get_value<details::ProgressBarOption::max_postfix_text_len>()) { if (new_value.length() >
get_value<details::ProgressBarOption::max_postfix_text_len>() = new_value.length(); get_value<details::ProgressBarOption::max_postfix_text_len>()) {
get_value<details::ProgressBarOption::max_postfix_text_len>() =
new_value.length();
} }
} }
@@ -119,7 +154,11 @@ public:
void tick() { void tick() {
{ {
std::lock_guard<std::mutex> lock{mutex_}; std::lock_guard<std::mutex> lock{mutex_};
progress_ += 1; const auto type = get_value<details::ProgressBarOption::progress_type>();
if (type == ProgressType::incremental)
progress_ += 1;
else
progress_ -= 1;
} }
save_start_time(); save_start_time();
print_progress(); print_progress();
@@ -127,10 +166,14 @@ public:
size_t current() { size_t current() {
std::lock_guard<std::mutex> lock{mutex_}; std::lock_guard<std::mutex> lock{mutex_};
return std::min(progress_, size_t(get_value<details::ProgressBarOption::max_progress>())); return (std::min)(
progress_,
size_t(get_value<details::ProgressBarOption::max_progress>()));
} }
bool is_completed() const { return get_value<details::ProgressBarOption::completed>(); } bool is_completed() const {
return get_value<details::ProgressBarOption::completed>();
}
void mark_as_completed() { void mark_as_completed() {
get_value<details::ProgressBarOption::completed>() = true; get_value<details::ProgressBarOption::completed>() = true;
@@ -139,13 +182,14 @@ public:
private: private:
template <details::ProgressBarOption id> template <details::ProgressBarOption id>
auto get_value() -> decltype((details::get_value<id>(std::declval<Settings &>()).value)) { auto get_value()
-> decltype((details::get_value<id>(std::declval<Settings &>()).value)) {
return details::get_value<id>(settings_).value; return details::get_value<id>(settings_).value;
} }
template <details::ProgressBarOption id> template <details::ProgressBarOption id>
auto get_value() const auto get_value() const -> decltype(
-> decltype((details::get_value<id>(std::declval<const Settings &>()).value)) { (details::get_value<id>(std::declval<const Settings &>()).value)) {
return details::get_value<id>(settings_).value; return details::get_value<id>(settings_).value;
} }
@@ -160,56 +204,41 @@ private:
std::atomic<bool> multi_progress_mode_{false}; std::atomic<bool> multi_progress_mode_{false};
void save_start_time() { void save_start_time() {
auto &show_elapsed_time = get_value<details::ProgressBarOption::show_elapsed_time>(); auto &show_elapsed_time =
auto &saved_start_time = get_value<details::ProgressBarOption::saved_start_time>(); get_value<details::ProgressBarOption::show_elapsed_time>();
auto &show_remaining_time = get_value<details::ProgressBarOption::show_remaining_time>(); auto &saved_start_time =
get_value<details::ProgressBarOption::saved_start_time>();
auto &show_remaining_time =
get_value<details::ProgressBarOption::show_remaining_time>();
if ((show_elapsed_time || show_remaining_time) && !saved_start_time) { if ((show_elapsed_time || show_remaining_time) && !saved_start_time) {
start_time_point_ = std::chrono::high_resolution_clock::now(); start_time_point_ = std::chrono::high_resolution_clock::now();
saved_start_time = true; saved_start_time = true;
} }
} }
public: std::pair<std::string, size_t> get_prefix_text() {
void print_progress(bool from_multi_progress = false) { std::stringstream os;
std::lock_guard<std::mutex> lock{mutex_};
auto& os = get_value<details::ProgressBarOption::stream>();
const auto max_progress = get_value<details::ProgressBarOption::max_progress>();
if (multi_progress_mode_ && !from_multi_progress) {
if (progress_ >= max_progress) {
get_value<details::ProgressBarOption::completed>() = true;
}
return;
}
auto now = std::chrono::high_resolution_clock::now();
if (!get_value<details::ProgressBarOption::completed>())
elapsed_ = std::chrono::duration_cast<std::chrono::nanoseconds>(now - start_time_point_);
if (get_value<details::ProgressBarOption::foreground_color>() != Color::unspecified)
details::set_stream_color(os, get_value<details::ProgressBarOption::foreground_color>());
for (auto &style : get_value<details::ProgressBarOption::font_styles>())
details::set_font_style(os, style);
os << get_value<details::ProgressBarOption::prefix_text>(); os << get_value<details::ProgressBarOption::prefix_text>();
const auto result = os.str();
const auto result_size = unicode::display_width(result);
return {result, result_size};
}
os << get_value<details::ProgressBarOption::start>(); std::pair<std::string, size_t> get_postfix_text() {
std::stringstream os;
details::ProgressScaleWriter writer{os, const auto max_progress =
get_value<details::ProgressBarOption::bar_width>(), get_value<details::ProgressBarOption::max_progress>();
get_value<details::ProgressBarOption::fill>(),
get_value<details::ProgressBarOption::lead>(),
get_value<details::ProgressBarOption::remainder>()};
writer.write(double(progress_) / double(max_progress) * 100.0f);
os << get_value<details::ProgressBarOption::end>();
if (get_value<details::ProgressBarOption::show_percentage>()) { if (get_value<details::ProgressBarOption::show_percentage>()) {
os << " " << std::min(static_cast<size_t>(static_cast<float>(progress_) / max_progress * 100), size_t(100)) << "%"; os << " "
<< (std::min)(static_cast<size_t>(static_cast<float>(progress_) /
max_progress * 100),
size_t(100))
<< "%";
} }
auto &saved_start_time = get_value<details::ProgressBarOption::saved_start_time>(); auto &saved_start_time =
get_value<details::ProgressBarOption::saved_start_time>();
if (get_value<details::ProgressBarOption::show_elapsed_time>()) { if (get_value<details::ProgressBarOption::show_elapsed_time>()) {
os << " ["; os << " [";
@@ -227,7 +256,10 @@ public:
if (saved_start_time) { if (saved_start_time) {
auto eta = std::chrono::nanoseconds( auto eta = std::chrono::nanoseconds(
progress_ > 0 ? static_cast<long long>(elapsed_.count() * max_progress / progress_) : 0); progress_ > 0
? static_cast<long long>(std::ceil(float(elapsed_.count()) *
max_progress / progress_))
: 0);
auto remaining = eta > elapsed_ ? (eta - elapsed_) : (elapsed_ - eta); auto remaining = eta > elapsed_ ? (eta - elapsed_) : (elapsed_ - eta);
details::write_duration(os, remaining); details::write_duration(os, remaining);
} else { } else {
@@ -240,13 +272,81 @@ public:
os << "]"; os << "]";
} }
if (get_value<details::ProgressBarOption::max_postfix_text_len>() == 0) os << " " << get_value<details::ProgressBarOption::postfix_text>();
get_value<details::ProgressBarOption::max_postfix_text_len>() = 10;
os << " " << get_value<details::ProgressBarOption::postfix_text>() const auto result = os.str();
<< std::string(get_value<details::ProgressBarOption::max_postfix_text_len>(), ' ') const auto result_size = unicode::display_width(result);
<< "\r"; return {result, result_size};
}
public:
void print_progress(bool from_multi_progress = false) {
std::lock_guard<std::mutex> lock{mutex_};
auto &os = get_value<details::ProgressBarOption::stream>();
const auto type = get_value<details::ProgressBarOption::progress_type>();
const auto min_progress =
get_value<details::ProgressBarOption::min_progress>();
const auto max_progress =
get_value<details::ProgressBarOption::max_progress>();
if (multi_progress_mode_ && !from_multi_progress) {
if ((type == ProgressType::incremental && progress_ >= max_progress) ||
(type == ProgressType::decremental && progress_ <= min_progress)) {
get_value<details::ProgressBarOption::completed>() = true;
}
return;
}
auto now = std::chrono::high_resolution_clock::now();
if (!get_value<details::ProgressBarOption::completed>())
elapsed_ = std::chrono::duration_cast<std::chrono::nanoseconds>(
now - start_time_point_);
if (get_value<details::ProgressBarOption::foreground_color>() !=
Color::unspecified)
details::set_stream_color(
os, get_value<details::ProgressBarOption::foreground_color>());
for (auto &style : get_value<details::ProgressBarOption::font_styles>())
details::set_font_style(os, style);
const auto prefix_pair = get_prefix_text();
const auto prefix_text = prefix_pair.first;
const auto prefix_length = prefix_pair.second;
os << "\r" << prefix_text;
os << get_value<details::ProgressBarOption::start>();
details::ProgressScaleWriter writer{
os, get_value<details::ProgressBarOption::bar_width>(),
get_value<details::ProgressBarOption::fill>(),
get_value<details::ProgressBarOption::lead>(),
get_value<details::ProgressBarOption::remainder>()};
writer.write(double(progress_) / double(max_progress) * 100.0f);
os << get_value<details::ProgressBarOption::end>();
const auto postfix_pair = get_postfix_text();
const auto postfix_text = postfix_pair.first;
const auto postfix_length = postfix_pair.second;
os << postfix_text;
// Get length of prefix text and postfix text
const auto start_length = get_value<details::ProgressBarOption::start>().size();
const auto bar_width = get_value<details::ProgressBarOption::bar_width>();
const auto end_length = get_value<details::ProgressBarOption::end>().size();
const auto terminal_width = terminal_size().second;
// prefix + bar_width + postfix should be <= terminal_width
const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length);
if (remaining > 0) {
os << std::string(remaining, ' ') << "\r";
} else if (remaining < 0) {
// Do nothing. Maybe in the future truncate postfix with ...
}
os.flush(); os.flush();
if (progress_ >= max_progress) {
if ((type == ProgressType::incremental && progress_ >= max_progress) ||
(type == ProgressType::decremental && progress_ <= min_progress)) {
get_value<details::ProgressBarOption::completed>() = true; get_value<details::ProgressBarOption::completed>() = true;
} }
if (get_value<details::ProgressBarOption::completed>() && if (get_value<details::ProgressBarOption::completed>() &&
@@ -256,3 +356,5 @@ public:
}; };
} // namespace indicators } // namespace indicators
#endif

View File

@@ -1,4 +1,6 @@
#pragma once
#ifndef INDICATORS_PROGRESS_SPINNER
#define INDICATORS_PROGRESS_SPINNER
#include <indicators/details/stream_helper.hpp> #include <indicators/details/stream_helper.hpp>
@@ -32,36 +34,37 @@ public:
Settings, typename std::decay<Args>::type...>::value, Settings, typename std::decay<Args>::type...>::value,
void *>::type = nullptr> void *>::type = nullptr>
explicit ProgressSpinner(Args &&... args) explicit ProgressSpinner(Args &&... args)
: settings_(details::get<details::ProgressBarOption::foreground_color>( : settings_(
option::ForegroundColor{Color::unspecified}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::foreground_color>(
details::get<details::ProgressBarOption::prefix_text>( option::ForegroundColor{Color::unspecified}, std::forward<Args>(args)...),
option::PrefixText{}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::prefix_text>(option::PrefixText{},
details::get<details::ProgressBarOption::postfix_text>( std::forward<Args>(args)...),
option::PostfixText{}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::postfix_text>(option::PostfixText{},
details::get<details::ProgressBarOption::show_percentage>( std::forward<Args>(args)...),
option::ShowPercentage{true}, std::forward<Args>(args)...), details::get<details::ProgressBarOption::show_percentage>(option::ShowPercentage{true},
details::get<details::ProgressBarOption::show_elapsed_time>(
option::ShowElapsedTime{false}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::show_remaining_time>(
option::ShowRemainingTime{false}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::spinner_show>(
option::ShowSpinner{true}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::saved_start_time>(
option::SavedStartTime{false}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::completed>(option::Completed{false},
std::forward<Args>(args)...), std::forward<Args>(args)...),
details::get<details::ProgressBarOption::max_postfix_text_len>( details::get<details::ProgressBarOption::show_elapsed_time>(
option::MaxPostfixTextLen{0}, std::forward<Args>(args)...), option::ShowElapsedTime{false}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::spinner_states>( details::get<details::ProgressBarOption::show_remaining_time>(
option::SpinnerStates{std::vector<std::string>{"", "", "", "", "", "", option::ShowRemainingTime{false}, std::forward<Args>(args)...),
"", "", "", ""}}, details::get<details::ProgressBarOption::spinner_show>(option::ShowSpinner{true},
std::forward<Args>(args)...), std::forward<Args>(args)...),
details::get<details::ProgressBarOption::font_styles>( details::get<details::ProgressBarOption::saved_start_time>(
option::FontStyles{std::vector<FontStyle>{}}, std::forward<Args>(args)...), option::SavedStartTime{false}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::max_progress>( details::get<details::ProgressBarOption::completed>(option::Completed{false},
option::MaxProgress{100}, std::forward<Args>(args)...), std::forward<Args>(args)...),
details::get<details::ProgressBarOption::stream>( details::get<details::ProgressBarOption::max_postfix_text_len>(
option::Stream{std::cout}, std::forward<Args>(args)...)) {} option::MaxPostfixTextLen{0}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::spinner_states>(
option::SpinnerStates{
std::vector<std::string>{"", "", "", "", "", "", "", "", "", ""}},
std::forward<Args>(args)...),
details::get<details::ProgressBarOption::font_styles>(
option::FontStyles{std::vector<FontStyle>{}}, std::forward<Args>(args)...),
details::get<details::ProgressBarOption::max_progress>(option::MaxProgress{100},
std::forward<Args>(args)...),
details::get<details::ProgressBarOption::stream>(option::Stream{std::cout},
std::forward<Args>(args)...)) {}
template <typename T, details::ProgressBarOption id> template <typename T, details::ProgressBarOption id>
void set_option(details::Setting<T, id> &&setting) { void set_option(details::Setting<T, id> &&setting) {
@@ -120,7 +123,7 @@ public:
size_t current() { size_t current() {
std::lock_guard<std::mutex> lock{mutex_}; std::lock_guard<std::mutex> lock{mutex_};
return std::min(progress_, size_t(get_value<details::ProgressBarOption::max_progress>())); return (std::min)(progress_, size_t(get_value<details::ProgressBarOption::max_progress>()));
} }
bool is_completed() const { return get_value<details::ProgressBarOption::completed>(); } bool is_completed() const { return get_value<details::ProgressBarOption::completed>(); }
@@ -162,7 +165,7 @@ public:
void print_progress() { void print_progress() {
std::lock_guard<std::mutex> lock{mutex_}; std::lock_guard<std::mutex> lock{mutex_};
auto& os = get_value<details::ProgressBarOption::stream>(); auto &os = get_value<details::ProgressBarOption::stream>();
const auto max_progress = get_value<details::ProgressBarOption::max_progress>(); const auto max_progress = get_value<details::ProgressBarOption::max_progress>();
auto now = std::chrono::high_resolution_clock::now(); auto now = std::chrono::high_resolution_clock::now();
@@ -179,7 +182,7 @@ public:
os << get_value<details::ProgressBarOption::spinner_states>() os << get_value<details::ProgressBarOption::spinner_states>()
[index_ % get_value<details::ProgressBarOption::spinner_states>().size()]; [index_ % get_value<details::ProgressBarOption::spinner_states>().size()];
if (get_value<details::ProgressBarOption::show_percentage>()) { if (get_value<details::ProgressBarOption::show_percentage>()) {
os << " " << std::min(progress_, size_t(max_progress)) << "%"; os << " " << std::size_t(progress_ / double(max_progress) * 100) << "%";
} }
if (get_value<details::ProgressBarOption::show_elapsed_time>()) { if (get_value<details::ProgressBarOption::show_elapsed_time>()) {
@@ -193,7 +196,10 @@ public:
else else
os << " ["; os << " [";
auto eta = std::chrono::nanoseconds( auto eta = std::chrono::nanoseconds(
progress_ > 0 ? static_cast<long long>(elapsed.count() * max_progress / progress_) : 0); progress_ > 0
? static_cast<long long>(std::ceil(float(elapsed.count()) *
max_progress / progress_))
: 0);
auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
details::write_duration(os, remaining); details::write_duration(os, remaining);
os << "]"; os << "]";
@@ -205,8 +211,7 @@ public:
if (get_value<details::ProgressBarOption::max_postfix_text_len>() == 0) if (get_value<details::ProgressBarOption::max_postfix_text_len>() == 0)
get_value<details::ProgressBarOption::max_postfix_text_len>() = 10; get_value<details::ProgressBarOption::max_postfix_text_len>() = 10;
os << " " << get_value<details::ProgressBarOption::postfix_text>() os << " " << get_value<details::ProgressBarOption::postfix_text>()
<< std::string(get_value<details::ProgressBarOption::max_postfix_text_len>(), ' ') << std::string(get_value<details::ProgressBarOption::max_postfix_text_len>(), ' ') << "\r";
<< "\r";
os.flush(); os.flush();
index_ += 1; index_ += 1;
if (progress_ > max_progress) { if (progress_ > max_progress) {
@@ -218,3 +223,5 @@ public:
}; };
} // namespace indicators } // namespace indicators
#endif

View File

@@ -0,0 +1,9 @@
#ifndef INDICATORS_PROGRESS_TYPE
#define INDICATORS_PROGRESS_TYPE
namespace indicators {
enum class ProgressType { incremental, decremental };
}
#endif

View File

@@ -1,3 +1,4 @@
/* /*
Activity Indicators for Modern C++ Activity Indicators for Modern C++
https://github.com/p-ranav/indicators https://github.com/p-ranav/indicators
@@ -24,12 +25,15 @@ 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#pragma once #ifndef INDICATORS_SETTING
#define INDICATORS_SETTING
#include <cstddef> #include <cstddef>
#include <indicators/color.hpp> #include <indicators/color.hpp>
#include <indicators/font_style.hpp> #include <indicators/font_style.hpp>
#include <indicators/progress_type.hpp>
#include <string> #include <string>
#include <tuple>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -90,7 +94,9 @@ enum class ProgressBarOption {
spinner_states, spinner_states,
font_styles, font_styles,
hide_bar_when_complete, hide_bar_when_complete,
min_progress,
max_progress, max_progress,
progress_type,
stream stream
}; };
@@ -135,14 +141,14 @@ template <ProgressBarOption Id, typename Default> Default &&get_impl(Default &&d
} }
template <ProgressBarOption Id, typename Default, typename T, typename... Args> template <ProgressBarOption Id, typename Default, typename T, typename... Args>
auto get_impl(Default &&/*def*/, T &&first, Args &&... /*tail*/) -> auto get_impl(Default && /*def*/, T &&first, Args &&... /*tail*/) ->
typename std::enable_if<(std::decay<T>::type::id == Id), typename std::enable_if<(std::decay<T>::type::id == Id),
decltype(std::forward<T>(first))>::type { decltype(std::forward<T>(first))>::type {
return std::forward<T>(first); return std::forward<T>(first);
} }
template <ProgressBarOption Id, typename Default, typename T, typename... Args> template <ProgressBarOption Id, typename Default, typename T, typename... Args>
auto get_impl(Default &&def, T &&/*first*/, Args &&... tail) -> auto get_impl(Default &&def, T && /*first*/, Args &&... tail) ->
typename std::enable_if<(std::decay<T>::type::id != Id), typename std::enable_if<(std::decay<T>::type::id != Id),
decltype(get_impl<Id>(std::forward<Default>(def), decltype(get_impl<Id>(std::forward<Default>(def),
std::forward<Args>(tail)...))>::type { std::forward<Args>(tail)...))>::type {
@@ -206,7 +212,11 @@ using HideBarWhenComplete =
details::BooleanSetting<details::ProgressBarOption::hide_bar_when_complete>; details::BooleanSetting<details::ProgressBarOption::hide_bar_when_complete>;
using FontStyles = using FontStyles =
details::Setting<std::vector<FontStyle>, details::ProgressBarOption::font_styles>; details::Setting<std::vector<FontStyle>, details::ProgressBarOption::font_styles>;
using MinProgress = details::IntegerSetting<details::ProgressBarOption::min_progress>;
using MaxProgress = details::IntegerSetting<details::ProgressBarOption::max_progress>; using MaxProgress = details::IntegerSetting<details::ProgressBarOption::max_progress>;
using Stream = details::Setting<std::ostream&, details::ProgressBarOption::stream>; using ProgressType = details::Setting<ProgressType, details::ProgressBarOption::progress_type>;
using Stream = details::Setting<std::ostream &, details::ProgressBarOption::stream>;
} // namespace option } // namespace option
} // namespace indicators } // namespace indicators
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +1,44 @@
#pragma once
#ifndef INDICATORS_TERMINAL_SIZE
#define INDICATORS_TERMINAL_SIZE
#include <utility> #include <utility>
#if defined(_WIN32)
#include <windows.h>
namespace indicators { namespace indicators {
#if defined(_MSC_VER) static inline std::pair<size_t, size_t> terminal_size() {
#include <windows.h> CONSOLE_SCREEN_BUFFER_INFO csbi;
int cols, rows;
std::pair<size_t, size_t> terminal_size() { GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
CONSOLE_SCREEN_BUFFER_INFO csbi; cols = csbi.srWindow.Right - csbi.srWindow.Left + 1;
int columns, rows; rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); return {static_cast<size_t>(rows), static_cast<size_t>(cols)};
columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
return {static_cast<size_t>(rows), static_cast<size_t>(cols)};
} }
size_t terminal_width() { static inline size_t terminal_width() { return terminal_size().second; }
return terminal_size().second;
} } // namespace indicators
#else #else
#include <sys/ioctl.h> //ioctl() and TIOCGWINSZ #include <sys/ioctl.h> //ioctl() and TIOCGWINSZ
#include <unistd.h> // for STDOUT_FILENO #include <unistd.h> // for STDOUT_FILENO
std::pair<size_t, size_t> terminal_size() { namespace indicators {
struct winsize size;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &size); static inline std::pair<size_t, size_t> terminal_size() {
return {static_cast<size_t>(size.ws_row), static_cast<size_t>(size.ws_col)}; struct winsize size{};
ioctl(STDOUT_FILENO, TIOCGWINSZ, &size);
return {static_cast<size_t>(size.ws_row), static_cast<size_t>(size.ws_col)};
} }
size_t terminal_width() { static inline size_t terminal_width() { return terminal_size().second; }
return terminal_size().second;
} } // namespace indicators
#endif #endif
} #endif

View File

@@ -14,9 +14,15 @@ target_link_libraries(progress_bar_set_progress PRIVATE indicators::indicators)
add_executable(progress_bar_tick progress_bar_tick.cpp) add_executable(progress_bar_tick progress_bar_tick.cpp)
target_link_libraries(progress_bar_tick PRIVATE indicators::indicators) target_link_libraries(progress_bar_tick PRIVATE indicators::indicators)
add_executable(progress_bar_countdown progress_bar_countdown.cpp)
target_link_libraries(progress_bar_countdown PRIVATE indicators::indicators)
add_executable(progress_bar_sstream progress_bar_sstream.cpp) add_executable(progress_bar_sstream progress_bar_sstream.cpp)
target_link_libraries(progress_bar_sstream PRIVATE indicators::indicators) target_link_libraries(progress_bar_sstream PRIVATE indicators::indicators)
add_executable(progress_bar_unicode progress_bar_unicode.cpp)
target_link_libraries(progress_bar_unicode PRIVATE indicators::indicators)
add_executable(progress_spinner progress_spinner.cpp) add_executable(progress_spinner progress_spinner.cpp)
target_link_libraries(progress_spinner PRIVATE indicators::indicators) target_link_libraries(progress_spinner PRIVATE indicators::indicators)
@@ -38,3 +44,6 @@ target_link_libraries(max_progress PRIVATE indicators::indicators)
add_executable(indeterminate_progress_bar indeterminate_progress_bar.cpp) add_executable(indeterminate_progress_bar indeterminate_progress_bar.cpp)
target_link_libraries(indeterminate_progress_bar PRIVATE indicators::indicators) target_link_libraries(indeterminate_progress_bar PRIVATE indicators::indicators)
add_executable(dynamic_postfix_text dynamic_postfix_text.cpp)
target_link_libraries(dynamic_postfix_text PRIVATE indicators::indicators)

View File

@@ -9,10 +9,9 @@ int main() {
indicators::show_console_cursor(false); indicators::show_console_cursor(false);
indicators::BlockProgressBar bar{ indicators::BlockProgressBar bar{
indicators::option::BarWidth{80}, indicators::option::BarWidth{80},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}} std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
};
// Update bar state // Update bar state
auto progress = 0.0f; auto progress = 0.0f;

View File

@@ -11,20 +11,15 @@ int main() {
// Random list of numbers // Random list of numbers
std::vector<size_t> numbers; std::vector<size_t> numbers;
for (size_t i = 0; i < 1259438; ++i) { for (size_t i = 0; i < 1259438; ++i) {
numbers.push_back(i); numbers.push_back(i);
} }
using namespace indicators; using namespace indicators;
BlockProgressBar bar{ BlockProgressBar bar{option::BarWidth{80}, option::ForegroundColor{Color::white},
option::BarWidth{80}, option::FontStyles{std::vector<FontStyle>{FontStyle::bold}},
option::ForegroundColor{Color::white}, option::MaxProgress{numbers.size()}};
option::FontStyles{
std::vector<FontStyle>{FontStyle::bold}},
option::MaxProgress{numbers.size()}
};
std::cout << "Iterating over a list of numbers (size = " std::cout << "Iterating over a list of numbers (size = " << numbers.size() << ")\n";
<< numbers.size() << ")\n";
std::vector<size_t> result; std::vector<size_t> result;
for (size_t i = 0; i < numbers.size(); ++i) { for (size_t i = 0; i < numbers.size(); ++i) {
@@ -33,9 +28,7 @@ int main() {
result.push_back(numbers[i] * numbers[i]); result.push_back(numbers[i] * numbers[i]);
// Show iteration as postfix text // Show iteration as postfix text
bar.set_option(option::PostfixText{ bar.set_option(option::PostfixText{std::to_string(i) + "/" + std::to_string(numbers.size())});
std::to_string(i) + "/" + std::to_string(numbers.size())
});
// update progress bar // update progress bar
bar.tick(); bar.tick();

View File

@@ -0,0 +1,46 @@
#include <indicators/progress_bar.hpp>
#include <indicators/multi_progress.hpp>
#include <indicators/terminal_size.hpp>
using namespace indicators;
int main() {
std::cout << "Terminal width: " << terminal_size().second << "\n";
// prepare progress bar
auto prepare_p = [](ProgressBar *p, const std::string &prefix){
p->set_option(option::PrefixText{prefix});
p->set_option(option::Start{""});
p->set_option(option::Fill{""});
p->set_option(option::Lead{""});
p->set_option(option::Remainder{""});
p->set_option(option::End{""});
p->set_option(option::BarWidth{0});
};
ProgressBar p1, p2;
prepare_p(&p1, "Progress #1");
prepare_p(&p2, "Progress #2");
MultiProgress<ProgressBar, 2> mp(p1, p2);
std::string some_text[] = {"foo", "bar", "independence", "beta", "alfa"};
std::string dynamic_text;
// first pb with static postfix text
p1.set_option(option::PostfixText{"Static text"});
// second pb with dynamic postfix text
for (auto &t: some_text) {
dynamic_text += t + " ";
p2.set_option(option::PostfixText{dynamic_text});
mp.set_progress<0>(size_t(0));
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// update postfix to little text for pb #2
p2.set_option(option::PostfixText{"abcd"});
mp.set_progress<0>(size_t(0));
}

View File

@@ -4,41 +4,53 @@ using namespace indicators;
int main() { int main() {
ProgressBar bar1{option::BarWidth{50}, option::ForegroundColor{Color::red}, ProgressBar bar1{option::BarWidth{50},
option::ShowElapsedTime{true}, option::ShowRemainingTime{true}, option::ForegroundColor{Color::red},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"5c90d4a2d1a8: Downloading "}, option::PrefixText{"5c90d4a2d1a8: Downloading "},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
ProgressBar bar2{option::BarWidth{50}, option::ForegroundColor{Color::yellow}, ProgressBar bar2{option::BarWidth{50},
option::ShowElapsedTime{true}, option::ShowRemainingTime{true}, option::ForegroundColor{Color::yellow},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"22337bfd13a9: Downloading "}, option::PrefixText{"22337bfd13a9: Downloading "},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
ProgressBar bar3{option::BarWidth{50}, option::ForegroundColor{Color::green}, ProgressBar bar3{option::BarWidth{50},
option::ShowElapsedTime{true}, option::ShowRemainingTime{true}, option::ForegroundColor{Color::green},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"10f26c680a34: Downloading "}, option::PrefixText{"10f26c680a34: Downloading "},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
ProgressBar bar4{option::BarWidth{50}, option::ForegroundColor{Color::white}, ProgressBar bar4{option::BarWidth{50},
option::ShowElapsedTime{true}, option::ShowRemainingTime{true}, option::ForegroundColor{Color::white},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"6364e0d7a283: Downloading "}, option::PrefixText{"6364e0d7a283: Downloading "},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
ProgressBar bar5{option::BarWidth{50}, option::ForegroundColor{Color::blue}, ProgressBar bar5{option::BarWidth{50},
option::ShowElapsedTime{true}, option::ShowRemainingTime{true}, option::ForegroundColor{Color::blue},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"ff1356ba118b: Downloading "}, option::PrefixText{"ff1356ba118b: Downloading "},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
ProgressBar bar6{option::BarWidth{50}, option::ForegroundColor{Color::cyan}, ProgressBar bar6{option::BarWidth{50},
option::ShowElapsedTime{true}, option::ShowRemainingTime{true}, option::ForegroundColor{Color::cyan},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"5a17453338b4: Downloading "}, option::PrefixText{"5a17453338b4: Downloading "},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
std::cout << termcolor::bold << termcolor::white << "Pulling image foo:bar/baz\n"; std::cout << termcolor::bold << termcolor::white << "Pulling image foo:bar/baz\n";

View File

@@ -1,7 +1,6 @@
#include <chrono> #include <chrono>
#include <indicators/indeterminate_progress_bar.hpp>
#include <indicators/cursor_control.hpp> #include <indicators/cursor_control.hpp>
#include <indicators/termcolor.hpp> #include <indicators/indeterminate_progress_bar.hpp>
#include <thread> #include <thread>
int main() { int main() {
@@ -14,16 +13,15 @@ int main() {
indicators::option::PostfixText{"Checking for Updates"}, indicators::option::PostfixText{"Checking for Updates"},
indicators::option::ForegroundColor{indicators::Color::yellow}, indicators::option::ForegroundColor{indicators::Color::yellow},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}} std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
};
indicators::show_console_cursor(false); indicators::show_console_cursor(false);
auto job = [&bar]() { auto job = [&bar]() {
std::this_thread::sleep_for(std::chrono::milliseconds(10000)); std::this_thread::sleep_for(std::chrono::milliseconds(10000));
bar.mark_as_completed(); bar.mark_as_completed();
std::cout << termcolor::bold << termcolor::green std::cout << termcolor::bold << termcolor::green << "System is up to date!\n"
<< "System is up to date!\n" << termcolor::reset; << termcolor::reset;
}; };
std::thread job_completion_thread(job); std::thread job_completion_thread(job);

View File

@@ -9,11 +9,10 @@ int main() {
indicators::show_console_cursor(false); indicators::show_console_cursor(false);
indicators::BlockProgressBar bar{ indicators::BlockProgressBar bar{
indicators::option::BarWidth{80}, indicators::option::BarWidth{80},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}, std::vector<indicators::FontStyle>{indicators::FontStyle::bold}},
indicators::option::MaxProgress{400} indicators::option::MaxProgress{400}};
};
// Update bar state // Update bar state
while (true) { while (true) {

View File

@@ -3,23 +3,29 @@
int main() { int main() {
using namespace indicators; using namespace indicators;
BlockProgressBar bar1{option::BarWidth{50}, option::ForegroundColor{Color::yellow}, BlockProgressBar bar1{option::BarWidth{50},
option::ShowElapsedTime{true}, option::ShowRemainingTime{true}, option::ForegroundColor{Color::yellow},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"Progress Bar #1 "}, option::PrefixText{"Progress Bar #1 "},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
BlockProgressBar bar2{option::BarWidth{50}, option::ForegroundColor{Color::cyan}, BlockProgressBar bar2{option::BarWidth{50},
option::ShowElapsedTime{true}, option::ShowRemainingTime{true}, option::ForegroundColor{Color::cyan},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"Progress Bar #2 "}, option::PrefixText{"Progress Bar #2 "},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
BlockProgressBar bar3{option::BarWidth{50}, option::ForegroundColor{Color::red}, BlockProgressBar bar3{option::BarWidth{50},
option::ShowElapsedTime{true}, option::ShowRemainingTime{true}, option::ForegroundColor{Color::red},
option::ShowElapsedTime{true},
option::ShowRemainingTime{true},
option::PrefixText{"Progress Bar #3 "}, option::PrefixText{"Progress Bar #3 "},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
indicators::MultiProgress<indicators::BlockProgressBar, 3> bars(bar1, bar2, bar3); indicators::MultiProgress<indicators::BlockProgressBar, 3> bars(bar1, bar2, bar3);

View File

@@ -13,8 +13,8 @@ int main() {
indicators::option::ShowElapsedTime{true}, indicators::option::ShowElapsedTime{true},
indicators::option::ShowRemainingTime{true}, indicators::option::ShowRemainingTime{true},
indicators::option::PrefixText{"Progress Bar #1 "}, indicators::option::PrefixText{"Progress Bar #1 "},
indicators::option::FontStyles{ indicators::option::FontStyles{std::vector<indicators::FontStyle>{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; indicators::FontStyle::bold}}};
indicators::ProgressBar bar2{indicators::option::BarWidth{50}, indicators::ProgressBar bar2{indicators::option::BarWidth{50},
indicators::option::Start{"["}, indicators::option::Start{"["},
@@ -26,8 +26,8 @@ int main() {
indicators::option::ShowElapsedTime{true}, indicators::option::ShowElapsedTime{true},
indicators::option::ShowRemainingTime{true}, indicators::option::ShowRemainingTime{true},
indicators::option::PrefixText{"Progress Bar #2 "}, indicators::option::PrefixText{"Progress Bar #2 "},
indicators::option::FontStyles{ indicators::option::FontStyles{std::vector<indicators::FontStyle>{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; indicators::FontStyle::bold}}};
indicators::ProgressBar bar3{indicators::option::BarWidth{50}, indicators::ProgressBar bar3{indicators::option::BarWidth{50},
indicators::option::Start{"["}, indicators::option::Start{"["},
@@ -39,8 +39,8 @@ int main() {
indicators::option::ShowElapsedTime{true}, indicators::option::ShowElapsedTime{true},
indicators::option::ShowRemainingTime{true}, indicators::option::ShowRemainingTime{true},
indicators::option::PrefixText{"Progress Bar #3 "}, indicators::option::PrefixText{"Progress Bar #3 "},
indicators::option::FontStyles{ indicators::option::FontStyles{std::vector<indicators::FontStyle>{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}}; indicators::FontStyle::bold}}};
indicators::MultiProgress<indicators::ProgressBar, 3> bars(bar1, bar2, bar3); indicators::MultiProgress<indicators::ProgressBar, 3> bars(bar1, bar2, bar3);

View File

@@ -3,17 +3,15 @@
int main() { int main() {
indicators::ProgressBar bar{ indicators::ProgressBar bar{indicators::option::BarWidth{50},
indicators::option::BarWidth{50}, indicators::option::Start{"["},
indicators::option::Start{"["}, indicators::option::Fill{""},
indicators::option::Fill{""}, indicators::option::Lead{""},
indicators::option::Lead{""}, indicators::option::Remainder{"-"},
indicators::option::Remainder{"-"}, indicators::option::End{" ]"},
indicators::option::End{" ]"}, indicators::option::ForegroundColor{indicators::Color::yellow},
indicators::option::ForegroundColor{indicators::Color::yellow}, indicators::option::FontStyles{
indicators::option::FontStyles{ std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// As configured, the bar will look like this: // As configured, the bar will look like this:
// //

View File

@@ -0,0 +1,31 @@
#include <chrono>
#include <indicators/progress_bar.hpp>
#include <thread>
using namespace indicators;
int main() {
ProgressBar bar{option::BarWidth{50},
option::ProgressType{ProgressType::decremental},
option::Start{"["},
option::Fill{""},
option::Lead{""},
option::Remainder{"-"},
option::End{"]"},
option::PostfixText{"Reverting System Restore"},
option::ForegroundColor{Color::yellow},
option::FontStyles{std::vector<FontStyle>{FontStyle::bold}}};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout << termcolor::bold << termcolor::white << "Task Failed Successfully\n"
<< termcolor::reset;
return 0;
}

View File

@@ -8,18 +8,16 @@ int main() {
// Hide cursor // Hide cursor
indicators::show_console_cursor(false); indicators::show_console_cursor(false);
indicators::ProgressBar bar{ indicators::ProgressBar bar{indicators::option::BarWidth{50},
indicators::option::BarWidth{50}, indicators::option::Start{"["},
indicators::option::Start{"["}, indicators::option::Fill{""},
indicators::option::Fill{""}, indicators::option::Lead{""},
indicators::option::Lead{""}, indicators::option::Remainder{"-"},
indicators::option::Remainder{"-"}, indicators::option::End{" ]"},
indicators::option::End{" ]"}, indicators::option::PostfixText{"Loading dependency 1/4"},
indicators::option::PostfixText{"Loading dependency 1/4"}, indicators::option::ForegroundColor{indicators::Color::cyan},
indicators::option::ForegroundColor{indicators::Color::cyan}, indicators::option::FontStyles{
indicators::option::FontStyles{ std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// Update bar state // Update bar state
bar.set_progress(10); // 10% done bar.set_progress(10); // 10% done

View File

@@ -1,7 +1,7 @@
#include <chrono> #include <chrono>
#include <indicators/progress_bar.hpp> #include <indicators/progress_bar.hpp>
#include <thread>
#include <sstream> #include <sstream>
#include <thread>
int main() { int main() {
using namespace indicators; using namespace indicators;
@@ -17,10 +17,8 @@ int main() {
option::End{"]"}, option::End{"]"},
option::PostfixText{"Getting started"}, option::PostfixText{"Getting started"},
option::ForegroundColor{indicators::Color::green}, option::ForegroundColor{indicators::Color::green},
option::FontStyles{ option::FontStyles{std::vector<indicators::FontStyle>{indicators::FontStyle::bold}},
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}, option::Stream{os}};
option::Stream{os}
};
// Update bar state // Update bar state
while (true) { while (true) {

View File

@@ -3,18 +3,16 @@
#include <thread> #include <thread>
int main() { int main() {
indicators::ProgressBar bar{ indicators::ProgressBar bar{indicators::option::BarWidth{50},
indicators::option::BarWidth{50}, indicators::option::Start{"["},
indicators::option::Start{"["}, indicators::option::Fill{"="},
indicators::option::Fill{"="}, indicators::option::Lead{">"},
indicators::option::Lead{">"}, indicators::option::Remainder{" "},
indicators::option::Remainder{" "}, indicators::option::End{" ]"},
indicators::option::End{" ]"}, indicators::option::PostfixText{"Getting started"},
indicators::option::PostfixText{"Getting started"}, indicators::option::ForegroundColor{indicators::Color::green},
indicators::option::ForegroundColor{indicators::Color::green}, indicators::option::FontStyles{
indicators::option::FontStyles{ std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// Update bar state // Update bar state
while (true) { while (true) {

View File

@@ -0,0 +1,171 @@
#include <chrono>
#include <indicators/cursor_control.hpp>
#include <indicators/indeterminate_progress_bar.hpp>
#include <indicators/progress_bar.hpp>
#include <thread>
int main() {
indicators::show_console_cursor(false);
{
// Plain old ASCII
indicators::ProgressBar bar{indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"="},
indicators::option::Lead{">"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Plain-old ASCII"},
indicators::option::ForegroundColor{indicators::Color::green},
indicators::option::FontStyles{std::vector<indicators::FontStyle>{
indicators::FontStyle::bold}}};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Unicode
indicators::ProgressBar bar{indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"驚くばかり"},
indicators::option::Lead{">"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Japanese"},
indicators::option::ForegroundColor{indicators::Color::yellow},
indicators::option::FontStyles{std::vector<indicators::FontStyle>{
indicators::FontStyle::bold}}};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Russian
indicators::ProgressBar bar{indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"Потрясающие"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Russian"},
indicators::option::ForegroundColor{indicators::Color::red},
indicators::option::FontStyles{std::vector<indicators::FontStyle>{
indicators::FontStyle::bold}}};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Greek
indicators::ProgressBar bar{indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"Φοβερός"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Greek"},
indicators::option::ForegroundColor{indicators::Color::cyan},
indicators::option::FontStyles{std::vector<indicators::FontStyle>{
indicators::FontStyle::bold}}};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Chinese
indicators::ProgressBar bar{indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"太棒了"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Chinese"},
indicators::option::ForegroundColor{indicators::Color::green},
indicators::option::FontStyles{std::vector<indicators::FontStyle>{
indicators::FontStyle::bold}}};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Emojis
indicators::ProgressBar bar{indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{"🔥"},
indicators::option::Lead{"🔥"},
indicators::option::Remainder{" "},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Emojis"},
indicators::option::ForegroundColor{indicators::Color::white},
indicators::option::FontStyles{std::vector<indicators::FontStyle>{
indicators::FontStyle::bold}}};
// Update bar state
while (true) {
bar.tick();
if (bar.is_completed())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
{
// Indeterminate progress bar
indicators::IndeterminateProgressBar bar{
indicators::option::BarWidth{50},
indicators::option::Start{"["},
indicators::option::Fill{""},
indicators::option::Lead{"載入中"},
indicators::option::End{" ]"},
indicators::option::PostfixText{"Loading Progress Bar"},
indicators::option::ForegroundColor{indicators::Color::yellow},
indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
auto job = [&bar]() {
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
bar.mark_as_completed();
};
std::thread job_completion_thread(job);
// Update bar state
while (!bar.is_completed()) {
bar.tick();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
job_completion_thread.join();
}
indicators::show_console_cursor(true);
return 0;
}

View File

@@ -12,8 +12,7 @@ int main() {
indicators::option::SpinnerStates{ indicators::option::SpinnerStates{
std::vector<std::string>{"", "", "", "", "", "", "", ""}}, std::vector<std::string>{"", "", "", "", "", "", "", ""}},
indicators::option::FontStyles{ indicators::option::FontStyles{
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}} std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
};
// Update spinner state // Update spinner state
auto job = [&spinner]() { auto job = [&spinner]() {

View File

@@ -7,20 +7,18 @@ int main() {
// Hide cursor // Hide cursor
indicators::show_console_cursor(false); indicators::show_console_cursor(false);
indicators::ProgressBar bar{ indicators::ProgressBar bar{indicators::option::BarWidth{50},
indicators::option::BarWidth{50}, indicators::option::Start{" ["},
indicators::option::Start{" ["}, indicators::option::Fill{""},
indicators::option::Fill{""}, indicators::option::Lead{""},
indicators::option::Lead{""}, indicators::option::Remainder{"-"},
indicators::option::Remainder{"-"}, indicators::option::End{"]"},
indicators::option::End{"]"}, indicators::option::PrefixText{"Training Gaze Network 👀"},
indicators::option::PrefixText{"Training Gaze Network 👀"}, indicators::option::ForegroundColor{indicators::Color::yellow},
indicators::option::ForegroundColor{indicators::Color::yellow}, indicators::option::ShowElapsedTime{true},
indicators::option::ShowElapsedTime{true}, indicators::option::ShowRemainingTime{true},
indicators::option::ShowRemainingTime{true}, indicators::option::FontStyles{
indicators::option::FontStyles{ std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}};
std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}
};
// Update bar state // Update bar state
while (true) { while (true) {

View File

@@ -4,6 +4,7 @@
"sources": [ "sources": [
"include/indicators/color.hpp", "include/indicators/color.hpp",
"include/indicators/font_style.hpp", "include/indicators/font_style.hpp",
"include/indicators/progress_type.hpp",
"include/indicators/termcolor.hpp", "include/indicators/termcolor.hpp",
"include/indicators/terminal_size.hpp", "include/indicators/terminal_size.hpp",
"include/indicators/setting.hpp", "include/indicators/setting.hpp",

File diff suppressed because it is too large Load Diff

View File

@@ -92,9 +92,9 @@ class Amalgamation(object):
# actual_path = self.actual_path(file_path) # actual_path = self.actual_path(file_path)
print(" - processing \"{0}\"".format(file_path)) print(" - processing \"{0}\"".format(file_path))
t = TranslationUnit(file_path, self, True) t = TranslationUnit(file_path, self, True)
amalgamation += t.content amalgamation += t.content + "\n\n"
with open(self.target, 'w') as f: with open(self.target, 'w', encoding="utf8") as f:
f.write(amalgamation) f.write(amalgamation)
print("...done!\n") print("...done!\n")
@@ -262,7 +262,7 @@ class TranslationUnit(object):
actual_path = self.amalgamation.actual_path(file_path) actual_path = self.amalgamation.actual_path(file_path)
if not os.path.isfile(actual_path): if not os.path.isfile(actual_path):
raise IOError("File not found: \"{0}\"".format(file_path)) raise IOError("File not found: \"{0}\"".format(file_path))
with open(actual_path, 'r') as f: with open(actual_path, 'r', encoding="utf8") as f:
self.content = f.read() self.content = f.read()
self._process() self._process()