editor: Fix inconsistent SelectPrevious behavior (#27695)
When starting a selection from only carets, the action `editor::SelectPrevious` behaved in a manner inconsistent with `editor::SelectNext` as well as equivalent keybinds in editors such as VSCode, by selecting substrings of whole words matching the initially selected string on subsequent triggers. This fix brings the `select_previous` function in line with `select_next_internal`by calling `select_match_ranges` (previously an internal function of `select_next_internal`) in the same way it was previously used in the function that exhibited expected behavior. Furthermore, the relevant test was adapted to bring it in line with the equivalent test for the `editor::SelectNext` action Closes #24346 Release Notes: - Fixed inconsistent SelectPrevious behavior
This commit is contained in:
parent
2eb10ab9fb
commit
a07ba3c718
2 changed files with 41 additions and 52 deletions
|
@ -12129,6 +12129,28 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
|
||||
fn select_match_ranges(
|
||||
&mut self,
|
||||
range: Range<usize>,
|
||||
reversed: bool,
|
||||
replace_newest: bool,
|
||||
auto_scroll: Option<Autoscroll>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Editor>,
|
||||
) {
|
||||
self.unfold_ranges(&[range.clone()], false, auto_scroll.is_some(), cx);
|
||||
self.change_selections(auto_scroll, window, cx, |s| {
|
||||
if replace_newest {
|
||||
s.delete(s.newest_anchor().id);
|
||||
}
|
||||
if reversed {
|
||||
s.insert_range(range.end..range.start);
|
||||
} else {
|
||||
s.insert_range(range);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn select_next_match_internal(
|
||||
&mut self,
|
||||
display_map: &DisplaySnapshot,
|
||||
|
@ -12137,28 +12159,6 @@ impl Editor {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Result<()> {
|
||||
fn select_next_match_ranges(
|
||||
this: &mut Editor,
|
||||
range: Range<usize>,
|
||||
reversed: bool,
|
||||
replace_newest: bool,
|
||||
auto_scroll: Option<Autoscroll>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Editor>,
|
||||
) {
|
||||
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);
|
||||
}
|
||||
if reversed {
|
||||
s.insert_range(range.end..range.start);
|
||||
} else {
|
||||
s.insert_range(range);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let buffer = &display_map.buffer_snapshot;
|
||||
let mut selections = self.selections.all::<usize>(cx);
|
||||
if let Some(mut select_next_state) = self.select_next_state.take() {
|
||||
|
@ -12203,8 +12203,7 @@ impl Editor {
|
|||
}
|
||||
|
||||
if let Some(next_selected_range) = next_selected_range {
|
||||
select_next_match_ranges(
|
||||
self,
|
||||
self.select_match_ranges(
|
||||
next_selected_range,
|
||||
last_selection.reversed,
|
||||
replace_newest,
|
||||
|
@ -12262,8 +12261,7 @@ impl Editor {
|
|||
selection.end = word_range.end.to_offset(display_map, Bias::Left);
|
||||
selection.goal = SelectionGoal::None;
|
||||
selection.reversed = false;
|
||||
select_next_match_ranges(
|
||||
self,
|
||||
self.select_match_ranges(
|
||||
selection.start..selection.end,
|
||||
selection.reversed,
|
||||
replace_newest,
|
||||
|
@ -12428,17 +12426,14 @@ impl Editor {
|
|||
}
|
||||
|
||||
if let Some(next_selected_range) = next_selected_range {
|
||||
self.unfold_ranges(&[next_selected_range.clone()], false, true, cx);
|
||||
self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
|
||||
if action.replace_newest {
|
||||
s.delete(s.newest_anchor().id);
|
||||
}
|
||||
if last_selection.reversed {
|
||||
s.insert_range(next_selected_range.end..next_selected_range.start);
|
||||
} else {
|
||||
s.insert_range(next_selected_range);
|
||||
}
|
||||
});
|
||||
self.select_match_ranges(
|
||||
next_selected_range,
|
||||
last_selection.reversed,
|
||||
action.replace_newest,
|
||||
Some(Autoscroll::newest()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
} else {
|
||||
select_prev_state.done = true;
|
||||
}
|
||||
|
@ -12489,6 +12484,14 @@ impl Editor {
|
|||
selection.end = word_range.end.to_offset(&display_map, Bias::Left);
|
||||
selection.goal = SelectionGoal::None;
|
||||
selection.reversed = false;
|
||||
self.select_match_ranges(
|
||||
selection.start..selection.end,
|
||||
selection.reversed,
|
||||
action.replace_newest,
|
||||
Some(Autoscroll::newest()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
if selections.len() == 1 {
|
||||
let selection = selections
|
||||
|
@ -12507,16 +12510,6 @@ impl Editor {
|
|||
} else {
|
||||
self.select_prev_state = None;
|
||||
}
|
||||
|
||||
self.unfold_ranges(
|
||||
&selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
|
||||
false,
|
||||
true,
|
||||
cx,
|
||||
);
|
||||
self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
|
||||
s.select(selections);
|
||||
});
|
||||
} else if let Some(selected_text) = selected_text {
|
||||
self.select_prev_state = Some(SelectNextState {
|
||||
query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
|
||||
|
|
|
@ -6130,11 +6130,7 @@ async fn test_select_previous_with_single_caret(cx: &mut TestAppContext) {
|
|||
|
||||
cx.update_editor(|e, window, cx| e.select_previous(&SelectPrevious::default(), window, cx))
|
||||
.unwrap();
|
||||
cx.assert_editor_state("«abcˇ»\n«abcˇ» abc\ndef«abcˇ»\n«abcˇ»");
|
||||
|
||||
cx.update_editor(|e, window, cx| e.select_previous(&SelectPrevious::default(), window, cx))
|
||||
.unwrap();
|
||||
cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndef«abcˇ»\n«abcˇ»");
|
||||
cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue