osmanip
Library with useful output stream tools like: color and style manipulators, progress bars and terminal graphics.
progress_bar.hpp
Go to the documentation of this file.
1 //====================================================
2 // File data
3 //====================================================
13 //====================================================
14 // Preprocessor settings
15 //====================================================
16 #pragma once
17 #ifndef OSMANIP_PROGRESSBAR_PROGRESSBAR_HPP
18 #define OSMANIP_PROGRESSBAR_PROGRESSBAR_HPP
19 
20 //====================================================
21 // Headers
22 //====================================================
23 
24 // My headers
30 
31 // STD headers
32 #include <stdint.h>
33 
34 #include <chrono>
35 #include <cmath>
36 #include <mutex>
37 #include <ratio>
38 #include <stdexcept>
39 #include <string>
40 #include <unordered_map>
41 #include <unordered_set>
42 #include <vector>
43 
44 namespace osm {
45 
46  //====================================================
47  // Aliases
48  //====================================================
49  using string_set_map = std::unordered_map<std::string, std::unordered_set<std::string>>;
51  using duration = std::chrono::duration<float, steady_clock::period>;
52 
53  //====================================================
54  // ProgressBar
55  //====================================================
63  template <typename bar_type>
64  class ProgressBar {
65  public:
66 
67  //====================================================
68  // Constructors and destructors
69  //====================================================
70 
71  // Default constructor
79  : max_(0),
80  min_(0),
81  style_(""),
82  type_(""),
83  message_(""),
84  time_count_(duration::zero().count()),
85  brackets_open_(""),
86  brackets_close_(""),
87  begin_timer(steady_clock::now()),
88  color_(feat(rst, "color")),
89  color_name_(""),
90  ticks_occurred(0),
91  time_flag_("off") {}
92 
93  // Parametric constructor
103  explicit ProgressBar(const bar_type &min, const bar_type &max)
104  : max_(max),
105  min_(min),
106  style_(""),
107  type_(""),
108  message_(""),
109  time_count_(duration::zero().count()),
110  brackets_open_(""),
111  brackets_close_(""),
112  begin_timer(steady_clock::now()),
113  color_(feat(rst, "color")),
114  color_name_(""),
115  ticks_occurred(0),
116  time_flag_("off") {}
117 
118  //====================================================
119  // Setters
120  //====================================================
121 
122  // setMax
129  void setMax(bar_type max) { max_ = max; }
130 
131  // setMin
138  void setMin(bar_type min) { min_ = min; }
139 
140  // setStyle first overload
149  void setStyle(const std::string &type, const std::string &style) {
150  try {
151  if (styles_map_.at(type).find(style) != styles_map_.at(type).end()) {
152  style_ = style;
153  type_ = type;
154  } else if (styles_map_.at(type).find(style) == styles_map_.at(type).end()) {
156  "Inserted "
157  "ProgressBar "
158  "style",
159  style,
160  "is not "
161  "supported for "
162  "this type!");
163  } else {
165  "Inserted "
166  "ProgressBar "
167  "type",
168  type,
169  "is not "
170  "supported!");
171  }
172  } catch (std::out_of_range const &exception) {
174  "Inserted ProgressBar "
175  "type",
176  type, "is not supported!");
177  }
178  }
179 
180  // setStyle second overload
190  void setStyle(const std::string &type, const std::string &style_p, const std::string &style_l) {
191  if (styles_map_.at("indicator").find(style_p) != styles_map_.at("indicator").end() &&
192  styles_map_.at("loader").find(style_l) != styles_map_.at("loader").end() && type == "complete") {
193  style_ = style_p + style_l;
194  style_p_ = style_p;
195  style_l_ = style_l;
196  type_ = type;
197  } else if (styles_map_.at("indicator").find(style_p) == styles_map_.at("indicator").end()) {
199  "Inserted indicator "
200  "style",
201  style_p,
202  "is not supported for "
203  "this type!");
204  } else if (styles_map_.at("loader").find(style_l) == styles_map_.at("loader").end()) {
205  throw osm::except_error_func("Inserted loader style", style_l,
206  "is not supported for "
207  "this type!");
208  } else {
210  "Inserted ProgressBar "
211  "type",
212  type, "is not supported!");
213  }
214  }
215 
216  // setMessage
223  void setMessage(std::string_view message) { message_ = message; }
224 
225  // setBegin
231  void setBegin() { begin = steady_clock::now(); }
232 
233  // setEnd
239  void setEnd() {
240  end = steady_clock::now();
241  time_count_ += std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
242  }
243 
244  // setBrackets
252  void setBrackets(std::string_view brackets_open, std::string_view brackets_close) {
253  brackets_open_ = brackets_open, brackets_close_ = brackets_close;
254  }
255 
256  // setColor
263  void setColor(const std::string &color) {
264  color_ = feat(col, color);
265  color_name_ = color;
266  }
267 
268  // setRemainingTimeFlag
275  void setRemainingTimeFlag(std::string_view time_flag) { time_flag_ = time_flag; }
276 
277  //====================================================
278  // Resetters
279  //====================================================
280 
281  // resetAll
287  void resetAll() {
288  max_ = static_cast<bar_type>(0), min_ = static_cast<bar_type>(0), style_ = "", type_ = "",
289  message_ = "", time_count_ = 0, ticks_occurred = 0, begin_timer = steady_clock::now(),
290  brackets_open_ = "", brackets_close_ = "", color_ = feat(rst, "color");
291  color_name_ = "";
292  time_flag_ = "off";
293  }
294 
295  // resetMax
301  void resetMax() { max_ = static_cast<bar_type>(0); }
302 
303  // resetMin
309  void resetMin() { min_ = static_cast<bar_type>(0); }
310 
311  // resetStyle
317  void resetStyle() {
318  style_.clear();
319  type_.clear();
320  }
321 
322  // resetMessage
328  void resetMessage() { message_.clear(); }
329 
330  // resetTime
336  void resetTime() { time_count_ = duration::zero().count(); }
337 
338  // resetRemainingTime
345  ticks_occurred = 0;
346  begin_timer = steady_clock::now();
347  }
348 
349  // resetBrackets
355  void resetBrackets() { brackets_open_.clear(), brackets_close_.clear(); }
356 
357  // resetColor
363  void resetColor() {
364  color_ = feat(rst, "color");
365  color_name_ = "";
366  }
367 
368  //====================================================
369  // Getters
370  //====================================================
371 
372  // getMax
379  bar_type getMax() const { return max_; }
380 
381  // getMin
388  bar_type getMin() const { return min_; }
389 
390  // getTime
397  long long getTime() const { return time_count_; }
398 
399  // getIteratingVar
406  bar_type getIteratingVar() const { return iterating_var_; }
407 
408  // getStyle
415  std::string getStyle() const { return style_; }
416 
417  // getStyleComplete
424  std::string getStyleComplete() const {
425  if (type_ == "complete") {
426  return "Percentage: \"" + style_p_ + "\"\n" + "Loader: \"" + style_l_ + "\"\n";
427  }
428  return style_;
429  }
430 
431  // getType
438  std::string getType() const { return type_; }
439 
440  // getMessage
447  std::string getMessage() const { return message_; }
448 
449  // getBrackets_open
456  std::string getBrackets_open() const { return brackets_open_; }
457 
458  // getBrackets_close
465  std::string getBrackets_close() const { return brackets_close_; }
466 
467  // getColor
474  std::string getColor() const { return color_; }
475 
476  // getColorName
483  std::string getColorName() const { return color_name_; }
484 
485  // getRemainingTimeFlag
492  std::string getRemainingTimeFlag() const { return time_flag_; }
493 
494  //====================================================
495  // Other methods
496  //====================================================
497 
498  // update
505  void update(bar_type iterating_var) {
506  std::lock_guard<std::mutex> lock{mutex_};
507 
508  iterating_var_ = 100 * (iterating_var - min_) / (max_ - min_ - osm::one(iterating_var)),
509  iterating_var_spin_ =
510  osm::isFloatingPoint(iterating_var) ? (osm::roundoff(iterating_var, 1) * 10) : iterating_var,
511  width_ = (iterating_var_ + 1) / 4;
512 
513  // Update of the progress indicator only:
514  if (styles_map_.at("indicator").find(style_) != styles_map_.at("indicator").end()) {
515  output_ = feat(crs, "left", 100) + getColor() +
516  std::to_string(static_cast<int32_t>(round(iterating_var_++))) + feat(rst, "color") +
517  getStyle();
518 
519  update_output(output_);
520  }
521 
522  // Update of the loader indicator only:
523  else if (styles_map_.at("loader").find(style_) != styles_map_.at("loader").end()) {
524  output_ =
525  feat(crs, "left", 100) + getBrackets_open() + getColor() + getStyle() * width_ +
526  osm::empty_space<std::string> * ((osm::isFloatingPoint(iterating_var) ? 26 : 25) - width_) +
527  feat(rst, "color") + getBrackets_close();
528 
529  update_output(output_);
530  }
531 
532  // Update of the whole progress bar:
533  else if (style_.find(style_p_) != std::string::npos && style_.find(style_l_) != std::string::npos &&
534  type_ == "complete") {
535  output_ =
536  feat(crs, "left", 100) + getBrackets_open() + getColor() + style_l_ * width_ +
537  osm::empty_space<std::string> * ((osm::isFloatingPoint(iterating_var) ? 26 : 25) - width_) +
538  feat(rst, "color") + getBrackets_close() + getColor() + osm::empty_space<std::string> +
539  std::to_string(static_cast<int32_t>(round(iterating_var_++))) + feat(rst, "color") + style_p_;
540 
541  update_output(output_);
542  }
543 
544  // Update of the progress spinner:
545  else if (styles_map_.at("spinner").find(style_) != styles_map_.at("spinner").end()) {
546  output_ = feat(crs, "left", 100) + getColor() +
547  getStyle()[static_cast<uint64_t>(iterating_var_spin_) & 3] + feat(col, "green") +
548  ((osm::roundoff(iterating_var, 1) == osm::roundoff(max_, 1) - osm::one(iterating_var))
549  ? (static_cast<std::string>(feat(crs, "left", 100) + "0"))
550  : "") +
551  feat(rst, "color");
552 
553  update_output(output_);
554  }
555 
556  else {
557  throw std::runtime_error(
558  "ProgressBar style has "
559  "not been set!");
560  }
561  }
562 
563  // print
569  void print() const {
570  osm::cout << "Max: " << max_ << "\n"
571  << "Min: " << min_ << "\n"
572  << "Time counter: " << time_count_ << "\n"
573  << "Style: " << style_ << "\n"
574  << "Type: " << type_ << "\n"
575  << "Message: " << message_ << "\n"
576  << "Brackets style: " << brackets_open_ << brackets_close_ << "\n"
577  << "Color: " << color_name_ << "\n"
578  << "Show remaining time: " << time_flag_ << "\n";
579  }
580 
581  // addStyle
589  void addStyle(const std::string &type, const std::string &style) { styles_map_.at(type).insert(style); }
590 
591  private:
592 
593  //====================================================
594  // Private methods
595  //====================================================
596 
597  // remaining_time
604  void remaining_time() {
605  max_spin_ = osm::isFloatingPoint(max_) ? (osm::roundoff(max_ - min_, 1) * 10 + 1) : (max_ - min_ + 1);
606 
607  duration time_taken = steady_clock::now() - begin_timer;
608  float percentage_done = static_cast<float>(ticks_occurred) / (max_spin_);
609  duration time_left = time_taken * (1 / percentage_done - 1);
610  std::chrono::minutes minutes_left = std::chrono::duration_cast<std::chrono::minutes>(time_left);
611  std::chrono::seconds seconds_left =
612  std::chrono::duration_cast<std::chrono::seconds>(time_left - minutes_left);
613 
614  osm::cout << "["
615  << feat(sty, "italics") +
616  "Estimated time "
617  "left: " +
618  feat(rst, "italics")
619  << feat(col, "green") << minutes_left.count() << feat(rst, "color") << "m "
620  << feat(col, "green") << seconds_left.count() << feat(rst, "color") << "s"
621  << "]" << feat(tcsc, "cln", 0);
622  }
623 
624  // update_output
631  void update_output(std::string_view output) {
632  osm::cout << output << getColor()
633  << ((message_ != osm::null_str<std::string>)
634  ? (osm::empty_space<std::string> + message_ + osm::empty_space<std::string>)
635  : osm::empty_space<std::string>)
636  << feat(rst, "color");
637 
638  if (time_flag_ == "on") {
639  ticks_occurred++;
640  remaining_time();
641  }
642 
643  osm::cout << std::flush;
644  }
645 
646  //====================================================
647  // Private static attributes
648  //====================================================
649  static string_set_map styles_map_;
650  static std::mutex mutex_;
651 
652  //====================================================
653  // Private attributes
654  //====================================================
655  long long time_count_;
656  std::uint64_t ticks_occurred;
657  bar_type max_, max_spin_, min_, iterating_var_, iterating_var_spin_, width_;
658  std::string style_, style_p_, style_l_, type_, message_, brackets_open_, brackets_close_, output_, color_,
659  time_flag_, color_name_;
660  steady_clock::time_point begin, end, begin_timer;
661  };
662 
663  //====================================================
664  // Operator << redefinition
665  //====================================================
674  template <typename bar_type>
675  std::ostream &operator<<(std::ostream &os, const ProgressBar<bar_type> &pb) {
676  os << "Max: " << pb.getMax() << "\n"
677  << "Min: " << pb.getMin() << "\n"
678  << "Time counter: " << pb.getTime() << "\n"
679  << "Style: " << pb.getStyle() << "\n"
680  << "Type: " << pb.getType() << "\n"
681  << "Message: " << pb.getMessage() << "\n"
682  << "Brackets style: " << pb.getBrackets_open() << pb.getBrackets_close() << "\n"
683  << "Color: " << pb.getColorName() << "\n"
684  << "Show remaining time: " << pb.getRemainingTimeFlag() << "\n";
685 
686  return os;
687  }
688 
689  //====================================================
690  // Static attributes declaration
691  //====================================================
692  template <typename bar_type>
693  string_set_map ProgressBar<bar_type>::styles_map_{
694  {"indicator", {"%", "/100"}},
695  {"loader", {"#", "■"}},
696  {"spinner", {"/-\\|"}},
697  };
698 
699  template <typename bar_type>
700  std::mutex ProgressBar<bar_type>::mutex_;
701 } // namespace osm
702 
703 #endif
Template class used to create customized progress bars.
Definition: progress_bar.hpp:64
void resetTime()
Reset the ProgressBar time count.
Definition: progress_bar.hpp:336
void update(bar_type iterating_var)
Update the progress bar indicator.
Definition: progress_bar.hpp:505
void setMax(bar_type max)
Set the maximum value of the ProgressBar.
Definition: progress_bar.hpp:129
bar_type getIteratingVar() const
Get the ProgressBar iterating variable value.
Definition: progress_bar.hpp:406
void setMessage(std::string_view message)
Set the message of the ProgressBar.
Definition: progress_bar.hpp:223
void resetColor()
Reset the ProgressBar color.
Definition: progress_bar.hpp:363
void resetAll()
Reset the ProgressBar variables.
Definition: progress_bar.hpp:287
std::string getRemainingTimeFlag() const
Get the ProgressBar time remaining variable.
Definition: progress_bar.hpp:492
std::string getColorName() const
Get the ProgressBar color name variable.
Definition: progress_bar.hpp:483
std::string getMessage() const
Get the ProgressBar Message variable.
Definition: progress_bar.hpp:447
void setRemainingTimeFlag(std::string_view time_flag)
Set the remaining time of the ProgressBar.
Definition: progress_bar.hpp:275
void resetStyle()
Reset the ProgressBar Style variable.
Definition: progress_bar.hpp:317
void print() const
Prints on the screen the progress bar variable values.
Definition: progress_bar.hpp:569
std::string getBrackets_open() const
Get the ProgressBar brackets_open variable.
Definition: progress_bar.hpp:456
ProgressBar()
Construct a new ProgressBar <bar_type>::ProgressBar object. Default constructor which set to null val...
Definition: progress_bar.hpp:78
std::string getStyle() const
Get the ProgressBar Style variable.
Definition: progress_bar.hpp:415
ProgressBar(const bar_type &min, const bar_type &max)
Construct a new ProgressBar <bar_type>::ProgressBar object. Parametric constructor which set to null ...
Definition: progress_bar.hpp:103
void resetBrackets()
Reset the ProgressBar brackets.
Definition: progress_bar.hpp:355
long long getTime() const
Get the ProgressBar current time value.
Definition: progress_bar.hpp:397
void setBrackets(std::string_view brackets_open, std::string_view brackets_close)
Set brackets of the ProgressBar.
Definition: progress_bar.hpp:252
void setBegin()
Set begin time count.
Definition: progress_bar.hpp:231
std::string getBrackets_close() const
Get the ProgressBar brackets_close variable.
Definition: progress_bar.hpp:465
void addStyle(const std::string &type, const std::string &style)
Add customized styles to the ProgressBar.
Definition: progress_bar.hpp:589
void resetMin()
Reset the ProgressBar Min variable.
Definition: progress_bar.hpp:309
std::string getStyleComplete() const
Get the ProgressBar Style variable for "complete" variable type.
Definition: progress_bar.hpp:424
bar_type getMin() const
Get the ProgressBar Min variable.
Definition: progress_bar.hpp:388
void setMin(bar_type min)
Set the minimum value of the ProgressBar.
Definition: progress_bar.hpp:138
void setEnd()
Set end time count.
Definition: progress_bar.hpp:239
std::string getType() const
Get the ProgressBar Type variable.
Definition: progress_bar.hpp:438
void setColor(const std::string &color)
Set the color of the ProgressBar.
Definition: progress_bar.hpp:263
void resetRemainingTime()
Reset the ProgressBar time remaining count.
Definition: progress_bar.hpp:344
void resetMessage()
Reset the ProgressBar Message variable.
Definition: progress_bar.hpp:328
bar_type getMax() const
Get the ProgressBar Max variable.
Definition: progress_bar.hpp:379
void setStyle(const std::string &type, const std::string &style)
Set the type and style of the ProgressBar. Available: "indicator" ("%", "/100"), "loader" ("#",...
Definition: progress_bar.hpp:149
void setStyle(const std::string &type, const std::string &style_p, const std::string &style_l)
Set the style of the complete ProgressBar. Available: "indicator" ("%", "/100"), "loader" ("#",...
Definition: progress_bar.hpp:190
std::string getColor() const
Get the ProgressBar color variable.
Definition: progress_bar.hpp:474
void resetMax()
Reset the ProgressBar Max variable.
Definition: progress_bar.hpp:301
Definition: canvas.cpp:30
std::ostream & operator<<(Decorator my_shell, const T &elem)
Operator overload to output a modified ostream object which properties are set thanks to the Decorato...
Definition: decorator.hpp:98
std::chrono::steady_clock steady_clock
Definition: progress_bar.hpp:50
bool isFloatingPoint(const T &)
Function to check if an expression (not a type) is a floating point or not. I know this function is a...
Definition: generic.hpp:140
std::unordered_map< std::string, std::unordered_set< std::string > > string_set_map
Definition: progress_bar.hpp:49
std::chrono::duration< float, steady_clock::period > duration
Definition: progress_bar.hpp:51
const std::unordered_map< std::string, std::string > rst
It is used to store the reset features commands.
Definition: colsty.cpp:114
const std::unordered_map< std::string, std::string > sty
It is used to store the styles.
Definition: colsty.cpp:95
T_err except_error_func(const std::string &beg="", std::string var=nullptr, const std::string &end="")
Function used to throw customized stdexception error. This function is extremely specific to my purpo...
Definition: generic.hpp:68
T one(const T &iterating_var)
Function to find the incremented unit of a loop. Not easy to understand its purpose without context,...
Definition: generic.hpp:156
const std::unordered_map< std::string, std::string > col
It is used to store the colors. Note: "bg" is the prefix of the background color features and "bd" is...
Definition: colsty.cpp:39
std::ostream cout
const string_pair_map tcsc
It is used to store the terminal control sequences for clear line / screen.
Definition: cursor.cpp:80
T roundoff(T value, unsigned char prec)
Function to round a floating point to n-th decimal place after comma.
Definition: generic.hpp:123
const string_pair_map crs
It is used to store the cursor commands.
Definition: cursor.cpp:42
const std::string & feat(const std::unordered_map< std::string, std::string > &generic_map, const std::string &feat_string)
It takes an std::map object as the first argument and an std::string object (map key) as the second a...
Definition: common.cpp:41