diff options
| author | Laurenz <laurmaedje@gmail.com> | 2019-10-17 10:12:34 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2019-10-17 10:12:34 +0200 |
| commit | f22f9513aea21408ebf6febd01912e630e9ad5e6 (patch) | |
| tree | 06885bca8bc31d26189f33c059649ed7909af282 /src/library | |
| parent | 9a1d57a11a510b8e6af024b4338ee58d791f3088 (diff) | |
Add pagebreak function ⏭
Diffstat (limited to 'src/library')
| -rw-r--r-- | src/library/align.rs | 17 | ||||
| -rw-r--r-- | src/library/breaks.rs | 24 | ||||
| -rw-r--r-- | src/library/mod.rs | 28 | ||||
| -rw-r--r-- | src/library/styles.rs | 36 |
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)]) + } } } }; |
