From d4a38eb034fad6fdfb707df5d1b8e3c482323cf3 Mon Sep 17 00:00:00 2001
From: Pranav Srinivas Kumar
Date: Sat, 22 Feb 2020 11:02:16 +0530
Subject: [PATCH 1/2] Closes 25 - Changed to
---
README.md | 2 +-
include/indicators/details/stream_helper.hpp | 4 ++--
include/indicators/dynamic_progress.hpp | 2 +-
include/indicators/multi_progress.hpp | 7 +++++++
include/indicators/progress_bar.hpp | 14 +++++++-------
include/indicators/progress_spinner.hpp | 10 +++++-----
6 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index 5c4d580..528ce9f 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,7 @@ To introduce a progress bar in your application, include `indicators/progress_ba
^^^^^^^^^^^^^ Bar Width ^^^^^^^^^^^^^^^
```
-The amount of progress in ProgressBar is maintained as a float in range `[0, 100]`. When progress reaches 100, the progression is complete.
+The amount of progress in ProgressBar is maintained as a size_t in range `[0, 100]`. When progress reaches 100, the progression is complete.
From application-level code, there are two ways in which you can update this progress:
diff --git a/include/indicators/details/stream_helper.hpp b/include/indicators/details/stream_helper.hpp
index d85c2e9..eececed 100644
--- a/include/indicators/details/stream_helper.hpp
+++ b/include/indicators/details/stream_helper.hpp
@@ -102,8 +102,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;
diff --git a/include/indicators/dynamic_progress.hpp b/include/indicators/dynamic_progress.hpp
index bc8f8a7..f97a7aa 100644
--- a/include/indicators/dynamic_progress.hpp
+++ b/include/indicators/dynamic_progress.hpp
@@ -123,7 +123,7 @@ private:
for (size_t i = 0; i < total_count_; ++i)
std::cout << "\x1b[A";
}
- for (auto &bar: bars_) {
+ for (auto &bar : bars_) {
bar.get().print_progress(true);
std::cout << "\n";
}
diff --git a/include/indicators/multi_progress.hpp b/include/indicators/multi_progress.hpp
index ae8065f..41c4e86 100644
--- a/include/indicators/multi_progress.hpp
+++ b/include/indicators/multi_progress.hpp
@@ -45,6 +45,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())
diff --git a/include/indicators/progress_bar.hpp b/include/indicators/progress_bar.hpp
index 200eac5..4959755 100644
--- a/include/indicators/progress_bar.hpp
+++ b/include/indicators/progress_bar.hpp
@@ -126,9 +126,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;
}
@@ -147,7 +147,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(); }
@@ -169,7 +169,7 @@ 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_;
@@ -192,7 +192,7 @@ 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;
@@ -217,7 +217,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()) {
@@ -246,7 +246,7 @@ private:
<< std::string(get_value(), ' ')
<< "\r";
std::cout.flush();
- if (progress_ > 100.0) {
+ if (progress_ > 100) {
get_value() = true;
}
if (get_value() &&
diff --git a/include/indicators/progress_spinner.hpp b/include/indicators/progress_spinner.hpp
index 9a4d7c2..a69c316 100644
--- a/include/indicators/progress_spinner.hpp
+++ b/include/indicators/progress_spinner.hpp
@@ -119,7 +119,7 @@ public:
}
}
- void set_progress(float value) {
+ void set_progress(size_t value) {
{
std::lock_guard lock{mutex_};
progress_ = value;
@@ -139,7 +139,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(); }
@@ -151,7 +151,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_;
@@ -189,7 +189,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()) {
@@ -219,7 +219,7 @@ private:
<< "\r";
std::cout.flush();
index_ += 1;
- if (progress_ > 100.0) {
+ if (progress_ > 100) {
get_value() = true;
}
if (get_value())
From 201ce9c4fb669049402ccd1b4bb4e1a9ed236b23 Mon Sep 17 00:00:00 2001
From: Pranav Srinivas Kumar
Date: Sat, 22 Feb 2020 11:13:04 +0530
Subject: [PATCH 2/2] 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 @@
-
+
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