mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
HackStudio: Migrate git-diff indicators to TextEditor API
As part of this, the CodeDocument now keeps track of the kind of difference for each line. Previously, we iterated every hunk every time the editor was painted, but now we do that once whenever the diff changes, and then save the type of difference for each line.
This commit is contained in:
parent
620bf45f43
commit
0761926127
Notes:
sideshowbarker
2024-07-17 06:54:15 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/SerenityOS/serenity/commit/0761926127 Pull-request: https://github.com/SerenityOS/serenity/pull/17864
5 changed files with 84 additions and 31 deletions
|
@ -32,4 +32,14 @@ CodeDocument::CodeDocument(Client* client)
|
|||
{
|
||||
}
|
||||
|
||||
CodeDocument::DiffType CodeDocument::line_difference(size_t line) const
|
||||
{
|
||||
return m_line_differences[line];
|
||||
}
|
||||
|
||||
void CodeDocument::set_line_differences(Badge<HackStudio::Editor>, Vector<HackStudio::CodeDocument::DiffType> line_differences)
|
||||
{
|
||||
m_line_differences = move(line_differences);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
namespace HackStudio {
|
||||
|
||||
class Editor;
|
||||
|
||||
class CodeDocument final : public GUI::TextDocument {
|
||||
public:
|
||||
virtual ~CodeDocument() override = default;
|
||||
|
@ -29,6 +31,15 @@ public:
|
|||
|
||||
virtual bool is_code_document() const override final { return true; }
|
||||
|
||||
enum class DiffType {
|
||||
None,
|
||||
AddedLine,
|
||||
ModifiedLine,
|
||||
DeletedLinesBefore,
|
||||
};
|
||||
DiffType line_difference(size_t line) const;
|
||||
void set_line_differences(Badge<Editor>, Vector<DiffType>);
|
||||
|
||||
private:
|
||||
explicit CodeDocument(DeprecatedString const& file_path, Client* client = nullptr);
|
||||
explicit CodeDocument(Client* client = nullptr);
|
||||
|
@ -37,6 +48,8 @@ private:
|
|||
Optional<Syntax::Language> m_language;
|
||||
Vector<size_t> m_breakpoint_lines;
|
||||
Optional<size_t> m_execution_position;
|
||||
|
||||
Vector<DiffType> m_line_differences;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -86,6 +86,24 @@ Editor::Editor()
|
|||
add_breakpoint(line).release_value_but_fixme_should_propagate_errors();
|
||||
};
|
||||
|
||||
m_git_diff_indicator_id = register_gutter_indicator(
|
||||
[&](auto& painter, Gfx::IntRect rect, size_t line) {
|
||||
auto diff_type = code_document().line_difference(line);
|
||||
switch (diff_type) {
|
||||
case CodeDocument::DiffType::AddedLine:
|
||||
painter.draw_text(rect, "+"sv, font(), Gfx::TextAlignment::Center);
|
||||
break;
|
||||
case CodeDocument::DiffType::ModifiedLine:
|
||||
painter.draw_text(rect, "!"sv, font(), Gfx::TextAlignment::Center);
|
||||
break;
|
||||
case CodeDocument::DiffType::DeletedLinesBefore:
|
||||
painter.draw_text(rect, "-"sv, font(), Gfx::TextAlignment::Center);
|
||||
break;
|
||||
case CodeDocument::DiffType::None:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}).release_value_but_fixme_should_propagate_errors();
|
||||
|
||||
m_breakpoint_indicator_id = register_gutter_indicator(
|
||||
[&](auto& painter, Gfx::IntRect rect, size_t) {
|
||||
auto const& icon = breakpoint_icon_bitmap();
|
||||
|
@ -159,36 +177,6 @@ void Editor::paint_event(GUI::PaintEvent& event)
|
|||
rect.set_height(rect.height() - horizontal_scrollbar().height());
|
||||
painter.draw_rect(rect, palette().selection());
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
}
|
||||
auto sign = (line_offset < deletions) ? "!"sv : "+"sv;
|
||||
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), "-"sv, font(), Gfx::TextAlignment::Center);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static HashMap<DeprecatedString, DeprecatedString>& man_paths()
|
||||
|
@ -827,4 +815,41 @@ void Editor::remove_breakpoint(size_t line_number)
|
|||
Debugger::the().on_breakpoint_change(wrapper().filename_title(), line_number, BreakpointChange::Removed);
|
||||
}
|
||||
|
||||
ErrorOr<void> Editor::update_git_diff_indicators()
|
||||
{
|
||||
clear_gutter_indicators(m_git_diff_indicator_id);
|
||||
|
||||
if (!wrapper().git_repo())
|
||||
return {};
|
||||
|
||||
Vector<CodeDocument::DiffType> line_differences;
|
||||
TRY(line_differences.try_ensure_capacity(document().line_count()));
|
||||
for (auto i = 0u; i < document().line_count(); ++i)
|
||||
line_differences.unchecked_append(CodeDocument::DiffType::None);
|
||||
|
||||
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;
|
||||
auto difference = (line_offset < deletions) ? CodeDocument::DiffType::ModifiedLine : CodeDocument::DiffType::AddedLine;
|
||||
line_differences[line] = difference;
|
||||
add_gutter_indicator(m_git_diff_indicator_id, line);
|
||||
}
|
||||
if (additions < deletions) {
|
||||
auto deletions_line = min(finish_line, line_count() - 1);
|
||||
line_differences[deletions_line] = CodeDocument::DiffType::DeletedLinesBefore;
|
||||
add_gutter_indicator(m_git_diff_indicator_id, deletions_line);
|
||||
}
|
||||
}
|
||||
code_document().set_line_differences({}, move(line_differences));
|
||||
update();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ public:
|
|||
void clear_execution_position();
|
||||
void set_debug_mode(bool);
|
||||
|
||||
ErrorOr<void> update_git_diff_indicators();
|
||||
|
||||
CodeDocument const& code_document() const;
|
||||
CodeDocument& code_document();
|
||||
|
||||
|
@ -125,6 +127,7 @@ private:
|
|||
|
||||
GutterIndicatorID m_breakpoint_indicator_id;
|
||||
GutterIndicatorID m_execution_indicator_id;
|
||||
GutterIndicatorID m_git_diff_indicator_id;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -87,8 +87,10 @@ void EditorWrapper::save()
|
|||
|
||||
void EditorWrapper::update_diff()
|
||||
{
|
||||
if (m_git_repo)
|
||||
if (m_git_repo) {
|
||||
m_hunks = Diff::parse_hunks(m_git_repo->unstaged_diff(filename()).value());
|
||||
editor().update_git_diff_indicators().release_value_but_fixme_should_propagate_errors();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorWrapper::set_project_root(DeprecatedString const& project_root)
|
||||
|
|
Loading…
Reference in a new issue