#pragma once #ifndef _NB_SMARTSTREAM #define _NB_SMARTSTREAM #include #include #include #include #include namespace nb { using RGB = std::array; std::string toANSI(const RGB& color) { return "\x1b[38;2;"+std::to_string(color[0])+";"+std::to_string(color[1])+ ";"+std::to_string(color[2])+"m"; } std::string toANSI(const unsigned int& color) { return "\x1b[38;5;"+std::to_string(color)+"m"; } template struct SmartText { SmartText(const U& val) : msg(val) {} const U msg; template void process(std::basic_ostream& stream) const; }; template struct SmartText { template SmartText(char const(&val) [N]) : msg(val) {} SmartText(const std::string& val) : msg(val) {} SmartText(const char* val) : msg(val) {} const std::string msg; template void process(std::basic_ostream& stream) const; }; template template void SmartText::process(std::basic_ostream& stream) const { if (std::is_void::value) { stream << msg; } else { static_cast(this)->process(stream); } } template std::basic_ostream& operator<<(std::basic_ostream& stream, const SmartText& smt) { if (std::is_void::value) { stream << smt.msg; } else { static_cast(&smt)->process(stream); } return stream; } template struct TerminalColor : public SmartText> { typedef SmartText> Base; using Base::msg; explicit TerminalColor(unsigned int color, const U& val) : Base(val), colorSequence(toANSI(color)) { } explicit TerminalColor(const RGB& color, const U& val) : Base(val), colorSequence(toANSI(color)) { } const std::string colorSequence; template void process(std::basic_ostream& stream) const { if (&stream == &std::cout) { stream << colorSequence << msg << "\x1b[0m"; } else { stream << msg; } } }; } #endif // _NB_SMARTSTREAM