HackStudio: Add header navigation

This commit is contained in:
Oriko 2020-03-12 00:18:13 +02:00 committed by Andreas Kling
parent d8a73dd979
commit 879bf3e97b
4 changed files with 95 additions and 4 deletions

View file

@ -34,14 +34,14 @@
#include <LibGUI/Painter.h>
#include <LibGUI/ScrollBar.h>
#include <LibGUI/Window.h>
#include <LibMarkdown/MDDocument.h>
#include <LibWeb/DOM/ElementFactory.h>
#include <LibWeb/DOM/HTMLHeadElement.h>
#include <LibWeb/DOM/Text.h>
#include <LibWeb/HtmlView.h>
#include <LibWeb/Parser/HTMLParser.h>
#include <LibMarkdown/MDDocument.h>
//#define EDITOR_DEBUG
// #define EDITOR_DEBUG
Editor::Editor()
{
@ -194,3 +194,76 @@ void Editor::mousemove_event(GUI::MouseEvent& event)
}
GUI::Application::the().hide_tooltip();
}
void Editor::mousedown_event(GUI::MouseEvent& event)
{
if (!(event.modifiers() & Mod_Ctrl)) {
GUI::TextEditor::mousedown_event(event);
return;
}
auto text_position = text_position_at(event.position());
if (!text_position.is_valid()) {
GUI::TextEditor::mousedown_event(event);
return;
}
for (auto& span : document().spans()) {
if (span.range.contains(text_position)) {
auto adjusted_range = span.range;
adjusted_range.end().set_column(adjusted_range.end().column() + 1);
auto span_text = document().text_in_range(adjusted_range);
auto header_path = span_text.substring(1, span_text.length() - 2);
#ifdef EDITOR_DEBUG
dbg() << "Ctrl+click: " << adjusted_range << " \"" << header_path << "\"";
#endif
navigate_to_include_if_available(header_path);
return;
}
}
GUI::TextEditor::mousedown_event(event);
}
static HashMap<String, String>& include_paths()
{
static HashMap<String, String> paths;
auto add_directory = [](String base, Optional<String> recursive, auto handle_directory) -> void {
Core::DirIterator it(recursive.value_or(base), Core::DirIterator::Flags::SkipDots);
while (it.has_next()) {
auto path = it.next_full_path();
if (!Core::File::is_directory(path)) {
auto key = path.substring(base.length() + 1, path.length() - base.length() - 1);
#ifdef EDITOR_DEBUG
dbg() << "Adding header \"" << key << "\" in path \"" << path << "\"";
#endif
paths.set(key, path);
} else {
handle_directory(base, path, handle_directory);
}
}
};
if (paths.is_empty()) {
add_directory(".", {}, add_directory);
add_directory("/usr/local/include", {}, add_directory);
add_directory("/usr/local/include/c++/9.2.0", {}, add_directory);
add_directory("/usr/include", {}, add_directory);
}
return paths;
}
void Editor::navigate_to_include_if_available(String path)
{
auto it = include_paths().find(path);
if (it == include_paths().end()) {
#ifdef EDITOR_DEBUG
dbg() << "no header " << path << " found.";
#endif
return;
}
on_open(it->value);
}

View file

@ -37,6 +37,7 @@ public:
virtual ~Editor() override;
Function<void()> on_focus;
Function<void(String)> on_open;
EditorWrapper& wrapper();
const EditorWrapper& wrapper() const;
@ -46,8 +47,10 @@ private:
virtual void focusout_event(Core::Event&) override;
virtual void paint_event(GUI::PaintEvent&) override;
virtual void mousemove_event(GUI::MouseEvent&) override;
virtual void mousedown_event(GUI::MouseEvent&) override;
void show_documentation_tooltip_if_available(const String&, const Gfx::Point& screen_location);
void navigate_to_include_if_available(String);
explicit Editor();

View file

@ -33,6 +33,7 @@
#include <LibGfx/Font.h>
extern RefPtr<EditorWrapper> g_current_editor_wrapper;
extern Function<void(String)> g_open_file;
EditorWrapper::EditorWrapper()
{
@ -67,6 +68,10 @@ EditorWrapper::EditorWrapper()
m_editor->on_focus = [this] {
g_current_editor_wrapper = this;
};
m_editor->on_open = [this](String path) {
g_open_file(path);
};
}
EditorWrapper::~EditorWrapper()

View file

@ -66,6 +66,7 @@
NonnullRefPtrVector<EditorWrapper> g_all_editor_wrappers;
RefPtr<EditorWrapper> g_current_editor_wrapper;
Function<void(String)> g_open_file;
String g_currently_open_file;
OwnPtr<Project> g_project;
@ -529,6 +530,8 @@ int main(int argc, char** argv)
remove_current_editor_action->set_enabled(g_all_editor_wrappers.size() > 1);
};
g_open_file = open_file;
open_file("main.cpp");
update_actions();
@ -547,8 +550,15 @@ void run(TerminalWrapper& wrapper)
void open_file(const String& filename)
{
auto file = g_project->get_file(filename);
current_editor().set_document(const_cast<GUI::TextDocument&>(file->document()));
auto project_file = g_project->get_file(filename);
if (project_file) {
current_editor().set_document(const_cast<GUI::TextDocument&>(project_file->document()));
current_editor().set_readonly(false);
} else {
auto external_file = ProjectFile::construct_with_name(filename);
current_editor().set_document(const_cast<GUI::TextDocument&>(external_file->document()));
current_editor().set_readonly(true);
}
if (filename.ends_with(".cpp") || filename.ends_with(".h"))
current_editor().set_syntax_highlighter(make<GUI::CppSyntaxHighlighter>());