From 201ce9c4fb669049402ccd1b4bb4e1a9ed236b23 Mon Sep 17 00:00:00 2001 From: Pranav Srinivas Kumar Date: Sat, 22 Feb 2020 11:13:04 +0530 Subject: [PATCH] Bumped to v1.8 --- CMakeLists.txt | 2 +- README.md | 2 +- single_include/indicators/indicators.hpp | 199 ++++++++++++++++++----- 3 files changed, 159 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 528bcfd..3965793 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ if(DEFINED PROJECT_NAME) set(INDICATORS_SUBPROJECT ON) endif() -project(indicators VERSION 1.7.0 LANGUAGES CXX +project(indicators VERSION 1.8.0 LANGUAGES CXX HOMEPAGE_URL "https://github.com/p-ranav/indicators" DESCRIPTION "Activity Indicators for Modern C++") diff --git a/README.md b/README.md index 528ce9f..1389b77 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ license - version + version

diff --git a/single_include/indicators/indicators.hpp b/single_include/indicators/indicators.hpp index 42453cb..be0e964 100644 --- a/single_include/indicators/indicators.hpp +++ b/single_include/indicators/indicators.hpp @@ -502,6 +502,8 @@ inline void win_change_attributes(std::ostream &stream, int foreground, int back #endif // TERMCOLOR_HPP_ +// details/stream_helper.hpp + namespace indicators { namespace details { @@ -591,8 +593,8 @@ public: const std::string &lead, const 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); + std::ostream &write(size_t progress) { + auto pos = static_cast(progress * bar_width / 100.0); for (size_t i = 0; i < bar_width; ++i) { if (i < pos) os << fill; @@ -615,32 +617,9 @@ private: } // namespace details } // namespace indicators -/* -Activity Indicators for Modern C++ -https://github.com/p-ranav/indicators - -Licensed under the MIT License . -SPDX-License-Identifier: MIT -Copyright (c) 2019 Dawid Pilarski . - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ +// +// setting.hpp +// namespace indicators { @@ -695,7 +674,8 @@ enum class ProgressBarOption { saved_start_time, foreground_color, spinner_show, - spinner_states + spinner_states, + hide_bar_when_complete }; template struct Setting { @@ -806,9 +786,15 @@ using ForegroundColor = details::Setting; using SpinnerStates = details::Setting, details::ProgressBarOption::spinner_states>; +using HideBarWhenComplete = + details::BooleanSetting; } // namespace option } // namespace indicators +// +// progress_bar.hpp +// + namespace indicators { class ProgressBar { @@ -893,9 +879,9 @@ public: } } - void set_progress(float new_progress) { + void set_progress(size_t new_progress) { { - std::lock_guard lck(mutex_); + std::lock_guard lock(mutex_); progress_ = new_progress; } @@ -914,7 +900,7 @@ public: size_t current() { std::lock_guard lock{mutex_}; - return std::min(static_cast(progress_), size_t(100)); + return std::min(progress_, size_t(100)); } bool is_completed() const { return get_value(); } @@ -936,13 +922,14 @@ private: return details::get_value(settings_).value; } - float progress_{0}; + size_t progress_{0}; Settings settings_; std::chrono::nanoseconds elapsed_; std::chrono::time_point start_time_point_; std::mutex mutex_; template friend class MultiProgress; + template friend class DynamicProgress; std::atomic multi_progress_mode_{false}; void save_start_time() { @@ -956,13 +943,13 @@ private: } void print_progress(bool from_multi_progress = false) { + std::lock_guard lock{mutex_}; if (multi_progress_mode_ && !from_multi_progress) { - if (progress_ > 100.0) { + if (progress_ > 100) { get_value() = true; } return; } - std::lock_guard lock{mutex_}; auto now = std::chrono::high_resolution_clock::now(); if (!get_value()) elapsed_ = std::chrono::duration_cast(now - start_time_point_); @@ -983,7 +970,7 @@ private: std::cout << get_value(); if (get_value()) { - std::cout << " " << std::min(static_cast(progress_), size_t(100)) << "%"; + std::cout << " " << std::min(progress_, size_t(100)) << "%"; } if (get_value()) { @@ -1012,7 +999,7 @@ private: << std::string(get_value(), ' ') << "\r"; std::cout.flush(); - if (progress_ > 100.0) { + if (progress_ > 100) { get_value() = true; } if (get_value() && @@ -1023,6 +1010,10 @@ private: } // namespace indicators +// +// block_progress_bar.hpp +// + namespace indicators { class BlockProgressBar { @@ -1147,6 +1138,7 @@ private: std::mutex mutex_; template friend class MultiProgress; + template friend class DynamicProgress; std::atomic multi_progress_mode_{false}; void save_start_time() { @@ -1221,6 +1213,10 @@ private: } // namespace indicators +// +// progress_spinner.hpp +// + namespace indicators { class ProgressSpinner { @@ -1298,7 +1294,7 @@ public: } } - void set_progress(float value) { + void set_progress(size_t value) { { std::lock_guard lock{mutex_}; progress_ = value; @@ -1318,7 +1314,7 @@ public: size_t current() { std::lock_guard lock{mutex_}; - return std::min(static_cast(progress_), size_t(100)); + return std::min(progress_, size_t(100)); } bool is_completed() const { return get_value(); } @@ -1330,7 +1326,7 @@ public: private: Settings settings_; - float progress_{0.0}; + size_t progress_{0}; size_t index_{0}; std::chrono::time_point start_time_point_; std::mutex mutex_; @@ -1368,7 +1364,7 @@ private: std::cout << get_value() [index_ % get_value().size()]; if (get_value()) { - std::cout << " " << std::min(static_cast(progress_), size_t(100)) << "%"; + std::cout << " " << std::min(progress_, size_t(100)) << "%"; } if (get_value()) { @@ -1398,7 +1394,7 @@ private: << "\r"; std::cout.flush(); index_ += 1; - if (progress_ > 100.0) { + if (progress_ > 100) { get_value() = true; } if (get_value()) @@ -1408,6 +1404,10 @@ private: } // namespace indicators +// +// multi_progress.hpp +// + namespace indicators { template class MultiProgress { @@ -1421,6 +1421,13 @@ public: } } + template + typename std::enable_if<(index >= 0 && index < count), void>::type set_progress(size_t value) { + if (!bars_[index].get().is_completed()) + bars_[index].get().set_progress(value); + print_progress(); + } + template typename std::enable_if<(index >= 0 && index < count), void>::type set_progress(float value) { if (!bars_[index].get().is_completed()) @@ -1468,3 +1475,111 @@ private: }; } // namespace indicators + +// +// dynamic_progress.hpp +// + +namespace indicators { + +template class DynamicProgress { + using Settings = std::tuple; + +public: + template explicit DynamicProgress(Indicators &... bars) { + bars_ = {bars...}; + for (auto &bar : bars_) { + bar.get().multi_progress_mode_ = true; + ++total_count_; + ++incomplete_count_; + } + } + + Indicator &operator[](size_t index) { + print_progress(); + std::lock_guard lock{mutex_}; + return bars_[index].get(); + } + + size_t push_back(Indicator &bar) { + std::lock_guard lock{mutex_}; + bar.multi_progress_mode_ = true; + bars_.push_back(bar); + return bars_.size() - 1; + } + + template + void set_option(details::Setting &&setting) { + static_assert(!std::is_same( + std::declval()))>::type>::value, + "Setting has wrong type!"); + std::lock_guard lock(mutex_); + get_value() = std::move(setting).value; + } + + template + void set_option(const details::Setting &setting) { + static_assert(!std::is_same( + std::declval()))>::type>::value, + "Setting has wrong type!"); + std::lock_guard lock(mutex_); + get_value() = setting.value; + } + +private: + Settings settings_; + std::atomic started_{false}; + std::mutex mutex_; + std::vector> bars_; + std::atomic total_count_{0}; + std::atomic incomplete_count_{0}; + + template + auto get_value() -> decltype((details::get_value(std::declval()).value)) { + return details::get_value(settings_).value; + } + + template + auto get_value() const + -> decltype((details::get_value(std::declval()).value)) { + return details::get_value(settings_).value; + } + + void print_progress() { + std::lock_guard lock{mutex_}; + auto &hide_bar_when_complete = get_value(); + if (hide_bar_when_complete) { + // Hide completed bars + if (started_) { + for (size_t i = 0; i < incomplete_count_; ++i) + std::cout << "\033[A\r\033[K" << std::flush; + } + incomplete_count_ = 0; + for (auto &bar : bars_) { + if (!bar.get().is_completed()) { + bar.get().print_progress(true); + std::cout << "\n"; + ++incomplete_count_; + } + } + if (!started_) + started_ = true; + } else { + // Don't hide any bars + if (started_) { + for (size_t i = 0; i < total_count_; ++i) + std::cout << "\x1b[A"; + } + for (auto &bar : bars_) { + bar.get().print_progress(true); + std::cout << "\n"; + } + if (!started_) + started_ = true; + } + total_count_ = bars_.size(); + std::cout << termcolor::reset; + } +}; + +} // namespace indicators