fix: target caret excerpts and retain diff viewport offsets
This commit is contained in:
@@ -1462,6 +1462,22 @@ impl Editor {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_diff_viewport(
|
||||
&mut self,
|
||||
comparison_id: u64,
|
||||
file: usize,
|
||||
top: usize,
|
||||
left_after: usize,
|
||||
) {
|
||||
if let Some(diff) = &mut self.diff
|
||||
&& diff.comparison_id == Some(comparison_id)
|
||||
&& diff.file == file
|
||||
{
|
||||
diff.top = top;
|
||||
diff.left_after = left_after;
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_diff(&mut self, input: Input) -> Option<Invocation> {
|
||||
if input == Input::Escape
|
||||
&& (self.count.is_some() || self.g_pending || self.line_pending.is_some())
|
||||
@@ -1565,6 +1581,14 @@ impl Editor {
|
||||
if live && !matches!(input, Input::Char('\t' | '[' | ']') | Input::BackTab) {
|
||||
return self.handle_input(input);
|
||||
}
|
||||
if live && matches!(input, Input::Char('[' | ']')) {
|
||||
let row = self.cursor().row;
|
||||
self.diff
|
||||
.as_mut()
|
||||
.expect("active diff")
|
||||
.expand_after_excerpt(input == Input::Char(']'), row);
|
||||
return None;
|
||||
}
|
||||
if !files_focused
|
||||
&& self
|
||||
.diff
|
||||
@@ -7050,6 +7074,66 @@ mod tests {
|
||||
buffers
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn editable_diff_brackets_expand_caret_excerpt_without_moving_source_anchor() {
|
||||
for selected in [30, 50] {
|
||||
let directory = Directory::new();
|
||||
let path = directory.path("file.txt");
|
||||
let before: Vec<String> = (0..80).map(|row| format!("line {row}")).collect();
|
||||
fs::write(&path, before.join("\n")).unwrap();
|
||||
let mut editor = Editor::open(Some(path), vec![]).unwrap();
|
||||
let mut after = before;
|
||||
for row in [10, 30, 50] {
|
||||
after[row] = format!("changed {row}");
|
||||
}
|
||||
editor
|
||||
.apply(vec![Effect::Replace(after.join("\n"))])
|
||||
.unwrap();
|
||||
editor.set_diff_context_options(1, 4);
|
||||
working_diff(&mut editor, &directory.0, &["file.txt"]);
|
||||
editor.handle(Input::BackTab);
|
||||
assert!(editor.diff_editing());
|
||||
editor.active.targets = vec![Target::caret(Cursor {
|
||||
row: selected,
|
||||
column: 2,
|
||||
})];
|
||||
let top = editor.diff().unwrap().after_display_row(9).unwrap();
|
||||
editor.diff.as_mut().unwrap().top = top;
|
||||
let cursor = editor.cursor();
|
||||
let visible = |editor: &Editor| editor.diff().unwrap().after_rows().collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
visible(&editor),
|
||||
(9..12).chain(29..32).chain(49..52).collect::<Vec<_>>()
|
||||
);
|
||||
editor.handle(Input::Char('['));
|
||||
editor.handle(Input::Char(']'));
|
||||
let expected = if selected == 30 {
|
||||
(9..12).chain(25..36).chain(49..52).collect::<Vec<_>>()
|
||||
} else {
|
||||
(9..12).chain(29..32).chain(45..56).collect::<Vec<_>>()
|
||||
};
|
||||
assert_eq!(visible(&editor), expected);
|
||||
assert_eq!(editor.cursor(), cursor);
|
||||
assert_eq!(
|
||||
editor.diff().unwrap().after_display_row(9),
|
||||
Some(editor.diff().unwrap().top)
|
||||
);
|
||||
if selected == 30 {
|
||||
// The caret keeps targeting the second excerpt after it merges
|
||||
// with the third, rather than expanding the first excerpt.
|
||||
for _ in 0..5 {
|
||||
editor.handle(Input::Char(']'));
|
||||
}
|
||||
assert_eq!(visible(&editor), (9..12).chain(25..56).collect::<Vec<_>>());
|
||||
assert_eq!(editor.cursor(), cursor);
|
||||
assert_eq!(
|
||||
editor.diff().unwrap().after_display_row(9),
|
||||
Some(editor.diff().unwrap().top)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn working_diff_reuses_dirty_buffers_and_normal_edit_undo_save_paths() {
|
||||
let directory = Directory::new();
|
||||
|
||||
Reference in New Issue
Block a user