#pragma once #ifndef _NB_ANSI_TERM #define _NB_ANSI_TERM #include #include #include #include #include #include #include #include "TypeTraits.hpp" namespace nb { template struct SmartText { using Type = ST; using ValType = U; static constexpr bool HasChild = Type::HasChild; }; template struct StyleFormatter : SmartText, U> { using Base = SmartText>; using Base::Type; using Base::ValType; static constexpr bool HasChild = true; std::string fmt; ValType val; std::string closing; }; template struct StyleFormatter : SmartText, void>{ using Base = SmartText; using Base::Type; using Base::ValType; static constexpr bool HasChild = false; std::string fmt; }; template struct ANSITextColor; template struct ANSITextColor : StyleFormatter, U> { using Base = StyleFormatter; using Base::ValType using Base::HasChild; template ::type> ANSITextColor(const U& _val) : Base{"\x1b[39m", _val, "\x1b[39m"} {} template > ANSITextColor() : Base{"\x1b[92m"} {} }; template <> struct ANSITextColor : StyleFormatter, std::string> { using Base = StyleFormatter, std::string>; static constexpr bool HasChild = Base::HasChild; template ANSITextColor(char const(&_val) [N]) : Base{"\x1b[92m", _val, "\x1b[39m"} {} ANSITextColor(const char* _val) : Base{"\x1b[92m", _val, "\x1b[39m"} {} ANSITextColor(const std::string& _val) : Base{"\x1b[92m", _val, "\x1b[39m"} {} }; struct CellBase { uint8_t width; uint8_t height; }; template struct Cell : SmartText, T> { using Base = SmartText, T>; using Base::ValType using Base::HasChild; Cell(const Type& _val, const uint8_t& w, const uint8_t& h=1) : val(_val), width(w), height(h) {} Type val; uint8_t width; uint8_t height; }; template <> struct Cell : SmartText, std::string> { using Base = SmartText, std::string>; using Base::ValType using Base::HasChild; template Cell( const(&_val) [N], const uint8_t& w, const uint8_t& h=0) : Cell(std::string(_val), w, h) {} Cell(char* _val, const uint8_t& w, const uint8_t& h=0) : Cell(std::string(_val), w, h) {} Cell(const ValType& _val, const uint8_t& w, const uint8_t& h=0) : val(_val), width(w) { unsigned int strsize = _val.size(); height = strsize / width; height += (strsize % width) ? 1 : 0; } ValType val; uint8_t width; uint8_t height; }; template std::ostream& operator<<(std::ostream& stream, const Cell& cll) { } template void ChangeCellHeight(int i, Cell& cll, const unsigned int& h) { if (h < cll.height) { cll.height=h; } } template void GetTallestCell(int i, Cell& cll, unsigned int& h) { if (cll.height > h) { h = cll.height; } } template struct TableRow { using RowCells = std::tuple...>; using CellWidths = std::array; using DelimiterArray = std::array; TableRow(CellWidths&& widths_, DelimiterArray&& delims_, const Pack&... vals_) : _widths(widths_), _delimiters(delims_) { nb::ForEach(_cells, GetTallestCell, _height); } static constexpr int num_columns = sizeof...(Pack); int height() const { return height; } inline int height(const unsigned int newh) { nb::ForEach(_cells, ChangeCellHeight, newh); return (_height=newh); } protected: const CellWidths _widths; const DelimiterArray _delimiters; RowCells _cells; int _height; }; template class Table { public: Table(const Pack&... _vals) : row(std::array(10), std::array(""), _vals...) {} private: TableRow row; }; } // namespace nb template std::ostream& operator<<(std::ostream& stream, const nb::StyleFormatter& msg) { if (&stream == &std::cout) { stream << msg.fmt; if (msg.HasChild) { stream << msg.val << msg.closing; } } else { if (msg.HasChild) { stream << msg.val; } } stream << std::flush; return stream; } #ifdef _NB_TARGET_WINDOWS template std::ostream& operator<<(std::ostream& stream, const nb::TableRow& row) { using PosType = decltype(stream.tellp()); constexpr int num_cells = sizeof...(Types); int col_num = 0; int col_start = 0; return stream; } #endif // _NB_TARGET_WINDOWS #endif // _NB_ANSI_TERM