From cc0bca634fb10a275e8476ec1e316c14b4d4f67b Mon Sep 17 00:00:00 2001 From: NaifBanana <30419422+NaifBanana@users.noreply.github.com> Date: Thu, 12 Feb 2026 01:05:33 -0600 Subject: [PATCH] Working on printing tables. Not done but have a framework going. --- engine/NBCore/ANSITerm.hpp | 194 +++++++++++++++++++++++++++++ engine/NBCore/Logger.hpp | 23 +++- engine/NBCore/TypeTraits.hpp | 33 +++++ engine/NBCore/tests/testErrors.cpp | 6 +- 4 files changed, 252 insertions(+), 4 deletions(-) create mode 100644 engine/NBCore/ANSITerm.hpp create mode 100644 engine/NBCore/TypeTraits.hpp diff --git a/engine/NBCore/ANSITerm.hpp b/engine/NBCore/ANSITerm.hpp new file mode 100644 index 0000000..448a5e8 --- /dev/null +++ b/engine/NBCore/ANSITerm.hpp @@ -0,0 +1,194 @@ +#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 \ No newline at end of file diff --git a/engine/NBCore/Logger.hpp b/engine/NBCore/Logger.hpp index 30d676c..8edef28 100644 --- a/engine/NBCore/Logger.hpp +++ b/engine/NBCore/Logger.hpp @@ -4,12 +4,13 @@ #include #include +#include #include #include #include -#include #include +#include "ANSITerm.hpp" #include "DataSink.hpp" #include "Processes.hpp" #include "ThreadSafeQueue.hpp" @@ -151,6 +152,13 @@ private: class DefaultDebugLogger : public DebugLogger { using LoggerType = DefaultDebugLogger; using Base = DebugLogger; + template + struct Field { + Field(int w, U v) : width{w}, val(v) {} + int width; + U val; + }; + public: using Base::Base; @@ -158,18 +166,27 @@ public: friend class BufferedDataProcessor, DefaultDebugLogger>; + template + friend STR& operator<<(STR&, const DefaultDebugLogger::Field&); + protected: using Base::_ostream; bool process(const LogEvent& msg) { for (const auto os : this->_ostream) { - (*os) << msg.pid << " - " << msg.tid << " : " << msg.msg << "\n"; + (*os) << "[ " << ANSITextColor("hey") << " | " + << Field(2, msg.tid) << " | " << Field(10, msg.msg) << " ]\n"; } return true; } - }; +template +STR& operator<<(STR& stream, const DefaultDebugLogger::Field& field) { + stream << std::setw(field.width) << field.val; + return stream; +} + /* class BasicLogger : public LoggerBase { public: using Base = LoggerBase; diff --git a/engine/NBCore/TypeTraits.hpp b/engine/NBCore/TypeTraits.hpp new file mode 100644 index 0000000..a049183 --- /dev/null +++ b/engine/NBCore/TypeTraits.hpp @@ -0,0 +1,33 @@ +#pragma once +#ifndef _NB_TYPE_TRAITS +#define _NB_TYPE_TRAITS + +#include + +namespace nb { + +template +inline typename std::enable_if::type +ForEach(std::tuple&, Func) {} + +template +inline typename std::enable_if::type +ForEach(std::tuple& tup, Func f) { + f(N, std::get(tup)); + ForEach(tup, f); +} + +template +inline typename std::enable_if::type +ForEach(std::tuple&, Func, const Args&) {} + +template +inline typename std::enable_if::type +ForEach(std::tuple& tup, Func f, const Args& arg) { + f(N, std::get(tup), arg); + ForEach(tup, f, arg); +} + +} // namespace nb + +#endif // _NB_TYPE_TRAITS \ No newline at end of file diff --git a/engine/NBCore/tests/testErrors.cpp b/engine/NBCore/tests/testErrors.cpp index 196ab32..73a4987 100644 --- a/engine/NBCore/tests/testErrors.cpp +++ b/engine/NBCore/tests/testErrors.cpp @@ -3,6 +3,7 @@ #include "Errors.hpp" #include #include +#include #include "Logger.hpp" using namespace nb; @@ -30,11 +31,14 @@ const ErrorCodeMap TestError::ErrorMessages{ TEST(ErrorTest, Test) { EXPECT_EQ(1, 1); - nb::DefaultDebugLogger logr(std::cout, std::cout, std::cout); + std::stringstream sstream; + nb::DefaultDebugLogger logr(std::cout, sstream); ASSERT_TRUE(logr.run()); ASSERT_TRUE(logr.isRunning()); while (!logr.isRunning()){ 1+1; } logr.log("Hey!"); + logr.stop(); + std::cout << "STRINGSTREAM:\n" << sstream.str(); } \ No newline at end of file