search.rs

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