diff --git a/Userland/DevTools/HackStudio/Editor.cpp b/Userland/DevTools/HackStudio/Editor.cpp index 0ae83188e7..eea4a8f01b 100644 --- a/Userland/DevTools/HackStudio/Editor.cpp +++ b/Userland/DevTools/HackStudio/Editor.cpp @@ -121,6 +121,7 @@ void Editor::paint_event(GUI::PaintEvent& event) if (gutter_visible()) { size_t first_visible_line = text_position_at(event.rect().top_left()).line(); size_t last_visible_line = text_position_at(event.rect().bottom_right()).line(); + for (size_t line : breakpoint_lines()) { if (line < first_visible_line || line > last_visible_line) { continue; @@ -132,6 +133,31 @@ void Editor::paint_event(GUI::PaintEvent& event) const auto& icon = current_position_icon_bitmap(); painter.blit(gutter_icon_rect(execution_position().value()).top_left(), icon, icon.rect()); } + + if (wrapper().git_repo()) { + for (auto& hunk : wrapper().hunks()) { + auto start_line = hunk.target_start_line; + auto finish_line = start_line + hunk.added_lines.size(); + + auto additions = hunk.added_lines.size(); + auto deletions = hunk.removed_lines.size(); + + for (size_t line_offset = 0; line_offset < additions; line_offset++) { + auto line = start_line + line_offset; + if (line < first_visible_line || line > last_visible_line) { + continue; + } + char const* sign = (line_offset < deletions) ? "!" : "+"; + painter.draw_text(gutter_icon_rect(line), sign, font(), Gfx::TextAlignment::Center); + } + if (additions < deletions) { + auto deletions_line = min(finish_line, line_count() - 1); + if (deletions_line <= last_visible_line) { + painter.draw_text(gutter_icon_rect(deletions_line), "-", font(), Gfx::TextAlignment::Center); + } + } + } + } } } diff --git a/Userland/DevTools/HackStudio/EditorWrapper.cpp b/Userland/DevTools/HackStudio/EditorWrapper.cpp index 698950c47b..1a5487eac5 100644 --- a/Userland/DevTools/HackStudio/EditorWrapper.cpp +++ b/Userland/DevTools/HackStudio/EditorWrapper.cpp @@ -92,6 +92,7 @@ void EditorWrapper::set_filename(const String& filename) { m_filename = filename; update_title(); + update_diff(); } void EditorWrapper::save() @@ -99,6 +100,32 @@ void EditorWrapper::save() editor().write_to_file(filename()); m_document_dirty = false; update_title(); + update_diff(); + editor().update(); +} + +void EditorWrapper::update_diff() +{ + if (m_git_repo) + m_hunks = Diff::parse_hunks(m_git_repo->unstaged_diff(LexicalPath(filename())).value()); +} + +void EditorWrapper::set_project_root(LexicalPath const& project_root) +{ + m_project_root = project_root; + + auto result = GitRepo::try_to_create(m_project_root); + switch (result.type) { + case GitRepo::CreateResult::Type::Success: + m_git_repo = result.repo; + break; + case GitRepo::CreateResult::Type::GitProgramNotFound: + break; + case GitRepo::CreateResult::Type::NoGitRepo: + break; + default: + VERIFY_NOT_REACHED(); + } } void EditorWrapper::update_title() diff --git a/Userland/DevTools/HackStudio/EditorWrapper.h b/Userland/DevTools/HackStudio/EditorWrapper.h index 5493be746e..27851485b8 100644 --- a/Userland/DevTools/HackStudio/EditorWrapper.h +++ b/Userland/DevTools/HackStudio/EditorWrapper.h @@ -7,9 +7,12 @@ #pragma once #include "Debugger/BreakpointCallback.h" +#include "Git/GitRepo.h" #include "LanguageClient.h" #include +#include #include +#include #include #include @@ -40,6 +43,14 @@ public: const String& filename() const { return m_filename; } bool document_dirty() const { return m_document_dirty; } + LexicalPath const& project_root() const { return m_project_root; } + void set_project_root(LexicalPath const& project_root); + + GitRepo const* git_repo() const { return m_git_repo; } + + void update_diff(); + Vector const& hunks() const { return m_hunks; } + private: EditorWrapper(); @@ -50,6 +61,10 @@ private: RefPtr m_cursor_label; RefPtr m_editor; bool m_document_dirty { false }; + + LexicalPath m_project_root; + RefPtr m_git_repo; + Vector m_hunks; }; } diff --git a/Userland/DevTools/HackStudio/HackStudioWidget.cpp b/Userland/DevTools/HackStudio/HackStudioWidget.cpp index d8462c679c..e4df70c9f1 100644 --- a/Userland/DevTools/HackStudio/HackStudioWidget.cpp +++ b/Userland/DevTools/HackStudio/HackStudioWidget.cpp @@ -196,6 +196,8 @@ void HackStudioWidget::open_project(const String& root_path) debugger.reset_breakpoints(); debugger.set_source_root(m_project->root_path()); } + for (auto& editor_wrapper : m_all_editor_wrappers) + editor_wrapper.set_project_root(LexicalPath(m_project->root_path())); } Vector HackStudioWidget::selected_file_paths() const @@ -498,6 +500,7 @@ void HackStudioWidget::add_new_editor(GUI::Widget& parent) m_current_editor_wrapper = wrapper; m_all_editor_wrappers.append(wrapper); wrapper->editor().set_focus(true); + wrapper->set_project_root(LexicalPath(m_project->root_path())); } NonnullRefPtr HackStudioWidget::create_switch_to_next_editor_action()