@@ -11573,7 +11573,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Editor>,
) {
- this.unfold_ranges(&[range.clone()], false, true, cx);
+ this.unfold_ranges(&[range.clone()], false, auto_scroll.is_some(), cx);
this.change_selections(auto_scroll, window, cx, |s| {
if replace_newest {
s.delete(s.newest_anchor().id);
@@ -11748,16 +11748,21 @@ impl Editor {
return Ok(());
}
- let mut new_selections = self.selections.all::<usize>(cx);
+ let mut new_selections = Vec::new();
+ let reversed = self.selections.oldest::<usize>(cx).reversed;
let buffer = &display_map.buffer_snapshot;
let query_matches = select_next_state
.query
.stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
- for query_match in query_matches {
- let query_match = query_match.unwrap(); // can only fail due to I/O
- let offset_range = query_match.start()..query_match.end();
+ for query_match in query_matches.into_iter() {
+ let query_match = query_match.context("query match for select all action")?; // can only fail due to I/O
+ let offset_range = if reversed {
+ query_match.end()..query_match.start()
+ } else {
+ query_match.start()..query_match.end()
+ };
let display_range = offset_range.start.to_display_point(&display_map)
..offset_range.end.to_display_point(&display_map);
@@ -11765,52 +11770,14 @@ impl Editor {
|| (!movement::is_inside_word(&display_map, display_range.start)
&& !movement::is_inside_word(&display_map, display_range.end))
{
- self.selections.change_with(cx, |selections| {
- new_selections.push(Selection {
- id: selections.new_selection_id(),
- start: offset_range.start,
- end: offset_range.end,
- reversed: false,
- goal: SelectionGoal::None,
- });
- });
+ new_selections.push(offset_range.start..offset_range.end);
}
}
- new_selections.sort_by_key(|selection| selection.start);
- let mut ix = 0;
- while ix + 1 < new_selections.len() {
- let current_selection = &new_selections[ix];
- let next_selection = &new_selections[ix + 1];
- if current_selection.range().overlaps(&next_selection.range()) {
- if current_selection.id < next_selection.id {
- new_selections.remove(ix + 1);
- } else {
- new_selections.remove(ix);
- }
- } else {
- ix += 1;
- }
- }
-
- let reversed = self.selections.oldest::<usize>(cx).reversed;
-
- for selection in new_selections.iter_mut() {
- selection.reversed = reversed;
- }
-
select_next_state.done = true;
- self.unfold_ranges(
- &new_selections
- .iter()
- .map(|selection| selection.range())
- .collect::<Vec<_>>(),
- false,
- false,
- cx,
- );
- self.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
- selections.select(new_selections)
+ self.unfold_ranges(&new_selections.clone(), false, false, cx);
+ self.change_selections(None, window, cx, |selections| {
+ selections.select_ranges(new_selections)
});
Ok(())
@@ -5842,6 +5842,37 @@ async fn test_select_all_matches(cx: &mut TestAppContext) {
cx.assert_editor_state("abc\n« ˇ»abc\nabc");
}
+#[gpui::test]
+async fn test_select_all_matches_does_not_scroll(cx: &mut TestAppContext) {
+ init_test(cx, |_| {});
+
+ let mut cx = EditorTestContext::new(cx).await;
+
+ let large_body_1 = "\nd".repeat(200);
+ let large_body_2 = "\ne".repeat(200);
+
+ cx.set_state(&format!(
+ "abc\nabc{large_body_1} «ˇa»bc{large_body_2}\nefabc\nabc"
+ ));
+ let initial_scroll_position = cx.update_editor(|editor, _, cx| {
+ let scroll_position = editor.scroll_position(cx);
+ assert!(scroll_position.y > 0.0, "Initial selection is between two large bodies and should have the editor scrolled to it");
+ scroll_position
+ });
+
+ cx.update_editor(|e, window, cx| e.select_all_matches(&SelectAllMatches, window, cx))
+ .unwrap();
+ cx.assert_editor_state(&format!(
+ "«ˇa»bc\n«ˇa»bc{large_body_1} «ˇa»bc{large_body_2}\nef«ˇa»bc\n«ˇa»bc"
+ ));
+ let scroll_position_after_selection =
+ cx.update_editor(|editor, _, cx| editor.scroll_position(cx));
+ assert_eq!(
+ initial_scroll_position, scroll_position_after_selection,
+ "Scroll position should not change after selecting all matches"
+ );
+}
+
#[gpui::test]
async fn test_select_next_with_multiple_carets(cx: &mut TestAppContext) {
init_test(cx, |_| {});