Support for wrap

This commit is contained in:
Laurenz 2022-01-28 22:32:53 +01:00
parent 9c906f92c5
commit 5c53b9ff60
3 changed files with 69 additions and 40 deletions

View File

@ -178,18 +178,33 @@ impl Eval for Markup {
type Output = Node;
fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output> {
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<Item = MarkupNode>,
) -> TypResult<Node> {
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<Node> {
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<Node> {
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<Self::Output> {
Err("wrap is not yet implemented").at(self.span())
Err("wrap is only allowed directly in markup").at(self.span())
}
}

BIN
tests/ref/style/wrap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,6 +1,23 @@
// Test wrap.
// Ref: false
---
// Error: 1-31 wrap is not yet implemented
#set page(height: 130pt)
#set text(70%)
#align(center)[
#text(130%)[*Essay on typography*] \
T. Ypst
]
#wrap body in columns(2, body)
Great typography is at the essence of great storytelling. It is the medium that
transports meaning from parchment to reader, the wave that sparks a flame
in booklovers and the great fulfiller of human need.
---
// Test wrap in template.
A [_B #wrap c in [*#c*]; C] D
---
// Error: 6-17 wrap is only allowed directly in markup
{1 + wrap x in y}