Branch data Line data Source code
1 : : #include <hpactor/cli/pretty_formatter.hpp>
2 : : #include <hpactor/cli/json_formatter.hpp>
3 : : #include <hpactor/cli/tabular_formatter.hpp>
4 : :
5 : : #include <algorithm>
6 : : #include <cstdio>
7 : : #include <cstdlib>
8 : :
9 : : namespace hpactor {
10 : : namespace cli {
11 : :
12 : : // UTF-8 box-drawing characters
13 : : static constexpr const char* kHDash = "\xe2\x94\x80"; // ─
14 : : static constexpr const char* kBranch = "\xe2\x94\x9c\xe2\x94\x80"; // ├─
15 : : static constexpr const char* kLast = "\xe2\x94\x94\xe2\x94\x80"; // └─
16 : :
17 : 16 : std::string PrettyFormatter::pad_right(const std::string& s, size_t width) {
18 : 16 : if (s.size() >= width) return s.substr(0, width);
19 : 26 : return s + std::string(width - s.size(), ' ');
20 : : }
21 : :
22 : 5 : std::string PrettyFormatter::horizontal_rule(size_t width) {
23 : 5 : std::string result;
24 : 5 : result.reserve(width * 3);
25 : 187 : for (size_t i = 0; i < width; ++i) result += kHDash;
26 : 5 : return result;
27 : : }
28 : :
29 : 2 : void PrettyFormatter::header(const std::string& title) {
30 : 2 : auto* cols_env = std::getenv("COLUMNS");
31 : 2 : if (cols_env) columns_ = std::atoi(cols_env);
32 : 2 : if (columns_ < 40) columns_ = 80;
33 : 2 : buffer_ += "\n" + bold(title) + "\n";
34 : 2 : buffer_ += dim(horizontal_rule(static_cast<size_t>(columns_))) + "\n";
35 : 2 : }
36 : :
37 : 1 : void PrettyFormatter::table(const std::vector<std::string>& cols,
38 : : const std::vector<std::vector<std::string>>& rows) {
39 : 1 : if (cols.empty()) return;
40 : 1 : std::vector<size_t> widths(cols.size());
41 : 4 : for (size_t i = 0; i < cols.size(); ++i) widths[i] = cols[i].size();
42 : 3 : for (const auto& row : rows)
43 : 8 : for (size_t i = 0; i < row.size() && i < widths.size(); ++i)
44 : 6 : widths[i] = std::max(widths[i], row[i].size());
45 : :
46 : 4 : for (size_t i = 0; i < cols.size(); ++i)
47 : 3 : buffer_ += bold(pad_right(cols[i], widths[i] + 2));
48 : 1 : buffer_ += "\n";
49 : :
50 : 4 : for (size_t i = 0; i < cols.size(); ++i)
51 : 3 : buffer_ += dim(pad_right(horizontal_rule(widths[i]), widths[i] + 2));
52 : 1 : buffer_ += "\n";
53 : :
54 : 3 : for (const auto& row : rows) {
55 : 8 : for (size_t i = 0; i < cols.size(); ++i)
56 : 6 : buffer_ += pad_right(i < row.size() ? row[i] : "-", widths[i] + 2);
57 : 2 : buffer_ += "\n";
58 : : }
59 : 1 : }
60 : :
61 : 2 : void PrettyFormatter::key_value(const std::map<std::string, std::string>& pairs) {
62 : 2 : size_t max_key = 0;
63 : 6 : for (const auto& kv : pairs) max_key = std::max(max_key, kv.first.size());
64 : 6 : for (const auto& kv : pairs)
65 : 4 : buffer_ += " " + cyan(pad_right(kv.first, max_key + 2)) + green(kv.second) + "\n";
66 : 2 : }
67 : :
68 : 0 : void PrettyFormatter::tree(const TreeNode& root) {
69 : 0 : auto print_node = [this](auto& self, const TreeNode& node, int depth, bool last) -> void {
70 : 0 : std::string indent(static_cast<size_t>(depth) * 2, ' ');
71 : 0 : if (depth > 0)
72 : 0 : buffer_ += indent + std::string(last ? kLast : kBranch) + " ";
73 : 0 : buffer_ += bold(node.name);
74 : 0 : if (!node.description.empty()) buffer_ += " " + dim(node.description);
75 : 0 : buffer_ += "\n";
76 : 0 : for (size_t i = 0; i < node.children.size(); ++i)
77 : 0 : self(self, node.children[i], depth + 1, i == node.children.size() - 1);
78 : 0 : };
79 : 0 : print_node(print_node, root, 0, true);
80 : 0 : }
81 : :
82 : 7 : void PrettyFormatter::raw(const std::string& text) {
83 : 7 : buffer_ += text;
84 : 7 : if (!text.empty() && text.back() != '\n') buffer_ += '\n';
85 : 7 : }
86 : :
87 : 1 : void PrettyFormatter::error(const std::string& message) {
88 : 1 : buffer_ += red("Error: ") + message + "\n";
89 : 1 : }
90 : :
91 : 8 : std::string PrettyFormatter::finalize() { return std::move(buffer_); }
92 : :
93 : 4 : std::unique_ptr<OutputFormatter> OutputFormatter::create(const std::string& format) {
94 : 4 : if (format == "json") return std::make_unique<JsonFormatter>();
95 : 3 : if (format == "tabular") return std::make_unique<TabularFormatter>();
96 : 2 : return std::make_unique<PrettyFormatter>();
97 : : }
98 : :
99 : : } // namespace cli
100 : : } // namespace hpactor
|