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,
|
alpha1, alphanumeric1, anychar, char as one_char, line_ending, not_line_ending, one_of, space1,
|
||||||
tab,
|
tab,
|
||||||
};
|
};
|
||||||
use nom::combinator::{eof, fail, not, opt, recognize};
|
use nom::combinator::{eof, fail, map, not, opt, recognize};
|
||||||
use nom::error::ErrorKind;
|
use nom::error::ErrorKind;
|
||||||
use nom::multi::{many0, many0_count, many1, many1_count, separated_list1};
|
use nom::multi::{many0, many0_count, many1, many1_count, separated_list1};
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
|
@ -13,6 +13,21 @@ use nom_locate::LocatedSpan;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Token<'a> {
|
pub enum Token<'a> {
|
||||||
PlainText(Cow<'a, str>),
|
PlainText(Cow<'a, str>),
|
||||||
|
@ -45,6 +60,11 @@ pub enum Token<'a> {
|
||||||
params: HashMap<Cow<'a, str>, Option<Cow<'a, str>>>,
|
params: HashMap<Cow<'a, str>, Option<Cow<'a, str>>>,
|
||||||
inner: Box<Token<'a>>,
|
inner: Box<Token<'a>>,
|
||||||
},
|
},
|
||||||
|
Mention {
|
||||||
|
name: Cow<'a, str>,
|
||||||
|
host: Option<Cow<'a, str>>,
|
||||||
|
mention_type: MentionType,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Token<'_> {
|
impl Token<'_> {
|
||||||
|
@ -92,6 +112,15 @@ impl Token<'_> {
|
||||||
.collect(),
|
.collect(),
|
||||||
inner: Box::new(inner.owned()),
|
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]
|
#[inline]
|
||||||
|
|
Loading…
Reference in New Issue