42 enum Align { LEFT, CENTER, RIGHT };
44 TablePrinter(std::ostream &s, std::vector<std::string> headers, Align align = RIGHT)
45 : _s(s), _headers(headers), _align(align) {
46 for (
auto &h : headers) _colWidth.push_back(h.length());
49 bool empty() {
return _data.empty(); }
51 void addRow(std::vector<std::string> row) {
52 BUG_CHECK(row.size() == _headers.size(),
"row size does not match header");
56 for (
unsigned i = 0; i < row.size(); i++) {
57 if (row[i].length() > _colWidth[i]) _colWidth[i] = row[i].length();
61 void addSep(
unsigned start_col = 0) { _seps[_data.size()] = start_col; }
64 unsigned cols = _colWidth.size();
66 std::vector<std::string> blank(cols,
"");
76 for (
unsigned i = 0; i < _data.size(); i++) {
77 printRow(_data.at(i));
78 if (_seps.count(i + 1) && i + 1 != _data.size()) printSep(_seps.at(i + 1));
85 unsigned getTableWidth()
const {
87 for (
auto cw : _colWidth) rv += cw + cellPad;
88 return rv + _headers.size() + 1;
91 void printSep(
unsigned start_col = 0)
const {
92 for (
unsigned i = 0; i < _colWidth.size(); i++) {
93 _s << (i < start_col ?
"|" :
"+")
94 << std::string(_colWidth.at(i) + cellPad, i >= start_col ?
'-' :
' ');
97 _s <<
"+" << std::endl;
100 void printCell(
unsigned col, std::string data)
const {
101 unsigned width = _colWidth.at(col);
102 if (_align == LEFT) _s << std::left;
103 _s << std::setw(width + cellPad);
104 if (_align == CENTER) data += std::string((width + cellPad - data.length() + 1) / 2,
' ');
108 void printRow(
const std::vector<std::string> &row)
const {
109 for (
unsigned i = 0; i < row.size(); i++) {
112 printCell(i, row.at(i));
114 if (i == row.size() - 1) _s <<
"|";
121 std::vector<std::vector<std::string>> _data;
122 std::map<unsigned, unsigned> _seps;
124 std::vector<std::string> _headers;
125 std::vector<unsigned> _colWidth;
127 Align _align = RIGHT;
128 const unsigned cellPad = 2;