2022-03-29 15:04:39 +00:00
|
|
|
pub use buffer_search::BufferSearchBar;
|
2022-06-07 08:02:04 +00:00
|
|
|
use editor::{display_map::ToDisplayPoint, Anchor, Bias, Editor, MultiBufferSnapshot};
|
2022-06-16 11:44:00 +00:00
|
|
|
use gpui::{actions, impl_actions, MutableAppContext, ViewHandle};
|
2022-03-31 16:36:39 +00:00
|
|
|
pub use project_search::{ProjectSearchBar, ProjectSearchView};
|
2022-06-16 11:44:00 +00:00
|
|
|
use serde::Deserialize;
|
2022-02-28 09:34:11 +00:00
|
|
|
use std::{
|
|
|
|
cmp::{self, Ordering},
|
|
|
|
ops::Range,
|
|
|
|
};
|
|
|
|
|
2022-03-29 15:04:39 +00:00
|
|
|
pub mod buffer_search;
|
|
|
|
pub mod project_search;
|
2022-01-28 22:00:00 +00:00
|
|
|
|
2022-02-24 18:07:00 +00:00
|
|
|
pub fn init(cx: &mut MutableAppContext) {
|
2022-02-27 15:15:38 +00:00
|
|
|
buffer_search::init(cx);
|
|
|
|
project_search::init(cx);
|
2022-01-28 22:00:00 +00:00
|
|
|
}
|
2022-01-28 00:16:51 +00:00
|
|
|
|
2022-06-16 11:44:00 +00:00
|
|
|
#[derive(Clone, PartialEq, Deserialize)]
|
|
|
|
pub struct ToggleSearchOption {
|
|
|
|
pub option: SearchOption,
|
|
|
|
}
|
2022-04-07 23:20:49 +00:00
|
|
|
|
2022-04-08 22:32:56 +00:00
|
|
|
actions!(search, [SelectNextMatch, SelectPrevMatch]);
|
2022-06-16 11:44:00 +00:00
|
|
|
impl_actions!(search, [ToggleSearchOption]);
|
2022-02-27 21:18:04 +00:00
|
|
|
|
2022-06-16 11:44:00 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq, Deserialize)]
|
2022-02-24 18:07:00 +00:00
|
|
|
pub enum SearchOption {
|
2022-01-28 00:16:51 +00:00
|
|
|
WholeWord,
|
|
|
|
CaseSensitive,
|
|
|
|
Regex,
|
|
|
|
}
|
2022-02-27 21:18:04 +00:00
|
|
|
|
2022-06-16 11:44:00 +00:00
|
|
|
impl SearchOption {
|
|
|
|
pub fn label(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
SearchOption::WholeWord => "Match Whole Word",
|
|
|
|
SearchOption::CaseSensitive => "Match Case",
|
|
|
|
SearchOption::Regex => "Use Regular Expression",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-27 21:18:04 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
|
|
pub enum Direction {
|
|
|
|
Prev,
|
|
|
|
Next,
|
|
|
|
}
|
2022-02-28 09:34:11 +00:00
|
|
|
|
|
|
|
pub(crate) fn active_match_index(
|
|
|
|
ranges: &[Range<Anchor>],
|
|
|
|
cursor: &Anchor,
|
|
|
|
buffer: &MultiBufferSnapshot,
|
|
|
|
) -> Option<usize> {
|
|
|
|
if ranges.is_empty() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
match ranges.binary_search_by(|probe| {
|
2022-03-24 18:48:31 +00:00
|
|
|
if probe.end.cmp(&cursor, &*buffer).is_lt() {
|
2022-02-28 09:34:11 +00:00
|
|
|
Ordering::Less
|
2022-03-24 18:48:31 +00:00
|
|
|
} else if probe.start.cmp(&cursor, &*buffer).is_gt() {
|
2022-02-28 09:34:11 +00:00
|
|
|
Ordering::Greater
|
|
|
|
} else {
|
|
|
|
Ordering::Equal
|
|
|
|
}
|
|
|
|
}) {
|
|
|
|
Ok(i) | Err(i) => Some(cmp::min(i, ranges.len() - 1)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn match_index_for_direction(
|
|
|
|
ranges: &[Range<Anchor>],
|
|
|
|
cursor: &Anchor,
|
|
|
|
mut index: usize,
|
|
|
|
direction: Direction,
|
|
|
|
buffer: &MultiBufferSnapshot,
|
|
|
|
) -> usize {
|
2022-03-24 18:48:31 +00:00
|
|
|
if ranges[index].start.cmp(&cursor, &buffer).is_gt() {
|
2022-02-28 09:34:11 +00:00
|
|
|
if direction == Direction::Prev {
|
|
|
|
if index == 0 {
|
|
|
|
index = ranges.len() - 1;
|
|
|
|
} else {
|
|
|
|
index -= 1;
|
|
|
|
}
|
|
|
|
}
|
2022-03-24 18:48:31 +00:00
|
|
|
} else if ranges[index].end.cmp(&cursor, &buffer).is_lt() {
|
2022-02-28 09:34:11 +00:00
|
|
|
if direction == Direction::Next {
|
|
|
|
index = 0;
|
|
|
|
}
|
|
|
|
} else if direction == Direction::Prev {
|
|
|
|
if index == 0 {
|
|
|
|
index = ranges.len() - 1;
|
|
|
|
} else {
|
|
|
|
index -= 1;
|
|
|
|
}
|
|
|
|
} else if direction == Direction::Next {
|
|
|
|
if index == ranges.len() - 1 {
|
|
|
|
index = 0
|
|
|
|
} else {
|
|
|
|
index += 1;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
index
|
|
|
|
}
|
2022-06-07 08:02:04 +00:00
|
|
|
|
|
|
|
pub(crate) fn query_suggestion_for_editor(
|
|
|
|
editor: &ViewHandle<Editor>,
|
|
|
|
cx: &mut MutableAppContext,
|
|
|
|
) -> String {
|
|
|
|
let display_map = editor
|
|
|
|
.update(cx, |editor, cx| editor.snapshot(cx))
|
|
|
|
.display_snapshot;
|
|
|
|
let selection = editor.read(cx).selections.newest::<usize>(cx);
|
|
|
|
if selection.start == selection.end {
|
|
|
|
let point = selection.start.to_display_point(&display_map);
|
|
|
|
let range = editor::movement::surrounding_word(&display_map, point);
|
|
|
|
let range = range.start.to_offset(&display_map, Bias::Left)
|
|
|
|
..range.end.to_offset(&display_map, Bias::Right);
|
|
|
|
let text: String = display_map.buffer_snapshot.text_for_range(range).collect();
|
|
|
|
if text.trim().is_empty() {
|
|
|
|
String::new()
|
|
|
|
} else {
|
|
|
|
text
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
display_map
|
|
|
|
.buffer_snapshot
|
|
|
|
.text_for_range(selection.start..selection.end)
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
}
|