summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-03-21 17:46:09 +0100
committerLaurenz <laurmaedje@gmail.com>2021-03-21 17:50:56 +0100
commit5e08028fb36aa766957cba64c5c665edf9b96fb7 (patch)
tree912799dad3c1e25b7032f3e3bee009537c6f555b /src/library
parent898728f260923a91444eb23b522d0abf01a4299b (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.rs2
-rw-r--r--src/library/base.rs30
-rw-r--r--src/library/markup.rs172
-rw-r--r--src/library/mod.rs22
-rw-r--r--src/library/page.rs2
-rw-r--r--src/library/par.rs4
-rw-r--r--src/library/spacing.rs4
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.