From 5c53b9ff606f927bf0f2e4c40daf19d50ece09d9 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 28 Jan 2022 22:32:53 +0100 Subject: [PATCH] Support for `wrap` --- src/eval/mod.rs | 88 ++++++++++++++++++++++----------------- tests/ref/style/wrap.png | Bin 0 -> 10612 bytes tests/typ/style/wrap.typ | 21 +++++++++- 3 files changed, 69 insertions(+), 40 deletions(-) create mode 100644 tests/ref/style/wrap.png diff --git a/src/eval/mod.rs b/src/eval/mod.rs index a8c6c688f..d459ba6ea 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -178,18 +178,33 @@ impl Eval for Markup { type Output = Node; fn eval(&self, ctx: &mut EvalContext) -> TypResult { - let prev = mem::take(&mut ctx.styles); - let nodes = self.nodes(); - let upper = nodes.size_hint().1.unwrap_or_default(); - let mut seq = Vec::with_capacity(upper); - for piece in nodes { - seq.push(Styled::new(piece.eval(ctx)?, ctx.styles.clone())); - } - ctx.styles = prev; - Ok(Node::Sequence(seq)) + process_nodes(ctx, &mut self.nodes()) } } +/// Evaluate a stream of nodes. +fn process_nodes( + ctx: &mut EvalContext, + nodes: &mut impl Iterator, +) -> TypResult { + let prev = mem::take(&mut ctx.styles); + let mut seq = Vec::with_capacity(nodes.size_hint().1.unwrap_or_default()); + while let Some(piece) = nodes.next() { + // Need to deal with wrap here. + let node = if let MarkupNode::Expr(Expr::Wrap(wrap)) = piece { + let tail = process_nodes(ctx, nodes)?; + ctx.scopes.def_mut(wrap.binding().take(), tail); + wrap.body().eval(ctx)?.show() + } else { + piece.eval(ctx)? + }; + + seq.push(Styled::new(node, ctx.styles.clone())); + } + ctx.styles = prev; + Ok(Node::Sequence(seq)) +} + impl Eval for MarkupNode { type Output = Node; @@ -265,8 +280,8 @@ impl RawNode { sequence.push(Styled::bare(Node::Linebreak)); } - for (style, line) in highlighter.highlight(line, &SYNTAXES) { - sequence.push(Self::styled_piece(style, line, foreground)); + for (style, piece) in highlighter.highlight(line, &SYNTAXES) { + sequence.push(style_piece(piece, foreground, style)); } } } @@ -279,11 +294,7 @@ impl RawNode { red.as_ref(), &highlighter, &mut |range, style| { - sequence.push(Self::styled_piece( - style, - &self.text[range], - foreground, - )); + sequence.push(style_piece(&self.text[range], foreground, style)); }, ) } @@ -291,31 +302,32 @@ impl RawNode { Node::Sequence(sequence).monospaced() } +} - fn styled_piece(style: SynStyle, piece: &str, foreground: Paint) -> Styled { - let paint = style.foreground.into(); - let node = Node::Text(piece.into()); +/// Style a piece of text with a syntect style. +fn style_piece(piece: &str, foreground: Paint, style: SynStyle) -> Styled { + let paint = style.foreground.into(); + let node = Node::Text(piece.into()); - let mut styles = StyleMap::new(); + let mut styles = StyleMap::new(); - if paint != foreground { - styles.set(TextNode::FILL, paint); - } - - if style.font_style.contains(FontStyle::BOLD) { - styles.set(TextNode::STRONG, true); - } - - if style.font_style.contains(FontStyle::ITALIC) { - styles.set(TextNode::EMPH, true); - } - - if style.font_style.contains(FontStyle::UNDERLINE) { - styles.set(TextNode::LINES, vec![DecoLine::Underline.into()]); - } - - Styled::new(node, styles) + if paint != foreground { + styles.set(TextNode::FILL, paint); } + + if style.font_style.contains(FontStyle::BOLD) { + styles.set(TextNode::STRONG, true); + } + + if style.font_style.contains(FontStyle::ITALIC) { + styles.set(TextNode::EMPH, true); + } + + if style.font_style.contains(FontStyle::UNDERLINE) { + styles.set(TextNode::LINES, vec![DecoLine::Underline.into()]); + } + + Styled::new(node, styles) } impl Eval for MathNode { @@ -776,7 +788,7 @@ impl Eval for WrapExpr { type Output = Value; fn eval(&self, _: &mut EvalContext) -> TypResult { - Err("wrap is not yet implemented").at(self.span()) + Err("wrap is only allowed directly in markup").at(self.span()) } } diff --git a/tests/ref/style/wrap.png b/tests/ref/style/wrap.png new file mode 100644 index 0000000000000000000000000000000000000000..346da53f82e8729bde74e2c27502540cd9a9e8a5 GIT binary patch literal 10612 zcma*NWl&sEvo1UX0}MU{haiI_1Shz|;4TR+K?4cy4g(AtEChE65Zv7c4;tJdNN^_* z94_xUr|SEDoLhCDs=c~u@7>Glsnxx@J3?Jm4i}383jhG%D#%M~0suhJ^P>xXegTN% zSkVUn-Uus5OTPD9JX*1OPb^1?JQMt4B-w|;Ob3oMK|Rcyr;Mz&In*$(>+x~l*Bg?OabNdx0n^U z`WN8;1`LbRZSy?a=sN=_2>Cf{ruoCt&vPqFl>v&>o@sAjpZhV#tv#@~?kW$|6+z?7 z;Jx8Nb_6EOa6;`>OLCm^``@TNgtX6h!5Rkl|N}TbBN=oq-7bNg37#JGUjQs|r{Ut*K3VZ(z z0r3hpje1rRNzO@+W7b!kw6&&-62g*_9WrQz#9(TufT1IrP0Z4zFJa;RhJ9BBvqoiCGCjF4#M|>E0ng0H#WqA+>GG^z_*Shh4^nKOCH7eVk zBg9M?wiaK`8^yb$LYmaW&q!BSi8lDHU!@V!Nv|FO9}r{%JsEjNUzA?uy>ddIf)fvK&|P%7b!}z$>329Aauc3A!Pkp3TZ%dL{p#cSMId! zZpPL{5Y#_Q&}DmMXIu&lEt^A1D8w@iGa_^C>zPx)PJuk{iYcQR{Oqh5wm>b4nmn?a zgr~{h_4XjkGGmRxGGk0I1Q})urcEf;8QDiHr?2~Y^Sjx9zl@Dblc6v;IJ%XYFd&l5 zVP#<+u(~P!C~QR25HGZ${nvv>J(Oh;F-`t2ojzjbgcyrQY%_ri5N!F3dt4)s?pSpUC}LU&D-BE!(D_;`E60rnT*aE$ zs|4$Yi(x!f@L6C6ZDU3hxhOr1qsO~KJEs%P@?No$Y@lQin-!1Gq07o^G6*O!4u(5Q zKM{UnlQjs(ecnVl&*XPJmeG(M(>R89bKQybqOnd8+Ij>eKPR8sl;W8@u0n|Fypi3` zQrsuZu4>bsP+UscqDPaawT+LcT#V%gj|-&ke-dPET$G5-VChQnJ}*BN=B1o3A&C_} z2e^M_h#n3{xbBpL7>jcqT|Z(+b{GbO15hI)IUqXfAZQ)6^_c$5g}|~ zt}5Op?7i;KG`5&nRfKsKNHx8Zu6`a~ N}y(AbaT|BOn$fywieWR-`kpcCSFQ$Sw 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