summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2019-10-17 10:12:34 +0200
committerLaurenz <laurmaedje@gmail.com>2019-10-17 10:12:34 +0200
commitf22f9513aea21408ebf6febd01912e630e9ad5e6 (patch)
tree06885bca8bc31d26189f33c059649ed7909af282 /src/library
parent9a1d57a11a510b8e6af024b4338ee58d791f3088 (diff)
Add pagebreak function ⏭
Diffstat (limited to 'src/library')
-rw-r--r--src/library/align.rs17
-rw-r--r--src/library/breaks.rs24
-rw-r--r--src/library/mod.rs28
-rw-r--r--src/library/styles.rs36
4 files changed, 71 insertions, 34 deletions
diff --git a/src/library/align.rs b/src/library/align.rs
index 922464a8..cc41f295 100644
--- a/src/library/align.rs
+++ b/src/library/align.rs
@@ -12,7 +12,7 @@ impl Function for AlignFunc {
fn parse(header: &FuncHeader, body: Option<&str>, ctx: ParseContext) -> ParseResult<Self>
where Self: Sized {
if header.args.len() != 1 || !header.kwargs.is_empty() {
- return err("expected exactly one positional argument specifying the alignment");
+ return err("align: expected exactly one positional argument");
}
let alignment = if let Expression::Ident(ident) = &header.args[0] {
@@ -29,11 +29,7 @@ impl Function for AlignFunc {
));
};
- let body = if let Some(body) = body {
- Some(parse(body, ctx)?)
- } else {
- None
- };
+ let body = parse_maybe_body(body, ctx)?;
Ok(AlignFunc { alignment, body })
}
@@ -45,14 +41,9 @@ impl Function for AlignFunc {
.. ctx
})?;
- let mut commands = CommandList::new();
- commands.add(Command::AddMany(layouts));
- Ok(commands)
+ Ok(commands![Command::AddMany(layouts)])
} else {
- let mut commands = CommandList::new();
- commands.add(Command::SetAlignment(self.alignment));
-
- Ok(commands)
+ Ok(commands![Command::SetAlignment(self.alignment)])
}
}
}
diff --git a/src/library/breaks.rs b/src/library/breaks.rs
new file mode 100644
index 00000000..22d572f0
--- /dev/null
+++ b/src/library/breaks.rs
@@ -0,0 +1,24 @@
+use super::prelude::*;
+
+/// Ends the current page.
+#[derive(Debug, PartialEq)]
+pub struct PagebreakFunc;
+
+impl Function for PagebreakFunc {
+ fn parse(header: &FuncHeader, body: Option<&str>, _: ParseContext) -> ParseResult<Self>
+ where Self: Sized {
+ if has_arguments(header) {
+ return err("pagebreak: expected no arguments");
+ }
+
+ if body.is_some() {
+ return err("pagebreak: expected no body");
+ }
+
+ Ok(PagebreakFunc)
+ }
+
+ fn layout(&self, _: LayoutContext) -> LayoutResult<CommandList> {
+ Ok(commands![Command::FinishLayout])
+ }
+}
diff --git a/src/library/mod.rs b/src/library/mod.rs
index 9a8b2e21..7c54a9f6 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -4,6 +4,7 @@ use crate::func::Scope;
mod align;
mod styles;
+mod breaks;
/// Useful imports for creating your own functions.
pub mod prelude {
@@ -12,13 +13,11 @@ pub mod prelude {
pub use crate::layout::{LayoutError, LayoutResult};
pub use crate::parsing::{parse, ParseContext, ParseError, ParseResult};
pub use crate::syntax::{Expression, FuncHeader, SyntaxTree};
-
- pub fn err<S: Into<String>, T>(message: S) -> ParseResult<T> {
- Err(ParseError::new(message))
- }
+ pub use super::helpers::*;
}
pub use align::AlignFunc;
+pub use breaks::PagebreakFunc;
pub use styles::{BoldFunc, ItalicFunc, MonospaceFunc};
/// Create a scope with all standard functions.
@@ -28,5 +27,26 @@ pub fn std() -> Scope {
std.add::<ItalicFunc>("italic");
std.add::<MonospaceFunc>("mono");
std.add::<AlignFunc>("align");
+ std.add::<PagebreakFunc>("pagebreak");
std
}
+
+pub mod helpers {
+ use super::prelude::*;
+
+ pub fn has_arguments(header: &FuncHeader) -> bool {
+ !header.args.is_empty() || !header.kwargs.is_empty()
+ }
+
+ pub fn parse_maybe_body(body: Option<&str>, ctx: ParseContext) -> ParseResult<Option<SyntaxTree>> {
+ if let Some(body) = body {
+ Ok(Some(parse(body, ctx)?))
+ } else {
+ Ok(None)
+ }
+ }
+
+ pub fn err<S: Into<String>, T>(message: S) -> ParseResult<T> {
+ Err(ParseError::new(message))
+ }
+}
diff --git a/src/library/styles.rs b/src/library/styles.rs
index f0e5bbdb..bc84ac3b 100644
--- a/src/library/styles.rs
+++ b/src/library/styles.rs
@@ -10,35 +10,37 @@ macro_rules! style_func {
) => {
$(#[$outer])*
#[derive(Debug, PartialEq)]
- pub struct $struct { body: SyntaxTree }
+ pub struct $struct {
+ body: Option<SyntaxTree>
+ }
impl Function for $struct {
fn parse(header: &FuncHeader, body: Option<&str>, ctx: ParseContext)
-> ParseResult<Self> where Self: Sized {
// Accept only invocations without arguments and with body.
- if header.args.is_empty() && header.kwargs.is_empty() {
- if let Some(body) = body {
- Ok($struct { body: parse(body, ctx)? })
- } else {
- Err(ParseError::new(format!("expected body for function `{}`", $name)))
- }
- } else {
- Err(ParseError::new(format!("unexpected arguments to function `{}`", $name)))
+ if has_arguments(header) {
+ return err(format!("{}: expected no arguments", $name));
}
+
+ let body = parse_maybe_body(body, ctx)?;
+
+ Ok($struct { body })
}
fn layout(&self, ctx: LayoutContext) -> LayoutResult<CommandList> {
- let mut commands = CommandList::new();
-
- let saved_style = ctx.style.clone();
let mut new_style = ctx.style.clone();
new_style.toggle_class(FontClass::$class);
- commands.add(Command::SetStyle(new_style));
- commands.add(Command::Layout(&self.body));
- commands.add(Command::SetStyle(saved_style));
-
- Ok(commands)
+ if let Some(body) = &self.body {
+ let saved_style = ctx.style.clone();
+ Ok(commands![
+ Command::SetStyle(new_style),
+ Command::Layout(body),
+ Command::SetStyle(saved_style),
+ ])
+ } else {
+ Ok(commands![Command::SetStyle(new_style)])
+ }
}
}
};