Skip to main content

tui_pages/command/
registry.rs

1use crate::command::CommandHint;
2use std::collections::HashMap;
3
4#[derive(Debug, Clone)]
5pub struct CommandRegistry<A> {
6    bindings: HashMap<String, (String, A)>,
7}
8
9impl<A> Default for CommandRegistry<A> {
10    fn default() -> Self {
11        Self::new()
12    }
13}
14
15impl<A> CommandRegistry<A> {
16    pub fn new() -> Self {
17        Self {
18            bindings: HashMap::new(),
19        }
20    }
21
22    pub fn bind(&mut self, action_name: impl Into<String>, alias: impl Into<String>, action: A) {
23        self.bindings
24            .insert(alias.into().to_lowercase(), (action_name.into(), action));
25    }
26
27    pub fn bind_aliases<I, S>(&mut self, action_name: impl Into<String>, aliases: I, action: A)
28    where
29        A: Clone,
30        I: IntoIterator<Item = S>,
31        S: Into<String>,
32    {
33        let action_name = action_name.into();
34        for alias in aliases {
35            self.bind(action_name.clone(), alias, action.clone());
36        }
37    }
38
39    pub fn is_empty(&self) -> bool {
40        self.bindings.is_empty()
41    }
42
43    pub fn len(&self) -> usize {
44        self.bindings.len()
45    }
46
47    pub fn is_prefix(&self, input: &str) -> bool {
48        if input.trim().is_empty() {
49            return false;
50        }
51
52        let input = input.trim().to_lowercase();
53        self.bindings
54            .keys()
55            .any(|alias| alias.starts_with(&input) && alias != &input)
56    }
57
58    pub fn get_hints(&self, input: &str) -> Vec<CommandHint> {
59        let input = input.trim().to_lowercase();
60        self.bindings
61            .iter()
62            .filter(|(alias, _)| alias.starts_with(&input) && *alias != &input)
63            .map(|(alias, (action_name, _))| CommandHint {
64                alias: alias.clone(),
65                action_name: action_name.clone(),
66            })
67            .collect()
68    }
69
70    pub fn all_commands(&self) -> Vec<CommandHint> {
71        self.bindings
72            .iter()
73            .map(|(alias, (action_name, _))| CommandHint {
74                alias: alias.clone(),
75                action_name: action_name.clone(),
76            })
77            .collect()
78    }
79}
80
81impl<A: Clone> CommandRegistry<A> {
82    pub fn match_action(&self, input: &str) -> Option<A> {
83        let input = input.trim().to_lowercase();
84        self.bindings.get(&input).map(|(_, action)| action.clone())
85    }
86}