diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-03-21 17:46:09 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-03-21 17:50:56 +0100 |
| commit | 5e08028fb36aa766957cba64c5c665edf9b96fb7 (patch) | |
| tree | 912799dad3c1e25b7032f3e3bee009537c6f555b /src/library | |
| parent | 898728f260923a91444eb23b522d0abf01a4299b (diff) | |
Syntax functions 🚀
This adds overridable functions that markup desugars into. Specifically:
- \ desugars into linebreak
- Two newlines desugar into parbreak
- * desugars into strong
- _ desugars into emph
- = .. desugars into heading
- `..` desugars into raw
Diffstat (limited to 'src/library')
| -rw-r--r-- | src/library/align.rs | 2 | ||||
| -rw-r--r-- | src/library/base.rs | 30 | ||||
| -rw-r--r-- | src/library/markup.rs | 172 | ||||
| -rw-r--r-- | src/library/mod.rs | 22 | ||||
| -rw-r--r-- | src/library/page.rs | 2 | ||||
| -rw-r--r-- | src/library/par.rs | 4 | ||||
| -rw-r--r-- | src/library/spacing.rs | 4 |
7 files changed, 210 insertions, 26 deletions
diff --git a/src/library/align.rs b/src/library/align.rs index 93c6db0d..765ed988 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -1,6 +1,6 @@ use super::*; -/// `align`: Align content along the layouting axes. +/// `align`: Configure the alignment along the layouting axes. /// /// # Positional parameters /// - Alignments: variadic, of type `alignment`. diff --git a/src/library/base.rs b/src/library/base.rs index 22adb1f4..fdabdc47 100644 --- a/src/library/base.rs +++ b/src/library/base.rs @@ -3,6 +3,20 @@ use crate::pretty::pretty; use super::*; +/// `type`: Get the name of a value's type. +/// +/// # Positional parameters +/// - Any value. +/// +/// # Return value +/// The name of the value's type as a string. +pub fn type_(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { + match args.require::<Value>(ctx, "value") { + Some(value) => value.type_name().into(), + None => Value::Error, + } +} + /// `repr`: Get the string representation of a value. /// /// # Positional parameters @@ -17,7 +31,7 @@ pub fn repr(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { } } -/// `rgb`: Create an RGB(A) color. +/// `rgb`: Construct an RGB(A) color. /// /// # Positional parameters /// - Red component: of type `float`, between 0.0 and 1.0. @@ -49,17 +63,3 @@ pub fn rgb(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { clamp(a, 255), ))) } - -/// `type`: Find out the name of a value's type. -/// -/// # Positional parameters -/// - Any value. -/// -/// # Return value -/// The name of the value's type as a string. -pub fn type_(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - match args.require::<Value>(ctx, "value") { - Some(value) => value.type_name().into(), - None => Value::Error, - } -} diff --git a/src/library/markup.rs b/src/library/markup.rs new file mode 100644 index 00000000..12a14d14 --- /dev/null +++ b/src/library/markup.rs @@ -0,0 +1,172 @@ +use super::*; +use crate::syntax::{HeadingNode, RawNode}; + +/// `linebreak`: Start a new line. +/// +/// # Syntax +/// This function has dedicated syntax: +/// ```typst +/// This line ends here, \ +/// And a new one begins. +/// ``` +/// +/// # Return value +/// A template that inserts a line break. +pub fn linebreak(_: &mut EvalContext, _: &mut FuncArgs) -> Value { + Value::template(Node::LINEBREAK, move |ctx| { + ctx.push_linebreak(); + }) +} + +/// `parbreak`: Start a new paragraph. +/// +/// # Return value +/// A template that inserts a paragraph break. +pub fn parbreak(_: &mut EvalContext, _: &mut FuncArgs) -> Value { + Value::template(Node::PARBREAK, move |ctx| { + ctx.push_parbreak(); + }) +} + +/// `strong`: Signify important text by setting it in bold. +/// +/// # Syntax +/// This function has dedicated syntax. +/// ```typst +/// This is *important*! +/// ``` +/// +/// # Positional parameters +/// - Body: optional, of type `template`. +/// +/// # Return value +/// A template that flips the strongness of text. The effect is scoped to the +/// body if present. +pub fn strong(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { + let body = args.find::<TemplateValue>(ctx); + Value::template(Node::STRONG, move |ctx| { + let snapshot = ctx.state.clone(); + ctx.state.font.strong ^= true; + + if let Some(body) = &body { + body.exec(ctx); + ctx.state = snapshot; + } + }) +} + +/// `emph`: Emphasize text by setting it in italics. +/// +/// # Syntax +/// This function has dedicated syntax. +/// ```typst +/// I would have _never_ thought so! +/// ``` +/// +/// # Positional parameters +/// - Body: optional, of type `template`. +/// +/// # Return value +/// A template that flips whether text is emphasized. The effect is scoped to +/// the body if present. +pub fn emph(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { + let body = args.find::<TemplateValue>(ctx); + Value::template(Node::EMPH, move |ctx| { + let snapshot = ctx.state.clone(); + ctx.state.font.emph ^= true; + + if let Some(body) = &body { + body.exec(ctx); + ctx.state = snapshot; + } + }) +} + +/// `heading`: A section heading. +/// +/// # Syntax +/// This function has dedicated syntax. +/// ```typst +/// = Section +/// ... +/// +/// == Subsection +/// ... +/// ``` +/// +/// # Positional parameters +/// - Body, of type `template`. +/// +/// # Named parameters +/// - Section depth: `level`, of type `integer` between 1 and 6. +/// +/// # Return value +/// A template that sets the body as a section heading, that is, large and in +/// bold. +pub fn heading(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { + let level = args.get(ctx, HeadingNode::LEVEL).unwrap_or(1); + let body = args + .require::<TemplateValue>(ctx, HeadingNode::BODY) + .unwrap_or_default(); + + Value::template(Node::HEADING, move |ctx| { + let snapshot = ctx.state.clone(); + let upscale = 1.6 - 0.1 * level as f64; + ctx.state.font.scale *= upscale; + ctx.state.font.strong = true; + + body.exec(ctx); + ctx.push_parbreak(); + + ctx.state = snapshot; + }) +} + +/// `raw`: Raw text. +/// +/// # Syntax +/// This function has dedicated syntax: +/// - For inline-level raw text: +/// ```typst +/// `...` +/// ``` +/// - For block-level raw text: +/// ````typst +/// ```rust +/// println!("Hello World!"); +/// ``` +/// ```` +/// +/// # Positional parameters +/// - Text, of type `string`. +/// +/// # Named parameters +/// - Language for syntax highlighting: `lang`, of type `string`. +/// - Whether the item is block level (split in its own paragraph): `block`, of +/// type `boolean`. +/// +/// # Return value +/// A template that sets the text raw, that is, in monospace with optional +/// syntax highlighting. +pub fn raw(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { + let text = args.require::<String>(ctx, RawNode::TEXT).unwrap_or_default(); + let _lang = args.get::<String>(ctx, RawNode::LANG); + let block = args.get(ctx, RawNode::BLOCK).unwrap_or(false); + + Value::template(Node::RAW, move |ctx| { + let snapshot = ctx.state.clone(); + + if block { + ctx.push_parbreak(); + } + + ctx.set_monospace(); + ctx.push_text(&text); + + if block { + ctx.push_parbreak(); + } + + ctx.state = snapshot; + }) +} diff --git a/src/library/mod.rs b/src/library/mod.rs index b09f94a0..834c9625 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -1,12 +1,13 @@ //! The standard library. //! -//! Call [`new`] to obtain a [`Scope`] containing all standard library +//! Call [`_new`] to obtain a [`Scope`] containing all standard library //! definitions. mod align; mod base; mod font; mod image; +mod markup; mod pad; mod page; mod par; @@ -17,6 +18,7 @@ pub use self::image::*; pub use align::*; pub use base::*; pub use font::*; +pub use markup::*; pub use pad::*; pub use page::*; pub use par::*; @@ -32,10 +34,10 @@ use crate::eval::{EvalContext, FuncArgs, TemplateValue, Value}; use crate::exec::{Exec, ExecContext}; use crate::geom::*; use crate::layout::VerticalFontMetric; -use crate::syntax::Spanned; +use crate::syntax::{Node, Spanned}; /// Construct a scope containing all standard library definitions. -pub fn new() -> Scope { +pub fn _new() -> Scope { let mut std = Scope::new(); macro_rules! func { @@ -50,6 +52,15 @@ pub fn new() -> Scope { }; } + // Syntax functions. + func!(Node::EMPH, emph); + func!(Node::HEADING, heading); + func!(Node::STRONG, strong); + func!(Node::RAW, raw); + func!(Node::LINEBREAK, linebreak); + func!(Node::PARBREAK, parbreak); + + // Library functions. func!("align", align); func!("circle", circle); func!("ellipse", ellipse); @@ -59,14 +70,15 @@ pub fn new() -> Scope { func!("pad", pad); func!("page", page); func!("pagebreak", pagebreak); - func!("paragraph", par); - func!("square", square); + func!("par", par); func!("rect", rect); func!("repr", repr); func!("rgb", rgb); + func!("square", square); func!("type", type_); func!("v", v); + // Constants. constant!("left", AlignValue::Left); constant!("center", AlignValue::Center); constant!("right", AlignValue::Right); diff --git a/src/library/page.rs b/src/library/page.rs index 067258f5..89722ba3 100644 --- a/src/library/page.rs +++ b/src/library/page.rs @@ -109,7 +109,7 @@ pub fn page(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { /// `pagebreak`: Start a new page. /// /// # Return value -/// A template that starts a new page. +/// A template that inserts a page break. pub fn pagebreak(_: &mut EvalContext, args: &mut FuncArgs) -> Value { let span = args.span; Value::template("pagebreak", move |ctx| { diff --git a/src/library/par.rs b/src/library/par.rs index a7db46de..0467af44 100644 --- a/src/library/par.rs +++ b/src/library/par.rs @@ -1,6 +1,6 @@ use super::*; -/// `paragraph`: Configure paragraphs. +/// `par`: Configure paragraphs. /// /// # Positional parameters /// - Body: optional, of type `template`. @@ -19,7 +19,7 @@ pub fn par(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let word_spacing = args.get(ctx, "word-spacing"); let body = args.find::<TemplateValue>(ctx); - Value::template("paragraph", move |ctx| { + Value::template("par", move |ctx| { let snapshot = ctx.state.clone(); if let Some(spacing) = spacing { diff --git a/src/library/spacing.rs b/src/library/spacing.rs index c96b8be4..5e3b7743 100644 --- a/src/library/spacing.rs +++ b/src/library/spacing.rs @@ -1,7 +1,7 @@ use super::*; use crate::layout::SpacingNode; -/// `h`: Add horizontal spacing. +/// `h`: Insert horizontal spacing. /// /// # Positional parameters /// - Amount of spacing: of type `linear` relative to current font size. @@ -12,7 +12,7 @@ pub fn h(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { spacing_impl(ctx, args, SpecAxis::Horizontal) } -/// `v`: Add vertical spacing. +/// `v`: Insert vertical spacing. /// /// # Positional parameters /// - Amount of spacing: of type `linear` relative to current font size. |
