summaryrefslogtreecommitdiff
path: root/src/library/font.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-08-04 13:48:07 +0200
committerLaurenz <laurmaedje@gmail.com>2020-08-04 13:48:07 +0200
commit2467cd6272c13b618ad53c5dadff5b8c8e7885bf (patch)
tree6ad13ec06a04997564efc514b40daa3fb65233e2 /src/library/font.rs
parented4fdcb0ada909f1cc3d7436334e253f0ec14d55 (diff)
Refactor function parsing ♻
Diffstat (limited to 'src/library/font.rs')
-rw-r--r--src/library/font.rs105
1 files changed, 60 insertions, 45 deletions
diff --git a/src/library/font.rs b/src/library/font.rs
index 6e711021..57ee92b3 100644
--- a/src/library/font.rs
+++ b/src/library/font.rs
@@ -3,53 +3,68 @@ use fontdock::{FontStyle, FontWeight, FontWidth};
use crate::length::ScaleLength;
use super::*;
-function! {
- /// `font`: Configure the font.
- #[derive(Debug, Clone, PartialEq)]
- pub struct FontFunc {
- body: Option<SyntaxTree>,
- size: Option<ScaleLength>,
- style: Option<FontStyle>,
- weight: Option<FontWeight>,
- width: Option<FontWidth>,
- list: Vec<String>,
- classes: Vec<(String, Vec<String>)>,
- }
-
- parse(header, body, state, f) {
- let size = header.args.pos.get::<ScaleLength>();
- let style = header.args.key.get::<FontStyle>("style", f);
- let weight = header.args.key.get::<FontWeight>("weight", f);
- let width = header.args.key.get::<FontWidth>("width", f);
+/// `font`: Configure the font.
+///
+/// # Positional arguments
+/// - The font size (optional, length or relative to previous font size).
+/// - A font family fallback list (optional, identifiers or strings).
+///
+/// # Keyword arguments
+/// - `style`: `normal`, `italic` or `oblique`.
+/// - `weight`: `100` - `900` or a name like `thin`.
+/// - `width`: `1` - `9` or a name like `condensed`.
+/// - Any other keyword argument whose value is a tuple of strings is a class
+/// fallback definition like:
+/// ```typst
+/// serif = ("Source Serif Pro", "Noto Serif")
+/// ```
+pub fn font(call: FuncCall, state: &ParseState) -> Pass<SyntaxNode> {
+ let mut f = Feedback::new();
+ let mut args = call.header.args;
- let list = header.args.pos.all::<StringLike>()
- .map(|s| s.0.to_lowercase())
- .collect();
+ let node = FontNode {
+ body: parse_body_maybe(call.body, state, &mut f),
+ size: args.pos.get::<ScaleLength>(),
+ style: args.key.get::<FontStyle>("style", &mut f),
+ weight: args.key.get::<FontWeight>("weight", &mut f),
+ width: args.key.get::<FontWidth>("width", &mut f),
+ list: {
+ args.pos.all::<StringLike>()
+ .map(|s| s.0.to_lowercase())
+ .collect()
+ },
+ classes: {
+ args.key.all::<Tuple>()
+ .collect::<Vec<_>>()
+ .into_iter()
+ .map(|(class, mut tuple)| {
+ let fallback = tuple.all::<StringLike>()
+ .map(|s| s.0.to_lowercase())
+ .collect();
+ (class.v.0, fallback)
+ })
+ .collect()
+ },
+ };
- let classes = header.args.key
- .all::<Tuple>()
- .collect::<Vec<_>>()
- .into_iter()
- .map(|(class, mut tuple)| {
- let fallback = tuple.all::<StringLike>()
- .map(|s| s.0.to_lowercase())
- .collect();
- (class.v.0, fallback)
- })
- .collect();
+ drain_args(args, &mut f);
+ Pass::node(node, f)
+}
- Self {
- body: parse_maybe_body(body, state, f),
- size,
- style,
- weight,
- width,
- list,
- classes,
- }
- }
+#[derive(Debug, Clone, PartialEq)]
+struct FontNode {
+ body: Option<SyntaxTree>,
+ size: Option<ScaleLength>,
+ style: Option<FontStyle>,
+ weight: Option<FontWeight>,
+ width: Option<FontWidth>,
+ list: Vec<String>,
+ classes: Vec<(String, Vec<String>)>,
+}
- layout(self, ctx, f) {
+#[async_trait(?Send)]
+impl Layout for FontNode {
+ async fn layout<'a>(&'a self, ctx: LayoutContext<'_>) -> Pass<Commands<'a>> {
let mut text = ctx.style.text.clone();
self.size.with(|s| match s {
@@ -76,13 +91,13 @@ function! {
text.fallback.flatten();
- match &self.body {
+ Pass::okay(match &self.body {
Some(tree) => vec![
SetTextStyle(text),
LayoutSyntaxTree(tree),
SetTextStyle(ctx.style.text.clone()),
],
None => vec![SetTextStyle(text)],
- }
+ })
}
}