Add editor actions for moving and selecting to next / previous excerpt (#25299)

Covers part of #5129 by adding `MoveToStartOfExcerpt`,
`MoveToEndOfExcerpt`, `SelectToStartOfExcerpt`, and
`SelectToEndOfExcerpt`.

No default linux bindings yet as it's unclear what to use. Currently,
`ctrl-up` / `ctrl-down` scroll up and down by one line (see #13269).
Considering changing the meaning of those.

Mac:

* Previously `cmd-up` and `cmd-down` were `editor::MoveToBeginning` and
`editor::MoveToEnd`. In singleton editors these will behave the same as
before. In multibuffers, they will now step through excerpts instead of
jumping to the beginning / end of the multibuffer.

* `cmd-home` and `cmd-end`, often typed as `cmd-fn-left` and
`cmd-fn-right` are now `editor::MoveToBeginning` and
`editor::MoveToEnd`. This is useful in multibuffers.

Release Notes:

- Mac: `cmd-up` now moves to the previous
multibuffer excerpt start, and `cmd-down` moves to the next multibuffer
excerpt end. Within normal buffers these behave the same as before, moving
to the beginning or end.
This commit is contained in:
Michael Sloan 2025-02-20 17:23:20 -07:00 committed by GitHub
parent ec00fb97fd
commit 30850fe3bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 174 additions and 47 deletions

View file

@ -2699,49 +2699,10 @@ fn section_motion(
};
for _ in 0..times {
let point = map.display_point_to_point(display_point, Bias::Left);
let Some(excerpt) = map.buffer_snapshot.excerpt_containing(point..point) else {
return display_point;
};
let next_point = match (direction, is_start) {
(Direction::Prev, true) => {
let mut start = excerpt.start_anchor().to_display_point(&map);
if start >= display_point && start.row() > DisplayRow(0) {
let Some(excerpt) = map.buffer_snapshot.excerpt_before(excerpt.id()) else {
return display_point;
};
start = excerpt.start_anchor().to_display_point(&map);
}
start
}
(Direction::Prev, false) => {
let mut start = excerpt.start_anchor().to_display_point(&map);
if start.row() > DisplayRow(0) {
*start.row_mut() -= 1;
}
map.clip_point(start, Bias::Left)
}
(Direction::Next, true) => {
let mut end = excerpt.end_anchor().to_display_point(&map);
*end.row_mut() += 1;
map.clip_point(end, Bias::Right)
}
(Direction::Next, false) => {
let mut end = excerpt.end_anchor().to_display_point(&map);
*end.column_mut() = 0;
if end <= display_point {
*end.row_mut() += 1;
let point_end = map.display_point_to_point(end, Bias::Right);
let Some(excerpt) =
map.buffer_snapshot.excerpt_containing(point_end..point_end)
else {
return display_point;
};
end = excerpt.end_anchor().to_display_point(&map);
*end.column_mut() = 0;
}
end
}
let next_point = if is_start {
movement::start_of_excerpt(map, display_point, direction)
} else {
movement::end_of_excerpt(map, display_point, direction)
};
if next_point == display_point {
break;