in src/cli.rs [834:962]
fn from_str(s: &str) -> Result<Self, Self::Err> {
use nom::{
branch::alt,
bytes::complete::{is_not, tag},
character::complete::multispace0,
combinator::{all_consuming, cut},
error::{convert_error, ParseError, VerboseError, VerboseErrorKind},
multi::separated_list1,
sequence::delimited,
Finish, IResult,
};
type ParseResult<I, O> = IResult<I, O, VerboseError<I>>;
fn parse(input: &str) -> ParseResult<&str, GraphFilter> {
all_consuming(alt((include_filter, exclude_filter)))(input)
}
fn include_filter(input: &str) -> ParseResult<&str, GraphFilter> {
let (rest, val) =
delimited(ws(tag("include(")), cut(filter_query), ws(tag(")")))(input)?;
Ok((rest, GraphFilter::Include(val)))
}
fn exclude_filter(input: &str) -> ParseResult<&str, GraphFilter> {
let (rest, val) =
delimited(ws(tag("exclude(")), cut(filter_query), ws(tag(")")))(input)?;
Ok((rest, GraphFilter::Exclude(val)))
}
fn filter_query(input: &str) -> ParseResult<&str, GraphFilterQuery> {
alt((any_query, all_query, not_query, prop_query))(input)
}
fn any_query(input: &str) -> ParseResult<&str, GraphFilterQuery> {
let (rest, val) = delimited(
ws(tag("any(")),
cut(separated_list1(tag(","), cut(filter_query))),
ws(tag(")")),
)(input)?;
Ok((rest, GraphFilterQuery::Any(val)))
}
fn all_query(input: &str) -> ParseResult<&str, GraphFilterQuery> {
let (rest, val) = delimited(
ws(tag("all(")),
cut(separated_list1(tag(","), cut(filter_query))),
ws(tag(")")),
)(input)?;
Ok((rest, GraphFilterQuery::All(val)))
}
fn not_query(input: &str) -> ParseResult<&str, GraphFilterQuery> {
let (rest, val) = delimited(ws(tag("not(")), cut(filter_query), ws(tag(")")))(input)?;
Ok((rest, GraphFilterQuery::Not(Box::new(val))))
}
fn prop_query(input: &str) -> ParseResult<&str, GraphFilterQuery> {
let (rest, val) = filter_property(input)?;
Ok((rest, GraphFilterQuery::Prop(val)))
}
fn filter_property(input: &str) -> ParseResult<&str, GraphFilterProperty> {
alt((
prop_name,
prop_version,
prop_is_root,
prop_is_workspace_member,
prop_is_third_party,
prop_is_dev_only,
))(input)
}
fn prop_name(input: &str) -> ParseResult<&str, GraphFilterProperty> {
let (rest, val) =
delimited(ws(tag("name(")), cut(val_package_name), ws(tag(")")))(input)?;
Ok((rest, GraphFilterProperty::Name(val.to_string())))
}
fn prop_version(input: &str) -> ParseResult<&str, GraphFilterProperty> {
let (rest, val) =
delimited(ws(tag("version(")), cut(val_version), ws(tag(")")))(input)?;
Ok((rest, GraphFilterProperty::Version(val)))
}
fn prop_is_root(input: &str) -> ParseResult<&str, GraphFilterProperty> {
let (rest, val) = delimited(ws(tag("is_root(")), cut(val_bool), ws(tag(")")))(input)?;
Ok((rest, GraphFilterProperty::IsRoot(val)))
}
fn prop_is_workspace_member(input: &str) -> ParseResult<&str, GraphFilterProperty> {
let (rest, val) =
delimited(ws(tag("is_workspace_member(")), cut(val_bool), ws(tag(")")))(input)?;
Ok((rest, GraphFilterProperty::IsWorkspaceMember(val)))
}
fn prop_is_third_party(input: &str) -> ParseResult<&str, GraphFilterProperty> {
let (rest, val) =
delimited(ws(tag("is_third_party(")), cut(val_bool), ws(tag(")")))(input)?;
Ok((rest, GraphFilterProperty::IsThirdParty(val)))
}
fn prop_is_dev_only(input: &str) -> ParseResult<&str, GraphFilterProperty> {
let (rest, val) =
delimited(ws(tag("is_dev_only(")), cut(val_bool), ws(tag(")")))(input)?;
Ok((rest, GraphFilterProperty::IsDevOnly(val)))
}
fn val_bool(input: &str) -> ParseResult<&str, bool> {
alt((val_true, val_false))(input)
}
fn val_true(input: &str) -> ParseResult<&str, bool> {
let (rest, _val) = ws(tag("true"))(input)?;
Ok((rest, true))
}
fn val_false(input: &str) -> ParseResult<&str, bool> {
let (rest, _val) = ws(tag("false"))(input)?;
Ok((rest, false))
}
fn val_package_name(input: &str) -> ParseResult<&str, &str> {
is_not(") ")(input)
}
fn val_version(input: &str) -> ParseResult<&str, VetVersion> {
let (rest, val) = is_not(") ")(input)?;
let val = VetVersion::from_str(val).map_err(|_e| {
nom::Err::Failure(VerboseError {
errors: vec![(val, VerboseErrorKind::Context("version parse error"))],
})
})?;
Ok((rest, val))
}
fn ws<'a, F, O, E: ParseError<&'a str>>(
inner: F,
) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
where
F: Fn(&'a str) -> IResult<&'a str, O, E>,
{
delimited(multispace0, inner, multispace0)
}
match parse(s).finish() {
Ok((_remaining, val)) => Ok(val),
Err(e) => Err(convert_error(s, e)),
}
}