33 table(
size_t column_count) : cols_count(column_count) {}
38 std::vector<std::string> colnames;
46 std::vector<std::string> cols;
47 positionning position;
50 std::vector<std::variant<rule, double_rule, rulled_data, data>> table_lines;
52 void add_rule() { table_lines.push_back(
rule{}); }
53 void add_double_rule() { table_lines.push_back(double_rule{}); }
54 void add_rulled_data(
const std::vector<std::string> &colnames) {
55 if (colnames.size() != cols_count) {
57 "the number of column does not match colnames.size() != cols_count ({} != {})",
63 void add_data(
const std::vector<std::string> &cols, positionning position) {
64 if (cols.size() != cols_count) {
66 "the number of column does not match cols.size() != cols_count ({} != {})",
70 table_lines.push_back(
data{.cols = cols, .position = position});
73 std::vector<size_t> compute_widths() {
74 std::vector<size_t> widths(cols_count);
75 for (
auto &line : table_lines) {
76 if (
data *data_line = std::get_if<data>(&line)) {
77 for (
u32 i = 0; i < cols_count; i++) {
78 widths[i] = std::max(widths[i], data_line->cols[i].size());
80 }
else if (
rulled_data *head_and_ruller_line = std::get_if<rulled_data>(&line)) {
81 for (
u32 i = 0; i < cols_count; i++) {
82 widths[i] = std::max(widths[i], head_and_ruller_line->colnames[i].size());
89 std::string render() {
91 std::vector<size_t> widths = compute_widths();
93 std::string
print =
"";
94 for (
auto &line : table_lines) {
95 if (
data *data_line = std::get_if<data>(&line)) {
97 for (
u32 i = 0; i < cols_count; i++) {
98 if (data_line->position == left) {
99 print += shambase::format(
" {:<{}} |", data_line->cols[i], widths[i]);
100 }
else if (data_line->position == right) {
101 print += shambase::format(
" {:>{}} |", data_line->cols[i], widths[i]);
102 }
else if (data_line->position == center) {
103 print += shambase::format(
" {:^{}} |", data_line->cols[i], widths[i]);
107 }
else if (
rulled_data *head_and_ruller_line = std::get_if<rulled_data>(&line)) {
108 std::string tmp =
"+";
109 for (
u32 i = 0; i < cols_count; i++) {
110 tmp += shambase::format(
111 " {:^{}} +", head_and_ruller_line->colnames[i], widths[i]);
114 auto neigh_char_is_good = [&](
char c) ->
bool {
115 return c ==
' ' || c ==
'-' || c ==
'<' || c ==
'>' || c ==
'+';
118 std::vector<bool> set_to_space = std::vector<bool>(tmp.size(),
false);
120 for (
size_t i = 1; i < tmp.size() - 1; i++) {
121 if (tmp[i] ==
' ' && neigh_char_is_good(tmp[i - 1])
122 && neigh_char_is_good(tmp[i + 1])) {
123 set_to_space[i] =
true;
127 for (
size_t i = 0; i < tmp.size() - 1; i++) {
128 if (set_to_space[i]) {
133 }
else if (
rule *rule_line = std::get_if<rule>(&line)) {
135 for (
u32 i = 0; i < cols_count; i++) {
136 print += shambase::format(
137 "-{:<{}}-+", std::string(widths[i],
'-'), widths[i]);
139 }
else if (
double_rule *double_rule_line = std::get_if<double_rule>(&line)) {
141 for (
u32 i = 0; i < cols_count; i++) {
142 print += shambase::format(
143 "={:<{}}=+", std::string(widths[i],
'='), widths[i]);