diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-11-18 19:10:06 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-11-18 19:10:06 +0100 |
commit | c8e02e60a6cfe9b6759c5cf1065d21759a8a4afc (patch) | |
tree | 245a16c0516701323bad3de22d8908a85416dc13 /DevTools/HackStudio | |
parent | 5f7f97355e48e4418d4e664555f019d590bdfcf3 (diff) | |
download | serenity-c8e02e60a6cfe9b6759c5cf1065d21759a8a4afc.zip |
HackStudio+LibGUI: Implement matching curly brace highlighting
This works for C++ syntax highlighted text documents by caching the C++
token type in a new "arbitrary data" member of GTextDocumentSpan.
When the cursor is placed immediately before a '{' or immediately after
a '}', we highlight both of these brace buddies by changing their
corresponding spans to have a different background color.
..and spans can also now have a custom background color. :^)
Diffstat (limited to 'DevTools/HackStudio')
-rw-r--r-- | DevTools/HackStudio/Editor.cpp | 69 | ||||
-rw-r--r-- | DevTools/HackStudio/Editor.h | 9 | ||||
-rw-r--r-- | DevTools/HackStudio/main.cpp | 3 |
3 files changed, 80 insertions, 1 deletions
diff --git a/DevTools/HackStudio/Editor.cpp b/DevTools/HackStudio/Editor.cpp index 682149b356..81d991a028 100644 --- a/DevTools/HackStudio/Editor.cpp +++ b/DevTools/HackStudio/Editor.cpp @@ -1,4 +1,5 @@ #include "Editor.h" +#include "CppLexer.h" #include "EditorWrapper.h" #include <AK/FileSystemPath.h> #include <LibCore/CDirIterator.h> @@ -170,3 +171,71 @@ void Editor::mousemove_event(GMouseEvent& event) } GApplication::the().hide_tooltip(); } + +void Editor::cursor_did_change() +{ + if (m_has_brace_buddies) { + if (m_brace_buddies[0].index >= 0 && m_brace_buddies[0].index < document().spans().size()) + document().set_span_at_index(m_brace_buddies[0].index, m_brace_buddies[0].span_backup); + if (m_brace_buddies[1].index >= 0 && m_brace_buddies[1].index < document().spans().size()) + document().set_span_at_index(m_brace_buddies[1].index, m_brace_buddies[1].span_backup); + m_has_brace_buddies = false; + update(); + } + + enum class Direction { + Forward, + Backward, + }; + + auto find_span_of_type = [&](int i, CppToken::Type type, CppToken::Type not_type, Direction direction) { + int nesting_level = 0; + bool forward = direction == Direction::Forward; + for (forward ? ++i : --i; forward ? (i < document().spans().size()) : (i >= 0); forward ? ++i : --i) { + auto& span = document().spans().at(i); + auto span_token_type = (CppToken::Type)((uintptr_t)span.data); + if (span_token_type == not_type) { + ++nesting_level; + } else if (span_token_type == type) { + if (nesting_level-- <= 0) + return i; + } + } + return -1; + }; + + auto make_buddies = [&](int index0, int index1) { + auto& buddy0 = const_cast<GTextDocumentSpan&>(document().spans()[index0]); + auto& buddy1 = const_cast<GTextDocumentSpan&>(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; + update(); + }; + + for (int i = 0; i < document().spans().size(); ++i) { + auto& span = const_cast<GTextDocumentSpan&>(document().spans().at(i)); + auto token_type = (CppToken::Type)((uintptr_t)span.data); + if (token_type == CppToken::Type::LeftCurly && span.range.start() == cursor()) { + auto buddy = find_span_of_type(i, CppToken::Type::RightCurly, CppToken::Type::LeftCurly, Direction::Forward); + if (buddy != -1) + make_buddies(i, buddy); + return; + } + + auto right_of_end = span.range.end(); + right_of_end.set_column(right_of_end.column() + 1); + if (token_type == CppToken::Type::RightCurly && right_of_end == cursor()) { + auto buddy = find_span_of_type(i, CppToken::Type::LeftCurly, CppToken::Type::RightCurly, Direction::Backward); + if (buddy != -1) + make_buddies(i, buddy); + return; + } + } +} diff --git a/DevTools/HackStudio/Editor.h b/DevTools/HackStudio/Editor.h index 87bd77692e..0b67cc788a 100644 --- a/DevTools/HackStudio/Editor.h +++ b/DevTools/HackStudio/Editor.h @@ -20,6 +20,7 @@ private: virtual void focusout_event(CEvent&) override; virtual void paint_event(GPaintEvent&) override; virtual void mousemove_event(GMouseEvent&) override; + virtual void cursor_did_change() override; void show_documentation_tooltip_if_available(const String&, const Point& screen_location); @@ -28,4 +29,12 @@ private: RefPtr<GWindow> m_documentation_tooltip_window; RefPtr<HtmlView> m_documentation_html_view; String m_last_parsed_token; + + struct BuddySpan { + int index { -1 }; + GTextDocumentSpan span_backup; + }; + + bool m_has_brace_buddies { false }; + BuddySpan m_brace_buddies[2]; }; diff --git a/DevTools/HackStudio/main.cpp b/DevTools/HackStudio/main.cpp index 4c6ee230a7..3ca86d6c13 100644 --- a/DevTools/HackStudio/main.cpp +++ b/DevTools/HackStudio/main.cpp @@ -423,7 +423,7 @@ int main(int argc, char** argv) remove_current_editor_action->set_enabled(g_all_editor_wrappers.size() > 1); }; - open_file("test.frm"); + open_file("main.cpp"); update_actions(); return app.exec(); @@ -484,6 +484,7 @@ static void rehighlight() span.color = style.color; span.font = style.font; span.is_skippable = token.m_type == CppToken::Type::Whitespace; + span.data = (void*)token.m_type; spans.append(span); } current_editor().document().set_spans(spans); |