search.rs

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