Gutter-highlight removed and added portions of expanded diff hunks separately (#24834)
cc @iamnbutler Release Notes: - Color gutter highlights separately for removed and deleted portions of git modification hunks Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
parent
4aae0e2f6c
commit
39c9b1f170
1 changed files with 100 additions and 38 deletions
|
@ -79,17 +79,18 @@ use workspace::{item::Item, notifications::NotifyTaskExt, Workspace};
|
|||
|
||||
const INLINE_BLAME_PADDING_EM_WIDTHS: f32 = 7.;
|
||||
|
||||
/// Note that for a "modified" MultiBufferDiffHunk, there are two DisplayDiffHunks,
|
||||
/// one for the deleted portion and one for the added portion.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum DisplayDiffHunk {
|
||||
Folded {
|
||||
display_row: DisplayRow,
|
||||
},
|
||||
Unfolded {
|
||||
diff_base_byte_range: Range<usize>,
|
||||
display_row_range: Range<DisplayRow>,
|
||||
multi_buffer_range: Range<Anchor>,
|
||||
status: DiffHunkStatus,
|
||||
contains_expanded: bool,
|
||||
expanded: bool,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -104,7 +105,7 @@ struct SelectionLayout {
|
|||
}
|
||||
|
||||
impl SelectionLayout {
|
||||
fn new<T: ToPoint + ToDisplayPoint + Clone>(
|
||||
fn new<T: multi_buffer::ToPoint + ToDisplayPoint + Clone>(
|
||||
selection: Selection<T>,
|
||||
line_mode: bool,
|
||||
cursor_shape: CursorShape,
|
||||
|
@ -1557,36 +1558,97 @@ impl EditorElement {
|
|||
let hunk_end_point = Point::new(hunk.row_range.end.0, 0);
|
||||
|
||||
let hunk_display_start = snapshot.point_to_display_point(hunk_start_point, Bias::Left);
|
||||
let hunk_added_start_at =
|
||||
Anchor::in_buffer(hunk.excerpt_id, hunk.buffer_id, hunk.buffer_range.start);
|
||||
let hunk_deleted_to_added_break = snapshot.point_to_display_point(
|
||||
hunk_added_start_at.to_point(&snapshot.buffer_snapshot),
|
||||
Bias::Right,
|
||||
);
|
||||
|
||||
let hunk_display_end = snapshot.point_to_display_point(hunk_end_point, Bias::Right);
|
||||
|
||||
let display_hunk = if hunk_display_start.column() != 0 {
|
||||
DisplayDiffHunk::Folded {
|
||||
display_row: hunk_display_start.row(),
|
||||
}
|
||||
if hunk_display_start.column() != 0 {
|
||||
display_hunks.push((
|
||||
DisplayDiffHunk::Folded {
|
||||
display_row: hunk_display_start.row(),
|
||||
},
|
||||
None,
|
||||
));
|
||||
} else {
|
||||
let mut end_row = hunk_display_end.row();
|
||||
if hunk_display_end.column() > 0 {
|
||||
end_row.0 += 1;
|
||||
}
|
||||
let start_row = hunk_display_start.row();
|
||||
let contains_expanded = snapshot
|
||||
.row_infos(start_row)
|
||||
.take(end_row.0 as usize - start_row.0 as usize)
|
||||
.any(|row_info| row_info.diff_status.is_some());
|
||||
DisplayDiffHunk::Unfolded {
|
||||
status: hunk.status(),
|
||||
diff_base_byte_range: hunk.diff_base_byte_range,
|
||||
display_row_range: hunk_display_start.row()..end_row,
|
||||
multi_buffer_range: Anchor::range_in_buffer(
|
||||
hunk.excerpt_id,
|
||||
hunk.buffer_id,
|
||||
hunk.buffer_range,
|
||||
),
|
||||
contains_expanded,
|
||||
let deleted_count = snapshot
|
||||
.buffer_snapshot
|
||||
.row_infos(hunk.row_range.start)
|
||||
.take(hunk.row_range.end.0 as usize - hunk.row_range.start.0 as usize)
|
||||
.take_while(|row_info| {
|
||||
matches!(row_info.diff_status, Some(DiffHunkStatus::Removed(_)))
|
||||
})
|
||||
.count();
|
||||
let has_added = snapshot
|
||||
.buffer_snapshot
|
||||
.row_infos(hunk.row_range.start)
|
||||
.take(hunk.row_range.end.0 as usize - hunk.row_range.start.0 as usize)
|
||||
.any(|row_info| matches!(row_info.diff_status, Some(DiffHunkStatus::Added(_))));
|
||||
let expanded = deleted_count > 0 || has_added;
|
||||
if deleted_count > 0 && has_added {
|
||||
display_hunks.push((
|
||||
DisplayDiffHunk::Unfolded {
|
||||
status: DiffHunkStatus::Removed(hunk.secondary_status),
|
||||
display_row_range: hunk_display_start.row()
|
||||
..hunk_display_start.row() + DisplayRow(deleted_count as u32),
|
||||
multi_buffer_range: Anchor::range_in_buffer(
|
||||
hunk.excerpt_id,
|
||||
hunk.buffer_id,
|
||||
hunk.buffer_range.clone(),
|
||||
),
|
||||
expanded,
|
||||
},
|
||||
None,
|
||||
));
|
||||
display_hunks.push((
|
||||
DisplayDiffHunk::Unfolded {
|
||||
status: DiffHunkStatus::Added(hunk.secondary_status),
|
||||
display_row_range: hunk_display_start.row()
|
||||
+ DisplayRow(deleted_count as u32)
|
||||
..end_row,
|
||||
multi_buffer_range: Anchor::range_in_buffer(
|
||||
hunk.excerpt_id,
|
||||
hunk.buffer_id,
|
||||
hunk.buffer_range,
|
||||
),
|
||||
expanded,
|
||||
},
|
||||
None,
|
||||
));
|
||||
} else {
|
||||
let status = if expanded && matches!(hunk.status(), DiffHunkStatus::Modified(_))
|
||||
{
|
||||
if hunk_display_start.row() < hunk_deleted_to_added_break.row() {
|
||||
DiffHunkStatus::Removed(hunk.secondary_status)
|
||||
} else {
|
||||
DiffHunkStatus::Added(hunk.secondary_status)
|
||||
}
|
||||
} else {
|
||||
hunk.status()
|
||||
};
|
||||
display_hunks.push((
|
||||
DisplayDiffHunk::Unfolded {
|
||||
status,
|
||||
display_row_range: hunk_display_start.row()..end_row,
|
||||
multi_buffer_range: Anchor::range_in_buffer(
|
||||
hunk.excerpt_id,
|
||||
hunk.buffer_id,
|
||||
hunk.buffer_range,
|
||||
),
|
||||
expanded,
|
||||
},
|
||||
None,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
display_hunks.push((display_hunk, None));
|
||||
}
|
||||
|
||||
let git_gutter_setting = ProjectSettings::get_global(cx)
|
||||
|
@ -1924,7 +1986,8 @@ impl EditorElement {
|
|||
if tasks.offset.0 < offset_range_start || tasks.offset.0 >= offset_range_end {
|
||||
return None;
|
||||
}
|
||||
let multibuffer_point = tasks.offset.0.to_point(&snapshot.buffer_snapshot);
|
||||
let multibuffer_point =
|
||||
multi_buffer::ToPoint::to_point(&tasks.offset.0, &snapshot.buffer_snapshot);
|
||||
let multibuffer_row = MultiBufferRow(multibuffer_point.row);
|
||||
let buffer_folded = snapshot
|
||||
.buffer_snapshot
|
||||
|
@ -4579,7 +4642,7 @@ impl EditorElement {
|
|||
DisplayDiffHunk::Unfolded {
|
||||
status,
|
||||
display_row_range,
|
||||
contains_expanded,
|
||||
expanded,
|
||||
..
|
||||
} => hitbox.as_ref().map(|hunk_hitbox| match status {
|
||||
DiffHunkStatus::Added(secondary_status) => (
|
||||
|
@ -4587,14 +4650,14 @@ impl EditorElement {
|
|||
cx.theme().colors().version_control_added.opacity(0.7),
|
||||
corners,
|
||||
secondary_status,
|
||||
*contains_expanded,
|
||||
*expanded,
|
||||
),
|
||||
DiffHunkStatus::Modified(secondary_status) => (
|
||||
hunk_hitbox.bounds,
|
||||
cx.theme().colors().version_control_modified.opacity(0.7),
|
||||
corners,
|
||||
secondary_status,
|
||||
*contains_expanded,
|
||||
*expanded,
|
||||
),
|
||||
DiffHunkStatus::Removed(secondary_status)
|
||||
if !display_row_range.is_empty() =>
|
||||
|
@ -4604,7 +4667,7 @@ impl EditorElement {
|
|||
cx.theme().colors().version_control_deleted.opacity(0.7),
|
||||
corners,
|
||||
secondary_status,
|
||||
*contains_expanded,
|
||||
*expanded,
|
||||
)
|
||||
}
|
||||
DiffHunkStatus::Removed(secondary_status) => (
|
||||
|
@ -4618,7 +4681,7 @@ impl EditorElement {
|
|||
cx.theme().colors().version_control_deleted.opacity(0.7),
|
||||
Corners::all(1. * line_height),
|
||||
secondary_status,
|
||||
*contains_expanded,
|
||||
*expanded,
|
||||
),
|
||||
}),
|
||||
};
|
||||
|
@ -4628,16 +4691,15 @@ impl EditorElement {
|
|||
background_color,
|
||||
corner_radii,
|
||||
secondary_status,
|
||||
contains_expanded,
|
||||
expanded,
|
||||
)) = hunk_to_paint
|
||||
{
|
||||
let background = if *secondary_status != DiffHunkSecondaryStatus::None
|
||||
&& contains_expanded
|
||||
{
|
||||
pattern_slash(background_color, line_height.0 / 2.5)
|
||||
} else {
|
||||
solid_color(background_color)
|
||||
};
|
||||
let background =
|
||||
if *secondary_status != DiffHunkSecondaryStatus::None && expanded {
|
||||
pattern_slash(background_color, line_height.0 / 2.5)
|
||||
} else {
|
||||
solid_color(background_color)
|
||||
};
|
||||
|
||||
window.paint_quad(quad(
|
||||
hunk_bounds,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue