diff options
author | Oriko <oriko1010@protonmail.com> | 2020-03-13 00:51:02 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-03-13 22:53:13 +0100 |
commit | c02037e944713d31d1cc113d8d261dfbcfe3e5ce (patch) | |
tree | 5ab6ec4d75d5a6e293c19500e655584a7ad85e05 /Libraries/LibGUI | |
parent | ac524b632f6f017ff6fe8321321bac3a5ba477a5 (diff) | |
download | serenity-c02037e944713d31d1cc113d8d261dfbcfe3e5ce.zip |
LibGUI: Abstract token pair matching
Diffstat (limited to 'Libraries/LibGUI')
-rw-r--r-- | Libraries/LibGUI/CppSyntaxHighlighter.cpp | 114 | ||||
-rw-r--r-- | Libraries/LibGUI/CppSyntaxHighlighter.h | 5 | ||||
-rw-r--r-- | Libraries/LibGUI/SyntaxHighlighter.cpp | 92 | ||||
-rw-r--r-- | Libraries/LibGUI/SyntaxHighlighter.h | 18 |
4 files changed, 124 insertions, 105 deletions
diff --git a/Libraries/LibGUI/CppSyntaxHighlighter.cpp b/Libraries/LibGUI/CppSyntaxHighlighter.cpp index aa68539ede..8f27fe3039 100644 --- a/Libraries/LibGUI/CppSyntaxHighlighter.cpp +++ b/Libraries/LibGUI/CppSyntaxHighlighter.cpp @@ -5,11 +5,6 @@ namespace GUI { -struct TextStyle { - Color color; - const Gfx::Font* font { nullptr }; -}; - static TextStyle style_for_token_type(CppToken::Type type) { switch (type) { @@ -79,105 +74,20 @@ void CppSyntaxHighlighter::rehighlight() m_editor->update(); } -void CppSyntaxHighlighter::highlight_matching_token_pair() +Vector<SyntaxHighlighter::MatchingTokenPair> CppSyntaxHighlighter::matching_token_pairs() const { - ASSERT(m_editor); - auto& document = m_editor->document(); - - enum class Direction { - Forward, - Backward, - }; - - auto find_span_of_type = [&](auto i, CppToken::Type type, CppToken::Type not_type, Direction direction) -> Optional<size_t> { - size_t nesting_level = 0; - bool forward = direction == Direction::Forward; - - if (forward) { - ++i; - if (i >= document.spans().size()) - return {}; - } else { - if (i == 0) - return {}; - --i; - } - - for (;;) { - auto& span = document.spans().at(i); - auto span_token_type = (CppToken::Type)((FlatPtr)span.data); - if (span_token_type == not_type) { - ++nesting_level; - } else if (span_token_type == type) { - if (nesting_level-- <= 0) - return i; - } - - if (forward) { - ++i; - if (i >= document.spans().size()) - return {}; - } else { - if (i == 0) - return {}; - --i; - } - } - - return {}; - }; - - auto make_buddies = [&](int index0, int index1) { - auto& buddy0 = const_cast<GUI::TextDocumentSpan&>(document.spans()[index0]); - auto& buddy1 = const_cast<GUI::TextDocumentSpan&>(document.spans()[index1]); - m_has_brace_buddies = true; - m_brace_buddies[0].index = index0; - m_brace_buddies[1].index = index1; - m_brace_buddies[0].span_backup = buddy0; - m_brace_buddies[1].span_backup = buddy1; - buddy0.background_color = Color::DarkCyan; - buddy1.background_color = Color::DarkCyan; - buddy0.color = Color::White; - buddy1.color = Color::White; - m_editor->update(); - }; - - struct MatchingTokenPair { - CppToken::Type open; - CppToken::Type close; - }; - - MatchingTokenPair pairs[] = { - { CppToken::Type::LeftCurly, CppToken::Type::RightCurly }, - { CppToken::Type::LeftParen, CppToken::Type::RightParen }, - { CppToken::Type::LeftBracket, CppToken::Type::RightBracket }, - }; - - for (size_t i = 0; i < document.spans().size(); ++i) { - auto& span = const_cast<GUI::TextDocumentSpan&>(document.spans().at(i)); - auto token_type = (CppToken::Type)((FlatPtr)span.data); - - for (auto& pair : pairs) { - if (token_type == pair.open && span.range.start() == m_editor->cursor()) { - auto buddy = find_span_of_type(i, pair.close, pair.open, Direction::Forward); - if (buddy.has_value()) - make_buddies(i, buddy.value()); - return; - } - } - - auto right_of_end = span.range.end(); - right_of_end.set_column(right_of_end.column() + 1); - - for (auto& pair : pairs) { - if (token_type == pair.close && right_of_end == m_editor->cursor()) { - auto buddy = find_span_of_type(i, pair.open, pair.close, Direction::Backward); - if (buddy.has_value()) - make_buddies(i, buddy.value()); - return; - } - } + static Vector<SyntaxHighlighter::MatchingTokenPair> pairs; + if (pairs.is_empty()) { + pairs.append({ reinterpret_cast<void*>(CppToken::Type::LeftCurly), reinterpret_cast<void*>(CppToken::Type::RightCurly) }); + pairs.append({ reinterpret_cast<void*>(CppToken::Type::LeftParen), reinterpret_cast<void*>(CppToken::Type::RightParen) }); + pairs.append({ reinterpret_cast<void*>(CppToken::Type::LeftBracket), reinterpret_cast<void*>(CppToken::Type::RightBracket) }); } + return pairs; +} + +bool CppSyntaxHighlighter::token_types_equal(void* token1, void* token2) const +{ + return static_cast<GUI::CppToken::Type>(reinterpret_cast<size_t>(token1)) == static_cast<GUI::CppToken::Type>(reinterpret_cast<size_t>(token2)); } CppSyntaxHighlighter::~CppSyntaxHighlighter() diff --git a/Libraries/LibGUI/CppSyntaxHighlighter.h b/Libraries/LibGUI/CppSyntaxHighlighter.h index a3f50deb0a..1d16f10c29 100644 --- a/Libraries/LibGUI/CppSyntaxHighlighter.h +++ b/Libraries/LibGUI/CppSyntaxHighlighter.h @@ -14,7 +14,10 @@ public: virtual SyntaxLanguage language() const override { return SyntaxLanguage::Cpp; } virtual void rehighlight() override; - virtual void highlight_matching_token_pair() override; + +protected: + virtual Vector<MatchingTokenPair> matching_token_pairs() const override; + virtual bool token_types_equal(void*, void*) const override; }; } diff --git a/Libraries/LibGUI/SyntaxHighlighter.cpp b/Libraries/LibGUI/SyntaxHighlighter.cpp index 0b4db76bcc..2726f73ff4 100644 --- a/Libraries/LibGUI/SyntaxHighlighter.cpp +++ b/Libraries/LibGUI/SyntaxHighlighter.cpp @@ -7,6 +7,98 @@ SyntaxHighlighter::~SyntaxHighlighter() { } +void SyntaxHighlighter::highlight_matching_token_pair() +{ + ASSERT(m_editor); + auto& document = m_editor->document(); + + enum class Direction { + Forward, + Backward, + }; + + auto find_span_of_type = [&](auto i, void* type, void* not_type, Direction direction) -> Optional<size_t> { + size_t nesting_level = 0; + bool forward = direction == Direction::Forward; + + if (forward) { + ++i; + if (i >= document.spans().size()) + return {}; + } else { + if (i == 0) + return {}; + --i; + } + + for (;;) { + auto& span = document.spans().at(i); + auto span_token_type = span.data; + if (token_types_equal(span_token_type, not_type)) { + ++nesting_level; + } else if (token_types_equal(span_token_type, type)) { + if (nesting_level-- <= 0) + return i; + } + + if (forward) { + ++i; + if (i >= document.spans().size()) + return {}; + } else { + if (i == 0) + return {}; + --i; + } + } + + return {}; + }; + + auto make_buddies = [&](int index0, int index1) { + auto& buddy0 = document.spans()[index0]; + auto& buddy1 = document.spans()[index1]; + m_has_brace_buddies = true; + m_brace_buddies[0].index = index0; + m_brace_buddies[1].index = index1; + m_brace_buddies[0].span_backup = buddy0; + m_brace_buddies[1].span_backup = buddy1; + buddy0.background_color = Color::DarkCyan; + buddy1.background_color = Color::DarkCyan; + buddy0.color = Color::White; + buddy1.color = Color::White; + m_editor->update(); + }; + + auto pairs = matching_token_pairs(); + + for (size_t i = 0; i < document.spans().size(); ++i) { + auto& span = const_cast<GUI::TextDocumentSpan&>(document.spans().at(i)); + auto token_type = span.data; + + for (auto& pair : pairs) { + if (token_types_equal(token_type, pair.open) && span.range.start() == m_editor->cursor()) { + auto buddy = find_span_of_type(i, pair.close, pair.open, Direction::Forward); + if (buddy.has_value()) + make_buddies(i, buddy.value()); + return; + } + } + + auto right_of_end = span.range.end(); + right_of_end.set_column(right_of_end.column() + 1); + + for (auto& pair : pairs) { + if (token_types_equal(token_type, pair.close) && right_of_end == m_editor->cursor()) { + auto buddy = find_span_of_type(i, pair.open, pair.close, Direction::Backward); + if (buddy.has_value()) + make_buddies(i, buddy.value()); + return; + } + } + } +} + void SyntaxHighlighter::attach(TextEditor& editor) { ASSERT(!m_editor); diff --git a/Libraries/LibGUI/SyntaxHighlighter.h b/Libraries/LibGUI/SyntaxHighlighter.h index 8a15114381..a89ea80f0e 100644 --- a/Libraries/LibGUI/SyntaxHighlighter.h +++ b/Libraries/LibGUI/SyntaxHighlighter.h @@ -8,7 +8,13 @@ namespace GUI { enum class SyntaxLanguage { PlainText, - Cpp + Cpp, + Javascript +}; + +struct TextStyle { + Color color; + const Gfx::Font* font { nullptr }; }; class SyntaxHighlighter { @@ -20,7 +26,7 @@ public: virtual SyntaxLanguage language() const = 0; virtual void rehighlight() = 0; - virtual void highlight_matching_token_pair() = 0; + virtual void highlight_matching_token_pair(); virtual bool is_identifier(void*) const { return false; }; virtual bool is_navigatable(void*) const { return false; }; @@ -34,6 +40,14 @@ protected: WeakPtr<TextEditor> m_editor; + struct MatchingTokenPair { + void* open; + void* close; + }; + + virtual Vector<MatchingTokenPair> matching_token_pairs() const = 0; + virtual bool token_types_equal(void*, void*) const = 0; + struct BuddySpan { int index { -1 }; GUI::TextDocumentSpan span_backup; |