use super::Command;
use crate::common::syntax::parse_arguments;
use crate::common::syntax::Mode;
use crate::common::syntax::OptionSpec;
use thiserror::Error;
use yash_env::semantics::Field;
use yash_env::Env;
use yash_syntax::source::pretty::AnnotationType;
use yash_syntax::source::pretty::Message;
#[derive(Clone, Debug, Eq, Error, PartialEq)]
#[non_exhaustive]
pub enum Error {
#[error(transparent)]
CommonError(#[from] crate::common::syntax::ParseError<'static>),
#[error("missing operand")]
MissingOperand,
}
impl Error {
pub fn to_message(&self) -> Message {
match self {
Error::CommonError(e) => e.into(),
Error::MissingOperand => Message {
r#type: AnnotationType::Error,
title: self.to_string().into(),
annotations: vec![],
footers: vec![],
},
}
}
}
impl<'a> From<&'a Error> for Message<'a> {
#[inline]
fn from(e: &'a Error) -> Self {
e.to_message()
}
}
const OPTION_SPECS: &[OptionSpec] = &[OptionSpec::new().short('r').long("raw-mode")];
pub fn parse(env: &Env, args: Vec<Field>) -> Result<Command, Error> {
let mode = Mode::with_env(env);
let (options, operands) = parse_arguments(OPTION_SPECS, mode, args)?;
let mut is_raw = false;
for option in options {
match option.spec.get_short() {
Some('r') => is_raw = true,
_ => unreachable!(),
}
}
let mut variables = operands;
let last_variable = variables.pop().ok_or(Error::MissingOperand)?;
Ok(Command {
is_raw,
variables,
last_variable,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_raw_mode() {
let env = Env::new_virtual();
assert_eq!(
parse(&env, Field::dummies(["var"])),
Ok(Command {
is_raw: false,
variables: vec![],
last_variable: Field::dummy("var"),
})
);
}
#[test]
fn raw_mode() {
let env = Env::new_virtual();
assert_eq!(
parse(&env, Field::dummies(["-r", "var"])),
Ok(Command {
is_raw: true,
variables: vec![],
last_variable: Field::dummy("var"),
})
);
}
#[test]
fn many_operands() {
let env = Env::new_virtual();
assert_eq!(
parse(&env, Field::dummies(["foo", "bar"])),
Ok(Command {
is_raw: false,
variables: Field::dummies(["foo"]),
last_variable: Field::dummy("bar"),
})
);
assert_eq!(
parse(&env, Field::dummies(["first", "second", "third"])),
Ok(Command {
is_raw: false,
variables: Field::dummies(["first", "second"]),
last_variable: Field::dummy("third"),
})
);
}
#[test]
fn missing_operand() {
let env = Env::new_virtual();
assert_eq!(parse(&env, vec![]), Err(Error::MissingOperand));
}
}