use crate::{
app::AppContext,
keys,
pattern::*,
verb::*,
};
pub struct MatchingVerbRow<'v> {
name: Option<String>,
shortcut: Option<String>,
pub description_md: String,
pub keys_desc: String,
pub verb: &'v Verb,
}
impl MatchingVerbRow<'_> {
pub fn name(&self) -> &str {
self.name
.as_deref()
.unwrap_or_else(|| match self.verb.names.first() {
Some(s) => s.as_str(),
_ => " ",
})
}
pub fn shortcut(&self) -> &str {
self.shortcut
.as_deref()
.unwrap_or_else(|| match self.verb.names.get(1) {
Some(s) => s.as_str(),
_ => " ",
})
}
}
pub fn matching_verb_rows<'v>(
pat: &Pattern,
con: &'v AppContext,
) -> Vec<MatchingVerbRow<'v>> {
let mut rows = Vec::new();
for verb in con.verb_store.verbs() {
if !verb.show_in_doc {
continue;
}
let mut name = None;
let mut shortcut = None;
let mut keys_desc = String::from(" ");
let keys = verb
.keys
.iter()
.filter(|&&k| con.modal || !keys::is_key_only_modal(k));
for (i, key) in keys.enumerate() {
if i > 0 {
keys_desc.push_str(", ");
}
keys_desc.push_str(keys::KEY_FORMAT.to_string(*key).as_str());
}
let mut desc_match = None;
let desc = &verb.description.content;
if pat.is_some() {
let mut ok = false;
name = verb.names.first().and_then(|s| {
pat.search_string(s).map(|nm| {
ok = true;
nm.wrap(s, "**", "**")
})
});
shortcut = verb.names.get(1).and_then(|s| {
pat.search_string(s).map(|nm| {
ok = true;
nm.wrap(s, "**", "**")
})
});
if let Some(nm) = pat.search_string(keys_desc.as_str()) {
keys_desc = nm.wrap(keys_desc.as_str(), "**", "**");
ok = true;
}
desc_match = pat.search_string(desc);
if desc_match.is_some() {
ok = true;
}
if !ok {
continue;
}
}
let description_md = match (desc_match, verb.description.code) {
(Some(m), false) => {
format!("`{}`", m.wrap(desc, "`**", "**`"))
}
(Some(m), true) => m.wrap(desc, "**", "**"),
(None, true) => {
format!("`{}`", desc)
}
(None, false) => desc.to_string(),
};
rows.push(MatchingVerbRow {
name,
shortcut,
keys_desc,
description_md,
verb,
});
}
rows
}