use super::components::palette::Entry;
use super::keys::COMMAND;
use super::page::{CommandRun, Page};
use super::store::Store;
const RECENT: usize = 8;
pub enum Target {
OpenPage(usize),
Page(usize, CommandRun),
Refresh,
Help,
Settings,
}
pub struct Item {
pub entry: Entry,
pub target: Target,
}
pub fn build(pages: &[Box<dyn Page>], store: &Store, recent: &[String]) -> Vec<Item> {
let mut items: Vec<Item> = Vec::new();
for (index, page) in pages.iter().enumerate() {
items.push(Item {
entry: Entry {
label: format!("Go to {}", page.title()),
detail: format!("{COMMAND}{}", index + 1),
},
target: Target::OpenPage(index),
});
}
items.push(item("Refresh", "F5", Target::Refresh));
items.push(item("Keyboard shortcuts", "?", Target::Help));
items.push(item("Settings", &format!("{COMMAND},"), Target::Settings));
for (index, page) in pages.iter().enumerate() {
items.extend(page.commands(store).into_iter().map(|c| Item {
entry: Entry {
label: c.label,
detail: c.detail,
},
target: Target::Page(index, c.run),
}));
}
items.sort_by_key(|i| {
recent
.iter()
.position(|r| *r == i.entry.label)
.unwrap_or(usize::MAX)
});
items
}
fn item(label: &str, detail: &str, target: Target) -> Item {
Item {
entry: Entry {
label: label.into(),
detail: detail.into(),
},
target,
}
}
pub fn remember(recent: &mut Vec<String>, label: &str) {
recent.retain(|r| r != label);
recent.insert(0, label.to_owned());
recent.truncate(RECENT);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn remembers_most_recent_first() {
let mut recent = Vec::new();
for label in ["a", "b", "a"] {
remember(&mut recent, label);
}
assert_eq!(recent, vec!["a", "b"]);
}
}