use {
super::{
Command,
CommandParts,
},
crate::{
app::AppContext,
errors::ProgramError,
verb::*,
},
};
#[derive(Debug, Clone)]
pub struct Sequence {
pub raw: String,
pub separator: String,
}
impl Sequence {
pub fn local_separator() -> String {
match std::env::var("BROOT_CMD_SEPARATOR") {
Ok(sep) if !sep.is_empty() => sep,
_ => String::from(";"),
}
}
pub fn new<S: Into<String>>(
raw: S,
separator: Option<S>,
) -> Self {
Self {
raw: raw.into(),
separator: separator.map_or_else(Sequence::local_separator, Into::into),
}
}
pub fn new_single<S: Into<String>>(cmd: S) -> Self {
Self {
separator: String::new(),
raw: cmd.into(),
}
}
pub fn new_local(raw: String) -> Self {
Self {
separator: Self::local_separator(),
raw,
}
}
pub fn parse(
&self,
con: &AppContext,
) -> Result<Vec<(String, Command)>, ProgramError> {
debug!("Splitting cmd sequence with {:?}", &self.separator);
let mut commands = Vec::new();
if self.separator.is_empty() {
add_commands(&self.raw, &mut commands, con)?;
} else {
for input in self.raw.split(&self.separator) {
add_commands(input, &mut commands, con)?;
}
}
Ok(commands)
}
pub fn has_selection_group(&self) -> bool {
str_has_selection_group(&self.raw)
}
pub fn has_other_panel_group(&self) -> bool {
str_has_other_panel_group(&self.raw)
}
}
fn add_commands(
input: &str,
commands: &mut Vec<(String, Command)>,
con: &AppContext,
) -> Result<(), ProgramError> {
let raw_parts = CommandParts::from(input.to_string());
let (pattern, verb_invocation) = raw_parts.split();
if let Some(pattern) = pattern {
commands.push((input.to_string(), Command::from_parts(pattern, false)));
}
if let Some(verb_invocation) = verb_invocation {
let mut command = Command::from_parts(verb_invocation, true);
if let Command::VerbInvocate(invocation) = &command {
match con.verb_store.search_prefix(&invocation.name, None) {
PrefixSearchResult::NoMatch => {
return Err(ProgramError::UnknownVerb {
name: invocation.name.clone(),
});
}
PrefixSearchResult::Matches(_) => {
return Err(ProgramError::AmbiguousVerbName {
name: invocation.name.clone(),
});
}
PrefixSearchResult::Match(_, verb) => {
if let Some(internal) = verb.get_internal() {
command = Command::Internal {
internal,
input_invocation: Some(invocation.clone()),
};
}
commands.push((input.to_string(), command));
}
}
}
}
Ok(())
}