indicium/simple/autocomplete/
mod.rs

1mod context;
2mod global;
3mod keyword;
4
5use crate::simple::AutocompleteType;
6use std::hash::Hash;
7
8// -----------------------------------------------------------------------------
9
10impl<K: Hash + Ord> crate::simple::SearchIndex<K>{
11    /// Returns matching autocompleted keywords for the provided search string.
12    /// This function will use the `AutocompleteType` setting stored in the
13    /// `SearchIndex`. Partial keywords must be an exact match. Results are
14    /// returned in lexographic order.
15    ///
16    /// Autocompletion behaviour can be changed by setting the
17    /// [`AutocompleteType`] in the `SearchIndex`. See also:
18    /// [`SearchIndexBuilder`] and [`SearchIndex::new()`].
19    ///
20    /// [`AutocompleteType`]: enum.AutocompleteType.html
21    /// [`SearchIndexBuilder`]: struct.SearchIndexBuilder.html
22    /// [`SearchIndex::new()`]: struct.SearchIndex.html#method.new
23    ///
24    /// Basic usage:
25    ///
26    /// ```rust
27    /// # use indicium::simple::{AutocompleteType, Indexable, SearchIndex, SearchType};
28    /// # use pretty_assertions::assert_eq;
29    /// #
30    /// # struct MyStruct {
31    /// #   title: String,
32    /// #   year: u16,
33    /// #   body: String,
34    /// # }
35    /// #
36    /// # impl Indexable for MyStruct {
37    /// #   fn strings(&self) -> Vec<String> {
38    /// #       vec![
39    /// #           self.title.clone(),
40    /// #           self.year.to_string(),
41    /// #           self.body.clone(),
42    /// #       ]
43    /// #   }
44    /// # }
45    /// #
46    /// # let my_vec = vec![
47    /// #   MyStruct {
48    /// #       title: "Harold Godwinson".to_string(),
49    /// #       year: 1066,
50    /// #       body: "Last crowned Anglo-Saxon king of England.".to_string(),
51    /// #   },
52    /// #   MyStruct {
53    /// #       title: "Edgar Ætheling".to_string(),
54    /// #       year: 1066,
55    /// #       body: "Last male member of the royal house of Cerdic of Wessex.".to_string(),
56    /// #   },
57    /// #   MyStruct {
58    /// #       title: "William the Conqueror".to_string(),
59    /// #       year: 1066,
60    /// #       body: "First Norman monarch of England.".to_string(),
61    /// #   },
62    /// #   MyStruct {
63    /// #       title: "William Rufus".to_string(),
64    /// #       year: 1087,
65    /// #       body: "Third son of William the Conqueror.".to_string(),
66    /// #   },
67    /// #   MyStruct {
68    /// #       title: "Henry Beauclerc".to_string(),
69    /// #       year: 1100,
70    /// #       body: "Fourth son of William the Conqueror.".to_string(),
71    /// #   },
72    /// # ];
73    /// #
74    /// # let mut search_index: SearchIndex<usize> = SearchIndex::default();
75    /// #
76    /// # my_vec
77    /// #   .iter()
78    /// #   .enumerate()
79    /// #   .for_each(|(index, element)|
80    /// #       search_index.insert(&index, element)
81    /// #   );
82    /// #
83    /// let autocomplete_options = search_index.autocomplete("Edgar last c");
84    /// assert_eq!(autocomplete_options, vec!["edgar last cerdic".to_string()]);
85    /// ```
86    #[tracing::instrument(level = "trace", name = "autocomplete", skip(self))]
87    pub fn autocomplete(&self, string: &str) -> Vec<String> {
88        let autocomplete_options: Vec<String> = match &self.autocomplete_type {
89            AutocompleteType::Context => {
90                self.autocomplete_context(&self.maximum_autocomplete_options, string)
91            }
92            AutocompleteType::Global => {
93                self.autocomplete_global(&self.maximum_autocomplete_options, string)
94            }
95            AutocompleteType::Keyword => self
96                .autocomplete_keyword(&self.maximum_autocomplete_options, string)
97                .into_iter()
98                .map(std::string::ToString::to_string)
99                .collect(),
100        };
101
102        // For debug builds:
103        #[cfg(debug_assertions)]
104        tracing::debug!(
105            "{} autocomplete options for \"{}\".",
106            autocomplete_options.len(),
107            string,
108        );
109
110        autocomplete_options
111    }
112
113    /// This autocomplete method allows the caller to define an
114    /// `AutocompleteType` parameter, effectively overriding the index settings.
115    /// See [`AutocompleteType`] for more information on the different
116    /// autocomplete types.
117    ///
118    /// Returns matching autocompleted keywords for the provided search string.
119    /// Partial keywords must be an exact match. Results are returned in
120    /// lexographic order.
121    ///
122    /// [`AutocompleteType`]: enum.AutocompleteType.html
123    ///
124    /// Basic usage:
125    ///
126    /// ```rust
127    /// # use indicium::simple::{AutocompleteType, Indexable, SearchIndex, SearchType};
128    /// # use pretty_assertions::assert_eq;
129    /// #
130    /// # struct MyStruct {
131    /// #   title: String,
132    /// #   year: u16,
133    /// #   body: String,
134    /// # }
135    /// #
136    /// # impl Indexable for MyStruct {
137    /// #   fn strings(&self) -> Vec<String> {
138    /// #       vec![
139    /// #           self.title.clone(),
140    /// #           self.year.to_string(),
141    /// #           self.body.clone(),
142    /// #       ]
143    /// #   }
144    /// # }
145    /// #
146    /// # let my_vec = vec![
147    /// #   MyStruct {
148    /// #       title: "Harold Godwinson".to_string(),
149    /// #       year: 1066,
150    /// #       body: "Last crowned Anglo-Saxon king of England.".to_string(),
151    /// #   },
152    /// #   MyStruct {
153    /// #       title: "Edgar Ætheling".to_string(),
154    /// #       year: 1066,
155    /// #       body: "Last male member of the royal house of Cerdic of Wessex.".to_string(),
156    /// #   },
157    /// #   MyStruct {
158    /// #       title: "William the Conqueror".to_string(),
159    /// #       year: 1066,
160    /// #       body: "First Norman monarch of England.".to_string(),
161    /// #   },
162    /// #   MyStruct {
163    /// #       title: "William Rufus".to_string(),
164    /// #       year: 1087,
165    /// #       body: "Third son of William the Conqueror.".to_string(),
166    /// #   },
167    /// #   MyStruct {
168    /// #       title: "Henry Beauclerc".to_string(),
169    /// #       year: 1100,
170    /// #       body: "Fourth son of William the Conqueror.".to_string(),
171    /// #   },
172    /// # ];
173    /// #
174    /// # let mut search_index: SearchIndex<usize> = SearchIndex::default();
175    /// #
176    /// # my_vec
177    /// #   .iter()
178    /// #   .enumerate()
179    /// #   .for_each(|(index, element)|
180    /// #       search_index.insert(&index, element)
181    /// #   );
182    /// #
183    /// let autocomplete_options =
184    ///     search_index.autocomplete_type(&AutocompleteType::Global, "1100 e");
185    ///
186    /// assert_eq!(
187    ///     autocomplete_options,
188    ///     vec![
189    ///         "1100 edgar".to_string(),
190    ///         "1100 edgar ætheling".to_string(),
191    ///         "1100 england".to_string()
192    ///     ]
193    /// );
194    /// ```
195    #[tracing::instrument(level = "trace", name = "autocomplete", skip(self))]
196    pub fn autocomplete_type(
197        &self,
198        autocomplete_type: &AutocompleteType,
199        string: &str,
200    ) -> Vec<String> {
201        let autocomplete_options: Vec<String> = match autocomplete_type {
202            AutocompleteType::Context => {
203                self.autocomplete_context(&self.maximum_autocomplete_options, string)
204            }
205            AutocompleteType::Global => {
206                self.autocomplete_global(&self.maximum_autocomplete_options, string)
207            }
208            AutocompleteType::Keyword => self
209                .autocomplete_keyword(&self.maximum_autocomplete_options, string)
210                .into_iter()
211                .map(std::string::ToString::to_string)
212                .collect(),
213        };
214
215        // For debug builds:
216        #[cfg(debug_assertions)]
217        tracing::debug!(
218            "{} autocomplete options for \"{}\".",
219            autocomplete_options.len(),
220            string,
221        );
222
223        autocomplete_options
224    }
225
226    /// This autocomplete method allows the caller to define a
227    /// `AutocompleteType` and the maximum number of autocomplete options to be
228    /// returned. These parameters override the index settings. See
229    /// [`AutocompleteType`] for more information on the different search types.
230    ///
231    /// Returns matching autocompleted keywords for the provided search string.
232    /// Partial keywords must be an exact match. Results are returned in
233    /// lexographic order.
234    ///
235    /// [`AutocompleteType`]: enum.AutocompleteType.html
236    ///
237    /// Basic usage:
238    ///
239    /// ```rust
240    /// # use indicium::simple::{AutocompleteType, Indexable, SearchIndex, SearchType};
241    /// # use pretty_assertions::assert_eq;
242    /// #
243    /// # struct MyStruct {
244    /// #   title: String,
245    /// #   year: u16,
246    /// #   body: String,
247    /// # }
248    /// #
249    /// # impl Indexable for MyStruct {
250    /// #   fn strings(&self) -> Vec<String> {
251    /// #       vec![
252    /// #           self.title.clone(),
253    /// #           self.year.to_string(),
254    /// #           self.body.clone(),
255    /// #       ]
256    /// #   }
257    /// # }
258    /// #
259    /// # let my_vec = vec![
260    /// #   MyStruct {
261    /// #       title: "Harold Godwinson".to_string(),
262    /// #       year: 1066,
263    /// #       body: "Last crowned Anglo-Saxon king of England.".to_string(),
264    /// #   },
265    /// #   MyStruct {
266    /// #       title: "Edgar Ætheling".to_string(),
267    /// #       year: 1066,
268    /// #       body: "Last male member of the royal house of Cerdic of Wessex.".to_string(),
269    /// #   },
270    /// #   MyStruct {
271    /// #       title: "William the Conqueror".to_string(),
272    /// #       year: 1066,
273    /// #       body: "First Norman monarch of England.".to_string(),
274    /// #   },
275    /// #   MyStruct {
276    /// #       title: "William Rufus".to_string(),
277    /// #       year: 1087,
278    /// #       body: "Third son of William the Conqueror.".to_string(),
279    /// #   },
280    /// #   MyStruct {
281    /// #       title: "Henry Beauclerc".to_string(),
282    /// #       year: 1100,
283    /// #       body: "Fourth son of William the Conqueror.".to_string(),
284    /// #   },
285    /// # ];
286    /// #
287    /// # let mut search_index: SearchIndex<usize> = SearchIndex::default();
288    /// #
289    /// # my_vec
290    /// #   .iter()
291    /// #   .enumerate()
292    /// #   .for_each(|(index, element)|
293    /// #       search_index.insert(&index, element)
294    /// #   );
295    /// #
296    /// let autocomplete_options =
297    ///     search_index.autocomplete_with(
298    ///         &AutocompleteType::Global,
299    ///         &5,
300    ///         "1100 e",
301    ///     );
302    ///
303    /// assert_eq!(
304    ///     autocomplete_options,
305    ///     vec![
306    ///         "1100 edgar".to_string(),
307    ///         "1100 edgar ætheling".to_string(),
308    ///         "1100 england".to_string()
309    ///     ]
310    /// );
311    /// ```
312    #[tracing::instrument(level = "trace", name = "autocomplete", skip(self))]
313    pub fn autocomplete_with(
314        &self,
315        autocomplete_type: &AutocompleteType,
316        maximum_autocomplete_options: &usize,
317        string: &str,
318    ) -> Vec<String> {
319        let autocomplete_options: Vec<String> = match autocomplete_type {
320            AutocompleteType::Context => {
321                self.autocomplete_context(maximum_autocomplete_options, string)
322            }
323            AutocompleteType::Global => {
324                self.autocomplete_global(maximum_autocomplete_options, string)
325            }
326            AutocompleteType::Keyword => self
327                .autocomplete_keyword(maximum_autocomplete_options, string)
328                .into_iter()
329                .map(std::string::ToString::to_string)
330                .collect(),
331        };
332
333        // For debug builds:
334        #[cfg(debug_assertions)]
335        tracing::debug!(
336            "{} autocomplete options for \"{}\".",
337            autocomplete_options.len(),
338            string,
339        );
340
341        autocomplete_options
342    }
343}