Select change range for goto_first/last_change commands (#5206)

This matches the behavior from 42ad1a9e04
but for the first and last change. The selection rules are the same
as for goto_next/prev_change: additions and modifications select the
added and modified range while deletions are represented with a point.
This commit is contained in:
Michael Davis 2023-02-06 21:43:48 -06:00 committed by GitHub
parent f71f27f804
commit 23ed8c12f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -2927,14 +2927,6 @@ fn exit_select_mode(cx: &mut Context) {
} }
} }
fn goto_pos(editor: &mut Editor, pos: usize) {
let (view, doc) = current!(editor);
push_jump(view, doc);
doc.set_selection(view.id, Selection::point(pos));
align_view(doc, view, Align::Center);
}
fn goto_first_diag(cx: &mut Context) { fn goto_first_diag(cx: &mut Context) {
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
let selection = match doc.diagnostics().first() { let selection = match doc.diagnostics().first() {
@ -3012,7 +3004,7 @@ fn goto_last_change(cx: &mut Context) {
fn goto_first_change_impl(cx: &mut Context, reverse: bool) { fn goto_first_change_impl(cx: &mut Context, reverse: bool) {
let editor = &mut cx.editor; let editor = &mut cx.editor;
let (_, doc) = current!(editor); let (view, doc) = current!(editor);
if let Some(handle) = doc.diff_handle() { if let Some(handle) = doc.diff_handle() {
let hunk = { let hunk = {
let hunks = handle.hunks(); let hunks = handle.hunks();
@ -3024,8 +3016,8 @@ fn goto_first_change_impl(cx: &mut Context, reverse: bool) {
hunks.nth_hunk(idx) hunks.nth_hunk(idx)
}; };
if hunk != Hunk::NONE { if hunk != Hunk::NONE {
let pos = doc.text().line_to_char(hunk.after.start as usize); let range = hunk_range(hunk, doc.text().slice(..));
goto_pos(editor, pos) doc.set_selection(view.id, Selection::single(range.anchor, range.head));
} }
} }
} }
@ -3069,14 +3061,7 @@ fn goto_next_change_impl(cx: &mut Context, direction: Direction) {
return range; return range;
}; };
let hunk = hunks.nth_hunk(hunk_idx); let hunk = hunks.nth_hunk(hunk_idx);
let new_range = hunk_range(hunk, doc_text);
let hunk_start = doc_text.line_to_char(hunk.after.start as usize);
let hunk_end = if hunk.after.is_empty() {
hunk_start + 1
} else {
doc_text.line_to_char(hunk.after.end as usize)
};
let new_range = Range::new(hunk_start, hunk_end);
if editor.mode == Mode::Select { if editor.mode == Mode::Select {
let head = if new_range.head < range.anchor { let head = if new_range.head < range.anchor {
new_range.anchor new_range.anchor
@ -3096,6 +3081,20 @@ fn goto_next_change_impl(cx: &mut Context, direction: Direction) {
cx.editor.last_motion = Some(Motion(Box::new(motion))); cx.editor.last_motion = Some(Motion(Box::new(motion)));
} }
/// Returns the [Range] for a [Hunk] in the given text.
/// Additions and modifications cover the added and modified ranges.
/// Deletions are represented as the point at the start of the deletion hunk.
fn hunk_range(hunk: Hunk, text: RopeSlice) -> Range {
let anchor = text.line_to_char(hunk.after.start as usize);
let head = if hunk.after.is_empty() {
anchor + 1
} else {
text.line_to_char(hunk.after.end as usize)
};
Range::new(anchor, head)
}
pub mod insert { pub mod insert {
use super::*; use super::*;
pub type Hook = fn(&Rope, &Selection, char) -> Option<Transaction>; pub type Hook = fn(&Rope, &Selection, char) -> Option<Transaction>;