implement symbols
e.g. :some-sym:
This commit is contained in:
parent
61f0d6281e
commit
0420aad0a5
4 changed files with 51 additions and 0 deletions
|
@ -402,6 +402,7 @@ impl<'s, I: Iterator<Item = Event<'s>>, W: std::fmt::Write> Writer<'s, I, W> {
|
||||||
number, number, number
|
number, number, number
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
Atom::Symbol(sym) => write!(self.out, ":{}:", sym)?,
|
||||||
Atom::LeftSingleQuote => self.out.write_str("‘")?,
|
Atom::LeftSingleQuote => self.out.write_str("‘")?,
|
||||||
Atom::RightSingleQuote => self.out.write_str("’")?,
|
Atom::RightSingleQuote => self.out.write_str("’")?,
|
||||||
Atom::LeftDoubleQuote => self.out.write_str("“")?,
|
Atom::LeftDoubleQuote => self.out.write_str("“")?,
|
||||||
|
|
|
@ -11,6 +11,7 @@ use Container::*;
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Atom {
|
pub enum Atom {
|
||||||
FootnoteReference,
|
FootnoteReference,
|
||||||
|
Symbol,
|
||||||
Softbreak,
|
Softbreak,
|
||||||
Hardbreak,
|
Hardbreak,
|
||||||
Escape,
|
Escape,
|
||||||
|
@ -115,6 +116,7 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
|
||||||
self.parse_verbatim(&first)
|
self.parse_verbatim(&first)
|
||||||
.or_else(|| self.parse_attributes(&first))
|
.or_else(|| self.parse_attributes(&first))
|
||||||
.or_else(|| self.parse_autolink(&first))
|
.or_else(|| self.parse_autolink(&first))
|
||||||
|
.or_else(|| self.parse_symbol(&first))
|
||||||
.or_else(|| self.parse_footnote_reference(&first))
|
.or_else(|| self.parse_footnote_reference(&first))
|
||||||
.or_else(|| self.parse_container(&first))
|
.or_else(|| self.parse_container(&first))
|
||||||
.or_else(|| self.parse_atom(&first))
|
.or_else(|| self.parse_atom(&first))
|
||||||
|
@ -351,6 +353,37 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_symbol(&mut self, first: &lex::Token) -> Option<Event> {
|
||||||
|
if first.kind == lex::Kind::Sym(Symbol::Colon) {
|
||||||
|
let mut ahead = self.lexer.chars();
|
||||||
|
let mut end = false;
|
||||||
|
let mut valid = true;
|
||||||
|
let len = (&mut ahead)
|
||||||
|
.take_while(|c| {
|
||||||
|
if *c == ':' {
|
||||||
|
end = true;
|
||||||
|
} else if !c.is_ascii_alphanumeric() && !matches!(c, '-' | '+' | '_') {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
!end && !c.is_whitespace()
|
||||||
|
})
|
||||||
|
.map(char::len_utf8)
|
||||||
|
.sum();
|
||||||
|
(end && valid).then(|| {
|
||||||
|
self.lexer = lex::Lexer::new(ahead);
|
||||||
|
self.span = self.span.after(len);
|
||||||
|
let span = self.span;
|
||||||
|
self.span = self.span.after(1);
|
||||||
|
Event {
|
||||||
|
kind: EventKind::Atom(Symbol),
|
||||||
|
span,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_footnote_reference(&mut self, first: &lex::Token) -> Option<Event> {
|
fn parse_footnote_reference(&mut self, first: &lex::Token) -> Option<Event> {
|
||||||
if first.kind == lex::Kind::Open(Delimiter::Bracket)
|
if first.kind == lex::Kind::Open(Delimiter::Bracket)
|
||||||
&& matches!(
|
&& matches!(
|
||||||
|
|
|
@ -49,6 +49,7 @@ pub enum Symbol {
|
||||||
Quote2,
|
Quote2,
|
||||||
Tilde,
|
Tilde,
|
||||||
Underscore,
|
Underscore,
|
||||||
|
Colon,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
@ -232,6 +233,7 @@ impl<I: Iterator<Item = char> + Clone> Lexer<I> {
|
||||||
}
|
}
|
||||||
'<' => Sym(Lt),
|
'<' => Sym(Lt),
|
||||||
'|' => Sym(Pipe),
|
'|' => Sym(Pipe),
|
||||||
|
':' => Sym(Colon),
|
||||||
|
|
||||||
'`' => self.eat_seq(Backtick),
|
'`' => self.eat_seq(Backtick),
|
||||||
'$' => self.eat_seq(Dollar),
|
'$' => self.eat_seq(Dollar),
|
||||||
|
|
15
src/lib.rs
15
src/lib.rs
|
@ -236,6 +236,8 @@ pub enum OrderedListStyle {
|
||||||
pub enum Atom<'s> {
|
pub enum Atom<'s> {
|
||||||
/// A footnote reference.
|
/// A footnote reference.
|
||||||
FootnoteReference(&'s str, usize),
|
FootnoteReference(&'s str, usize),
|
||||||
|
/// A symbol, by default rendered literally but may be treated specially.
|
||||||
|
Symbol(CowStr<'s>),
|
||||||
/// Left single quotation mark.
|
/// Left single quotation mark.
|
||||||
LeftSingleQuote,
|
LeftSingleQuote,
|
||||||
/// Right double quotation mark.
|
/// Right double quotation mark.
|
||||||
|
@ -654,6 +656,7 @@ impl<'s> Parser<'s> {
|
||||||
number,
|
number,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
inline::Atom::Symbol => Atom::Symbol(self.inlines.src(inline.span)),
|
||||||
inline::Atom::Quote { ty, left } => match (ty, left) {
|
inline::Atom::Quote { ty, left } => match (ty, left) {
|
||||||
(inline::QuoteType::Single, true) => Atom::LeftSingleQuote,
|
(inline::QuoteType::Single, true) => Atom::LeftSingleQuote,
|
||||||
(inline::QuoteType::Single, false) => Atom::RightSingleQuote,
|
(inline::QuoteType::Single, false) => Atom::RightSingleQuote,
|
||||||
|
@ -1088,6 +1091,18 @@ mod test {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn symbol() {
|
||||||
|
test_parse!(
|
||||||
|
"abc :+1: def",
|
||||||
|
Start(Paragraph, Attributes::new()),
|
||||||
|
Str("abc ".into()),
|
||||||
|
Atom(Symbol("+1".into())),
|
||||||
|
Str(" def".into()),
|
||||||
|
End(Paragraph),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn link_inline() {
|
fn link_inline() {
|
||||||
test_parse!(
|
test_parse!(
|
||||||
|
|
Loading…
Reference in a new issue