Console Library 4.7.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
progress.h
Go to the documentation of this file.
1
10
11/*
12Copyright (c) 2026 MrXie1109
13
14Permission is hereby granted, free of charge, to any person obtaining a copy
15of this software and associated documentation files (the "Software"), to deal
16in the Software without restriction, including without limitation the rights
17to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18copies of the Software, and to permit persons to whom the Software is
19furnished to do so, subject to the following conditions:
20
21The above copyright notice and this permission notice shall be included in all
22copies or substantial portions of the Software.
23
24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30SOFTWARE.
31*/
32
33#pragma once
34#include <iostream>
35#include <string>
36#include <iterator>
37#include <chrono>
38#include "csexc.h"
39
40namespace console
41{
48 {
49 std::ostream &os;
50 int width;
51 std::string fill_char;
52 std::string empty_char;
53 std::string prefix;
54 std::string suffix;
56
67 ProgressConfig(std::ostream &o = std::cout, int w = 50,
68 std::string fc = "#", std::string ec = ".",
69 std::string pre = "[", std::string suf = "]",
70 bool sp = true)
71 : os(o), width(w), fill_char(std::move(fc)),
72 empty_char(std::move(ec)), prefix(std::move(pre)),
73 suffix(std::move(suf)), show_percent(sp) {}
74 };
75
84 template <class Iter>
86 {
87 public:
95 {
96 const ProgressConfig *config_;
97 size_t current_;
98 size_t total_;
99 Iter it_;
100 std::chrono::steady_clock::time_point last_draw_;
101
107 void draw()
108 {
109 if (!config_)
110 return;
111 auto now = std::chrono::steady_clock::now();
112 if (current_ < total_ &&
113 (now - last_draw_) < std::chrono::milliseconds{50})
114 {
115 return;
116 }
117 int percent = current_ * 100 / total_;
118 int filled = percent * config_->width / 100;
119 config_->os << '\r' << config_->prefix;
120 for (int i = 0; i < filled; ++i)
121 config_->os << config_->fill_char;
122 for (int i = filled; i < config_->width; ++i)
123 config_->os << config_->empty_char;
124 config_->os << config_->suffix;
125 if (config_->show_percent)
126 {
127 config_->os.width(4);
128 config_->os << percent << '%';
129 }
130 config_->os.flush();
131 last_draw_ = now;
132 }
133
134 public:
142 iterator(const ProgressConfig *config, size_t current,
143 size_t total, Iter it)
144 : config_(config), current_(current),
145 total_(total), it_(it),
146 last_draw_(std::chrono::steady_clock::now()) {}
147
150 {
151 if (current_ < total_)
152 {
153 ++current_;
154 ++it_;
155 draw();
156 }
157 return *this;
158 }
159
162 {
163 iterator tmp = *this;
164 ++(*this);
165 return tmp;
166 }
167
169 bool operator==(const iterator &other) const
170 {
171 return current_ == other.current_;
172 }
173
175 bool operator!=(const iterator &other) const
176 {
177 return current_ != other.current_;
178 }
179
181 decltype(*it_) operator*() const
182 {
183 return *it_;
184 }
185 };
186
193 template <typename Cont>
194 Progress(const Cont &cont, const ProgressConfig &config = {})
195 : config_(config),
196 total_(std::distance(std::begin(cont), std::end(cont))),
197 begin_(std::begin(cont)),
198 end_(std::end(cont)) {}
199
206 template <typename Cont>
207 Progress(Cont &cont, const ProgressConfig &config = {})
208 : config_(config),
209 total_(std::distance(std::begin(cont), std::end(cont))),
210 begin_(std::begin(cont)),
211 end_(std::end(cont)) {}
212
218 {
219 config_.os << std::endl;
220 }
221
224 {
225 return iterator(&config_, 0, total_, begin_);
226 }
227
230 {
231 return iterator(&config_, total_, total_, end_);
232 }
233
234 private:
235 ProgressConfig config_;
236 size_t total_;
237 Iter begin_;
238 Iter end_;
239 };
240
247 {
252 inline const ProgressConfig &normal()
253 {
254 static ProgressConfig cfg{};
255 return cfg;
256 }
257
262 inline const ProgressConfig &simple()
263 {
264 static ProgressConfig cfg{std::cout, 50, "=", "-", "", "", false};
265 return cfg;
266 }
267
273 inline const ProgressConfig &beautiful()
274 {
275 static ProgressConfig cfg{std::cout, 50, "\u2588", "\u2591",
276 "\u2595", "\u258F", true};
277 return cfg;
278 }
279 }
280
295 template <class Cont>
296 auto progress(Cont &&cont, const ProgressConfig &pc = {})
297 -> Progress<decltype(std::begin(cont))>
298 {
299 return {std::forward<Cont>(cont), pc};
300 }
301}
进度条的迭代器,负责绘制进度条。
Definition progress.h:95
decltype(*it_) operator*() const
解引用:返回底层迭代器所指向的元素。
Definition progress.h:181
bool operator==(const iterator &other) const
比较迭代器是否相等(通过当前进度索引)。
Definition progress.h:169
iterator(const ProgressConfig *config, size_t current, size_t total, Iter it)
构造进度条迭代器。
Definition progress.h:142
iterator operator++(int)
后置递增(调用前置递增)。
Definition progress.h:161
iterator & operator++()
前置递增:移动到下一个元素,并更新进度条。
Definition progress.h:149
bool operator!=(const iterator &other) const
比较迭代器是否不等。
Definition progress.h:175
Progress(const Cont &cont, const ProgressConfig &config={})
从 const 容器构造进度条对象。
Definition progress.h:194
Progress(Cont &cont, const ProgressConfig &config={})
从非 const 容器构造进度条对象。
Definition progress.h:207
~Progress()
析构函数,确保最后输出换行。
Definition progress.h:217
iterator begin()
返回指向第一个元素的迭代器(进度条起始)。
Definition progress.h:223
iterator end()
返回指向末尾的迭代器(进度条结束)。
Definition progress.h:229
定义 console 库使用的自定义异常类层次结构。
预定义的进度条样式。
const ProgressConfig & beautiful()
美观样式(使用 Unicode 块字符):宽度 50,填充 '█',空白 '░',边框 '▒' 和 '▏',显示百分比。
Definition progress.h:273
const ProgressConfig & simple()
简洁样式:宽度 50,填充 '=',空白 '-',无前后缀,不显示百分比。
Definition progress.h:262
const ProgressConfig & normal()
普通样式:宽度 50,填充 '#',空白 '.',前后缀 "[]",显示百分比。
Definition progress.h:252
本库所有组件所在的顶层命名空间。
auto progress(Cont &&cont, const ProgressConfig &pc={}) -> Progress< decltype(std::begin(cont))>
创建进度条对象的辅助函数(自动推导容器类型)。
Definition progress.h:296
Time now()
获取当前时间点(自纪元以来的纳秒数)。
Definition time.h:125
进度条显示配置。
Definition progress.h:48
std::string empty_char
未填充部分使用的字符(如 ".")。
Definition progress.h:52
std::string fill_char
已填充部分使用的字符(如 "#")。
Definition progress.h:51
std::string suffix
进度条后缀字符串(如 "]"]。
Definition progress.h:54
std::ostream & os
输出目标流,默认为 std::cout。
Definition progress.h:49
std::string prefix
进度条前缀字符串(如 "[")。
Definition progress.h:53
ProgressConfig(std::ostream &o=std::cout, int w=50, std::string fc="#", std::string ec=".", std::string pre="[", std::string suf="]", bool sp=true)
构造一个进度条配置对象。
Definition progress.h:67
int width
进度条的宽度(字符数)。
Definition progress.h:50
bool show_percent
是否在进度条后显示百分比数字。
Definition progress.h:55