summaryrefslogtreecommitdiff
path: root/Libraries/LibGUI
diff options
context:
space:
mode:
authorOriko <oriko1010@protonmail.com>2020-03-13 00:51:02 +0200
committerAndreas Kling <kling@serenityos.org>2020-03-13 22:53:13 +0100
commitc02037e944713d31d1cc113d8d261dfbcfe3e5ce (patch)
tree5ab6ec4d75d5a6e293c19500e655584a7ad85e05 /Libraries/LibGUI
parentac524b632f6f017ff6fe8321321bac3a5ba477a5 (diff)
downloadserenity-c02037e944713d31d1cc113d8d261dfbcfe3e5ce.zip
LibGUI: Abstract token pair matching
Diffstat (limited to 'Libraries/LibGUI')
-rw-r--r--Libraries/LibGUI/CppSyntaxHighlighter.cpp114
-rw-r--r--Libraries/LibGUI/CppSyntaxHighlighter.h5
-rw-r--r--Libraries/LibGUI/SyntaxHighlighter.cpp92
-rw-r--r--Libraries/LibGUI/SyntaxHighlighter.h18
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;