mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
Keep selection in SwitchToHelixNormalMode (#41583)
Closes #41125 Release Notes: - Fixed `SwitchToHelixNormalMode` to keep selection - Added default keybinds for `SwitchToHelixNormalMode` when in Helix mode
This commit is contained in:
parent
c2537fad43
commit
eab06eb1d9
16 changed files with 182 additions and 74 deletions
|
|
@ -421,6 +421,12 @@
|
|||
"ctrl-[": "editor::Cancel"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "vim_mode == helix_select && !menu",
|
||||
"bindings": {
|
||||
"escape": "vim::SwitchToHelixNormalMode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "(vim_mode == helix_normal || vim_mode == helix_select) && !menu",
|
||||
"bindings": {
|
||||
|
|
|
|||
|
|
@ -2591,11 +2591,12 @@ impl SearchableItem for TextThreadEditor {
|
|||
&mut self,
|
||||
index: usize,
|
||||
matches: &[Self::Match],
|
||||
collapse: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.activate_match(index, matches, window, cx);
|
||||
editor.activate_match(index, matches, collapse, window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1029,11 +1029,13 @@ impl SearchableItem for DapLogView {
|
|||
&mut self,
|
||||
index: usize,
|
||||
matches: &[Self::Match],
|
||||
collapse: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.editor
|
||||
.update(cx, |e, cx| e.activate_match(index, matches, window, cx))
|
||||
self.editor.update(cx, |e, cx| {
|
||||
e.activate_match(index, matches, collapse, window, cx)
|
||||
})
|
||||
}
|
||||
|
||||
fn select_matches(
|
||||
|
|
|
|||
|
|
@ -1069,7 +1069,6 @@ pub struct Editor {
|
|||
searchable: bool,
|
||||
cursor_shape: CursorShape,
|
||||
current_line_highlight: Option<CurrentLineHighlight>,
|
||||
collapse_matches: bool,
|
||||
autoindent_mode: Option<AutoindentMode>,
|
||||
workspace: Option<(WeakEntity<Workspace>, Option<WorkspaceId>)>,
|
||||
input_enabled: bool,
|
||||
|
|
@ -2119,7 +2118,7 @@ impl Editor {
|
|||
.unwrap_or_default(),
|
||||
current_line_highlight: None,
|
||||
autoindent_mode: Some(AutoindentMode::EachLine),
|
||||
collapse_matches: false,
|
||||
|
||||
workspace: None,
|
||||
input_enabled: !is_minimap,
|
||||
use_modal_editing: full_mode,
|
||||
|
|
@ -2272,7 +2271,7 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
EditorEvent::Edited { .. } => {
|
||||
if !vim_enabled(cx) {
|
||||
if vim_flavor(cx).is_none() {
|
||||
let display_map = editor.display_snapshot(cx);
|
||||
let selections = editor.selections.all_adjusted_display(&display_map);
|
||||
let pop_state = editor
|
||||
|
|
@ -2881,12 +2880,12 @@ impl Editor {
|
|||
self.current_line_highlight = current_line_highlight;
|
||||
}
|
||||
|
||||
pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
|
||||
self.collapse_matches = collapse_matches;
|
||||
}
|
||||
|
||||
pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
|
||||
if self.collapse_matches {
|
||||
pub fn range_for_match<T: std::marker::Copy>(
|
||||
&self,
|
||||
range: &Range<T>,
|
||||
collapse: bool,
|
||||
) -> Range<T> {
|
||||
if collapse {
|
||||
return range.start..range.start;
|
||||
}
|
||||
range.clone()
|
||||
|
|
@ -16654,7 +16653,7 @@ impl Editor {
|
|||
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
let range = target_range.to_point(target_buffer.read(cx));
|
||||
let range = editor.range_for_match(&range);
|
||||
let range = editor.range_for_match(&range, false);
|
||||
let range = collapse_multiline_range(range);
|
||||
|
||||
if !split
|
||||
|
|
@ -21457,7 +21456,7 @@ impl Editor {
|
|||
.and_then(|e| e.to_str())
|
||||
.map(|a| a.to_string()));
|
||||
|
||||
let vim_mode = vim_enabled(cx);
|
||||
let vim_mode = vim_flavor(cx).is_some();
|
||||
|
||||
let edit_predictions_provider = all_language_settings(file, cx).edit_predictions.provider;
|
||||
let copilot_enabled = edit_predictions_provider
|
||||
|
|
@ -22088,10 +22087,26 @@ fn edit_for_markdown_paste<'a>(
|
|||
(range, new_text)
|
||||
}
|
||||
|
||||
fn vim_enabled(cx: &App) -> bool {
|
||||
vim_mode_setting::VimModeSetting::try_get(cx)
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum VimFlavor {
|
||||
Vim,
|
||||
Helix,
|
||||
}
|
||||
|
||||
pub fn vim_flavor(cx: &App) -> Option<VimFlavor> {
|
||||
if vim_mode_setting::HelixModeSetting::try_get(cx)
|
||||
.map(|helix_mode| helix_mode.0)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Some(VimFlavor::Helix)
|
||||
} else if vim_mode_setting::VimModeSetting::try_get(cx)
|
||||
.map(|vim_mode| vim_mode.0)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Some(VimFlavor::Vim)
|
||||
} else {
|
||||
None // neither vim nor helix mode
|
||||
}
|
||||
}
|
||||
|
||||
fn process_completion_for_edit(
|
||||
|
|
|
|||
|
|
@ -1587,11 +1587,12 @@ impl SearchableItem for Editor {
|
|||
&mut self,
|
||||
index: usize,
|
||||
matches: &[Range<Anchor>],
|
||||
collapse: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.unfold_ranges(&[matches[index].clone()], false, true, cx);
|
||||
let range = self.range_for_match(&matches[index]);
|
||||
let range = self.range_for_match(&matches[index], collapse);
|
||||
self.change_selections(Default::default(), window, cx, |s| {
|
||||
s.select_ranges([range]);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -812,11 +812,13 @@ impl SearchableItem for LspLogView {
|
|||
&mut self,
|
||||
index: usize,
|
||||
matches: &[Self::Match],
|
||||
collapse: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.editor
|
||||
.update(cx, |e, cx| e.activate_match(index, matches, window, cx))
|
||||
self.editor.update(cx, |e, cx| {
|
||||
e.activate_match(index, matches, collapse, window, cx)
|
||||
})
|
||||
}
|
||||
|
||||
fn select_matches(
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ use any_vec::AnyVec;
|
|||
use anyhow::Context as _;
|
||||
use collections::HashMap;
|
||||
use editor::{
|
||||
DisplayPoint, Editor, EditorSettings,
|
||||
DisplayPoint, Editor, EditorSettings, VimFlavor,
|
||||
actions::{Backtab, Tab},
|
||||
vim_flavor,
|
||||
};
|
||||
use futures::channel::oneshot;
|
||||
use gpui::{
|
||||
|
|
@ -825,7 +826,8 @@ impl BufferSearchBar {
|
|||
.searchable_items_with_matches
|
||||
.get(&active_searchable_item.downgrade())
|
||||
{
|
||||
active_searchable_item.activate_match(match_ix, matches, window, cx)
|
||||
let collapse = editor::vim_flavor(cx) == Some(VimFlavor::Vim);
|
||||
active_searchable_item.activate_match(match_ix, matches, collapse, window, cx)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -970,7 +972,8 @@ impl BufferSearchBar {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.select_match(Direction::Next, 1, window, cx);
|
||||
let collapse = vim_flavor(cx) == Some(VimFlavor::Vim);
|
||||
self.select_match(Direction::Next, 1, collapse, window, cx);
|
||||
}
|
||||
|
||||
fn select_prev_match(
|
||||
|
|
@ -979,7 +982,8 @@ impl BufferSearchBar {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.select_match(Direction::Prev, 1, window, cx);
|
||||
let collapse = vim_flavor(cx) == Some(VimFlavor::Vim);
|
||||
self.select_match(Direction::Prev, 1, collapse, window, cx);
|
||||
}
|
||||
|
||||
pub fn select_all_matches(
|
||||
|
|
@ -1004,6 +1008,7 @@ impl BufferSearchBar {
|
|||
&mut self,
|
||||
direction: Direction,
|
||||
count: usize,
|
||||
collapse: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
|
|
@ -1026,7 +1031,7 @@ impl BufferSearchBar {
|
|||
.match_index_for_direction(matches, index, direction, count, window, cx);
|
||||
|
||||
searchable_item.update_matches(matches, window, cx);
|
||||
searchable_item.activate_match(new_match_index, matches, window, cx);
|
||||
searchable_item.activate_match(new_match_index, matches, collapse, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1040,7 +1045,8 @@ impl BufferSearchBar {
|
|||
return;
|
||||
}
|
||||
searchable_item.update_matches(matches, window, cx);
|
||||
searchable_item.activate_match(0, matches, window, cx);
|
||||
let collapse = vim_flavor(cx) == Some(VimFlavor::Vim);
|
||||
searchable_item.activate_match(0, matches, collapse, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1055,7 +1061,8 @@ impl BufferSearchBar {
|
|||
}
|
||||
let new_match_index = matches.len() - 1;
|
||||
searchable_item.update_matches(matches, window, cx);
|
||||
searchable_item.activate_match(new_match_index, matches, window, cx);
|
||||
let collapse = vim_flavor(cx) == Some(VimFlavor::Vim);
|
||||
searchable_item.activate_match(new_match_index, matches, collapse, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ use anyhow::Context as _;
|
|||
use collections::HashMap;
|
||||
use editor::{
|
||||
Anchor, Editor, EditorEvent, EditorSettings, MAX_TAB_TITLE_LEN, MultiBuffer, PathKey,
|
||||
SelectionEffects,
|
||||
SelectionEffects, VimFlavor,
|
||||
actions::{Backtab, SelectAll, Tab},
|
||||
items::active_match_index,
|
||||
multibuffer_context_lines,
|
||||
multibuffer_context_lines, vim_flavor,
|
||||
};
|
||||
use futures::{StreamExt, stream::FuturesOrdered};
|
||||
use gpui::{
|
||||
|
|
@ -1344,7 +1344,8 @@ impl ProjectSearchView {
|
|||
|
||||
let range_to_select = match_ranges[new_index].clone();
|
||||
self.results_editor.update(cx, |editor, cx| {
|
||||
let range_to_select = editor.range_for_match(&range_to_select);
|
||||
let collapse = vim_flavor(cx) == Some(VimFlavor::Vim);
|
||||
let range_to_select = editor.range_for_match(&range_to_select, collapse);
|
||||
editor.unfold_ranges(std::slice::from_ref(&range_to_select), false, true, cx);
|
||||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.select_ranges([range_to_select])
|
||||
|
|
@ -1415,9 +1416,10 @@ impl ProjectSearchView {
|
|||
let is_new_search = self.search_id != prev_search_id;
|
||||
self.results_editor.update(cx, |editor, cx| {
|
||||
if is_new_search {
|
||||
let collapse = vim_flavor(cx) == Some(VimFlavor::Vim);
|
||||
let range_to_select = match_ranges
|
||||
.first()
|
||||
.map(|range| editor.range_for_match(range));
|
||||
.map(|range| editor.range_for_match(range, collapse));
|
||||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.select_ranges(range_to_select)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1447,6 +1447,7 @@ impl SearchableItem for TerminalView {
|
|||
&mut self,
|
||||
index: usize,
|
||||
_: &[Self::Match],
|
||||
_collapse: bool,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -450,7 +450,7 @@ impl Vim {
|
|||
prior_selections,
|
||||
prior_operator: self.operator_stack.last().cloned(),
|
||||
prior_mode: self.mode,
|
||||
helix_select: true,
|
||||
is_helix_regex_search: true,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -1278,6 +1278,24 @@ mod test {
|
|||
cx.assert_state("«one ˇ»two", Mode::HelixSelect);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_exit_visual_mode(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
|
||||
cx.set_state("ˇone two", Mode::Normal);
|
||||
cx.simulate_keystrokes("v w");
|
||||
cx.assert_state("«one tˇ»wo", Mode::Visual);
|
||||
cx.simulate_keystrokes("escape");
|
||||
cx.assert_state("one ˇtwo", Mode::Normal);
|
||||
|
||||
cx.enable_helix();
|
||||
cx.set_state("ˇone two", Mode::HelixNormal);
|
||||
cx.simulate_keystrokes("v w");
|
||||
cx.assert_state("«one ˇ»two", Mode::HelixSelect);
|
||||
cx.simulate_keystrokes("escape");
|
||||
cx.assert_state("«one ˇ»two", Mode::HelixNormal);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_helix_select_regex(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
|
|
@ -1297,9 +1315,47 @@ mod test {
|
|||
cx.simulate_keystrokes("enter");
|
||||
cx.assert_state("«oneˇ» two «oneˇ»", Mode::HelixNormal);
|
||||
|
||||
cx.set_state("ˇone two one", Mode::HelixNormal);
|
||||
cx.simulate_keystrokes("s o n e enter");
|
||||
cx.assert_state("ˇone two one", Mode::HelixNormal);
|
||||
// TODO: change "search_in_selection" to not perform any search when in helix select mode with no selection
|
||||
// cx.set_state("ˇstuff one two one", Mode::HelixNormal);
|
||||
// cx.simulate_keystrokes("s o n e enter");
|
||||
// cx.assert_state("ˇstuff one two one", Mode::HelixNormal);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_helix_select_next_match(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
|
||||
cx.set_state("ˇhello two one two one two one", Mode::Visual);
|
||||
cx.simulate_keystrokes("/ o n e");
|
||||
cx.simulate_keystrokes("enter");
|
||||
cx.simulate_keystrokes("n n");
|
||||
cx.assert_state("«hello two one two one two oˇ»ne", Mode::Visual);
|
||||
|
||||
cx.set_state("ˇhello two one two one two one", Mode::Normal);
|
||||
cx.simulate_keystrokes("/ o n e");
|
||||
cx.simulate_keystrokes("enter");
|
||||
cx.simulate_keystrokes("n n");
|
||||
cx.assert_state("hello two one two one two ˇone", Mode::Normal);
|
||||
|
||||
cx.set_state("ˇhello two one two one two one", Mode::Normal);
|
||||
cx.simulate_keystrokes("/ o n e");
|
||||
cx.simulate_keystrokes("enter");
|
||||
cx.simulate_keystrokes("n g n g n");
|
||||
cx.assert_state("hello two one two «one two oneˇ»", Mode::Visual);
|
||||
|
||||
cx.enable_helix();
|
||||
|
||||
cx.set_state("ˇhello two one two one two one", Mode::HelixNormal);
|
||||
cx.simulate_keystrokes("/ o n e");
|
||||
cx.simulate_keystrokes("enter");
|
||||
cx.simulate_keystrokes("n n");
|
||||
cx.assert_state("hello two one two one two «oneˇ»", Mode::HelixNormal);
|
||||
|
||||
cx.set_state("ˇhello two one two one two one", Mode::HelixSelect);
|
||||
cx.simulate_keystrokes("/ o n e");
|
||||
cx.simulate_keystrokes("enter");
|
||||
cx.simulate_keystrokes("n n");
|
||||
cx.assert_state("ˇhello two «oneˇ» two «oneˇ» two «oneˇ»", Mode::HelixSelect);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
|
|
|||
|
|
@ -672,31 +672,40 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
|
|||
|
||||
impl Vim {
|
||||
pub(crate) fn search_motion(&mut self, m: Motion, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if let Motion::ZedSearchResult {
|
||||
prior_selections, ..
|
||||
let Motion::ZedSearchResult {
|
||||
prior_selections,
|
||||
new_selections,
|
||||
} = &m
|
||||
{
|
||||
match self.mode {
|
||||
Mode::Visual | Mode::VisualLine | Mode::VisualBlock => {
|
||||
if !prior_selections.is_empty() {
|
||||
self.update_editor(cx, |_, editor, cx| {
|
||||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.select_ranges(prior_selections.iter().cloned())
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
Mode::Normal | Mode::Replace | Mode::Insert => {
|
||||
if self.active_operator().is_none() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
Mode::HelixNormal | Mode::HelixSelect => {}
|
||||
match self.mode {
|
||||
Mode::Visual | Mode::VisualLine | Mode::VisualBlock => {
|
||||
if !prior_selections.is_empty() {
|
||||
self.update_editor(cx, |_, editor, cx| {
|
||||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.select_ranges(prior_selections.iter().cloned());
|
||||
});
|
||||
});
|
||||
}
|
||||
self.motion(m, window, cx);
|
||||
}
|
||||
Mode::Normal | Mode::Replace | Mode::Insert => {
|
||||
if self.active_operator().is_some() {
|
||||
self.motion(m, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
Mode::HelixNormal => {}
|
||||
Mode::HelixSelect => {
|
||||
self.update_editor(cx, |_, editor, cx| {
|
||||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.select_ranges(prior_selections.iter().chain(new_selections).cloned());
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.motion(m, window, cx)
|
||||
}
|
||||
|
||||
pub(crate) fn motion(&mut self, motion: Motion, window: &mut Window, cx: &mut Context<Self>) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use editor::{Editor, EditorSettings};
|
||||
use editor::{Editor, EditorSettings, VimFlavor};
|
||||
use gpui::{Action, Context, Window, actions};
|
||||
|
||||
use language::Point;
|
||||
use schemars::JsonSchema;
|
||||
use search::{BufferSearchBar, SearchOptions, buffer_search};
|
||||
|
|
@ -195,7 +196,7 @@ impl Vim {
|
|||
prior_selections,
|
||||
prior_operator: self.operator_stack.last().cloned(),
|
||||
prior_mode,
|
||||
helix_select: false,
|
||||
is_helix_regex_search: false,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -219,7 +220,7 @@ impl Vim {
|
|||
let new_selections = self.editor_selections(window, cx);
|
||||
let result = pane.update(cx, |pane, cx| {
|
||||
let search_bar = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>()?;
|
||||
if self.search.helix_select {
|
||||
if self.search.is_helix_regex_search {
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
search_bar.select_all_matches(&Default::default(), window, cx)
|
||||
});
|
||||
|
|
@ -240,7 +241,8 @@ impl Vim {
|
|||
count = count.saturating_sub(1)
|
||||
}
|
||||
self.search.count = 1;
|
||||
search_bar.select_match(direction, count, window, cx);
|
||||
let collapse = !self.mode.is_helix();
|
||||
search_bar.select_match(direction, count, collapse, window, cx);
|
||||
search_bar.focus_editor(&Default::default(), window, cx);
|
||||
|
||||
let prior_selections: Vec<_> = self.search.prior_selections.drain(..).collect();
|
||||
|
|
@ -307,7 +309,8 @@ impl Vim {
|
|||
if !search_bar.has_active_match() || !search_bar.show(window, cx) {
|
||||
return false;
|
||||
}
|
||||
search_bar.select_match(direction, count, window, cx);
|
||||
let collapse = !self.mode.is_helix();
|
||||
search_bar.select_match(direction, count, collapse, window, cx);
|
||||
true
|
||||
})
|
||||
});
|
||||
|
|
@ -316,6 +319,7 @@ impl Vim {
|
|||
}
|
||||
|
||||
let new_selections = self.editor_selections(window, cx);
|
||||
|
||||
self.search_motion(
|
||||
Motion::ZedSearchResult {
|
||||
prior_selections,
|
||||
|
|
@ -381,7 +385,8 @@ impl Vim {
|
|||
cx.spawn_in(window, async move |_, cx| {
|
||||
search.await?;
|
||||
search_bar.update_in(cx, |search_bar, window, cx| {
|
||||
search_bar.select_match(direction, count, window, cx);
|
||||
let collapse = editor::vim_flavor(cx) == Some(VimFlavor::Vim);
|
||||
search_bar.select_match(direction, count, collapse, window, cx);
|
||||
|
||||
vim.update(cx, |vim, cx| {
|
||||
let new_selections = vim.editor_selections(window, cx);
|
||||
|
|
@ -444,7 +449,7 @@ impl Vim {
|
|||
cx.spawn_in(window, async move |_, cx| {
|
||||
search.await?;
|
||||
search_bar.update_in(cx, |search_bar, window, cx| {
|
||||
search_bar.select_match(direction, 1, window, cx)
|
||||
search_bar.select_match(direction, 1, true, window, cx)
|
||||
})?;
|
||||
anyhow::Ok(())
|
||||
})
|
||||
|
|
|
|||
|
|
@ -66,12 +66,16 @@ impl Display for Mode {
|
|||
}
|
||||
|
||||
impl Mode {
|
||||
pub fn is_visual(&self) -> bool {
|
||||
pub fn is_visual(self) -> bool {
|
||||
match self {
|
||||
Self::Visual | Self::VisualLine | Self::VisualBlock | Self::HelixSelect => true,
|
||||
Self::Normal | Self::Insert | Self::Replace | Self::HelixNormal => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_helix(self) -> bool {
|
||||
matches!(self, Mode::HelixNormal | Mode::HelixSelect)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Mode {
|
||||
|
|
@ -990,7 +994,7 @@ pub struct SearchState {
|
|||
pub prior_selections: Vec<Range<Anchor>>,
|
||||
pub prior_operator: Option<Operator>,
|
||||
pub prior_mode: Mode,
|
||||
pub helix_select: bool,
|
||||
pub is_helix_regex_search: bool,
|
||||
}
|
||||
|
||||
impl Operator {
|
||||
|
|
|
|||
|
|
@ -669,7 +669,7 @@ impl Vim {
|
|||
editor,
|
||||
cx,
|
||||
|vim, _: &SwitchToHelixNormalMode, window, cx| {
|
||||
vim.switch_mode(Mode::HelixNormal, false, window, cx)
|
||||
vim.switch_mode(Mode::HelixNormal, true, window, cx)
|
||||
},
|
||||
);
|
||||
Vim::action(editor, cx, |_, _: &PushForcedMotion, _, cx| {
|
||||
|
|
@ -953,7 +953,6 @@ impl Vim {
|
|||
fn deactivate(editor: &mut Editor, cx: &mut Context<Editor>) {
|
||||
editor.set_cursor_shape(CursorShape::Bar, cx);
|
||||
editor.set_clip_at_line_ends(false, cx);
|
||||
editor.set_collapse_matches(false);
|
||||
editor.set_input_enabled(true);
|
||||
editor.set_autoindent(true);
|
||||
editor.selections.set_line_mode(false);
|
||||
|
|
@ -1929,7 +1928,6 @@ impl Vim {
|
|||
self.update_editor(cx, |vim, editor, cx| {
|
||||
editor.set_cursor_shape(vim.cursor_shape(cx), cx);
|
||||
editor.set_clip_at_line_ends(vim.clip_at_line_ends(), cx);
|
||||
editor.set_collapse_matches(true);
|
||||
editor.set_input_enabled(vim.editor_input_enabled());
|
||||
editor.set_autoindent(vim.should_autoindent());
|
||||
editor
|
||||
|
|
|
|||
|
|
@ -847,9 +847,6 @@ impl Vim {
|
|||
let mut start_selection = 0usize;
|
||||
let mut end_selection = 0usize;
|
||||
|
||||
self.update_editor(cx, |_, editor, _| {
|
||||
editor.set_collapse_matches(false);
|
||||
});
|
||||
if vim_is_normal {
|
||||
pane.update(cx, |pane, cx| {
|
||||
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>()
|
||||
|
|
@ -860,7 +857,7 @@ impl Vim {
|
|||
}
|
||||
// without update_match_index there is a bug when the cursor is before the first match
|
||||
search_bar.update_match_index(window, cx);
|
||||
search_bar.select_match(direction.opposite(), 1, window, cx);
|
||||
search_bar.select_match(direction.opposite(), 1, false, window, cx);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -878,7 +875,7 @@ impl Vim {
|
|||
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
|
||||
search_bar.update(cx, |search_bar, cx| {
|
||||
search_bar.update_match_index(window, cx);
|
||||
search_bar.select_match(direction, count, window, cx);
|
||||
search_bar.select_match(direction, count, false, window, cx);
|
||||
match_exists = search_bar.match_exists(window, cx);
|
||||
});
|
||||
}
|
||||
|
|
@ -905,7 +902,6 @@ impl Vim {
|
|||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.select_ranges([start_selection..end_selection]);
|
||||
});
|
||||
editor.set_collapse_matches(true);
|
||||
});
|
||||
|
||||
match self.maybe_pop_operator() {
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ pub trait SearchableItem: Item + EventEmitter<SearchEvent> {
|
|||
&mut self,
|
||||
index: usize,
|
||||
matches: &[Self::Match],
|
||||
collapse: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
);
|
||||
|
|
@ -184,6 +185,7 @@ pub trait SearchableItemHandle: ItemHandle {
|
|||
&self,
|
||||
index: usize,
|
||||
matches: &AnyVec<dyn Send>,
|
||||
collapse: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
);
|
||||
|
|
@ -274,12 +276,13 @@ impl<T: SearchableItem> SearchableItemHandle for Entity<T> {
|
|||
&self,
|
||||
index: usize,
|
||||
matches: &AnyVec<dyn Send>,
|
||||
collapse: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
let matches = matches.downcast_ref().unwrap();
|
||||
self.update(cx, |this, cx| {
|
||||
this.activate_match(index, matches.as_slice(), window, cx)
|
||||
this.activate_match(index, matches.as_slice(), collapse, window, cx)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue