use super::parser::{parse_lino, LinoNode};
use super::SHELL_INTENTS_LINO;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ShellIntentArgument {
#[default]
None,
Path,
NameLead,
}
#[derive(Debug, Clone, Default)]
pub struct ShellIntent {
pub command: String,
pub argument: ShellIntentArgument,
pub cues: Vec<String>,
}
#[derive(Debug, Clone, Default)]
pub struct ShellIntentVocabulary {
pub name_leads: Vec<String>,
pub intents: Vec<ShellIntent>,
}
#[must_use]
pub fn shell_intent_vocabulary() -> ShellIntentVocabulary {
let tree = parse_lino(SHELL_INTENTS_LINO);
let mut vocab = ShellIntentVocabulary::default();
let Some(root) = tree.children.first() else {
return vocab;
};
for group in &root.children {
match group.name.as_str() {
"name_leads" => vocab.name_leads = collect_language_values(group, "lead"),
"intents" => {
vocab.intents = group
.children
.iter()
.filter(|c| c.name == "intent")
.map(parse_intent)
.collect();
}
_ => {}
}
}
vocab
}
fn parse_intent(node: &LinoNode) -> ShellIntent {
ShellIntent {
command: node.find_child_value("command").to_owned(),
argument: match node.find_child_value("argument") {
"path" => ShellIntentArgument::Path,
"name_lead" => ShellIntentArgument::NameLead,
_ => ShellIntentArgument::None,
},
cues: collect_language_values(node, "cue")
.into_iter()
.map(|cue| cue.to_lowercase())
.collect(),
}
}
fn collect_language_values(group: &LinoNode, child_name: &str) -> Vec<String> {
group
.children
.iter()
.filter(|c| c.name == "language")
.flat_map(|lang| {
lang.children
.iter()
.filter(|c| c.name == child_name)
.map(|c| c.id.clone())
})
.collect()
}