From 0939406db45ef678ac7cd6b66bcba1e3a01240f9 Mon Sep 17 00:00:00 2001 From: hyperxor Date: Tue, 21 Jan 2020 07:49:47 +0300 Subject: [PATCH] Extract progress scale writing code into separate classes --- include/indicators/block_progress_bar.hpp | 26 ++------ include/indicators/details/stream_helper.hpp | 70 +++++++++++++++++++- include/indicators/progress_bar.hpp | 19 +++--- include/indicators/progress_spinner.hpp | 4 +- 4 files changed, 84 insertions(+), 35 deletions(-) diff --git a/include/indicators/block_progress_bar.hpp b/include/indicators/block_progress_bar.hpp index 5b82e33..1f0a05d 100644 --- a/include/indicators/block_progress_bar.hpp +++ b/include/indicators/block_progress_bar.hpp @@ -26,20 +26,18 @@ SOFTWARE. */ #pragma once +#include #include #define NOMINMAX #include #include #include -#include -#include #include #include #include #include #include -#include namespace indicators { @@ -124,9 +122,6 @@ private: size_t _bar_width{100}; std::string _prefix_text{""}; std::string _start{"["}; - std::string _fill{"█"}; - std::string _lead{" "}; - std::string _remainder{" "}; std::string _end{"]"}; std::string _postfix_text{""}; std::atomic _max_postfix_text_length{0}; @@ -165,19 +160,8 @@ private: std::cout << _prefix_text; std::cout << _start; - std::vector lead_characters{" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"}; - auto progress = std::min(1.0f, std::max(0.0f, _progress / 100.0f)); - auto whole_width = std::floor(progress * _bar_width); - auto remainder_width = fmod((progress * _bar_width), 1.0f); - auto part_width = std::floor(remainder_width * lead_characters.size()); - _lead = lead_characters[size_t(part_width)]; - if ((_bar_width - whole_width - 1) < 0) - _lead = ""; - for (size_t i = 0; i < whole_width; ++i) - std::cout << _fill; - std::cout << _lead; - for (size_t i = 0; i < (_bar_width - whole_width - 1); ++i) - std::cout << " "; + details::BlockProgressScaleWriter writer{std::cout, _bar_width}; + writer.write(_progress); std::cout << _end; if (_show_percentage) { @@ -186,7 +170,7 @@ private: if (_show_elapsed_time) { std::cout << " ["; - details::print_duration(std::cout, elapsed); + details::write_duration(std::cout, elapsed); } if (_show_remaining_time) { @@ -197,7 +181,7 @@ private: auto eta = std::chrono::nanoseconds( _progress > 0 ? static_cast(elapsed.count() * 100 / _progress) : 0); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); - details::print_duration(std::cout, remaining); + details::write_duration(std::cout, remaining); std::cout << "]"; } else { if (_show_elapsed_time) diff --git a/include/indicators/details/stream_helper.hpp b/include/indicators/details/stream_helper.hpp index 0922437..c68346e 100644 --- a/include/indicators/details/stream_helper.hpp +++ b/include/indicators/details/stream_helper.hpp @@ -3,11 +3,15 @@ #include #include +#include #include #include #include +#include +#include #include +#include namespace indicators { namespace details { @@ -43,7 +47,7 @@ inline void set_stream_color(std::ostream &os, Color color) { } } -std::ostream &print_duration(std::ostream &os, std::chrono::nanoseconds ns) { +inline std::ostream &write_duration(std::ostream &os, std::chrono::nanoseconds ns) { using namespace std; using namespace std::chrono; using days = duration>; @@ -65,5 +69,69 @@ std::ostream &print_duration(std::ostream &os, std::chrono::nanoseconds ns) { return os; }; +class BlockProgressScaleWriter +{ +public: + BlockProgressScaleWriter(std::ostream& os, size_t bar_width) + : os(os) + , bar_width(bar_width) + {} + + std::ostream &write(float progress) { + std::string fill_text{"█"}; + std::vector lead_characters{" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"}; + auto value = std::min(1.0f, std::max(0.0f, progress / 100.0f)); + auto whole_width = std::floor(value * bar_width); + auto remainder_width = fmod((value * bar_width), 1.0f); + auto part_width = std::floor(remainder_width * lead_characters.size()); + std::string lead_text = lead_characters[size_t(part_width)]; + if ((bar_width - whole_width - 1) < 0) + lead_text = ""; + for (size_t i = 0; i < whole_width; ++i) + os << fill_text; + os << lead_text; + for (size_t i = 0; i < (bar_width - whole_width - 1); ++i) + os << " "; + } +private: + std::ostream& os; + size_t bar_width = 0; +}; + +class ProgressScaleWriter +{ +public: + ProgressScaleWriter(std::ostream& os, + size_t bar_width, + std::string fill, + std::string lead, + std::string remainder) + : os(os) + , bar_width(bar_width) + , fill(fill) + , lead(lead) + , remainder(remainder) + {} + + std::ostream &write(float progress) { + auto pos = static_cast(progress * static_cast(bar_width) / 100.0); + for (size_t i = 0; i < bar_width; ++i) { + if (i < pos) + std::cout << fill; + else if (i == pos) + std::cout << lead; + else + std::cout << remainder; + } + } + +private: + std::ostream& os; + size_t bar_width = 0; + std::string fill; + std::string lead; + std::string remainder; +}; + } } \ No newline at end of file diff --git a/include/indicators/progress_bar.hpp b/include/indicators/progress_bar.hpp index f4d7e86..5cbc9fb 100644 --- a/include/indicators/progress_bar.hpp +++ b/include/indicators/progress_bar.hpp @@ -177,24 +177,21 @@ private: std::cout << termcolor::bold; details::set_stream_color(std::cout, _foreground_color); std::cout << _prefix_text; + std::cout << _start; - auto pos = static_cast(_progress * static_cast(_bar_width) / 100.0); - for (size_t i = 0; i < _bar_width; ++i) { - if (i < pos) - std::cout << _fill; - else if (i == pos) - std::cout << _lead; - else - std::cout << _remainder; - } + + details::ProgressScaleWriter writer{std::cout, _bar_width, _fill, _lead, _remainder}; + writer.write(_progress); + std::cout << _end; + if (_show_percentage) { std::cout << " " << std::min(static_cast(_progress), size_t(100)) << "%"; } if (_show_elapsed_time) { std::cout << " ["; - details::print_duration(std::cout, elapsed); + details::write_duration(std::cout, elapsed); } if (_show_remaining_time) { @@ -205,7 +202,7 @@ private: auto eta = std::chrono::nanoseconds( _progress > 0 ? static_cast(elapsed.count() * 100 / _progress) : 0); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); - details::print_duration(std::cout, remaining); + details::write_duration(std::cout, remaining); std::cout << "]"; } else { if (_show_elapsed_time) diff --git a/include/indicators/progress_spinner.hpp b/include/indicators/progress_spinner.hpp index 55033c9..c8f1c5e 100644 --- a/include/indicators/progress_spinner.hpp +++ b/include/indicators/progress_spinner.hpp @@ -153,7 +153,7 @@ private: if (_show_elapsed_time) { std::cout << " ["; - details::print_duration(std::cout, elapsed); + details::write_duration(std::cout, elapsed); } if (_show_remaining_time) { @@ -164,7 +164,7 @@ private: auto eta = std::chrono::nanoseconds( _progress > 0 ? static_cast(elapsed.count() * 100 / _progress) : 0); auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); - details::print_duration(std::cout, remaining); + details::write_duration(std::cout, remaining); std::cout << "]"; } else { if (_show_elapsed_time)