Mention parsing
This commit is contained in:
parent
9b26691ff4
commit
52dc491a47
|
@ -4,7 +4,7 @@ use nom::character::complete::{
|
|||
alpha1, alphanumeric1, anychar, char as one_char, line_ending, not_line_ending, one_of, space1,
|
||||
tab,
|
||||
};
|
||||
use nom::combinator::{eof, fail, not, opt, recognize};
|
||||
use nom::combinator::{eof, fail, map, not, opt, recognize};
|
||||
use nom::error::ErrorKind;
|
||||
use nom::multi::{many0, many0_count, many1, many1_count, separated_list1};
|
||||
use nom::sequence::tuple;
|
||||
|
@ -13,6 +13,21 @@ use nom_locate::LocatedSpan;
|
|||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum MentionType {
|
||||
Community,
|
||||
User,
|
||||
}
|
||||
|
||||
impl MentionType {
|
||||
pub fn to_char(&self) -> char {
|
||||
match self {
|
||||
MentionType::Community => '!',
|
||||
MentionType::User => '@',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Token<'a> {
|
||||
PlainText(Cow<'a, str>),
|
||||
|
@ -45,6 +60,11 @@ pub enum Token<'a> {
|
|||
params: HashMap<Cow<'a, str>, Option<Cow<'a, str>>>,
|
||||
inner: Box<Token<'a>>,
|
||||
},
|
||||
Mention {
|
||||
name: Cow<'a, str>,
|
||||
host: Option<Cow<'a, str>>,
|
||||
mention_type: MentionType,
|
||||
},
|
||||
}
|
||||
|
||||
impl Token<'_> {
|
||||
|
@ -92,6 +112,15 @@ impl Token<'_> {
|
|||
.collect(),
|
||||
inner: Box::new(inner.owned()),
|
||||
},
|
||||
Token::Mention {
|
||||
name,
|
||||
host,
|
||||
mention_type,
|
||||
} => Token::Mention {
|
||||
name: Cow::Owned(name.clone().into_owned()),
|
||||
host: host.as_ref().map(|v| Cow::Owned(v.clone().into_owned())),
|
||||
mention_type: *mention_type,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -613,6 +642,42 @@ impl Context {
|
|||
},
|
||||
))
|
||||
}
|
||||
|
||||
fn mention<'a>(&self, input: Span<'a>) -> IResult<Span<'a>, Token<'a>> {
|
||||
// TODO: Escaping and skip when preceded by alphanumerics
|
||||
|
||||
let tags = one_of("@!");
|
||||
let (input, mention_type) = map(tags, |c| match c {
|
||||
'@' => MentionType::User,
|
||||
'!' => MentionType::Community,
|
||||
_ => unreachable!(),
|
||||
})(input)?;
|
||||
|
||||
let (input, name) = map(
|
||||
recognize(many1(alt((alphanumeric1, recognize(one_of("-_")))))),
|
||||
Span::into_fragment,
|
||||
)(input)?;
|
||||
|
||||
let (input, host) = map(
|
||||
opt(tuple((
|
||||
tag("@"),
|
||||
map(
|
||||
recognize(many1(alt((alphanumeric1, recognize(one_of("-_")))))),
|
||||
Span::into_fragment,
|
||||
),
|
||||
))),
|
||||
|maybe_tag_host| maybe_tag_host.map(|(_, host)| host),
|
||||
)(input)?;
|
||||
|
||||
Ok((
|
||||
input,
|
||||
Token::Mention {
|
||||
mention_type,
|
||||
name: name.into(),
|
||||
host: host.map(|h| h.into()),
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
Loading…
Reference in New Issue