search.rs

  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}