syncable_cli/agent/ui/
autocomplete.rs1use inquire::autocompletion::{Autocomplete, Replacement};
7use crate::agent::commands::SLASH_COMMANDS;
8
9#[derive(Clone, Default)]
12pub struct SlashCommandAutocomplete {
13 filtered_commands: Vec<&'static str>,
15}
16
17impl SlashCommandAutocomplete {
18 pub fn new() -> Self {
19 Self {
20 filtered_commands: Vec::new(),
21 }
22 }
23}
24
25impl Autocomplete for SlashCommandAutocomplete {
26 fn get_suggestions(&mut self, input: &str) -> Result<Vec<String>, inquire::CustomUserError> {
27 if !input.starts_with('/') {
29 self.filtered_commands.clear();
30 return Ok(vec![]);
31 }
32
33 let filter = input.trim_start_matches('/').to_lowercase();
34
35 self.filtered_commands = SLASH_COMMANDS.iter()
37 .filter(|cmd| {
38 cmd.name.to_lowercase().starts_with(&filter) ||
39 cmd.alias.map(|a| a.to_lowercase().starts_with(&filter)).unwrap_or(false)
40 })
41 .take(6)
42 .map(|cmd| cmd.name)
43 .collect();
44
45 let suggestions: Vec<String> = SLASH_COMMANDS.iter()
47 .filter(|cmd| {
48 cmd.name.to_lowercase().starts_with(&filter) ||
49 cmd.alias.map(|a| a.to_lowercase().starts_with(&filter)).unwrap_or(false)
50 })
51 .take(6)
52 .map(|cmd| format!("/{:<12} {}", cmd.name, cmd.description))
53 .collect();
54
55 Ok(suggestions)
56 }
57
58 fn get_completion(
59 &mut self,
60 _input: &str,
61 highlighted_suggestion: Option<String>,
62 ) -> Result<Replacement, inquire::CustomUserError> {
63 if let Some(suggestion) = highlighted_suggestion {
64 if let Some(cmd_with_slash) = suggestion.split_whitespace().next() {
67 return Ok(Replacement::Some(cmd_with_slash.to_string()));
68 }
69 }
70 Ok(Replacement::None)
71 }
72}