From 161dfec96d60e8221c7bee36e497069c9923f7b4 Mon Sep 17 00:00:00 2001 From: Noah Hellman Date: Sun, 15 Jan 2023 23:48:55 +0100 Subject: [PATCH] inline: word attributes --- src/inline.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/lib.rs | 4 ++- 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/src/inline.rs b/src/inline.rs index 13d9e11..ee7056b 100644 --- a/src/inline.rs +++ b/src/inline.rs @@ -56,6 +56,7 @@ pub enum EventKind { Exit(Container), Atom(Atom), Str, + Whitespace, Attributes, AttributesDummy, } @@ -108,11 +109,16 @@ impl + Clone> Parser { self.reset_span(); self.eat().map(|first| { self.parse_verbatim(&first) + .or_else(|| self.parse_attributes(&first)) .or_else(|| self.parse_autolink(&first)) .or_else(|| self.parse_container(&first)) .or_else(|| self.parse_atom(&first)) .unwrap_or(Event { - kind: EventKind::Str, + kind: if first.kind == lex::Kind::Whitespace { + EventKind::Whitespace + } else { + EventKind::Str + }, span: self.span, }) }) @@ -225,6 +231,58 @@ impl + Clone> Parser { }) } + fn parse_attributes(&mut self, first: &lex::Token) -> Option { + if first.kind == lex::Kind::Open(Delimiter::Brace) + && self + .events + .back() + .map_or(false, |e| e.kind == EventKind::Str) + { + let mut ahead = self.lexer.inner().clone(); + let mut attr_len = attr::valid(std::iter::once('{').chain(&mut ahead)) - 1; + if attr_len > 0 { + while attr_len > 0 { + self.lexer = lex::Lexer::new(ahead.clone()); + self.span = self.span.extend(attr_len); + attr_len = attr::valid(&mut ahead); + } + + let i = self + .events + .iter() + .rposition(|e| e.kind != EventKind::Str) + .map_or(0, |i| i + 1); + let span_str = Span::new( + self.events[i].span.start(), + self.events[self.events.len() - 1].span.end(), + ); + self.events.drain(i..); + + self.events.push_back(Event { + kind: EventKind::Attributes, + span: self.span, + }); + self.events.push_back(Event { + kind: EventKind::Enter(Container::Span), + span: Span::empty_at(span_str.start()), + }); + self.events.push_back(Event { + kind: EventKind::Str, + span: span_str, + }); + + Some(Event { + kind: EventKind::Exit(Container::Span), + span: Span::empty_at(span_str.end()), + }) + } else { + None + } + } else { + None + } + } + fn parse_autolink(&mut self, first: &lex::Token) -> Option { if first.kind == lex::Kind::Sym(Symbol::Lt) { let mut ahead = self.lexer.inner().clone(); @@ -482,10 +540,12 @@ impl + Clone> Iterator for Parser { fn next(&mut self) -> Option { while self.events.is_empty() || !self.openers.is_empty() - || self // for merge + || self // for merge or attributes .events .back() - .map_or(false, |ev| matches!(ev.kind, EventKind::Str)) + .map_or(false, |ev| { + matches!(ev.kind, EventKind::Str | EventKind::Whitespace) + }) { if let Some(ev) = self.parse_event() { self.events.push_back(ev); @@ -496,11 +556,14 @@ impl + Clone> Iterator for Parser { self.events.pop_front().and_then(|e| { match e.kind { - EventKind::Str => { + EventKind::Str | EventKind::Whitespace => { // merge str events let mut span = e.span; while self.events.front().map_or(false, |e| { - matches!(e.kind, EventKind::Str | EventKind::AttributesDummy) + matches!( + e.kind, + EventKind::Str | EventKind::Whitespace | EventKind::AttributesDummy + ) }) { let ev = self.events.pop_front().unwrap(); assert_eq!(span.end(), ev.span.start()); @@ -864,4 +927,17 @@ mod test { (Str, " {.d}"), ); } + + #[test] + fn attr() { + test_parse!( + "some word{.a}{.b} with attrs", + (Str, "some "), + (Attributes, "{.a}{.b}"), + (Enter(Span), ""), + (Str, "word"), + (Exit(Span), ""), + (Str, " with attrs"), + ); + } } diff --git a/src/lib.rs b/src/lib.rs index 4882c66..6a985af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -357,7 +357,9 @@ impl<'s> Parser<'s> { inline::Atom::Escape => Event::Atom(Atom::Escape), }, inline::EventKind::Str => Event::Str(self.inlines.src(inline.span)), - inline::EventKind::Attributes | inline::EventKind::AttributesDummy => { + inline::EventKind::Whitespace + | inline::EventKind::Attributes + | inline::EventKind::AttributesDummy => { panic!("{:?}", inline) } })