44
55#include < indicators/color.hpp>
66#include < indicators/details/stream_helper.hpp>
7+ #include < indicators/cursor_control.hpp>
78
89#include < algorithm>
910#include < atomic>
1213#include < indicators/terminal_size.hpp>
1314#include < iomanip>
1415#include < iostream>
15- #include < sstream>
1616#include < mutex>
17+ #include < sstream>
1718#include < string>
1819#include < thread>
1920#include < tuple>
@@ -33,7 +34,7 @@ class BlockProgressBar {
3334 typename std::enable_if<details::are_settings_from_tuple<
3435 Settings, typename std::decay<Args>::type...>::value,
3536 void *>::type = nullptr >
36- explicit BlockProgressBar (Args &&... args)
37+ explicit BlockProgressBar (Args &&...args)
3738 : settings_(details::get<details::ProgressBarOption::foreground_color>(
3839 option::ForegroundColor{Color::unspecified}, std::forward<Args>(args)...),
3940 details::get<details::ProgressBarOption::bar_width>(option::BarWidth{100 },
@@ -123,7 +124,7 @@ class BlockProgressBar {
123124 size_t current () {
124125 std::lock_guard<std::mutex> lock{mutex_};
125126 return (std::min)(static_cast <size_t >(progress_),
126- size_t (get_value<details::ProgressBarOption::max_progress>()));
127+ size_t (get_value<details::ProgressBarOption::max_progress>()));
127128 }
128129
129130 bool is_completed () const { return get_value<details::ProgressBarOption::completed>(); }
@@ -133,22 +134,28 @@ class BlockProgressBar {
133134 print_progress ();
134135 }
135136
137+ size_t extra_wrapped_lines () {
138+ std::lock_guard<std::mutex> lock{mutex_};
139+ return extra_wrapped_lines_;
140+ }
141+
136142private:
137143 template <details::ProgressBarOption id>
138144 auto get_value () -> decltype((details::get_value<id>(std::declval<Settings &>()).value)) {
139145 return details::get_value<id>(settings_).value ;
140146 }
141147
142148 template <details::ProgressBarOption id>
143- auto get_value () const
144- -> decltype((details::get_value<id>(std::declval<const Settings &>()).value)) {
149+ auto
150+ get_value () const -> decltype ((details::get_value<id>(std::declval<const Settings &>()).value)) {
145151 return details::get_value<id>(settings_).value ;
146152 }
147153
148154 Settings settings_;
149155 float progress_{0.0 };
150156 std::chrono::time_point<std::chrono::high_resolution_clock> start_time_point_;
151157 std::mutex mutex_;
158+ size_t extra_wrapped_lines_{0 };
152159
153160 template <typename Indicator, size_t count> friend class MultiProgress ;
154161 template <typename Indicator> friend class DynamicProgress ;
@@ -201,10 +208,9 @@ class BlockProgressBar {
201208
202209 if (saved_start_time) {
203210 auto eta = std::chrono::nanoseconds (
204- progress_ > 0
205- ? static_cast <long long >(std::ceil (float (elapsed.count ()) *
206- max_progress / progress_))
207- : 0 );
211+ progress_ > 0 ? static_cast <long long >(
212+ std::ceil (float (elapsed.count ()) * max_progress / progress_))
213+ : 0 );
208214 auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta);
209215 details::write_duration (os, remaining);
210216 } else {
@@ -244,6 +250,10 @@ class BlockProgressBar {
244250 for (auto &style : get_value<details::ProgressBarOption::font_styles>())
245251 details::set_font_style (os, style);
246252
253+ // Need to erase previously written text across multiple lines to solve
254+ // issue https://github.com/p-ranav/indicators/issues/132
255+ erase_lines (extra_wrapped_lines_);
256+
247257 const auto prefix_pair = get_prefix_text ();
248258 const auto prefix_text = prefix_pair.first ;
249259 const auto prefix_length = prefix_pair.second ;
@@ -267,17 +277,19 @@ class BlockProgressBar {
267277 const auto bar_width = get_value<details::ProgressBarOption::bar_width>();
268278 const auto end_length = get_value<details::ProgressBarOption::end>().size ();
269279 const auto terminal_width = terminal_size ().second ;
270- // prefix + bar_width + postfix should be <= terminal_width
271- const int remaining = terminal_width - (prefix_length + start_length + bar_width + end_length + postfix_length);
280+ const auto number_of_characters =
281+ prefix_length + start_length + bar_width + end_length + postfix_length;
282+ // If prefix + bar_width + postfix > terminal_width, lines will be wrapped
283+ const int remaining = terminal_width - number_of_characters;
272284 if (prefix_length == -1 || postfix_length == -1 ) {
273285 os << " \r " ;
274286 } else if (remaining > 0 ) {
275287 os << std::string (remaining, ' ' ) << " \r " ;
276- } else if (remaining < 0 ) {
277- // Do nothing. Maybe in the future truncate postfix with ...
278288 }
279289 os.flush ();
280290
291+ extra_wrapped_lines_ = details::extra_wrapped_lines (number_of_characters);
292+
281293 if (progress_ > max_progress) {
282294 get_value<details::ProgressBarOption::completed>() = true ;
283295 }
0 commit comments