Created
June 19, 2021 05:45
-
-
Save snooze6214/630d3c6c8be0adb473b21d93e9e70056 to your computer and use it in GitHub Desktop.
we do a little pretty printed trees here
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <vector> | |
#include <string> | |
#include <sstream> | |
#include <algorithm> | |
#include <ostream> | |
class TextBox { | |
public: | |
struct xy { | |
TextBox& tb; | |
int x, y; | |
xy operator<< (const std::string& s) const { | |
return {tb, x + tb.puts(x, y, s), y}; | |
} | |
xy operator<< (const int i) const { | |
std::string s = std::to_string(i); | |
return {tb, x + tb.puts(x, y, s), y}; | |
} | |
xy operator<< (const char c) const { | |
tb.putc(x, y, c); | |
return {tb, x + 1, y}; | |
} | |
xy operator<< (const TextBox& _tb) const { | |
tb.puttb(x, y, _tb); | |
return {tb, x + _tb.width(), y}; | |
} | |
}; | |
std::string str() const { | |
std::stringstream ss; | |
for (auto& s : m_buffer) { | |
//ss << s << '\n'; | |
for (char c : s) { | |
if (c > 0b1111) | |
ss << c; | |
else { | |
switch (static_cast<int>(c) & 0b1111) { | |
case 0b01: | |
ss << '-'; | |
break; | |
case 0b10: | |
ss << '|'; | |
break; | |
case 0b11: | |
ss << '+'; | |
break; | |
default: | |
ss << c; | |
} | |
} | |
} | |
ss << '\n'; | |
} | |
return ss.str(); | |
} | |
TextBox::xy operator() (int x, int y) const { | |
return {const_cast<TextBox&>(*this), x, y}; | |
} | |
int width() const { | |
int w = -1; | |
for (auto& s : m_buffer) | |
w = std::max(w, static_cast<int>(s.size())); | |
return w; | |
} | |
int height() const { | |
return m_buffer.size(); | |
} | |
void hline(int x, int y, int width) { | |
if (y >= m_buffer.size()) | |
m_buffer.resize(y+1); | |
if (x+width >= m_buffer[y].size()) | |
m_buffer[y].resize(x+width, ' '); | |
for (int i = 0; i < width; i++) { | |
if (m_buffer[y][x+i] > 0b1111) | |
m_buffer[y][x+i] = 0; | |
m_buffer[y][x+i] |= 0b1; | |
} | |
} | |
void vline(int x, int y, int height) { | |
if (y+height >= m_buffer.size()) | |
m_buffer.resize(y+height); | |
for (int i = 0; i < height; i++) { | |
if (x >= m_buffer[y+i].size()) | |
m_buffer[y+i].resize(x+1, ' '); | |
if (m_buffer[y+i][x] > 0b1111) | |
m_buffer[y+i][x] = 0; | |
m_buffer[y+i][x] |= 0b10; | |
} | |
} | |
private: | |
void putc(int x, int y, char c) { | |
if (y >= m_buffer.size()) | |
m_buffer.resize(y+1); | |
if (x >= m_buffer[y].size()) | |
m_buffer[y].resize(x+1, ' '); | |
m_buffer[y][x] = c; | |
} | |
int puts(int x, int y, const std::string& s) { | |
if (s.empty()) return x; | |
for (int i = 0; i < s.size(); i++) | |
putc(x+i, y, s[i]); | |
return x + s.size(); | |
} | |
void puttb(int x, int y, const TextBox& tb) { | |
for (int i = 0; i < tb.height(); i++) { | |
puts(x, y+i, tb.m_buffer[i]); | |
} | |
} | |
private: | |
std::vector<std::string> m_buffer; | |
}; | |
template<typename T> | |
struct Tree { | |
struct TreeNode { | |
T data; | |
std::vector<TreeNode> children; | |
TreeNode(T _data) : data(_data) {} | |
void add_child(T c) { | |
children.emplace_back(c); | |
} | |
}; | |
TreeNode root; | |
Tree(T _root) : root(_root) {} | |
friend std::ostream& operator<< (std::ostream& os, Tree<T>& tree) { | |
TextBox tb = create_tree_textbox(tree.root); | |
os << tb.str(); | |
return os; | |
} | |
private: | |
static TextBox create_tree_textbox(const TreeNode& node) { | |
TextBox tb; | |
constexpr int padding = 2; | |
tb(0, 0) << node.data; | |
if (node.children.empty()) | |
return tb; | |
std::vector<TextBox> child_tbs; | |
for (auto child : node.children) | |
child_tbs.push_back(create_tree_textbox(child)); | |
tb.vline(0, 1, 1); | |
int i = 0; | |
for (auto child : child_tbs) { | |
tb.vline(i, 2, 2); | |
tb(i, 4) << child; | |
i += child.width() + padding; | |
} | |
tb.hline(0, 2, i - child_tbs[child_tbs.size() - 1].width() - padding + 1); | |
return tb; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment