search_provider/lib.rs
1//! The crate aims to provide an easy to use wrapper around the GNOME Shell Search Provider DBus interface.
2//!
3//! - [Writing a Search Provider tutorial](https://developer.gnome.org/documentation/tutorials/search-provider.html)
4//!
5//!
6//! # How to use
7//!
8//! - [Register a new search provider](https://developer.gnome.org/documentation/tutorials/search-provider.html#registering-a-new-search-provider)
9//! - Implement the [`SearchProviderImpl`] trait for the struct that holds your Application.
10//! - Once the application is installed, enable it in GNOME Settings -> Search.
11//!
12//! ```
13//! use search_provider::{ResultID, ResultMeta, SearchProviderImpl};
14//! use std::collections::HashMap;
15//!
16//! #[derive(Debug)]
17//! struct Application {
18//! results: HashMap<String, String>,
19//! }
20//! impl SearchProviderImpl for Application {
21//! fn activate_result(&self, identifier: ResultID, terms: &[String], timestamp: u32) {
22//! let result = self.results.get(&identifier);
23//! println!(
24//! "activating result {:#?} identified by {}",
25//! result, identifier
26//! );
27//! }
28//!
29//! fn initial_result_set(&self, terms: &[String]) -> Vec<ResultID> {
30//! // Here do your search logic
31//! if terms.contains(&"some_value".to_owned()) {
32//! vec!["some_key".to_owned()]
33//! } else {
34//! vec![]
35//! }
36//! }
37//!
38//! fn result_metas(&self, identifiers: &[ResultID]) -> Vec<ResultMeta> {
39//! self.results
40//! .iter()
41//! .map(|(identifier, value)| {
42//! ResultMeta::builder(identifier.to_owned(), "Some name")
43//! .description("Some description of the current identifier")
44//! .build()
45//! })
46//! .collect::<Vec<_>>()
47//! }
48//! }
49//! ```
50//!
51//! - Create an instance of [`SearchProvider`]
52//!
53//! ```ignore
54//! use search_provider::SearchProvider;
55//! use std::collections::HashMap;
56//!
57//! async fn main_entry() -> zbus::Result<()> {
58//! let mut results = HashMap::new();
59//! results.insert("some_key".to_string(), "some_value".to_string());
60//! let app = Application { results };
61//! let provider = SearchProvider::new(
62//! app,
63//! "org.gnome.design.IconLibrary.SearchProvider",
64//! "/org/gnome/design/IconLibrary/SearchProvider",
65//! )
66//! .await?;
67//! Ok(())
68//! }
69//! ```
70
71mod search_provider;
72pub use crate::search_provider::SearchProvider;
73
74mod result_metadata;
75pub use crate::result_metadata::{IconData, ResultMeta, ResultMetaBuilder};
76
77/// A result identifier.
78pub type ResultID = String;
79
80/// A trait to implement to communicate with the search provider
81/// interface.
82pub trait SearchProviderImpl {
83 /// The method is called when a user clicks on an individual search result
84 /// to open it in the application.
85 ///
86 /// # Arguments
87 ///
88 /// * `identifier` - the result ID.
89 /// * `terms` - current search terms.
90 /// * `timestamp` - current timestamp.
91 fn activate_result(&self, identifier: ResultID, terms: &[String], timestamp: u32);
92
93 /// The method is called when a new search is started.
94 ///
95 /// # Arguments
96 ///
97 /// * `terms` - current search terms.
98 /// * `timestamp` - current timestamp.
99 ///
100 /// # Returns
101 ///
102 /// A list of search results IDs. GNOME Shell, will call [`result_metas()`](SearchProviderImpl::result_metas`)
103 /// on some of those IDs to retrieve the corresponding [`ResultMeta`].
104 #[doc(alias = "get_initial_result_set")]
105 fn initial_result_set(&self, terms: &[String]) -> Vec<ResultID>;
106
107 /// The method is called to refine the initial search results when more characters were typed
108 /// in the search entry.
109 ///
110 /// # Arguments
111 ///
112 /// * `previous_results` - list of results ID returned by a previous call to [`initial_result_set()`](SearchProviderImpl::initial_result_set`).
113 /// * `terms` - current search terms.
114 ///
115 /// # Returns
116 ///
117 /// A list of search results IDs. GNOME Shell, will call [`result_metas()`](SearchProviderImpl::result_metas`)
118 /// on some of those IDs to retrieve the corresponding [`ResultMeta`].
119 ///
120 /// By default the method calls [`initial_result_set()`](SearchProviderImpl::initial_result_set`).
121 #[doc(alias = "get_subsearch_result_set")]
122 fn subsearch_result_set(
123 &self,
124 _previous_results: &[ResultID],
125 terms: &[String],
126 ) -> Vec<ResultID> {
127 self.initial_result_set(terms)
128 }
129
130 /// The method is called to obtain detailed information of the results.
131 ///
132 /// # Arguments
133 ///
134 /// * `identifiers` - search result IDs.
135 ///
136 /// # Returns
137 ///
138 /// A list of their corresponding [`ResultMeta`], see [`ResultMeta::builder`] on how to construct one.
139 #[doc(alias = "get_result_metas")]
140 fn result_metas(&self, identifiers: &[ResultID]) -> Vec<ResultMeta>;
141
142 /// The method is called when a user clicks on the provider icon to
143 /// display more search results in the application.
144 ///
145 /// # Arguments
146 ///
147 /// * `terms` - current search terms.
148 /// * `timestamp` - current timestamp.
149 ///
150 /// By default the method does nothing.
151 fn launch_search(&self, _terms: &[String], _timestamp: u32) {}
152}