editor: Show relative line numbers for deleted rows (#42378)

Closes #42191

This PR adds support for relative line numbers in deleted hunks. Note
that this only applies in cases where there is a form of relative
numbering.

It also adds some tests for this functionality as well as missing tests
for other cases in line layouting that was previously untested.

Release Notes:

- Line numbers will now be shown in deleted git hunks if relative line
numbering is enabled
This commit is contained in:
Finn Evers
2025-11-10 21:00:50 +01:00
committed by GitHub
parent 2c375e2e0a
commit 87d0401e64
+107 -12
View File
@@ -3255,11 +3255,9 @@ impl EditorElement {
(newest_selection_head, relative)
});
let relative_to = if relative.enabled() {
Some(newest_selection_head.row())
} else {
None
};
let relative_line_numbers_enabled = relative.enabled();
let relative_to = relative_line_numbers_enabled.then(|| newest_selection_head.row());
let relative_rows =
self.calculate_relative_line_numbers(snapshot, &rows, relative_to, relative.wrapped());
let mut line_number = String::new();
@@ -3271,17 +3269,18 @@ impl EditorElement {
} else {
row_info.buffer_row? + 1
};
let number = relative_rows
.get(&display_row)
.unwrap_or(&non_relative_number);
write!(&mut line_number, "{number}").unwrap();
if row_info
.diff_status
.is_some_and(|status| status.is_deleted())
let relative_number = relative_rows.get(&display_row);
if !(relative_line_numbers_enabled && relative_number.is_some())
&& row_info
.diff_status
.is_some_and(|status| status.is_deleted())
{
return None;
}
let number = relative_number.unwrap_or(&non_relative_number);
write!(&mut line_number, "{number}").unwrap();
let color = active_rows
.get(&display_row)
.map(|spec| {
@@ -11455,6 +11454,46 @@ mod tests {
assert_eq!(relative_rows[&DisplayRow(0)], 5);
assert_eq!(relative_rows[&DisplayRow(1)], 4);
assert_eq!(relative_rows[&DisplayRow(2)], 3);
const DELETED_LINE: u32 = 3;
let layouts = cx
.update_window(*window, |_, window, cx| {
element.layout_line_numbers(
None,
GutterDimensions {
left_padding: Pixels::ZERO,
right_padding: Pixels::ZERO,
width: px(30.0),
margin: Pixels::ZERO,
git_blame_entries_width: None,
},
line_height,
gpui::Point::default(),
DisplayRow(0)..DisplayRow(6),
&(0..6)
.map(|row| RowInfo {
buffer_row: Some(row),
diff_status: (row == DELETED_LINE).then(|| {
DiffHunkStatus::deleted(
buffer_diff::DiffHunkSecondaryStatus::NoSecondaryHunk,
)
}),
..Default::default()
})
.collect::<Vec<_>>(),
&BTreeMap::default(),
Some(DisplayPoint::new(DisplayRow(0), 0)),
&snapshot,
window,
cx,
)
})
.unwrap();
assert_eq!(layouts.len(), 5,);
assert!(
layouts.get(&MultiBufferRow(DELETED_LINE)).is_none(),
"Deleted line should not have a line number"
);
}
#[gpui::test]
@@ -11530,6 +11569,62 @@ mod tests {
// current line has no relative number
assert_eq!(relative_rows[&DisplayRow(4)], 1);
assert_eq!(relative_rows[&DisplayRow(5)], 2);
let layouts = cx
.update_window(*window, |_, window, cx| {
element.layout_line_numbers(
None,
GutterDimensions {
left_padding: Pixels::ZERO,
right_padding: Pixels::ZERO,
width: px(30.0),
margin: Pixels::ZERO,
git_blame_entries_width: None,
},
line_height,
gpui::Point::default(),
DisplayRow(0)..DisplayRow(6),
&(0..6)
.map(|row| RowInfo {
buffer_row: Some(row),
diff_status: Some(DiffHunkStatus::deleted(
buffer_diff::DiffHunkSecondaryStatus::NoSecondaryHunk,
)),
..Default::default()
})
.collect::<Vec<_>>(),
&BTreeMap::from_iter([(DisplayRow(0), LineHighlightSpec::default())]),
Some(DisplayPoint::new(DisplayRow(0), 0)),
&snapshot,
window,
cx,
)
})
.unwrap();
assert!(
layouts.is_empty(),
"Deleted lines should have no line number"
);
let relative_rows = window
.update(cx, |editor, window, cx| {
let snapshot = editor.snapshot(window, cx);
element.calculate_relative_line_numbers(
&snapshot,
&(DisplayRow(0)..DisplayRow(6)),
Some(DisplayRow(3)),
true,
)
})
.unwrap();
// Deleted lines should still have relative numbers
assert_eq!(relative_rows[&DisplayRow(0)], 3);
assert_eq!(relative_rows[&DisplayRow(1)], 2);
assert_eq!(relative_rows[&DisplayRow(2)], 1);
// current line, even if deleted, has no relative number
assert_eq!(relative_rows[&DisplayRow(4)], 1);
assert_eq!(relative_rows[&DisplayRow(5)], 2);
}
#[gpui::test]