diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index c57bbf0aed..dc662969dc 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -438,6 +438,14 @@ pub struct NavigationData { offset: usize, } +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] +pub enum CharKind { + Newline, + Punctuation, + Whitespace, + Word, +} + impl Editor { pub fn single_line(build_settings: BuildSettings, cx: &mut ViewContext) -> Self { let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx)); @@ -4215,6 +4223,18 @@ pub fn settings_builder( }) } +pub fn char_kind(c: char) -> CharKind { + if c == '\n' { + CharKind::Newline + } else if c.is_whitespace() { + CharKind::Whitespace + } else if c.is_alphanumeric() || c == '_' { + CharKind::Word + } else { + CharKind::Punctuation + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/editor/src/movement.rs b/crates/editor/src/movement.rs index 466b6e9323..9a800f9abb 100644 --- a/crates/editor/src/movement.rs +++ b/crates/editor/src/movement.rs @@ -1,5 +1,5 @@ use super::{Bias, DisplayPoint, DisplaySnapshot, SelectionGoal, ToDisplayPoint}; -use crate::ToPoint; +use crate::{char_kind, CharKind, ToPoint}; use anyhow::Result; use std::{cmp, ops::Range}; @@ -215,26 +215,6 @@ pub fn surrounding_word(map: &DisplaySnapshot, point: DisplayPoint) -> Range CharKind { - if c == '\n' { - CharKind::Newline - } else if c.is_whitespace() { - CharKind::Whitespace - } else if c.is_alphanumeric() || c == '_' { - CharKind::Word - } else { - CharKind::Punctuation - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/find/src/find.rs b/crates/find/src/find.rs index 2b862fc075..cea47a4a77 100644 --- a/crates/find/src/find.rs +++ b/crates/find/src/find.rs @@ -1,5 +1,5 @@ use aho_corasick::AhoCorasickBuilder; -use editor::{Editor, EditorSettings}; +use editor::{char_kind, Editor, EditorSettings}; use gpui::{ action, elements::*, keymap::Binding, Entity, MutableAppContext, RenderContext, View, ViewContext, ViewHandle, @@ -200,9 +200,28 @@ impl FindBar { let buffer = editor.buffer().read(cx).snapshot(cx); let ranges = search .stream_find_iter(buffer.bytes_in_range(0..buffer.len())) - .map(|mat| { + .filter_map(|mat| { let mat = mat.unwrap(); - buffer.anchor_after(mat.start())..buffer.anchor_before(mat.end()) + + if self.whole_word_mode { + let prev_kind = + buffer.reversed_chars_at(mat.start()).next().map(char_kind); + let start_kind = + char_kind(buffer.chars_at(mat.start()).next().unwrap()); + let end_kind = + char_kind(buffer.reversed_chars_at(mat.end()).next().unwrap()); + let next_kind = buffer.chars_at(mat.end()).next().map(char_kind); + if Some(start_kind) != prev_kind && Some(end_kind) != next_kind { + Some( + buffer.anchor_after(mat.start()) + ..buffer.anchor_before(mat.end()), + ) + } else { + None + } + } else { + Some(buffer.anchor_after(mat.start())..buffer.anchor_before(mat.end())) + } }) .collect(); editor.highlight_ranges::(ranges, theme.match_background, cx);