use nom::{
bytes::complete::{is_not, tag, take},
combinator::{peek, recognize},
sequence::{delimited, tuple},
IResult,
};
use crate::parser::LinkDestination;
use super::base_parsers::CustomError;
use super::markdown_elements::{delimited_email_address, delimited_link};
use super::text_elements::parse_text_element;
use super::Element;
pub(crate) fn labeled_link(input: &str) -> IResult<&str, Element, CustomError<&str>> {
let (input, raw_label) = delimited(tag("["), is_not("]"), tag("]"))(input)?;
if raw_label.is_empty() {
return Err(nom::Err::Error(CustomError::NoContent));
}
let label = vec![Element::Text(raw_label)];
let (input, (_, destination, _)) =
tuple((tag("("), LinkDestination::parse_labelled, tag(")")))(input)?;
Ok((input, Element::LabeledLink { label, destination }))
}
fn eat_desktopset_text(input: &str) -> IResult<&str, (), CustomError<&str>> {
let mut remaining = input;
while !remaining.is_empty() {
let (remainder, taken) = take(1usize)(remaining)?;
remaining = remainder;
if peek(|input| parse_element(input, taken.chars().next()))(remaining).is_ok() {
break;
}
}
Ok((remaining, ()))
}
pub(crate) fn desktopset_text(input: &str) -> IResult<&str, Element, CustomError<&str>> {
let (rest, content) = recognize(eat_desktopset_text)(input)?;
Ok((rest, Element::Text(content)))
}
pub(crate) fn parse_element(
input: &str,
prev_char: Option<char>,
) -> IResult<&str, Element, CustomError<&str>> {
if let Ok((i, elm)) = labeled_link(input) {
Ok((i, elm))
} else if let Ok((i, elm)) = delimited_email_address(input) {
Ok((i, elm))
} else if let Ok((i, elm)) = delimited_link(input) {
Ok((i, elm))
} else {
parse_text_element(input, prev_char)
}
}