Sfoglia il codice sorgente

HackStudio: Add header navigation

Oriko 5 anni fa
parent
commit
879bf3e97b

+ 75 - 2
DevTools/HackStudio/Editor.cpp

@@ -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);
+}

+ 3 - 0
DevTools/HackStudio/Editor.h

@@ -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();
 

+ 5 - 0
DevTools/HackStudio/EditorWrapper.cpp

@@ -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()

+ 12 - 2
DevTools/HackStudio/main.cpp

@@ -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>());