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,
OnePath,
TwoPaths,
Remainder,
SearchQuery,
}
#[derive(Debug, Clone, Default)]
pub struct ShellIntent {
pub command: String,
pub argument: ShellIntentArgument,
pub cues: Vec<String>,
}
#[derive(Debug, Clone, Default)]
pub struct WorkspaceCommands {
pub marker: String,
pub test: String,
pub install: String,
pub build: String,
}
#[derive(Debug, Clone, Default)]
pub struct ShellIntentVocabulary {
pub name_leads: Vec<String>,
pub argument_noise: Vec<String>,
pub local_search_scopes: Vec<String>,
pub workspace_commands: Vec<WorkspaceCommands>,
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"),
"argument_noise" => {
vocab.argument_noise = collect_language_values(group, "word");
}
"local_search_scopes" => {
vocab.local_search_scopes = collect_language_values(group, "scope");
}
"workspace_commands" => {
vocab.workspace_commands = group
.children
.iter()
.filter(|child| child.name == "workspace")
.map(|node| WorkspaceCommands {
marker: node.find_child_value("marker").to_owned(),
test: node.find_child_value("test").to_owned(),
install: node.find_child_value("install").to_owned(),
build: node.find_child_value("build").to_owned(),
})
.collect();
}
"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,
"one_path" => ShellIntentArgument::OnePath,
"two_paths" => ShellIntentArgument::TwoPaths,
"remainder" => ShellIntentArgument::Remainder,
"search_query" => ShellIntentArgument::SearchQuery,
_ => 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()
}