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