1use bitflags::bitflags;
2pub use buffer_search::BufferSearchBar;
3use gpui::{
4 actions,
5 elements::{Component, StyleableComponent, TooltipStyle},
6 Action, AnyElement, AppContext, Element, View,
7};
8pub use mode::SearchMode;
9use project::search::SearchQuery;
10pub use project_search::{ProjectSearchBar, ProjectSearchView};
11use theme::components::{
12 action_button::ActionButton, svg::Svg, ComponentExt, ToggleIconButtonStyle,
13};
14
15pub mod buffer_search;
16mod history;
17mod mode;
18pub mod project_search;
19pub(crate) mod search_bar;
20
21pub fn init(cx: &mut AppContext) {
22 buffer_search::init(cx);
23 project_search::init(cx);
24}
25
26actions!(
27 search,
28 [
29 CycleMode,
30 ToggleWholeWord,
31 ToggleCaseSensitive,
32 SelectNextMatch,
33 SelectPrevMatch,
34 SelectAllMatches,
35 NextHistoryQuery,
36 PreviousHistoryQuery,
37 ActivateTextMode,
38 ActivateRegexMode
39 ]
40);
41
42bitflags! {
43 #[derive(Default)]
44 pub struct SearchOptions: u8 {
45 const NONE = 0b000;
46 const WHOLE_WORD = 0b001;
47 const CASE_SENSITIVE = 0b010;
48 }
49}
50
51impl SearchOptions {
52 pub fn label(&self) -> &'static str {
53 match *self {
54 SearchOptions::WHOLE_WORD => "Match Whole Word",
55 SearchOptions::CASE_SENSITIVE => "Match Case",
56 _ => panic!("{:?} is not a named SearchOption", self),
57 }
58 }
59
60 pub fn icon(&self) -> &'static str {
61 match *self {
62 SearchOptions::WHOLE_WORD => "icons/word_search_12.svg",
63 SearchOptions::CASE_SENSITIVE => "icons/case_insensitive_12.svg",
64 _ => panic!("{:?} is not a named SearchOption", self),
65 }
66 }
67
68 pub fn to_toggle_action(&self) -> Box<dyn Action> {
69 match *self {
70 SearchOptions::WHOLE_WORD => Box::new(ToggleWholeWord),
71 SearchOptions::CASE_SENSITIVE => Box::new(ToggleCaseSensitive),
72 _ => panic!("{:?} is not a named SearchOption", self),
73 }
74 }
75
76 pub fn none() -> SearchOptions {
77 SearchOptions::NONE
78 }
79
80 pub fn from_query(query: &SearchQuery) -> SearchOptions {
81 let mut options = SearchOptions::NONE;
82 options.set(SearchOptions::WHOLE_WORD, query.whole_word());
83 options.set(SearchOptions::CASE_SENSITIVE, query.case_sensitive());
84 options
85 }
86
87 pub fn as_button<V: View>(
88 &self,
89 active: bool,
90 tooltip_style: TooltipStyle,
91 button_style: ToggleIconButtonStyle,
92 ) -> AnyElement<V> {
93 ActionButton::new_dynamic(
94 self.to_toggle_action(),
95 format!("Toggle {}", self.label()),
96 tooltip_style,
97 )
98 .with_contents(Svg::new(self.icon()))
99 .toggleable(active)
100 .with_style(button_style)
101 .into_element()
102 .into_any()
103 }
104}