Added ConsoleRicuhString functionality, and custom text styling language

This commit is contained in:
OmniaX 2023-12-02 01:45:43 +01:00
parent ac3858b36d
commit 37f33e5a77
9 changed files with 449 additions and 88 deletions

View file

@ -29,7 +29,7 @@
"compilerPath": "C:\\msys64\\ucrt64\\bin\\clang++",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "linux-clang-x64"
"intelliSenseMode": "windows-clang-x64"
//"compileCommands": "${workspaceFolder}/compile_commands.json"
}
],

View file

@ -79,10 +79,10 @@ list(APPEND OSTD_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/ostd/ShuntingYard.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Signals.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Random.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/RichString.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Serial.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/SineWave.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/StringEditor.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/TextStyleParser.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Utils.cpp
)
#-----------------------------------------------------------------------------------------

View file

@ -2,6 +2,7 @@
#include "Color.hpp"
#include "BaseObject.hpp"
#include "Logger.hpp"
#include "TextStyleParser.hpp"
#include <TermColor.hpp>
#include <iomanip>
@ -163,6 +164,17 @@ namespace ostd
}
return *this;
}
IOutputHandler& ConsoleOutputHandler::pStyled(const String& styled)
{
return pStyled(TextStyleParser::parse(styled));
}
IOutputHandler& ConsoleOutputHandler::pStyled(const TextStyleParser::tStyledString& styled)
{
std::cout << styled;
return *this;
}
IOutputHandler& ConsoleOutputHandler::nl(void)
{

View file

@ -1,51 +0,0 @@
#include "RichString.hpp"
#include "Logger.hpp"
namespace ostd
{
tRichChar RichString::at(uint32_t index) const
{
if (index >= m_text.size())
{
OX_WARN("ox::RichString::at(...): Index out of bounds.");
return tRichChar();
}
return { (unsigned char)m_text[index], m_foreground[index], m_background[index] };
}
void RichString::add(tRichChar rchar)
{
m_text += rchar.ascii;
m_foreground.push_back(rchar.foreground);
m_background.push_back(rchar.background);
}
void RichString::add(String str, Color fg, Color bg)
{
for (auto& c : str)
{
m_text += c;
m_foreground.push_back(fg);
m_background.push_back(bg);
}
}
void RichString::add(String str)
{
Color fcol(255);
Color bcol(0, 0);
if (m_text.length() > 0)
{
fcol = m_foreground[m_foreground.size() - 1];
bcol = m_background[m_background.size() - 1];
}
add(str, fcol, bcol);
}
void RichString::clear(void)
{
m_text = "";
m_background.clear();
m_foreground.clear();
}
}

View file

@ -1,33 +0,0 @@
#ifndef __RICH_STRING_HPP__
#define __RICH_STRING_HPP__
#include <ostd/Color.hpp>
namespace ostd
{
struct tRichChar
{
unsigned char ascii { 0 };
Color foreground { 0, 0 };
Color background { 0, 0 };
};
class RichString
{
public:
inline RichString(void) { }
inline String getText(void) const { return m_text; }
tRichChar at(uint32_t index) const;
void add(tRichChar rchar);
void add(String str, Color fg, Color bg);
void add(String str);
void clear(void);
private:
String m_text { "" };
std::vector<Color> m_foreground;
std::vector<Color> m_background;
};
}
#endif

View file

@ -0,0 +1,316 @@
#include "TextStyleParser.hpp"
#include "Utils.hpp"
namespace ostd
{
std::ostream &operator<<(std::ostream &os, TextStyleParser::tStyledString const &str)
{
if (!str.validate()) return os;
ostd::ConsoleOutputHandler out;
for (int32_t i = 0; i < str.text.length(); i++)
out.col(str.backgroundColors[i].consoleColor).col(str.foregroundColors[i].consoleColor).p(str.text[i]);
out.reset();
return os;
}
std::ostream &operator<<(std::ostream &os, TextStyleBuilder::Console const &builder)
{
return os << builder.getStyledString();
}
void TextStyleParser::tColor::convertToBackground(void)
{
StringEditor edit(consoleColor);
if (edit.startsWith("o-")) return;
consoleColor = "o-" + edit.str();
}
void TextStyleParser::tColor::convertToForeground(void)
{
StringEditor edit(consoleColor);
if (!edit.startsWith("o-")) return;
consoleColor = edit.substr(2);
}
void TextStyleParser::tStyledString::add(const String& str, tColor background, tColor foreground)
{
text += str;
background.convertToBackground();
foreground.convertToForeground();
for (int32_t i = 0; i < str.length(); i++)
{
backgroundColors.push_back(background);
foregroundColors.push_back(foreground);
}
}
bool TextStyleParser::tStyledString::validate(void) const
{
return text.length() > 0 && text.length() == backgroundColors.size() && text.length() == foregroundColors.size();
}
TextStyleParser::tStyledString TextStyleParser::parse(const String& styledString)
{
return parse(styledString, ConsoleColors["black"], ConsoleColors["white"]);
}
TextStyleParser::tStyledString TextStyleParser::parse(const String& styledString, tColor defaultBackgorundColor, tColor defaultForegroundColor)
{
tStyledString rstring;
bool insideBlock = false;
bool validBlockStart = false;
int32_t countBlockStart = 0;
defaultBackgorundColor.convertToBackground();
defaultForegroundColor.convertToForeground();
s_defaultBackgroundColor = defaultBackgorundColor;
s_defaultForegroundColor = defaultForegroundColor;
tColor fgcol = defaultForegroundColor;
tColor bgcol = defaultBackgorundColor;
String blockText = "";
String _styledString = StringEditor(styledString).trim().str();
for (int32_t i = 0; i < _styledString.length(); i++)
{
char c = _styledString[i];
if (c == '[')
{
if (insideBlock)
return tStyledString(); //TODO: Error, no nested blocks allowed
insideBlock = true;
continue;
}
if(c == ']')
{
if (!insideBlock)
return tStyledString(); //TODO: Error, closing block without opeinng one
insideBlock = false;
validBlockStart = false;
countBlockStart = 0;
auto blockParseResult = parse_block(blockText, bgcol, fgcol);
if (blockParseResult == eBlockParserReturnValue::InvalidBlock)
return tStyledString(); //TODO: Error, Invalid block
blockText = "";
continue;
}
if (!insideBlock)
{
rstring.add(StringEditor("").add(c).str(), bgcol, fgcol);
continue;
}
if (validBlockStart)
{
blockText += c;
continue;
}
if (c == '@')
{
countBlockStart++;
if (countBlockStart == 2)
{
validBlockStart = true;
continue;
}
}
else
{
return tStyledString(); //TODO: Error, invalid block start sequence
}
}
return rstring;
}
TextStyleParser::eBlockParserReturnValue TextStyleParser::parse_block(const String& blockString, tColor& outBackgroundColor, tColor& outForegroundColor)
{
StringEditor blockEditor = blockString;
blockEditor.trim().toLower();
if (blockEditor.str() == BlockString_Close)
{
outBackgroundColor = s_defaultBackgroundColor;
outForegroundColor = s_defaultForegroundColor;
return eBlockParserReturnValue::CloseBlock;
}
if (blockEditor.startsWith(BlockString_Style))
{
blockEditor = blockEditor.substr(BlockString_Style.length());
blockEditor.trim();
blockEditor.replaceAll(" ", "");
auto tokens = blockEditor.tokenize(",");
for (auto param : tokens)
{
StringEditor paramEdit = param;
if (!paramEdit.contains(":"))
continue; //TODO: Error, invalid param
StringEditor name = paramEdit.substr(0, paramEdit.indexOf(":"));
name.trim();
StringEditor value = paramEdit.substr(paramEdit.indexOf(":") + 1);
value.trim();
if (name.str() == "background")
{
auto col = parse_color(value.str());
col.convertToBackground();
outBackgroundColor = col;
}
else if (name.str() == "foreground")
{
auto col = parse_color(value.str());
col.convertToForeground();
outForegroundColor = col;
}
else continue; //TODO: Error, unknown style parameter
}
}
return eBlockParserReturnValue::ValidBlock;
}
const TextStyleParser::tColor TextStyleParser::parse_color(const String& colorStr)
{
StringEditor colorStrEditor = colorStr;
colorStrEditor.trim().toLower();
for (auto& col : ConsoleColors)
{
if (col.first == colorStrEditor.str())
return col.second;
}
tColor col;
col.consoleColor = "black";
col.fullColor.set(colorStrEditor.str());
return col;
}
TextStyleBuilder::Console::Console(void)
{
m_backgroundColor = TextStyleParser::ConsoleColors["black"];
m_foregroundColor = TextStyleParser::ConsoleColors["white"];
m_backgroundColor.convertToBackground();
m_foregroundColor.convertToForeground();
}
TextStyleBuilder::Console& TextStyleBuilder::Console::bg(const String& consoleColor)
{
m_backgroundColor = find_color(consoleColor);
m_backgroundColor.convertToBackground();
return *this;
}
TextStyleBuilder::Console& TextStyleBuilder::Console::fg(const String& consoleColor)
{
m_foregroundColor = find_color(consoleColor);
m_foregroundColor.convertToForeground();
return *this;
}
TextStyleBuilder::Console& TextStyleBuilder::Console::clr(void)
{
m_styledString.backgroundColors.clear();
m_styledString.foregroundColors.clear();
m_styledString.text = "";
return *this;
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(const String& text)
{
m_styledString.add(text, m_backgroundColor, m_foregroundColor);
return *this;
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(uint8_t i)
{
StringEditor edit("");
edit.addi(i);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(int8_t i)
{
StringEditor edit("");
edit.addi(i);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(uint16_t i)
{
StringEditor edit("");
edit.addi(i);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(int16_t i)
{
StringEditor edit("");
edit.addi(i);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(uint32_t i)
{
StringEditor edit("");
edit.addi(i);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(int32_t i)
{
StringEditor edit("");
edit.addi(i);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(uint64_t i)
{
StringEditor edit("");
edit.addi(i);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(int64_t i)
{
StringEditor edit("");
edit.addi(i);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(float f)
{
StringEditor edit("");
edit.addf(f);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::add(double f)
{
StringEditor edit("");
edit.addf(f);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::addc(char c)
{
StringEditor edit("");
edit.add(c);
return add(edit.str());
}
TextStyleBuilder::Console& TextStyleBuilder::Console::print(IOutputHandler& out)
{
out.pStyled(m_styledString);
return *this;
}
TextStyleBuilder::Console& TextStyleBuilder::Console::print(void)
{
ConsoleOutputHandler out;
out.pStyled(m_styledString);
return *this;
}
TextStyleParser::tColor TextStyleBuilder::Console::find_color(const String& consoleColor)
{
StringEditor edit(consoleColor);
edit.toLower().trim();
if (auto findit = TextStyleParser::ConsoleColors.find(edit.str()); findit != TextStyleParser::ConsoleColors.end())
return findit->second;
return TextStyleParser::ConsoleColors["black"];
}
}

View file

@ -0,0 +1,110 @@
#pragma once
#include <ostd/Color.hpp>
#include <unordered_map>
namespace ostd
{
class TextStyleParser
{
public: enum class eBlockParserReturnValue { CloseBlock = 0, ValidBlock, InvalidBlock };
public: struct tColor {
Color fullColor;
String consoleColor;
void convertToBackground(void);
void convertToForeground(void);
};
public: struct tStyledString {
String text { "" };
std::vector<tColor> backgroundColors;
std::vector<tColor> foregroundColors;
void add(const String& str, tColor background, tColor foreground);
bool validate(void) const;
friend std::ostream& operator<<(std::ostream&, tStyledString const&);
};
public:
static tStyledString parse(const String& styledString);
static tStyledString parse(const String& styledString, tColor defaultBackgorundColor, tColor defaultForegroundColor);
private:
static eBlockParserReturnValue parse_block(const String& blockString, tColor& outBackgroundColor, tColor& outForegroundColor);
static const tColor parse_color(const String& colorStr);
private:
inline static tColor s_defaultBackgroundColor;
inline static tColor s_defaultForegroundColor;
inline static const String BlockString_Close = "/";
inline static const String BlockString_Style = "style";
public:
inline static std::unordered_map<String, tColor> ConsoleColors {
{ "red", { { 255, 0, 0, 255 }, "red" } },
{ "brightred", { { 255, 70, 70, 255 }, "b-red" } },
{ "green", { { 0, 255, 0, 255 }, "green" } },
{ "brightgreen", { { 70, 255, 70, 255 }, "b-green" } },
{ "blue", { { 0, 255, 0, 255 }, "blue" } },
{ "brightblue", { { 70, 70, 255, 255 }, "b-blue" } },
{ "magenta", { { 255, 0, 255, 255 }, "magenta" } },
{ "brightmagenta", { { 255, 120, 255, 255 }, "b-magenta" } },
{ "cyan", { { 0, 255, 255, 255 }, "cyan" } },
{ "brightcyan", { { 170, 120, 255, 255 }, "b-cyan" } },
{ "yellow", { { 255, 255, 0, 255 }, "yellow" } },
{ "brightyellow", { { 255, 255, 170, 255 }, "b-yellow" } },
{ "black", { { 0, 0, 0, 255 }, "gray" } },
{ "Gray", { { 50, 50, 50, 255 }, "b-gray" } },
{ "brightgray", { { 150, 150, 150, 255 }, "lgray" } },
{ "white", { { 255, 255, 255, 255 }, "white" } }
};
};
class TextStyleBuilder
{
public: class Console {
public:
Console(void);
Console& bg(const String& consoleColor);
Console& fg(const String& consoleColor);
Console& clr(void);
Console& add(const String& text);
Console& add(uint8_t i);
Console& add(int8_t i);
Console& add(uint16_t i);
Console& add(int16_t i);
Console& add(uint32_t i);
Console& add(int32_t i);
Console& add(uint64_t i);
Console& add(int64_t i);
Console& add(float f);
Console& add(double f);
Console& addc(char c);
Console& print(IOutputHandler& out);
Console& print(void);
inline TextStyleParser::tStyledString getStyledString(void) const { return m_styledString; }
friend std::ostream& operator<<(std::ostream&, Console const&);
private:
TextStyleParser::tColor find_color(const String& consoleColor);
private:
TextStyleParser::tStyledString m_styledString;
TextStyleParser::tColor m_backgroundColor;
TextStyleParser::tColor m_foregroundColor;
};
//TODO: Implement
// public: class FullColor {
// };
};
typedef TextStyleBuilder::Console ConsoleRichString;
}

View file

@ -2,6 +2,7 @@
#define __DATATYPES__HPP__
#include <ostd/Types.hpp>
#include <ostd/TextStyleParser.hpp>
#include <filesystem>
@ -315,7 +316,7 @@ namespace ostd
inline static constexpr const char* Gray = "lgray";
inline static constexpr const char* White = "white";
inline static constexpr const char* onGray = "o-lgray";
inline static constexpr const char* OnWhite = "ob-lgray";
inline static constexpr const char* OnWhite = "o-white";
};
class Color;
@ -340,6 +341,8 @@ namespace ostd
virtual IOutputHandler& pi(int64_t i) = 0;
virtual IOutputHandler& pf(float f, uint8_t precision = 0) = 0;
virtual IOutputHandler& pf(double f, uint8_t precision = 0) = 0;
virtual IOutputHandler& pStyled(const String& styled) = 0;
virtual IOutputHandler& pStyled(const TextStyleParser::tStyledString& styled) = 0;
virtual IOutputHandler& nl(void) = 0;
virtual IOutputHandler& flush(void) = 0;
virtual IOutputHandler& reset(void) = 0;
@ -372,6 +375,8 @@ namespace ostd
IOutputHandler& pi(int64_t i) override;
IOutputHandler& pf(float f, uint8_t precision = 0) override;
IOutputHandler& pf(double f, uint8_t precision = 0) override;
IOutputHandler& pStyled(const String& styled) override;
IOutputHandler& pStyled(const TextStyleParser::tStyledString& styled) override;
IOutputHandler& nl(void) override;
IOutputHandler& flush(void) override;
IOutputHandler& reset(void) override;
@ -398,6 +403,8 @@ namespace ostd
IOutputHandler& pi(int64_t i) override;
IOutputHandler& pf(float f, uint8_t precision = 0) override;
IOutputHandler& pf(double f, uint8_t precision = 0) override;
IOutputHandler& pStyled(const String& styled) override { return *this; };
IOutputHandler& pStyled(const TextStyleParser::tStyledString& styled) override { return *this; };
IOutputHandler& nl(void) override;
inline IOutputHandler& flush(void) override { return *this; }
inline IOutputHandler& reset(void) override { return *this; }

View file

@ -1 +1 @@
1718
1725