use std::fmt;
#[derive(Debug, Clone)]
pub struct Binding {
keys: Vec<String>,
help: Help,
disabled: bool,
}
pub type BindingOpt = Box<dyn FnOnce(&mut Binding)>;
pub fn new_binding(opts: Vec<BindingOpt>) -> Binding {
let mut b = Binding {
keys: Vec::new(),
help: Help {
key: String::new(),
desc: String::new(),
},
disabled: false,
};
for opt in opts {
opt(&mut b);
}
b
}
pub fn with_keys(keys: &[&str]) -> BindingOpt {
let keys: Vec<String> = keys.iter().map(|k| k.to_string()).collect();
Box::new(move |b| {
b.keys = keys;
})
}
pub fn with_help(key: &str, desc: &str) -> BindingOpt {
let key = key.to_string();
let desc = desc.to_string();
Box::new(move |b| {
b.help = Help { key, desc };
})
}
pub fn with_disabled() -> BindingOpt {
Box::new(|b| {
b.disabled = true;
})
}
impl Binding {
pub fn set_keys(&mut self, keys: &[&str]) {
self.keys = keys.iter().map(|k| k.to_string()).collect();
}
pub fn keys(&self) -> Vec<String> {
self.keys.clone()
}
pub fn set_help(&mut self, key: &str, desc: &str) {
self.help = Help {
key: key.to_string(),
desc: desc.to_string(),
};
}
pub fn help(&self) -> Help {
self.help.clone()
}
pub fn enabled(&self) -> bool {
!self.disabled && !self.keys.is_empty()
}
pub fn set_enabled(&mut self, v: bool) {
self.disabled = !v;
}
pub fn unbind(&mut self) {
self.keys.clear();
self.help = Help {
key: String::new(),
desc: String::new(),
};
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Help {
pub key: String,
pub desc: String,
}
pub fn matches<K: fmt::Display>(k: K, bindings: &[Binding]) -> bool {
let keys = k.to_string();
for binding in bindings {
for v in &binding.keys {
if keys == *v && binding.enabled() {
return true;
}
}
}
false
}