pub struct Command {
pub id: String,
pub label: String,
pub shortcut: Option<String>,
pub action: Box<dyn Fn() + Send + Sync>,
}
pub struct CommandPalette {
commands: Vec<Command>,
}
impl CommandPalette {
pub fn new() -> Self {
Self {
commands: Vec::new(),
}
}
pub fn register(
&mut self,
id: impl Into<String>,
label: impl Into<String>,
action: impl Fn() + Send + Sync + 'static,
) {
self.commands.push(Command {
id: id.into(),
label: label.into(),
shortcut: None,
action: Box::new(action),
});
}
pub fn register_with_shortcut(
&mut self,
id: impl Into<String>,
label: impl Into<String>,
shortcut: Option<String>,
action: impl Fn() + Send + Sync + 'static,
) {
self.commands.push(Command {
id: id.into(),
label: label.into(),
shortcut,
action: Box::new(action),
});
}
pub fn search(&self, query: &str) -> Vec<&Command> {
let query_lc = query.to_lowercase();
self.commands
.iter()
.filter(|cmd| {
let label_lc = cmd.label.to_lowercase();
let mut q_iter = query_lc.chars();
let mut current = q_iter.next();
for ch in label_lc.chars() {
if current == Some(ch) {
current = q_iter.next();
}
if current.is_none() {
return true;
}
}
current.is_none()
})
.collect()
}
pub fn len(&self) -> usize {
self.commands.len()
}
pub fn is_empty(&self) -> bool {
self.commands.is_empty()
}
}
impl Default for CommandPalette {
fn default() -> Self {
Self::new()
}
}