use {
super::{
builtin::builtin_verbs,
Internal,
Verb,
},
crate::{
app::SelectionType,
conf::Conf,
errors::ConfError,
keys,
},
crossterm::event::KeyEvent,
std::convert::TryFrom,
};
#[derive(Default)]
pub struct VerbStore {
pub verbs: Vec<Verb>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum PrefixSearchResult<'v, T> {
NoMatch,
Match(&'v str, T),
Matches(Vec<&'v str>),
}
impl VerbStore {
pub fn init(&mut self, conf: &mut Conf) -> Result<(), ConfError> {
for vc in &conf.verbs {
self.verbs.push(Verb::try_from(vc)?);
}
self.verbs.extend(builtin_verbs());
Ok(())
}
pub fn search<'v>(
&'v self,
prefix: &str,
stype: Option<SelectionType>,
) -> PrefixSearchResult<'v, &Verb> {
let mut found_index = 0;
let mut nb_found = 0;
let mut completions: Vec<&str> = Vec::new();
for (index, verb) in self.verbs.iter().enumerate() {
if let Some(stype) = stype {
if !stype.respects(verb.selection_condition) {
continue;
}
}
for name in &verb.names {
if name.starts_with(prefix) {
if name == prefix {
return PrefixSearchResult::Match(name, &verb);
}
found_index = index;
nb_found += 1;
completions.push(name);
continue;
}
}
}
match nb_found {
0 => PrefixSearchResult::NoMatch,
1 => PrefixSearchResult::Match(completions[0], &self.verbs[found_index]),
_ => PrefixSearchResult::Matches(completions),
}
}
pub fn index_of_key(&self, key: KeyEvent) -> Option<usize> {
for i in 0..self.verbs.len() {
for verb_key in &self.verbs[i].keys {
if *verb_key == key {
return Some(i);
}
}
}
None
}
pub fn key_desc_of_internal_stype(
&self,
internal: Internal,
stype: SelectionType,
) -> Option<String> {
for verb in &self.verbs {
if verb.get_internal() == Some(internal) && stype.respects(verb.selection_condition) {
return verb.keys.get(0).map(|&k| keys::key_event_desc(k));
}
}
None
}
pub fn key_desc_of_internal(
&self,
internal: Internal,
) -> Option<String> {
for verb in &self.verbs {
if verb.get_internal() == Some(internal) {
return verb.keys.get(0).map(|&k| keys::key_event_desc(k));
}
}
None
}
}