photon_ui/
autocomplete.rs1use crate::fuzzy::fuzzy_filter;
2
3pub trait AutocompleteProvider {
5 fn suggest(&self, query: &str) -> Vec<String>;
7}
8
9pub struct SimpleAutocomplete {
13 items: Vec<String>,
14}
15
16impl SimpleAutocomplete {
17 pub fn new(items: Vec<String>) -> Self {
19 Self { items }
20 }
21}
22
23impl AutocompleteProvider for SimpleAutocomplete {
24 fn suggest(&self, query: &str) -> Vec<String> {
25 if query.is_empty() {
26 return self.items.clone();
27 }
28 let filtered = fuzzy_filter(&self.items, query, |s| s.as_str());
29 filtered.into_iter().map(|s| s.clone()).collect()
30 }
31}
32
33pub struct CombinedAutocompleteProvider {
39 commands: Vec<String>,
40 _base_path: String,
41}
42
43impl CombinedAutocompleteProvider {
44 pub fn new(commands: Vec<String>, base_path: impl Into<String>) -> Self {
46 Self {
47 commands,
48 _base_path: base_path.into(),
49 }
50 }
51}
52
53impl AutocompleteProvider for CombinedAutocompleteProvider {
54 fn suggest(&self, query: &str) -> Vec<String> {
55 if query.starts_with('/') {
56 fuzzy_filter(&self.commands, &query[1..], |s| s.as_str())
57 .into_iter()
58 .map(|s| format!("/{}", s))
59 .collect()
60 } else {
61 fuzzy_filter(&self.commands, query, |s| s.as_str())
62 .into_iter()
63 .map(|s| s.clone())
64 .collect()
65 }
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn simple_autocomplete_empty_query() {
75 let auto = SimpleAutocomplete::new(vec!["apple".into(), "banana".into()]);
76 let suggestions = auto.suggest("");
77 assert_eq!(suggestions.len(), 2);
78 }
79
80 #[test]
81 fn combined_autocomplete_non_slash() {
82 let auto = CombinedAutocompleteProvider::new(vec!["cmd".into()], "/base");
83 let suggestions = auto.suggest("c");
84 assert_eq!(suggestions.len(), 1);
85 assert_eq!(suggestions[0], "cmd");
86 }
87
88 #[test]
89 fn combined_autocomplete_slash() {
90 let auto = CombinedAutocompleteProvider::new(vec!["cmd".into()], "/base");
91 let suggestions = auto.suggest("/c");
92 assert_eq!(suggestions.len(), 1);
93 assert_eq!(suggestions[0], "/cmd");
94 }
95}