diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-01-30 12:50:58 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-01-30 22:46:59 +0100 |
| commit | 8d1ce390e21ce0a5812a4211c893ec359906d6f1 (patch) | |
| tree | 5dbe1ad96af8ce8f9f01887340fe06025462e959 /src/syntax | |
| parent | d7072f378fef733ae994fd9a1e767df4e4dd878e (diff) | |
Rework strong and emph
- Star and underscore not parsed as strong/emph inside of words
- Stars/underscores must be balanced and they cannot go over paragraph break
- New `strong` and `emph` classes
Diffstat (limited to 'src/syntax')
| -rw-r--r-- | src/syntax/ast.rs | 40 | ||||
| -rw-r--r-- | src/syntax/highlight.rs | 12 | ||||
| -rw-r--r-- | src/syntax/mod.rs | 41 | ||||
| -rw-r--r-- | src/syntax/pretty.rs | 24 |
4 files changed, 81 insertions, 36 deletions
diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs index 13c639f9..560d7c30 100644 --- a/src/syntax/ast.rs +++ b/src/syntax/ast.rs @@ -63,8 +63,6 @@ impl Markup { NodeKind::Space(_) => Some(MarkupNode::Space), NodeKind::Linebreak => Some(MarkupNode::Linebreak), NodeKind::Parbreak => Some(MarkupNode::Parbreak), - NodeKind::Strong => Some(MarkupNode::Strong), - NodeKind::Emph => Some(MarkupNode::Emph), NodeKind::Text(s) | NodeKind::TextInLine(s) => { Some(MarkupNode::Text(s.clone())) } @@ -72,8 +70,10 @@ impl Markup { NodeKind::EnDash => Some(MarkupNode::Text('\u{2013}'.into())), NodeKind::EmDash => Some(MarkupNode::Text('\u{2014}'.into())), NodeKind::NonBreakingSpace => Some(MarkupNode::Text('\u{00A0}'.into())), - NodeKind::Math(math) => Some(MarkupNode::Math(math.as_ref().clone())), + NodeKind::Strong => node.cast().map(MarkupNode::Strong), + NodeKind::Emph => node.cast().map(MarkupNode::Emph), NodeKind::Raw(raw) => Some(MarkupNode::Raw(raw.as_ref().clone())), + NodeKind::Math(math) => Some(MarkupNode::Math(math.as_ref().clone())), NodeKind::Heading => node.cast().map(MarkupNode::Heading), NodeKind::List => node.cast().map(MarkupNode::List), NodeKind::Enum => node.cast().map(MarkupNode::Enum), @@ -91,12 +91,12 @@ pub enum MarkupNode { Linebreak, /// A paragraph break: Two or more newlines. Parbreak, - /// Strong text was enabled / disabled: `*`. - Strong, - /// Emphasized text was enabled / disabled: `_`. - Emph, /// Plain text. Text(EcoString), + /// Strong content: `*Strong*`. + Strong(StrongNode), + /// Emphasized content: `_Emphasized_`. + Emph(EmphNode), /// A raw block with optional syntax highlighting: `` `...` ``. Raw(RawNode), /// A math formula: `$a^2 = b^2 + c^2$`. @@ -111,6 +111,32 @@ pub enum MarkupNode { Expr(Expr), } +node! { + /// Strong content: `*Strong*`. + StrongNode: Strong +} + +impl StrongNode { + /// The contents of the strong node. + pub fn body(&self) -> Markup { + self.0.cast_first_child().expect("strong node is missing markup body") + } +} + +node! { + /// Emphasized content: `_Emphasized_`. + EmphNode: Emph +} + +impl EmphNode { + /// The contents of the emphasis node. + pub fn body(&self) -> Markup { + self.0 + .cast_first_child() + .expect("emphasis node is missing markup body") + } +} + /// A raw block with optional syntax highlighting: `` `...` ``. #[derive(Debug, Clone, PartialEq)] pub struct RawNode { diff --git a/src/syntax/highlight.rs b/src/syntax/highlight.rs index 315e8f17..b806b4e4 100644 --- a/src/syntax/highlight.rs +++ b/src/syntax/highlight.rs @@ -151,7 +151,10 @@ impl Category { NodeKind::From => Some(Category::Keyword), NodeKind::Include => Some(Category::Keyword), NodeKind::Plus => Some(Category::Operator), - NodeKind::Star => Some(Category::Operator), + NodeKind::Star => match parent.kind() { + NodeKind::Strong => None, + _ => Some(Category::Operator), + }, NodeKind::Slash => Some(Category::Operator), NodeKind::PlusEq => Some(Category::Operator), NodeKind::HyphEq => Some(Category::Operator), @@ -191,6 +194,7 @@ impl Category { NodeKind::Str(_) => Some(Category::String), NodeKind::Error(_, _) => Some(Category::Invalid), NodeKind::Unknown(_) => Some(Category::Invalid), + NodeKind::Underscore => None, NodeKind::Markup(_) => None, NodeKind::Space(_) => None, NodeKind::Parbreak => None, @@ -276,11 +280,7 @@ mod tests { assert_eq!(vec, goal); } - test("= *AB*", &[ - (0 .. 6, Heading), - (2 .. 3, Strong), - (5 .. 6, Strong), - ]); + test("= *AB*", &[(0 .. 6, Heading), (2 .. 6, Strong)]); test("#f(x + 1)", &[ (0 .. 2, Function), diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 9b606e0e..fdd50a7a 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -496,6 +496,8 @@ pub enum NodeKind { RightParen, /// An asterisk: `*`. Star, + /// An underscore: `_`. + Underscore, /// A comma: `,`. Comma, /// A semicolon: `;`. @@ -599,25 +601,25 @@ pub enum NodeKind { /// A slash and the letter "u" followed by a hexadecimal unicode entity /// enclosed in curly braces: `\u{1F5FA}`. Escape(char), - /// Strong text was enabled / disabled: `*`. + /// Strong content: `*Strong*`. Strong, - /// Emphasized text was enabled / disabled: `_`. + /// Emphasized content: `_Emphasized_`. Emph, + /// An arbitrary number of backticks followed by inner contents, terminated + /// with the same number of backticks: `` `...` ``. + Raw(Rc<RawNode>), + /// Dollar signs surrounding inner contents. + Math(Rc<MathNode>), /// A section heading: `= Introduction`. Heading, + /// An item in an unordered list: `- ...`. + List, /// An item in an enumeration (ordered list): `1. ...`. Enum, /// A numbering: `23.`. /// /// Can also exist without the number: `.`. EnumNumbering(Option<usize>), - /// An item in an unordered list: `- ...`. - List, - /// An arbitrary number of backticks followed by inner contents, terminated - /// with the same number of backticks: `` `...` ``. - Raw(Rc<RawNode>), - /// Dollar signs surrounding inner contents. - Math(Rc<MathNode>), /// An identifier: `center`. Ident(EcoString), /// A boolean: `true`, `false`. @@ -736,14 +738,14 @@ impl NodeKind { matches!(self, Self::LeftParen | Self::RightParen) } - /// Whether this is whitespace. - pub fn is_whitespace(&self) -> bool { - matches!(self, Self::Space(_) | Self::Parbreak) + /// Whether this is a space. + pub fn is_space(&self) -> bool { + matches!(self, Self::Space(_)) } /// Whether this is trivia. pub fn is_trivia(&self) -> bool { - self.is_whitespace() || matches!(self, Self::LineComment | Self::BlockComment) + self.is_space() || matches!(self, Self::LineComment | Self::BlockComment) } /// Whether this is some kind of error. @@ -761,7 +763,7 @@ impl NodeKind { } } - /// Which mode this token can appear in, in both if `None`. + /// Which mode this node can appear in, in both if `None`. pub fn mode(&self) -> Option<TokenMode> { match self { Self::Markup(_) @@ -814,6 +816,7 @@ impl NodeKind { Self::LeftParen => "opening paren", Self::RightParen => "closing paren", Self::Star => "star", + Self::Underscore => "underscore", Self::Comma => "comma", Self::Semicolon => "semicolon", Self::Colon => "colon", @@ -864,14 +867,14 @@ impl NodeKind { Self::EnDash => "en dash", Self::EmDash => "em dash", Self::Escape(_) => "escape sequence", - Self::Strong => "strong", - Self::Emph => "emphasis", + Self::Strong => "strong content", + Self::Emph => "emphasized content", + Self::Raw(_) => "raw block", + Self::Math(_) => "math formula", + Self::List => "list item", Self::Heading => "heading", Self::Enum => "enumeration item", Self::EnumNumbering(_) => "enumeration item numbering", - Self::List => "list item", - Self::Raw(_) => "raw block", - Self::Math(_) => "math formula", Self::Ident(_) => "identifier", Self::Bool(_) => "boolean", Self::Int(_) => "integer", diff --git a/src/syntax/pretty.rs b/src/syntax/pretty.rs index e8110262..07ab979b 100644 --- a/src/syntax/pretty.rs +++ b/src/syntax/pretty.rs @@ -95,8 +95,8 @@ impl Pretty for MarkupNode { Self::Space => p.push(' '), Self::Linebreak => p.push_str(r"\"), Self::Parbreak => p.push_str("\n\n"), - Self::Strong => p.push('*'), - Self::Emph => p.push('_'), + Self::Strong(strong) => strong.pretty(p), + Self::Emph(emph) => emph.pretty(p), Self::Text(text) => p.push_str(text), Self::Raw(raw) => raw.pretty(p), Self::Math(math) => math.pretty(p), @@ -113,6 +113,22 @@ impl Pretty for MarkupNode { } } +impl Pretty for StrongNode { + fn pretty(&self, p: &mut Printer) { + p.push('*'); + self.body().pretty(p); + p.push('*'); + } +} + +impl Pretty for EmphNode { + fn pretty(&self, p: &mut Printer) { + p.push('_'); + self.body().pretty(p); + p.push('_'); + } +} + impl Pretty for RawNode { fn pretty(&self, p: &mut Printer) { // Find out how many backticks we need. @@ -604,12 +620,12 @@ mod tests { #[test] fn test_pretty_print_markup() { // Basic stuff. - roundtrip("*"); - roundtrip("_"); roundtrip(" "); + roundtrip("*ab*"); roundtrip("\\ "); roundtrip("\n\n"); roundtrip("hi"); + roundtrip("_ab_"); roundtrip("= *Ok*"); roundtrip("- Ok"); |
