diff --git a/res/devtools/default_syntax_scheme.toml b/res/devtools/default_syntax_scheme.toml new file mode 100644 index 00000000..885defd6 --- /dev/null +++ b/res/devtools/default_syntax_scheme.toml @@ -0,0 +1,19 @@ +[default] +bold = false +italic = false +strikethrough = false +underline = false +color = [0.8, 0.8, 0.8, 1] + +[keyword] +bold = true +color = [0.9, 0.6, 0.4, 1] + +[literal] +color = [0.4, 0.8, 0.5, 1] + +[comment] +color = [0.5, 0.7, 1.0, 1] + +[error] +color = [1.0, 0.2, 0.1, 1] diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 571bf32f..dcca0f28 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -150,6 +150,18 @@ _MENU = _GUI_ROOT.menu menu = _MENU gui.root = _GUI_ROOT +do + local status, err = pcall(function() + local default_styles = toml.parse(file.read( + "res:devtools/default_syntax_scheme.toml" + )) + gui.set_syntax_styles(default_styles) + end) + if not status then + debug.error("could not to load default syntax scheme: "..err) + end +end + --- Console library extension --- console.cheats = {} diff --git a/src/devtools/SyntaxProcessor.cpp b/src/devtools/SyntaxProcessor.cpp index a4a1c7cf..c1c3f179 100644 --- a/src/devtools/SyntaxProcessor.cpp +++ b/src/devtools/SyntaxProcessor.cpp @@ -7,19 +7,15 @@ using namespace devtools; static std::unique_ptr build_styles( + const FontStylesScheme& colorScheme, const std::vector& tokens ) { using devtools::TokenTag; - FontStylesScheme styles { - { - {false, false, false, false, glm::vec4(0.8f, 0.8f, 0.8f, 1)}, // default - {true, false, false, false, glm::vec4(0.9, 0.6f, 0.4f, 1)}, // keyword - {false, false, false, false, glm::vec4(0.4, 0.8f, 0.5f, 1)}, // string - {false, false, false, false, glm::vec4(0.3, 0.3f, 0.3f, 1)}, // comment - {true, false, false, false, glm::vec4(1.0f, 0.2f, 0.1f, 1)}, // unexpected - }, - {} - }; + FontStylesScheme styles {colorScheme.palette, {}}; + if (styles.palette.empty()) { + styles.palette.push_back(FontStyle { + false, false, false, false, glm::vec4(0.8f, 0.8f, 0.8f, 1)}); + } size_t offset = 0; for (int i = 0; i < tokens.size(); i++) { const auto& token = tokens.at(i); @@ -47,6 +43,9 @@ static std::unique_ptr build_styles( styleIndex = 0; break; } + if (styleIndex >= styles.palette.size()) { + styleIndex = 0; + } styles.map.insert( styles.map.end(), token.end.pos - token.start.pos, styleIndex ); @@ -67,7 +66,9 @@ void SyntaxProcessor::addSyntax( } std::unique_ptr SyntaxProcessor::highlight( - const std::string& ext, std::wstring_view source + const FontStylesScheme& colorScheme, + const std::string& ext, + std::wstring_view source ) const { const auto& found = langsExtensions.find(ext); if (found == langsExtensions.end()) { @@ -76,7 +77,7 @@ std::unique_ptr SyntaxProcessor::highlight( const auto& syntax = *found->second; try { auto tokens = tokenize(syntax, "", source); - return build_styles(tokens); + return build_styles(colorScheme, tokens); } catch (const parsing_error& err) { return nullptr; } diff --git a/src/devtools/SyntaxProcessor.hpp b/src/devtools/SyntaxProcessor.hpp index afb975a8..d0ae41e7 100644 --- a/src/devtools/SyntaxProcessor.hpp +++ b/src/devtools/SyntaxProcessor.hpp @@ -18,7 +18,9 @@ namespace devtools { class SyntaxProcessor { public: std::unique_ptr highlight( - const std::string& ext, std::wstring_view source + const FontStylesScheme& colorScheme, + const std::string& ext, + std::wstring_view source ) const; void addSyntax(std::unique_ptr syntax); diff --git a/src/graphics/commons/FontStyle.cpp b/src/graphics/commons/FontStyle.cpp new file mode 100644 index 00000000..53cc0657 --- /dev/null +++ b/src/graphics/commons/FontStyle.cpp @@ -0,0 +1,37 @@ +#include "FontStyle.hpp" + +#include "data/dv.hpp" +#include "data/dv_util.hpp" +#include "devtools/SyntaxProcessor.hpp" + +FontStyle FontStyle::parse(const dv::value& src) { + FontStyle style {}; + src.at("bold").get(style.bold); + src.at("italic").get(style.italic); + src.at("strikethrough").get(style.strikethrough); + src.at("underline").get(style.underline); + dv::get_vec(src, "color", style.color); + return style; +} + +static void parse_style( + const dv::value& src, + FontStylesScheme& scheme, + const std::string& name, + devtools::SyntaxStyles tag +) { + if (src.has(name)) { + scheme.palette[static_cast(tag)] = FontStyle::parse(src[name]); + } +} + +FontStylesScheme FontStylesScheme::parse(const dv::value& src) { + FontStylesScheme scheme {}; + scheme.palette.resize(8); + parse_style(src, scheme, "default", devtools::SyntaxStyles::DEFAULT); + parse_style(src, scheme, "keyword", devtools::SyntaxStyles::KEYWORD); + parse_style(src, scheme, "literal", devtools::SyntaxStyles::LITERAL); + parse_style(src, scheme, "comment", devtools::SyntaxStyles::COMMENT); + parse_style(src, scheme, "error", devtools::SyntaxStyles::ERROR); + return scheme; +} diff --git a/src/graphics/commons/FontStyle.hpp b/src/graphics/commons/FontStyle.hpp new file mode 100644 index 00000000..5f0129f9 --- /dev/null +++ b/src/graphics/commons/FontStyle.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "data/dv_fwd.hpp" + +#include +#include + +struct FontStyle { + bool bold = false; + bool italic = false; + bool strikethrough = false; + bool underline = false; + glm::vec4 color {1, 1, 1, 1}; + + FontStyle() = default; + + FontStyle( + bool bold, + bool italic, + bool strikethrough, + bool underline, + glm::vec4 color + ) + : bold(bold), + italic(italic), + strikethrough(strikethrough), + underline(underline), + color(std::move(color)) { + } + + static FontStyle parse(const dv::value& src); +}; + +struct FontStylesScheme { + std::vector palette; + std::vector map; + + static FontStylesScheme parse(const dv::value& src); +}; diff --git a/src/graphics/core/Font.hpp b/src/graphics/core/Font.hpp index 12371595..f30335be 100644 --- a/src/graphics/core/Font.hpp +++ b/src/graphics/core/Font.hpp @@ -7,41 +7,14 @@ #include "typedefs.hpp" #include "FontMetics.hpp" +#include "data/dv_fwd.hpp" +#include "../commons/FontStyle.hpp" class Texture; class Batch2D; class Batch3D; class Camera; -struct FontStyle { - bool bold = false; - bool italic = false; - bool strikethrough = false; - bool underline = false; - glm::vec4 color {1, 1, 1, 1}; - - FontStyle() = default; - - FontStyle( - bool bold, - bool italic, - bool strikethrough, - bool underline, - glm::vec4 color - ) - : bold(bold), - italic(italic), - strikethrough(strikethrough), - underline(underline), - color(std::move(color)) { - } -}; - -struct FontStylesScheme { - std::vector palette; - std::vector map; -}; - class Font { int lineHeight; int yoffset; diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index 3ab438b1..99eb3375 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -80,6 +80,14 @@ std::shared_ptr GUI::getMenu() { return menu; } +void GUI::setSyntaxColorScheme(std::unique_ptr scheme) { + syntaxColorScheme = std::move(scheme); +} + +FontStylesScheme* GUI::getSyntaxColorScheme() const { + return syntaxColorScheme.get(); +} + void GUI::onAssetsLoad(Assets* assets) { rootDocument->rebuildIndices(); assets->store(rootDocument, "core:root"); diff --git a/src/graphics/ui/GUI.hpp b/src/graphics/ui/GUI.hpp index f2255fb5..16d8e358 100644 --- a/src/graphics/ui/GUI.hpp +++ b/src/graphics/ui/GUI.hpp @@ -17,6 +17,7 @@ struct CursorState; class Engine; class Input; class Window; +struct FontStylesScheme; namespace devtools { class Editor; @@ -73,6 +74,7 @@ namespace gui { std::shared_ptr focus; std::shared_ptr tooltip; std::shared_ptr rootDocument; + std::unique_ptr syntaxColorScheme; std::unordered_map> storage; std::unique_ptr uicamera; @@ -157,6 +159,9 @@ namespace gui { /// @deprecated std::shared_ptr getContainer() const; + void setSyntaxColorScheme(std::unique_ptr scheme); + FontStylesScheme* getSyntaxColorScheme() const; + void onAssetsLoad(Assets* assets); void postRunnable(const runnable& callback); diff --git a/src/graphics/ui/elements/TextBox.cpp b/src/graphics/ui/elements/TextBox.cpp index 83c15544..26160e12 100644 --- a/src/graphics/ui/elements/TextBox.cpp +++ b/src/graphics/ui/elements/TextBox.cpp @@ -918,7 +918,9 @@ void TextBox::onTab(bool shiftPressed) { void TextBox::refreshSyntax() { if (!syntax.empty()) { const auto& processor = gui.getEditor().getSyntaxProcessor(); - if (auto styles = processor.highlight(syntax, input)) { + auto scheme = gui.getSyntaxColorScheme(); + if (auto styles = + processor.highlight(scheme ? *scheme : FontStylesScheme {}, syntax, input)) { label->setStyles(std::move(styles)); } } diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index 01bfd0d6..79f5cfc4 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -1089,6 +1089,13 @@ static int l_gui_load_document(lua::State* L) { return 0; } +static int l_set_syntax_styles(lua::State* L) { + engine->getGUI().setSyntaxColorScheme(std::make_unique( + FontStylesScheme::parse(lua::tovalue(L, 1)) + )); + return 0; +} + const luaL_Reg guilib[] = { {"get_viewport", lua::wrap}, {"getattr", lua::wrap}, @@ -1101,6 +1108,7 @@ const luaL_Reg guilib[] = { {"confirm", lua::wrap}, {"alert", lua::wrap}, {"load_document", lua::wrap}, + {"set_syntax_styles", lua::wrap}, {"__reindex", lua::wrap}, {nullptr, nullptr} };