cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
print.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <cstdint>
6#include <cstdlib>
7#include <cstring>
8#include <deque>
9#include <functional>
10#include <iostream>
11#include <iterator>
12#include <list>
13#include <map>
14#include <queue>
15#include <set>
16#include <sstream>
17#include <string>
18#include <type_traits>
19#include <unordered_map>
20#include <unordered_set>
21#include <utility>
22#include <vector>
23
25#include "cpp-toolbox/cpp-toolbox_export.hpp"
26#include "cpp-toolbox/macro.hpp"
28#ifdef CPP_TOOLBOX_PLATFORM_WINDOWS
29# define NOMINMAX
30# define WIN32_LEAN_AND_MEAN
31# include <windows.h>
32#endif
33
34namespace toolbox::utils
35{
40enum class CPP_TOOLBOX_EXPORT align_t : std::uint8_t
41{
42 LEFT,
45};
46
51enum class CPP_TOOLBOX_EXPORT color_t : std::uint8_t
52{
53 DEFAULT,
62};
63
71struct CPP_TOOLBOX_EXPORT print_style_t
72{
74 {
75 std::string top_left = "+";
76 std::string top_right = "+";
77 std::string bottom_left = "+";
78 std::string bottom_right = "+";
79 std::string left_joint = "+";
80 std::string right_joint = "+";
81 std::string top_joint = "+";
82 std::string bottom_joint = "+";
83 std::string center = "+";
84 } box;
85
86 std::string border_h = "-";
87 std::string border_v = "|";
88 std::string padding = " ";
89 bool show_header = true;
90 bool show_border = true;
91 size_t min_width = 0;
92 align_t alignment = align_t::LEFT;
93 color_t header_fg = color_t::DEFAULT;
94 color_t header_bg = color_t::DEFAULT;
95 color_t data_fg = color_t::DEFAULT;
96 color_t data_bg = color_t::DEFAULT;
97 color_t border_color = color_t::DEFAULT;
98 bool use_colors = true;
99};
100
108inline auto get_default_style() -> const print_style_t&
109{
110 static const print_style_t style = print_style_t();
111 return style;
112}
113
121inline auto get_ascii_style() -> const print_style_t&
122{
123 static const print_style_t style = [] {
125 s.border_h = "-";
126 s.border_v = "|";
127 s.box.top_left = "+";
128 s.box.top_right = "+";
129 s.box.bottom_left = "+";
130 s.box.bottom_right = "+";
131 s.box.left_joint = "+";
132 s.box.right_joint = "+";
133 s.box.top_joint = "+";
134 s.box.bottom_joint = "+";
135 s.box.center = "+";
136 return s;
137 }();
138 return style;
139}
140
144inline auto get_rounded_style() -> const print_style_t&
145{
146 static const print_style_t style = [] {
148#ifdef CPP_TOOLBOX_PLATFORM_WINDOWS
149 // 在 Windows 上使用 ASCII 字符
150 s.border_h = "-";
151 s.border_v = "|";
152 s.box.top_left = "+";
153 s.box.top_right = "+";
154 s.box.bottom_left = "+";
155 s.box.bottom_right = "+";
156 s.box.left_joint = "+";
157 s.box.right_joint = "+";
158 s.box.top_joint = "+";
159 s.box.bottom_joint = "+";
160 s.box.center = "+";
161#else
162 // 在其他平台上使用 Unicode 字符
163 s.border_h = "\xE2\x94\x80"; // "─"
164 s.border_v = "\xE2\x94\x82"; // "│"
165 s.box.top_left = "\xE2\x94\x8C"; // "┌"
166 s.box.top_right = "\xE2\x94\x90"; // "┐"
167 s.box.bottom_left = "\xE2\x94\x94"; // "└"
168 s.box.bottom_right = "\xE2\x94\x98"; // "┘"
169 s.box.left_joint = "\xE2\x94\x9C"; // "├"
170 s.box.right_joint = "\xE2\x94\xA4"; // "┤"
171 s.box.top_joint = "\xE2\x94\xAC"; // "┬"
172 s.box.bottom_joint = "\xE2\x94\xB4"; // "┴"
173 s.box.center = "\xE2\x94\xBC"; // "┼"
174#endif
175 return s;
176 }();
177 return style;
178}
179
186class CPP_TOOLBOX_EXPORT color_handler_t
187{
188 inline static bool is_windows =
189 false;
190 inline static bool has_color_support =
191 false;
192
196 static void initialize()
197 {
198 static bool initialized = false;
199 if (!initialized) {
200#ifdef _WIN32
201 is_windows = true;
202 // 在Windows上检查并启用ANSI支持/Check and enable ANSI support on Windows
203 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
204 DWORD dwMode = 0;
205 has_color_support = GetConsoleMode(hOut, &dwMode)
206 && SetConsoleMode(hOut, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
207#else
208 is_windows = false;
209 // 使用 toolbox::base::get_environment_variable 替换 std::getenv/Use
210 // toolbox::base::get_environment_variable instead of std::getenv
211 const std::string term_str =
213 has_color_support =
214 !term_str.empty() // 显式检查非空/Explicitly check non-empty
215 && (term_str == "xterm" || term_str == "xterm-color"
216 || term_str == "xterm-256color" || term_str == "screen"
217 || term_str == "screen-256color" || term_str == "tmux"
218 || term_str == "tmux-256color" || term_str == "rxvt"
219 || term_str == "rxvt-unicode" || term_str == "linux"
220 || term_str == "cygwin");
221#endif
222 initialized = true;
223 }
224 }
225
226public:
232 static auto get_fg_code(color_t color) -> std::string
233 {
234 initialize();
235 if (!has_color_support || color == color_t::DEFAULT) {
236 return "";
237 }
238
239 switch (color) {
240 case color_t::BLACK:
241 return "\033[30m";
242 case color_t::RED:
243 return "\033[31m";
244 case color_t::GREEN:
245 return "\033[32m";
246 case color_t::YELLOW:
247 return "\033[33m";
248 case color_t::BLUE:
249 return "\033[34m";
250 case color_t::MAGENTA:
251 return "\033[35m";
252 case color_t::CYAN:
253 return "\033[36m";
254 case color_t::WHITE:
255 return "\033[37m";
256 default:
257 return "";
258 }
259 }
260
266 static auto get_bg_code(color_t color) -> std::string
267 {
268 initialize();
269 if (!has_color_support || color == color_t::DEFAULT) {
270 return "";
271 }
272
273 switch (color) {
274 case color_t::BLACK:
275 return "\033[40m";
276 case color_t::RED:
277 return "\033[41m";
278 case color_t::GREEN:
279 return "\033[42m";
280 case color_t::YELLOW:
281 return "\033[43m";
282 case color_t::BLUE:
283 return "\033[44m";
284 case color_t::MAGENTA:
285 return "\033[45m";
286 case color_t::CYAN:
287 return "\033[46m";
288 case color_t::WHITE:
289 return "\033[47m";
290 default:
291 return "";
292 }
293 }
294
299 static auto reset() -> std::string
300 {
301 initialize();
302 return has_color_support ? "\033[0m" : "";
303 }
304
316 static auto colorize(const std::string& text, color_t fg, color_t bg)
317 -> std::string
318 {
319 initialize();
320 if (!has_color_support
321 || (fg == color_t::DEFAULT && bg == color_t::DEFAULT))
322 {
323 return text;
324 }
325
326 std::string result;
327 result.reserve(text.size()
328 + 20); // 预留ANSI代码空间/Reserve space for ANSI codes
329
330 result += get_fg_code(fg);
331 result += get_bg_code(bg);
332 result += text;
333 result += reset();
334
335 return result;
336 }
337
345 static auto supports_color() -> bool
346 {
347 initialize();
348 return has_color_support;
349 }
350};
351
362template<typename T>
363auto to_string_value(const T& value) -> std::string
364{
365 // 专门处理 std::string 本身
366 if constexpr (std::is_same_v<T, std::string>) {
367 return value;
368 }
369 // 如果是可迭代容器(且不是 string),就把它当作列表打印
370 else if constexpr (toolbox::traits::is_iterable_v<T>)
371 {
372 std::ostringstream oss;
373 oss << "[";
374 bool first = true;
375 for (auto const& elem : value) {
376 if (!first) {
377 oss << ", ";
378 }
379 oss << to_string_value(elem); // 递归;如果 elem 也是容器会继续走这里
380 first = false;
381 }
382 oss << "]";
383 return oss.str();
384 }
385 // 否则尝试用 operator<< 打印
386 else {
387 std::ostringstream oss;
388 oss << value; // 只有当 stream << T 可用才会编译
389 return oss.str();
390 }
391}
392
404inline auto align_text(const std::string& text,
405 size_t width,
406 align_t align,
407 [[maybe_unused]] const std::string& padding = " ")
408 -> std::string
409{
410 if (text.length() >= width) {
411 return text;
412 }
413
414 const size_t padding_length = width - text.length();
415
416 switch (align) {
417 case align_t::RIGHT: {
418 return std::string(padding_length, ' ') + text;
419 }
420 case align_t::CENTER: {
421 const size_t left_padding = padding_length / 2;
422 const size_t right_padding = padding_length - left_padding;
423 return std::string(left_padding, ' ') + text
424 + std::string(right_padding, ' ');
425 }
426 case align_t::LEFT:
427 default: {
428 return text + std::string(padding_length, ' ');
429 }
430 }
431}
432
461class CPP_TOOLBOX_EXPORT table_t;
462
463CPP_TOOLBOX_EXPORT std::ostream& operator<<(std::ostream& os,
464 const table_t& tbl);
465
466class CPP_TOOLBOX_EXPORT table_t
467{
468public:
470 explicit table_t(const print_style_t& style = get_default_style());
471
477 table_t& set_headers(const std::vector<std::string>& hdrs);
478
485 table_t& add_row(const std::vector<std::string>& row);
486
497 template<typename... Args,
498 // SFINAE: Disable this template if called with a single
499 // std::vector<std::string> to ensure the non-template overload
500 // add_row(const std::vector<std::string>&) is chosen instead.
501 std::enable_if_t<
502 !(sizeof...(Args) == 1
503 && std::is_same_v<
504 std::decay_t<std::tuple_element_t<0, std::tuple<Args...>>>,
505 std::vector<std::string>>),
506 int> = 0>
507 auto add_row(Args&&... args) -> table_t&
508 {
509 // No need for static_assert check anymore due to SFINAE constraint above.
510
511 std::vector<std::string> row_data;
512 row_data.reserve(sizeof...(args));
513 // Convert all arguments to string and collect them
514 (row_data.push_back(to_string_value(std::forward<Args>(args))), ...);
515
516 // Call the non-template add_row(const std::vector<std::string>&) overload.
517 // Passing 'row_data' as an lvalue ensures the correct overload is selected.
518 return this->add_row(row_data);
519 }
520
526 table_t& set_title(const std::string& title);
527
533 table_t& set_footer(const std::string& footer);
534
541 table_t& set_column_align(size_t column_index, align_t align);
542
549
556 table_t& set_column_width(size_t col, size_t width);
557
566 table_t& set_column_min_max(size_t col, size_t min_width, size_t max_width);
567
574 table_t& set_row_height(size_t row, size_t height);
575
582 table_t& enable_wrap(bool enable);
583
589 table_t& set_wrap_ellipsis(const std::string& ellipsis);
590
599 table_t& span_cells(size_t start_row,
600 size_t start_col,
601 size_t row_span,
602 size_t col_span);
603
609 table_t& enable_zebra(bool enable);
610
618 table_t& set_zebra_colors(color_t odd_bg, color_t even_bg);
619
627 std::function<print_style_t(size_t, size_t, const std::string&)> cb);
628
637
646
652 [[nodiscard]] auto to_string(bool with_color = true) const -> std::string;
653
660 friend CPP_TOOLBOX_EXPORT std::ostream& operator<<(std::ostream& os,
661 const table_t& tbl);
662
663private:
665 std::vector<std::string> m_headers;
666
668 std::vector<std::vector<std::string>> m_data;
669
671 print_style_t m_style;
672
674 std::string m_title;
675
677 std::string m_footer;
678
680 std::unordered_map<size_t, size_t> m_col_fixed_width;
681
684 std::unordered_map<size_t, std::pair<size_t, size_t>> m_col_min_max;
685
687 std::unordered_map<size_t, size_t> m_row_fixed_height;
688
690 std::vector<align_t> m_col_aligns;
691
693 bool m_wrap_enabled;
694
696 std::string m_wrap_ellipsis;
697
702 struct Span
703 {
704 size_t row, col, row_span, col_span;
705 };
706 std::vector<Span> m_spans;
707
709 bool m_zebra_enabled;
710
712 color_t m_zebra_odd_bg;
713 color_t m_zebra_even_bg;
714
716 std::function<print_style_t(size_t, size_t, const std::string&)>
717 m_highlight_cb;
718
721 bool m_out_color;
722
724 bool m_file_color;
725
730 void calculate_col_widths() const;
731
736 enum class border_pos_t
737 {
738 TOP,
739 MIDDLE,
740 BOTTOM
741 };
742
743 void print_horizontal_border(std::ostream& os, border_pos_t pos) const;
744
753 void print_wrapped_row(std::ostream& os,
754 const std::vector<std::string>& row_data,
755 bool is_header,
756 size_t row_index) const;
757
765 bool is_spanned_cell(size_t row, size_t col) const;
766
768 mutable std::vector<size_t> m_col_widths;
769};
770
776template<typename Container>
777class CPP_TOOLBOX_EXPORT container_printer_t
778{
779private:
780 const Container& m_container;
781 std::string m_name;
782 print_style_t m_style;
783 bool m_partial{false};
784 size_t m_head_count{3};
785 size_t m_tail_count{3};
786 std::string m_partial_ellipsis{"..."};
787
788protected:
793 auto get_container() const -> const Container& { return m_container; }
798 [[nodiscard]] auto get_name() const -> const std::string& { return m_name; }
803 [[nodiscard]] auto get_style() const -> const print_style_t&
804 {
805 return m_style;
806 }
807
812 [[nodiscard]] virtual auto get_size() const -> size_t = 0;
813
818 virtual void print_content(std::ostream& os) const = 0;
819
820public:
827 container_printer_t(const Container& c, std::string name, print_style_t style)
828 : m_container(c)
829 , m_name(std::move(name))
830 , m_style(std::move(style))
831 {
832 }
833
840 {
841 m_partial = enable;
842 return *this;
843 }
844
848 container_printer_t& set_head_tail_count(size_t head, size_t tail)
849 {
850 m_head_count = head;
851 m_tail_count = tail;
852 return *this;
853 }
854
858 container_printer_t& set_partial_ellipsis(const std::string& ellipsis)
859 {
860 m_partial_ellipsis = ellipsis;
861 return *this;
862 }
863
864protected:
865 [[nodiscard]] auto partial_enabled() const -> bool { return m_partial; }
866 [[nodiscard]] auto head_count() const -> size_t { return m_head_count; }
867 [[nodiscard]] auto tail_count() const -> size_t { return m_tail_count; }
868 [[nodiscard]] auto ellipsis() const -> const std::string&
869 {
870 return m_partial_ellipsis;
871 }
872
876 virtual ~container_printer_t() = default;
877
882
883 // 声明外部模板函数为友元 (注意 <>) / Declare external template function as
884 // friend (note < >)
885 template<typename C> // C 代表容器类型 / C represents the container type
886 friend auto operator<<(std::ostream& os,
887 const container_printer_t<C>& printer)
888 -> std::ostream&;
889};
890
891// 在类外部定义 operator<< 模板函数 / Define the operator<< template function
892// outside the class
903template<typename Container>
904auto operator<<(std::ostream& os, const container_printer_t<Container>& printer)
905 -> std::ostream&
906{
907 std::string name_colored = printer.get_style().use_colors
908 ? color_handler_t::colorize(printer.get_name(),
909 printer.get_style().header_fg,
910 printer.get_style().header_bg)
911 : printer.get_name();
912
913 os << name_colored << " [" << printer.get_size() << "] = {"
914 << "\n";
915 printer.print_content(os); // 调用虚函数 / Call virtual function
916 os << "}"
917 << "\n";
918 return os;
919}
920
930template<typename T>
931class CPP_TOOLBOX_EXPORT vector_printer_t
932 : public container_printer_t<std::vector<T>>
933{
934protected:
939 [[nodiscard]] auto get_size() const -> size_t override
940 {
941 return this->get_container().size();
942 }
943
948 void print_content(std::ostream& os) const override
949 {
950 size_t total = this->get_container().size();
951 bool partial = this->partial_enabled() &&
952 total > (this->head_count() + this->tail_count());
953 size_t head = partial ? this->head_count() : total;
954 size_t tail_start = partial ? total - this->tail_count() : total;
955
956 for (size_t i = 0; i < head; ++i) {
957 const std::string index = "[" + std::to_string(i) + "]: ";
958 const std::string value = to_string_value(this->get_container()[i]);
959
960 const std::string colored_index = this->get_style().use_colors
961 ? color_handler_t::colorize(
962 index, this->get_style().header_fg, color_t::DEFAULT)
963 : index;
964 const std::string colored_value = this->get_style().use_colors
965 ? color_handler_t::colorize(
966 value, this->get_style().data_fg, color_t::DEFAULT)
967 : value;
968
969 os << " " << colored_index << colored_value;
970 if (partial || i < total - 1) {
971 os << ",";
972 }
973 os << "\n";
974 }
975
976 if (partial) {
977 os << " " << this->ellipsis();
978 if (tail_start < total) {
979 os << ",";
980 }
981 os << "\n";
982 }
983
984 for (size_t i = std::max(head, tail_start); i < total; ++i) {
985 const std::string index = "[" + std::to_string(i) + "]: ";
986 const std::string value = to_string_value(this->get_container()[i]);
987
988 const std::string colored_index = this->get_style().use_colors
989 ? color_handler_t::colorize(
990 index, this->get_style().header_fg, color_t::DEFAULT)
991 : index;
992 const std::string colored_value = this->get_style().use_colors
993 ? color_handler_t::colorize(
994 value, this->get_style().data_fg, color_t::DEFAULT)
995 : value;
996
997 os << " " << colored_index << colored_value;
998 if (i < total - 1) {
999 os << ",";
1000 }
1001 os << "\n";
1002 }
1003 }
1004
1005public:
1006 using container_printer_t<std::vector<T>>::container_printer_t;
1007};
1008
1019template<typename K, typename V>
1020class CPP_TOOLBOX_EXPORT map_printer_t
1021 : public container_printer_t<std::map<K, V>>
1022{
1023protected:
1028 [[nodiscard]] auto get_size() const -> size_t override
1029 {
1030 return this->get_container().size();
1031 }
1032
1037 void print_content(std::ostream& os) const override
1038 {
1039 size_t total = this->get_container().size();
1040 bool partial = this->partial_enabled() &&
1041 total > (this->head_count() + this->tail_count());
1042 size_t head = partial ? this->head_count() : total;
1043 size_t tail_start = partial ? total - this->tail_count() : total;
1044
1045 size_t idx = 0;
1046 for (auto it = this->get_container().begin();
1047 it != this->get_container().end() && idx < head; ++it, ++idx)
1048 {
1049 const auto& [key, value] = *it;
1050 const std::string key_str = to_string_value(key);
1051 const std::string value_str = to_string_value(value);
1052 const std::string arrow = " => ";
1053
1054 const std::string colored_key = this->get_style().use_colors
1055 ? color_handler_t::colorize(
1056 key_str, this->get_style().header_fg, color_t::DEFAULT)
1057 : key_str;
1058 const std::string colored_value = this->get_style().use_colors
1059 ? color_handler_t::colorize(
1060 value_str, this->get_style().data_fg, color_t::DEFAULT)
1061 : value_str;
1062
1063 os << " " << colored_key << arrow << colored_value;
1064 if (partial || idx < total - 1) {
1065 os << ",";
1066 }
1067 os << "\n";
1068 }
1069
1070 if (partial) {
1071 os << " " << this->ellipsis();
1072 if (tail_start < total) {
1073 os << ",";
1074 }
1075 os << "\n";
1076
1077 auto it = this->get_container().begin();
1078 std::advance(it, tail_start);
1079 for (; it != this->get_container().end(); ++it) {
1080 const auto& [key, value] = *it;
1081 const std::string key_str = to_string_value(key);
1082 const std::string value_str = to_string_value(value);
1083 const std::string arrow = " => ";
1084
1085 const std::string colored_key = this->get_style().use_colors
1086 ? color_handler_t::colorize(
1087 key_str, this->get_style().header_fg, color_t::DEFAULT)
1088 : key_str;
1089 const std::string colored_value = this->get_style().use_colors
1090 ? color_handler_t::colorize(
1091 value_str, this->get_style().data_fg, color_t::DEFAULT)
1092 : value_str;
1093
1094 os << " " << colored_key << arrow << colored_value;
1095 if (std::next(it) != this->get_container().end()) {
1096 os << ",";
1097 }
1098 os << "\n";
1099 }
1100 }
1101 }
1102
1103public:
1104 using container_printer_t<std::map<K, V>>::container_printer_t;
1105};
1106
1117template<typename K, typename V>
1118class CPP_TOOLBOX_EXPORT unorderedmap_printer_t
1119 : public container_printer_t<std::unordered_map<K, V>>
1120{
1121protected:
1126 [[nodiscard]] auto get_size() const -> size_t override
1127 {
1128 return this->get_container().size();
1129 }
1130
1135 void print_content(std::ostream& os) const override
1136 {
1137 size_t i = 0;
1138 for (const auto& [key, value] : this->get_container()) {
1139 const std::string key_str = to_string_value(key);
1140 const std::string value_str = to_string_value(value);
1141 const std::string arrow = " => ";
1142
1143 const std::string colored_key = this->get_style().use_colors
1144 ? color_handler_t::colorize(
1145 key_str, this->get_style().header_fg, color_t::DEFAULT)
1146 : key_str;
1147 const std::string colored_value = this->get_style().use_colors
1148 ? color_handler_t::colorize(
1149 value_str, this->get_style().data_fg, color_t::DEFAULT)
1150 : value_str;
1151
1152 os << " " << colored_key << arrow << colored_value;
1153 if (i < this->get_container().size() - 1) {
1154 os << ",";
1155 }
1156 os << "\n";
1157 i++;
1158 }
1159 }
1160
1161public:
1162 using container_printer_t<std::unordered_map<K, V>>::container_printer_t;
1163};
1164
1174template<typename T>
1175class CPP_TOOLBOX_EXPORT set_printer_t : public container_printer_t<std::set<T>>
1176{
1177protected:
1182 [[nodiscard]] auto get_size() const -> size_t override
1183 {
1184 return this->get_container().size();
1185 }
1186
1191 void print_content(std::ostream& os) const override
1192 {
1193 size_t i = 0;
1194 for (const auto& item : this->get_container()) {
1195 const std::string value = to_string_value(item);
1196
1197 const std::string colored_value = this->get_style().use_colors
1198 ? color_handler_t::colorize(
1199 value, this->get_style().data_fg, color_t::DEFAULT)
1200 : value;
1201
1202 os << " " << colored_value;
1203 if (i < this->get_container().size() - 1) {
1204 os << ",";
1205 }
1206 os << "\n";
1207 i++;
1208 }
1209 }
1210
1211public:
1212 using container_printer_t<std::set<T>>::container_printer_t;
1213};
1214
1224template<typename T>
1225class CPP_TOOLBOX_EXPORT unorderedset_printer_t
1226 : public container_printer_t<std::unordered_set<T>>
1227{
1228protected:
1233 [[nodiscard]] auto get_size() const -> size_t override
1234 {
1235 return this->get_container().size();
1236 }
1237
1242 void print_content(std::ostream& os) const override
1243 {
1244 size_t i = 0;
1245 for (const auto& item : this->get_container()) {
1246 const std::string value = to_string_value(item);
1247
1248 const std::string colored_value = this->get_style().use_colors
1249 ? color_handler_t::colorize(
1250 value, this->get_style().data_fg, color_t::DEFAULT)
1251 : value;
1252
1253 os << " " << colored_value;
1254 if (i < this->get_container().size() - 1) {
1255 os << ",";
1256 }
1257 os << "\n";
1258 i++;
1259 }
1260 }
1261
1262public:
1263 using container_printer_t<std::unordered_set<T>>::container_printer_t;
1264};
1265
1275template<typename T>
1276class CPP_TOOLBOX_EXPORT deque_printer_t
1277 : public container_printer_t<std::deque<T>>
1278{
1279protected:
1284 [[nodiscard]] auto get_size() const -> size_t override
1285 {
1286 return this->get_container().size();
1287 }
1288
1293 void print_content(std::ostream& os) const override
1294 {
1295 for (size_t i = 0; i < this->get_container().size(); ++i) {
1296 const std::string index = "[" + std::to_string(i) + "]: ";
1297 const std::string value = to_string_value(this->get_container()[i]);
1298
1299 const std::string colored_index = this->get_style().use_colors
1300 ? color_handler_t::colorize(
1301 index, this->get_style().header_fg, color_t::DEFAULT)
1302 : index;
1303 const std::string colored_value = this->get_style().use_colors
1304 ? color_handler_t::colorize(
1305 value, this->get_style().data_fg, color_t::DEFAULT)
1306 : value;
1307
1308 os << " " << colored_index << colored_value;
1309 if (i < this->get_container().size() - 1) {
1310 os << ",";
1311 }
1312 os << "\n";
1313 }
1314 }
1315
1316public:
1317 using container_printer_t<std::deque<T>>::container_printer_t;
1318};
1319
1329template<typename T>
1330class CPP_TOOLBOX_EXPORT list_printer_t
1331 : public container_printer_t<std::list<T>>
1332{
1333protected:
1338 [[nodiscard]] auto get_size() const -> size_t override
1339 {
1340 return this->get_container().size();
1341 }
1342
1347 void print_content(std::ostream& os) const override
1348 {
1349 size_t i = 0;
1350 const auto& container = this->get_container(); // Cache container reference
1351 for (const auto& item : container) { // 使用 getter
1352 const std::string index = "[" + std::to_string(i) + "]: "; // const
1353 const std::string value = to_string_value(item); // const
1354
1355 const std::string colored_index = this->get_style().use_colors
1356 ? color_handler_t::colorize(
1357 index, this->get_style().header_fg, color_t::DEFAULT)
1358 : index;
1359 const std::string colored_value = this->get_style().use_colors
1360 ? color_handler_t::colorize(
1361 value, this->get_style().data_fg, color_t::DEFAULT)
1362 : value;
1363
1364 os << " " << colored_index << colored_value;
1365 // 使用 std::next 获取下一个迭代器来检查是否是最后一个元素
1366 // Cast i + 1 to difference_type to avoid sign conversion warning
1367 using diff_t = typename std::list<T>::difference_type;
1368 if (std::next(container.begin(), static_cast<diff_t>(i + 1))
1369 != container.end())
1370 {
1371 os << ",";
1372 }
1373 os << "\n";
1374 i++;
1375 }
1376 }
1377
1378public:
1379 using container_printer_t<std::list<T>>::container_printer_t;
1380};
1381
1392template<typename T, size_t N>
1393class CPP_TOOLBOX_EXPORT array_printer_t
1394 : public container_printer_t<std::array<T, N>>
1395{
1396protected:
1401 [[nodiscard]] auto get_size() const -> size_t override { return N; }
1402
1407 void print_content(std::ostream& os) const override
1408 {
1409 for (size_t i = 0; i < N; ++i) {
1410 const std::string index = "[" + std::to_string(i) + "]: ";
1411 const std::string value = to_string_value(this->get_container()[i]);
1412
1413 const std::string colored_index = this->get_style().use_colors
1414 ? color_handler_t::colorize(
1415 index, this->get_style().header_fg, color_t::DEFAULT)
1416 : index;
1417 const std::string colored_value = this->get_style().use_colors
1418 ? color_handler_t::colorize(
1419 value, this->get_style().data_fg, color_t::DEFAULT)
1420 : value;
1421
1422 os << " " << colored_index << colored_value;
1423 if (i < N - 1) {
1424 os << ",";
1425 }
1426 os << "\n";
1427 }
1428 }
1429
1430public:
1431 using container_printer_t<std::array<T, N>>::container_printer_t;
1432};
1433
1453template<typename T>
1454class CPP_TOOLBOX_EXPORT queue_printer_t
1455 : public container_printer_t<std::queue<T>>
1456{
1457protected:
1462 [[nodiscard]] auto get_size() const -> size_t override
1463 {
1464 return this->get_container().size();
1465 }
1466
1475 void print_content(std::ostream& os) const override
1476 {
1477 // 由于 std::queue 不支持随机访问,这里需要复制一份队列进行遍历
1478 // Since std::queue does not support random access, we need to copy the
1479 // queue for traversal.
1480 std::queue<T> q_copy = this->get_container();
1481 size_t i = 0;
1482 const size_t total_size = q_copy.size(); // 先获取总大小
1483 while (!q_copy.empty()) {
1484 const std::string index = "[" + std::to_string(i) + "]: ";
1485 const std::string value =
1486 to_string_value(q_copy.front()); // 获取队首元素
1487
1488 const std::string colored_index = this->get_style().use_colors
1489 ? color_handler_t::colorize(
1490 index, this->get_style().header_fg, color_t::DEFAULT)
1491 : index;
1492 const std::string colored_value = this->get_style().use_colors
1493 ? color_handler_t::colorize(
1494 value, this->get_style().data_fg, color_t::DEFAULT)
1495 : value;
1496
1497 os << " " << colored_index << colored_value;
1498 if (i < total_size - 1) { // 使用总大小判断是否需要逗号
1499 os << ",";
1500 }
1501 os << "\n";
1502 q_copy.pop(); // 弹出队首元素
1503 ++i;
1504 }
1505 }
1506
1507public:
1508 // 继承基类构造函数/Inherit base class constructors
1509 using container_printer_t<std::queue<T>>::container_printer_t;
1510};
1511
1524template<typename T>
1525auto print_vector(const std::vector<T>& vec,
1526 const std::string& name = "Vector",
1527 const print_style_t& style = get_default_style())
1529{
1530 return vector_printer_t<T>(vec, name, style);
1531}
1532
1546template<typename K, typename V>
1547auto print_map(const std::map<K, V>& m,
1548 const std::string& name = "Map",
1549 const print_style_t& style = get_default_style())
1551{
1552 return map_printer_t<K, V>(m, name, style);
1553}
1554
1568template<typename K, typename V>
1569auto print_unordered_map(const std::unordered_map<K, V>& m,
1570 const std::string& name = "Unordered Map",
1571 const print_style_t& style = get_default_style())
1573{
1574 return unorderedmap_printer_t<K, V>(m, name, style);
1575}
1576
1589template<typename T>
1590auto print_set(const std::set<T>& s,
1591 const std::string& name = "Set",
1592 const print_style_t& style = get_default_style())
1594{
1595 return set_printer_t<T>(s, name, style);
1596}
1597
1610template<typename T>
1611auto print_unordered_set(const std::unordered_set<T>& s,
1612 const std::string& name = "Unordered Set",
1613 const print_style_t& style = get_default_style())
1615{
1616 return unorderedset_printer_t<T>(s, name, style);
1617}
1618
1631template<typename T>
1632auto print_deque(const std::deque<T>& d,
1633 const std::string& name = "Deque",
1634 const print_style_t& style = get_default_style())
1636{
1637 return deque_printer_t<T>(d, name, style);
1638}
1639
1652template<typename T>
1653auto print_list(const std::list<T>& l,
1654 const std::string& name = "List",
1655 const print_style_t& style = get_default_style())
1657{
1658 return list_printer_t<T>(l, name, style);
1659}
1660
1674template<typename T, size_t N>
1675auto print_array(const std::array<T, N>& arr,
1676 const std::string& name = "Array",
1677 const print_style_t& style = get_default_style())
1679{
1680 return array_printer_t<T, N>(arr, name, style);
1681}
1682
1696template<typename T>
1697auto print_queue(const std::queue<T>& q,
1698 const std::string& name = "Queue",
1699 const print_style_t& style = get_default_style())
1701{
1702 return queue_printer_t<T>(q, name, style);
1703}
1704
1705} // namespace toolbox::utils
Array 打印器/Array printer.
Definition print.hpp:1395
void print_content(std::ostream &os) const override
打印内容/Print content
Definition print.hpp:1407
auto get_size() const -> size_t override
获取容器大小/Get container size
Definition print.hpp:1401
平台无关的颜色处理类/Platform-independent color handler
Definition print.hpp:187
static auto colorize(const std::string &text, color_t fg, color_t bg) -> std::string
应用颜色到文本/Apply color to text
Definition print.hpp:316
static auto supports_color() -> bool
检查是否支持颜色/Check if color is supported
Definition print.hpp:345
static auto get_bg_code(color_t color) -> std::string
获取背景色ANSI代码/Get ANSI code for background color
Definition print.hpp:266
static auto get_fg_code(color_t color) -> std::string
获取前景色ANSI代码/Get ANSI code for foreground color
Definition print.hpp:232
static auto reset() -> std::string
重置所有颜色/Reset all colors
Definition print.hpp:299
通用容器打印器基类/Generic container printer base class
Definition print.hpp:778
auto partial_enabled() const -> bool
Definition print.hpp:865
container_printer_t(const container_printer_t &)=delete
container_printer_t & operator=(container_printer_t &&)=delete
auto head_count() const -> size_t
Definition print.hpp:866
container_printer_t & operator=(const container_printer_t &)=delete
auto ellipsis() const -> const std::string &
Definition print.hpp:868
container_printer_t & set_partial_ellipsis(const std::string &ellipsis)
设置省略符/Set ellipsis string for partial printing
Definition print.hpp:858
container_printer_t & set_head_tail_count(size_t head, size_t tail)
设置头尾元素数量/Set head and tail element counts
Definition print.hpp:848
friend auto operator<<(std::ostream &os, const container_printer_t< C > &printer) -> std::ostream &
virtual auto get_size() const -> size_t=0
获取容器大小的虚函数/Virtual function to get container size
container_printer_t & enable_partial(bool enable)
启用或禁用首尾打印/Enable or disable head-tail printing
Definition print.hpp:839
auto tail_count() const -> size_t
Definition print.hpp:867
auto get_style() const -> const print_style_t &
获取打印风格/Get print style
Definition print.hpp:803
virtual ~container_printer_t()=default
析构函数/Destructor
auto get_container() const -> const Container &
获取容器引用/Get container reference
Definition print.hpp:793
auto get_name() const -> const std::string &
获取名称/Get name
Definition print.hpp:798
container_printer_t(container_printer_t &&)=delete
Deque 打印器/Deque printer.
Definition print.hpp:1278
auto get_size() const -> size_t override
获取容器大小/Get container size
Definition print.hpp:1284
void print_content(std::ostream &os) const override
打印内容/Print content
Definition print.hpp:1293
List 打印器/List printer.
Definition print.hpp:1332
void print_content(std::ostream &os) const override
打印内容/Print content
Definition print.hpp:1347
auto get_size() const -> size_t override
获取容器大小/Get container size
Definition print.hpp:1338
Map 打印器/Map printer.
Definition print.hpp:1022
void print_content(std::ostream &os) const override
打印内容/Print content
Definition print.hpp:1037
auto get_size() const -> size_t override
获取容器大小/Get container size
Definition print.hpp:1028
队列打印器/Queue printer
Definition print.hpp:1456
auto get_size() const -> size_t override
获取队列大小/Get queue size
Definition print.hpp:1462
void print_content(std::ostream &os) const override
打印队列内容/Print queue content
Definition print.hpp:1475
Set 打印器/Set printer.
Definition print.hpp:1176
void print_content(std::ostream &os) const override
打印内容/Print content
Definition print.hpp:1191
auto get_size() const -> size_t override
获取容器大小/Get container size
Definition print.hpp:1182
格式化打印表格工具/Formatted table printing utility
Definition print.hpp:467
table_t & enable_zebra(bool enable)
启用或禁用斑马纹 / Enable or disable zebra striping
table_t & set_title(const std::string &title)
设置表格标题 / Set table title text
table_t & set_zebra_colors(color_t odd_bg, color_t even_bg)
设置斑马纹的奇偶行背景色 / Set zebra background colors for odd/even rows
table_t & add_row(const std::vector< std::string > &row)
添加一行数据 / Add a data row
auto add_row(Args &&... args) -> table_t &
添加一行数据(可变参数)/ Add a row with variadic arguments
Definition print.hpp:507
table_t & set_wrap_ellipsis(const std::string &ellipsis)
设置截断时的省略符 / Set ellipsis string when truncating
table_t & set_output_color(bool enable)
控制终端输出时是否保留颜色码 / Control whether to keep ANSI colors for terminal output
table_t & set_column_min_max(size_t col, size_t min_width, size_t max_width)
为指定列设置最小和最大宽度约束 / Set min and max width constraints for a column
table_t(const print_style_t &style=get_default_style())
构造函数 / Constructor
table_t & set_highlight_callback(std::function< print_style_t(size_t, size_t, const std::string &)> cb)
设置条件高亮回调 / Set conditional highlight callback
table_t & enable_wrap(bool enable)
启用或禁用自动内容换行 / Enable or disable automatic content wrapping
table_t & set_row_height(size_t row, size_t height)
为指定行设置固定行高 / Set fixed height for a row
table_t & set_footer(const std::string &footer)
设置表格尾部文本 / Set table footer text
table_t & set_all_columns_align(align_t align)
设置所有列的对齐方式 / Set alignment for all columns
table_t & span_cells(size_t start_row, size_t start_col, size_t row_span, size_t col_span)
合并单元格 / Merge cells
table_t & set_headers(const std::vector< std::string > &hdrs)
设置表头 / Set table_t headers
table_t & set_column_width(size_t col, size_t width)
为指定列设置固定宽度 / Set fixed width for a column
auto to_string(bool with_color=true) const -> std::string
将表格渲染为字符串 / Render table as a string
table_t & set_column_align(size_t column_index, align_t align)
设置指定列的对齐方式 / Set alignment for a specific column
table_t & set_file_output_color(bool enable)
控制写入文件时是否保留颜色码 / Control whether to keep ANSI colors for file output
Unordered Map 打印器/Unordered map printer.
Definition print.hpp:1120
void print_content(std::ostream &os) const override
打印内容/Print content
Definition print.hpp:1135
auto get_size() const -> size_t override
获取容器大小/Get container size
Definition print.hpp:1126
Unordered Set 打印器/Unordered set printer.
Definition print.hpp:1227
auto get_size() const -> size_t override
获取容器大小/Get container size
Definition print.hpp:1233
void print_content(std::ostream &os) const override
打印内容/Print content
Definition print.hpp:1242
Vector 打印器/Vector printer.
Definition print.hpp:933
void print_content(std::ostream &os) const override
打印内容/Print content
Definition print.hpp:948
auto get_size() const -> size_t override
获取容器大小/Get container size
Definition print.hpp:939
通用的编译器、平台、架构检测和实用宏定义 / Common macros for compiler, platform, architecture detection and utility macro...
CPP_TOOLBOX_EXPORT auto get_environment_variable(const std::string &name) -> std::string
获取环境变量的值 (Retrieves the value of an environment variable)
< 用于 std::out_of_range/For std::out_of_range
Definition click.hpp:11
enum CPP_TOOLBOX_EXPORT WHITE
< 白色/White
Definition print.hpp:62
enum CPP_TOOLBOX_EXPORT GREEN
绿色/Green
Definition print.hpp:56
auto print_array(const std::array< T, N > &arr, const std::string &name="Array", const print_style_t &style=get_default_style()) -> array_printer_t< T, N >
打印array的工厂函数/Factory function to print array
Definition print.hpp:1675
enum CPP_TOOLBOX_EXPORT RED
红色/Red
Definition print.hpp:55
auto get_default_style() -> const print_style_t &
获取默认打印风格/Get default print style
Definition print.hpp:108
enum CPP_TOOLBOX_EXPORT align_t
左对齐/Left align
Definition print.hpp:40
enum CPP_TOOLBOX_EXPORT CYAN
青色/Cyan
Definition print.hpp:60
auto print_list(const std::list< T > &l, const std::string &name="List", const print_style_t &style=get_default_style()) -> list_printer_t< T >
打印list的工厂函数/Factory function to print list
Definition print.hpp:1653
auto align_text(const std::string &text, size_t width, align_t align, const std::string &padding=" ") -> std::string
处理对齐功能/Handle text alignment
Definition print.hpp:404
enum CPP_TOOLBOX_EXPORT color_t
默认颜色/Default color
Definition print.hpp:51
enum CPP_TOOLBOX_EXPORT YELLOW
黄色/Yellow
Definition print.hpp:57
auto print_map(const std::map< K, V > &m, const std::string &name="Map", const print_style_t &style=get_default_style()) -> map_printer_t< K, V >
打印map的工厂函数/Factory function to print map
Definition print.hpp:1547
auto get_rounded_style() -> const print_style_t &
获取圆角边框风格/Style using Unicode box drawing characters
Definition print.hpp:144
enum CPP_TOOLBOX_EXPORT BLACK
黑色/Black
Definition print.hpp:54
CPP_TOOLBOX_EXPORT std::ostream & operator<<(std::ostream &os, const table_t &tbl)
auto print_unordered_set(const std::unordered_set< T > &s, const std::string &name="Unordered Set", const print_style_t &style=get_default_style()) -> unorderedset_printer_t< T >
打印unordered_set的工厂函数/Factory function to print unordered_set
Definition print.hpp:1611
auto print_deque(const std::deque< T > &d, const std::string &name="Deque", const print_style_t &style=get_default_style()) -> deque_printer_t< T >
打印deque的工厂函数/Factory function to print deque
Definition print.hpp:1632
enum CPP_TOOLBOX_EXPORT BLUE
蓝色/Blue
Definition print.hpp:58
enum CPP_TOOLBOX_EXPORT CENTER
< 居中对齐/Center align
Definition print.hpp:45
auto get_ascii_style() -> const print_style_t &
获取 ASCII 风格的表格边框/Get ASCII style table borders
Definition print.hpp:121
auto print_vector(const std::vector< T > &vec, const std::string &name="Vector", const print_style_t &style=get_default_style()) -> vector_printer_t< T >
打印vector的工厂函数/Factory function to print vector
Definition print.hpp:1525
enum CPP_TOOLBOX_EXPORT RIGHT
右对齐/Right align
Definition print.hpp:43
auto print_queue(const std::queue< T > &q, const std::string &name="Queue", const print_style_t &style=get_default_style()) -> queue_printer_t< T >
打印queue的工厂函数/Factory function to print queue
Definition print.hpp:1697
auto to_string_value(const T &value) -> std::string
获取字符串表示形式的通用函数/Generic function to get string representation
Definition print.hpp:363
enum CPP_TOOLBOX_EXPORT MAGENTA
品红/Magenta
Definition print.hpp:59
auto print_set(const std::set< T > &s, const std::string &name="Set", const print_style_t &style=get_default_style()) -> set_printer_t< T >
打印set的工厂函数/Factory function to print set
Definition print.hpp:1590
auto print_unordered_map(const std::unordered_map< K, V > &m, const std::string &name="Unordered Map", const print_style_t &style=get_default_style()) -> unorderedmap_printer_t< K, V >
打印unordered_map的工厂函数/Factory function to print unordered_map
Definition print.hpp:1569
std::string top_joint
Definition print.hpp:81
std::string left_joint
Definition print.hpp:79
std::string right_joint
Definition print.hpp:80
std::string bottom_left
Definition print.hpp:77
std::string bottom_joint
Definition print.hpp:82
std::string center
Definition print.hpp:83
std::string top_right
Definition print.hpp:76
std::string bottom_right
Definition print.hpp:78
std::string top_left
Definition print.hpp:75
打印风格设置/Print style settings
Definition print.hpp:72
struct toolbox::utils::print_style_t::box_chars_t box
std::string border_v
垂直边框字符/Vertical border character
Definition print.hpp:87
std::string border_h
水平边框字符/Horizontal border character
Definition print.hpp:86
类型特征工具集合/Type traits utilities collection