summaryrefslogtreecommitdiff
path: root/DevTools/HackStudio
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-11-18 19:10:06 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-11-18 19:10:06 +0100
commitc8e02e60a6cfe9b6759c5cf1065d21759a8a4afc (patch)
tree245a16c0516701323bad3de22d8908a85416dc13 /DevTools/HackStudio
parent5f7f97355e48e4418d4e664555f019d590bdfcf3 (diff)
downloadserenity-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.cpp69
-rw-r--r--DevTools/HackStudio/Editor.h9
-rw-r--r--DevTools/HackStudio/main.cpp3
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);