some ansi codes

v2
Brett 2024-10-03 19:55:04 -04:00
parent bbb48a6b8f
commit 7fa4fd0af2
3 changed files with 572 additions and 428 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
include(cmake/color.cmake) include(cmake/color.cmake)
set(BLT_VERSION 2.0.4) set(BLT_VERSION 2.0.5)
set(BLT_TARGET BLT) set(BLT_TARGET BLT)

View File

@ -18,6 +18,149 @@
namespace blt::logging namespace blt::logging
{ {
namespace ansi
{
inline auto ESC(std::string_view str)
{
return std::string("\033") += str;
}
inline const auto CUR_HOME = ESC("[H");
inline auto CUR_MOVE(blt::size_t line, blt::size_t column)
{
return ESC("[{" + std::to_string(line) + "};{" + std::to_string(column) + "}H");
}
inline auto CUR_UP(blt::size_t lines)
{
return ESC("[" + std::to_string(lines) + "A");
}
inline auto CUR_DOWN(blt::size_t lines)
{
return ESC("[" + std::to_string(lines) + "B");
}
inline auto CUR_RIGHT(blt::size_t columns)
{
return ESC("[" + std::to_string(columns) + "C");
}
inline auto CUR_LEFT(blt::size_t columns)
{
return ESC("[" + std::to_string(columns) + "D");
}
inline auto CUR_BEGIN_NEXT(blt::size_t lines_down)
{
return ESC("[" + std::to_string(lines_down) + "E");
}
inline auto CUR_BEGIN_PREV(blt::size_t lines_up)
{
return ESC("[" + std::to_string(lines_up) + "F");
}
inline auto CUR_COLUMN(blt::size_t column)
{
return ESC("[" + std::to_string(column) + "G");
}
inline auto CUR_POS()
{
return ESC("[6n");
}
inline auto CUR_SCROLL_UP()
{
return ESC(" M");
}
inline auto CUR_SAVE_DEC()
{
return ESC(" 7");
}
inline auto CUR_LOAD_DEC()
{
return ESC(" 8");
}
inline auto CUR_SAVE_SCO()
{
return ESC("[s");
}
inline auto CUR_LOAD_SCO()
{
return ESC("[u");
}
inline auto RESET = ESC("[0m");
inline auto BOLD = "1";
inline auto RESET_BOLD = "22";
inline auto DIM = "2";
inline auto RESET_DIM = "22";
inline auto ITALIC = "3";
inline auto RESET_ITALIC = "23";
inline auto UNDERLINE = "4";
inline auto RESET_UNDERLINE = "24";
inline auto BLINKING = "5";
inline auto RESET_BLINKING = "25";
inline auto INVERSE = "7";
inline auto RESET_INVERSE = "27";
inline auto HIDDEN = "8";
inline auto RESET_HIDDEN = "28";
inline auto STRIKETHROUGH = "9";
inline auto RESET_STRIKETHROUGH = "29";
inline auto COLOR_DEFAULT = "39";
inline auto BACKGROUND_DEFAULT = "49";
inline auto BLACK = "30";
inline auto RED = "31";
inline auto GREEN = "32";
inline auto YELLOW = "33";
inline auto BLUE = "34";
inline auto MAGENTA = "35";
inline auto CYAN = "36";
inline auto WHITE = "37";
inline auto BLACK_BACKGROUND = "40";
inline auto RED_BACKGROUND = "41";
inline auto GREEN_BACKGROUND = "42";
inline auto YELLOW_BACKGROUND = "43";
inline auto BLUE_BACKGROUND = "44";
inline auto MAGENTA_BACKGROUND = "45";
inline auto CYAN_BACKGROUND = "46";
inline auto WHITE_BACKGROUND = "47";
inline auto BRIGHT_BLACK = "90";
inline auto BRIGHT_RED = "91";
inline auto BRIGHT_GREEN = "92";
inline auto BRIGHT_YELLOW = "93";
inline auto BRIGHT_BLUE = "94";
inline auto BRIGHT_MAGENTA = "95";
inline auto BRIGHT_CYAN = "96";
inline auto BRIGHT_WHITE = "97";
inline auto BRIGHT_BLACK_BACKGROUND = "100";
inline auto BRIGHT_RED_BACKGROUND = "101";
inline auto BRIGHT_GREEN_BACKGROUND = "102";
inline auto BRIGHT_YELLOW_BACKGROUND = "103";
inline auto BRIGHT_BLUE_BACKGROUND = "104";
inline auto BRIGHT_MAGENTA_BACKGROUND = "105";
inline auto BRIGHT_CYAN_BACKGROUND = "106";
inline auto BRIGHT_WHITE_BACKGROUND = "107";
template<typename... Args>
inline auto MAKE_COLOR(Args... colors)
{
std::string mode;
((mode + std::string(colors) + ";"), ...);
return ESC("[" + mode.substr(0, mode.size() - 1) + "m");
}
}
enum class log_level enum class log_level
{ {
// default // default
@ -146,7 +289,8 @@ namespace blt::logging
} else if constexpr (std::is_same_v<T, std::string>) } else if constexpr (std::is_same_v<T, std::string>)
{ {
log_internal(t, level, file, line, args); log_internal(t, level, file, line, args);
} else if constexpr (std::is_same_v<T, const char*>){ } else if constexpr (std::is_same_v<T, const char*>)
{
log_internal(std::string(t), level, file, line, args); log_internal(std::string(t), level, file, line, args);
} else } else
{ {
@ -216,15 +360,15 @@ namespace blt::logging
#include <ios> #include <ios>
#include <fstream> #include <fstream>
template<typename K, typename V> template<typename K, typename V>
using hashmap = std::unordered_map<K, V>; using hashmap = std::unordered_map<K, V>;
namespace blt::logging { namespace blt::logging {
/** /**
* Used to store fast associations between built in tags and their respective values * Used to store fast associations between built in tags and their respective values
*/ */
class tag_map { class tag_map {
private: private:
tag* tags; tag* tags;
size_t size; size_t size;
@ -279,9 +423,9 @@ namespace blt::logging {
delete[] tags; delete[] tags;
tags = nullptr; tags = nullptr;
} }
}; };
class LogFileWriter { class LogFileWriter {
private: private:
std::string m_path; std::string m_path;
std::fstream* output = nullptr; std::fstream* output = nullptr;
@ -319,7 +463,7 @@ namespace blt::logging {
clear(); clear();
delete(output); delete(output);
} }
}; };
#ifdef WIN32 #ifdef WIN32
#define BLT_NOW() auto t = std::time(nullptr); tm now{}; localtime_s(&now, &t) #define BLT_NOW() auto t = std::time(nullptr); tm now{}; localtime_s(&now, &t)
@ -339,7 +483,7 @@ namespace blt::logging {
S += ':'; \ S += ':'; \
S += ensureHasDigits(now.tm_sec, 2); S += ensureHasDigits(now.tm_sec, 2);
static inline std::string ensureHasDigits(int current, int digits) { static inline std::string ensureHasDigits(int current, int digits) {
std::string asString = std::to_string(current); std::string asString = std::to_string(current);
auto length = digits - asString.length(); auto length = digits - asString.length();
if (length <= 0) if (length <= 0)
@ -350,14 +494,14 @@ namespace blt::logging {
zeros += '0'; zeros += '0';
} }
return zeros + asString; return zeros + asString;
} }
log_format loggingFormat {}; log_format loggingFormat {};
hashmap<std::thread::id, std::string> loggingThreadNames; hashmap<std::thread::id, std::string> loggingThreadNames;
hashmap<std::thread::id, hashmap<blt::logging::log_level, std::string>> loggingStreamLines; hashmap<std::thread::id, hashmap<blt::logging::log_level, std::string>> loggingStreamLines;
LogFileWriter writer; LogFileWriter writer;
const std::unique_ptr<tag_map> tagMap = std::make_unique<tag_map>(tag_map{ const std::unique_ptr<tag_map> tagMap = std::make_unique<tag_map>(tag_map{
{"YEAR", [](const tag_func_param&) -> std::string { {"YEAR", [](const tag_func_param&) -> std::string {
BLT_NOW(); BLT_NOW();
return std::to_string(now.tm_year); return std::to_string(now.tm_year);
@ -442,9 +586,9 @@ namespace blt::logging {
{"STR", [](const tag_func_param& f) -> std::string { {"STR", [](const tag_func_param& f) -> std::string {
return f.formatted_string; return f.formatted_string;
}} }}
}); });
static inline std::vector<std::string> split(std::string s, const std::string& delim) { static inline std::vector<std::string> split(std::string s, const std::string& delim) {
size_t pos = 0; size_t pos = 0;
std::vector<std::string> tokens; std::vector<std::string> tokens;
while ((pos = s.find(delim)) != std::string::npos) { while ((pos = s.find(delim)) != std::string::npos) {
@ -454,9 +598,9 @@ namespace blt::logging {
} }
tokens.push_back(s); tokens.push_back(s);
return tokens; return tokens;
} }
inline std::string filename(const std::string& path){ inline std::string filename(const std::string& path){
if (loggingFormat.printFullFileName) if (loggingFormat.printFullFileName)
return path; return path;
auto paths = split(path, "/"); auto paths = split(path, "/");
@ -464,9 +608,9 @@ namespace blt::logging {
if (final == "/") if (final == "/")
return paths[paths.size()-2]; return paths[paths.size()-2];
return final; return final;
} }
class string_parser { class string_parser {
private: private:
std::string _str; std::string _str;
size_t _pos; size_t _pos;
@ -480,9 +624,9 @@ namespace blt::logging {
[[nodiscard]] inline bool has_next() const { [[nodiscard]] inline bool has_next() const {
return _pos < _str.size(); return _pos < _str.size();
} }
}; };
std::string stripANSI(const std::string& str){ std::string stripANSI(const std::string& str){
string_parser parser(str); string_parser parser(str);
std::string out; std::string out;
while (parser.has_next()){ while (parser.has_next()){
@ -493,9 +637,9 @@ namespace blt::logging {
out += c; out += c;
} }
return out; return out;
} }
void applyCFormatting(const std::string& format, std::string& output, std::va_list& args){ void applyCFormatting(const std::string& format, std::string& output, std::va_list& args){
// args must be copied because they will be consumed by the first vsnprintf // args must be copied because they will be consumed by the first vsnprintf
va_list args_copy; va_list args_copy;
va_copy(args_copy, args); va_copy(args_copy, args);
@ -509,12 +653,12 @@ namespace blt::logging {
delete[] buffer; delete[] buffer;
va_end(args_copy); va_end(args_copy);
} }
/** /**
* Checks if the next character in the parser is a tag opening, if not output the buffer to the out string * Checks if the next character in the parser is a tag opening, if not output the buffer to the out string
*/ */
inline bool tagOpening(string_parser& parser, std::string& out){ inline bool tagOpening(string_parser& parser, std::string& out){
char c = ' '; char c = ' ';
if (parser.has_next() && (c = parser.next()) == '{') if (parser.has_next() && (c = parser.next()) == '{')
if (parser.has_next() && (c = parser.next()) == '{') if (parser.has_next() && (c = parser.next()) == '{')
@ -524,9 +668,9 @@ namespace blt::logging {
else else
out += c; out += c;
return false; return false;
} }
void parseString(string_parser& parser, std::string& out, const std::string& userStr, log_level level, const char* file, int line){ void parseString(string_parser& parser, std::string& out, const std::string& userStr, log_level level, const char* file, int line){
while (parser.has_next()){ while (parser.has_next()){
char c = parser.next(); char c = parser.next();
std::string nonTag; std::string nonTag;
@ -562,9 +706,9 @@ namespace blt::logging {
out += nonTag; out += nonTag;
} }
} }
} }
std::string applyFormatString(const std::string& str, log_level level, const char* file, int line){ std::string applyFormatString(const std::string& str, log_level level, const char* file, int line){
// this can be speedup by preprocessing the string into an easily callable class // this can be speedup by preprocessing the string into an easily callable class
// where all the variables are ready to be substituted in one step // where all the variables are ready to be substituted in one step
// and all static information already entered // and all static information already entered
@ -573,9 +717,9 @@ namespace blt::logging {
parseString(parser, out, str, level, file, line); parseString(parser, out, str, level, file, line);
return out; return out;
} }
void log_internal(const std::string& format, log_level level, const char* file, int line, std::va_list& args) { void log_internal(const std::string& format, log_level level, const char* file, int line, std::va_list& args) {
std::string withoutLn = format; std::string withoutLn = format;
auto len = withoutLn.length(); auto len = withoutLn.length();
@ -628,9 +772,9 @@ namespace blt::logging {
writer.writeLine(path, stripANSI(finalFormattedOutput)); writer.writeLine(path, stripANSI(finalFormattedOutput));
} }
//std::cout.flush(); //std::cout.flush();
} }
void log_stream_internal(const std::string& str, const logger& logger) { void log_stream_internal(const std::string& str, const logger& logger) {
auto& s = loggingStreamLines[std::this_thread::get_id()][logger.level]; auto& s = loggingStreamLines[std::this_thread::get_id()][logger.level];
// s += str; // s += str;
for (char c : str){ for (char c : str){
@ -640,49 +784,49 @@ namespace blt::logging {
s = ""; s = "";
} }
} }
} }
void setThreadName(const std::string& name) { void setThreadName(const std::string& name) {
loggingThreadNames[std::this_thread::get_id()] = name; loggingThreadNames[std::this_thread::get_id()] = name;
} }
void setLogFormat(const log_format& format){ void setLogFormat(const log_format& format){
loggingFormat = format; loggingFormat = format;
} }
void setLogColor(log_level level, const std::string& newFormat){ void setLogColor(log_level level, const std::string& newFormat){
loggingFormat.levelColors[(int)level] = newFormat; loggingFormat.levelColors[(int)level] = newFormat;
} }
void setLogName(log_level level, const std::string& newFormat){ void setLogName(log_level level, const std::string& newFormat){
loggingFormat.levelNames[(int)level] = newFormat; loggingFormat.levelNames[(int)level] = newFormat;
} }
void setLogOutputFormat(const std::string& newFormat){ void setLogOutputFormat(const std::string& newFormat){
loggingFormat.logOutputFormat = newFormat; loggingFormat.logOutputFormat = newFormat;
} }
void setLogToFile(bool shouldLogToFile){ void setLogToFile(bool shouldLogToFile){
loggingFormat.logToFile = shouldLogToFile; loggingFormat.logToFile = shouldLogToFile;
} }
void setLogToConsole(bool shouldLogToConsole){ void setLogToConsole(bool shouldLogToConsole){
loggingFormat.logToConsole = shouldLogToConsole; loggingFormat.logToConsole = shouldLogToConsole;
} }
void setLogPath(const std::string& path){ void setLogPath(const std::string& path){
loggingFormat.logFilePath = path; loggingFormat.logFilePath = path;
} }
void setLogFileName(const std::string& fileName){ void setLogFileName(const std::string& fileName){
loggingFormat.logFileName = fileName; loggingFormat.logFileName = fileName;
} }
void setMaxFileSize(size_t fileSize) { void setMaxFileSize(size_t fileSize) {
loggingFormat.logMaxFileSize = fileSize; loggingFormat.logMaxFileSize = fileSize;
} }
void flush() { void flush() {
std::cerr.flush(); std::cerr.flush();
std::cout.flush(); std::cout.flush();
} }
void newline() void newline()
{ {
std::cout << std::endl; std::cout << std::endl;
} }
} }

@ -1 +1 @@
Subproject commit 93201da2ba5a6aba0a6e57ada64973555629b3e3 Subproject commit 63acc3336f941c6f324c88eb9ee4ce623a460cd5