search.rs

 1pub use buffer_search::BufferSearchBar;
 2use editor::{Anchor, MultiBufferSnapshot};
 3use gpui::{actions, impl_internal_actions, MutableAppContext};
 4pub use project_search::{ProjectSearchBar, ProjectSearchView};
 5use std::{
 6    cmp::{self, Ordering},
 7    ops::Range,
 8};
 9
10pub mod buffer_search;
11pub mod project_search;
12
13pub fn init(cx: &mut MutableAppContext) {
14    buffer_search::init(cx);
15    project_search::init(cx);
16}
17
18#[derive(Clone)]
19pub struct ToggleSearchOption(pub SearchOption);
20
21actions!(search, [SelectNextMatch, SelectPrevMatch]);
22impl_internal_actions!(search, [ToggleSearchOption]);
23
24#[derive(Clone, Copy)]
25pub enum SearchOption {
26    WholeWord,
27    CaseSensitive,
28    Regex,
29}
30
31#[derive(Clone, Copy, PartialEq, Eq)]
32pub enum Direction {
33    Prev,
34    Next,
35}
36
37pub(crate) fn active_match_index(
38    ranges: &[Range<Anchor>],
39    cursor: &Anchor,
40    buffer: &MultiBufferSnapshot,
41) -> Option<usize> {
42    if ranges.is_empty() {
43        None
44    } else {
45        match ranges.binary_search_by(|probe| {
46            if probe.end.cmp(&cursor, &*buffer).is_lt() {
47                Ordering::Less
48            } else if probe.start.cmp(&cursor, &*buffer).is_gt() {
49                Ordering::Greater
50            } else {
51                Ordering::Equal
52            }
53        }) {
54            Ok(i) | Err(i) => Some(cmp::min(i, ranges.len() - 1)),
55        }
56    }
57}
58
59pub(crate) fn match_index_for_direction(
60    ranges: &[Range<Anchor>],
61    cursor: &Anchor,
62    mut index: usize,
63    direction: Direction,
64    buffer: &MultiBufferSnapshot,
65) -> usize {
66    if ranges[index].start.cmp(&cursor, &buffer).is_gt() {
67        if direction == Direction::Prev {
68            if index == 0 {
69                index = ranges.len() - 1;
70            } else {
71                index -= 1;
72            }
73        }
74    } else if ranges[index].end.cmp(&cursor, &buffer).is_lt() {
75        if direction == Direction::Next {
76            index = 0;
77        }
78    } else if direction == Direction::Prev {
79        if index == 0 {
80            index = ranges.len() - 1;
81        } else {
82            index -= 1;
83        }
84    } else if direction == Direction::Next {
85        if index == ranges.len() - 1 {
86            index = 0
87        } else {
88            index += 1;
89        }
90    };
91    index
92}