use super::Command;
use thiserror::Error;
use yash_env::Env;
use yash_env::semantics::Field;
use yash_env::source::pretty::{Report, ReportType, Snippet};
#[derive(Clone, Debug, Eq, Error, PartialEq)]
pub enum Error {
#[error("no such alias `{0}`")]
UndefinedAlias(Field),
}
impl Error {
#[must_use]
fn to_report(&self) -> Report<'_> {
let mut report = Report::new();
report.r#type = ReportType::Error;
report.title = "cannot remove alias".into();
match self {
Self::UndefinedAlias(alias) => {
report.snippets = Snippet::with_primary_span(
&alias.origin,
format!("no such alias `{alias}`").into(),
);
}
}
report
}
}
impl<'a> From<&'a Error> for Report<'a> {
#[inline]
fn from(error: &'a Error) -> Self {
error.to_report()
}
}
impl Command {
#[must_use]
pub fn execute<S>(self, env: &mut Env<S>) -> Vec<Error> {
match self {
Command::RemoveAll => {
env.aliases.clear();
vec![]
}
Command::Remove(operands) => operands
.into_iter()
.filter(|operand| !env.aliases.remove(operand.value.as_str()))
.map(Error::UndefinedAlias)
.collect(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use yash_env::alias::HashEntry;
use yash_env::source::Location;
#[test]
fn remove_all() {
let mut env = Env::new_virtual();
env.aliases.insert(HashEntry::new(
"foo".into(),
"FOO".into(),
false,
Location::dummy("foo location"),
));
env.aliases.insert(HashEntry::new(
"bar".into(),
"BAR".into(),
false,
Location::dummy("bar location"),
));
let errors = Command::RemoveAll.execute(&mut env);
assert_eq!(errors, []);
assert_eq!(env.aliases.len(), 0, "remaining: {:?}", env.aliases);
}
#[test]
fn remove_some() {
let mut env = Env::new_virtual();
env.aliases.insert(HashEntry::new(
"foo".into(),
"FOO".into(),
false,
Location::dummy("foo location"),
));
let bar = HashEntry::new(
"bar".into(),
"BAR".into(),
false,
Location::dummy("bar location"),
);
env.aliases.insert(bar.clone());
env.aliases.insert(HashEntry::new(
"baz".into(),
"BAZ".into(),
false,
Location::dummy("baz location"),
));
let names = Field::dummies(["foo", "baz"]);
let errors = Command::Remove(names).execute(&mut env);
assert_eq!(errors, []);
let aliases = env.aliases.into_iter().collect::<Vec<_>>();
assert_eq!(aliases, [bar]);
}
#[test]
fn remove_undefined() {
let mut env = Env::new_virtual();
env.aliases.insert(HashEntry::new(
"foo".into(),
"FOO".into(),
false,
Location::dummy("foo location"),
));
let bar = HashEntry::new(
"bar".into(),
"BAR".into(),
false,
Location::dummy("bar location"),
);
env.aliases.insert(bar.clone());
env.aliases.insert(HashEntry::new(
"baz".into(),
"BAZ".into(),
false,
Location::dummy("baz location"),
));
let names = Field::dummies(["foo", "gar", "baz", "qux"]);
let errors = Command::Remove(names).execute(&mut env);
assert_eq!(
errors,
[
Error::UndefinedAlias(Field::dummy("gar")),
Error::UndefinedAlias(Field::dummy("qux")),
]
);
let aliases = env.aliases.into_iter().collect::<Vec<_>>();
assert_eq!(aliases, [bar]);
}
}