summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/func.rs1
-rw-r--r--src/layout/mod.rs9
-rw-r--r--src/layout/tree.rs2
-rw-r--r--src/library/mod.rs12
-rw-r--r--src/library/spacing.rs76
-rw-r--r--src/parsing/mod.rs4
-rw-r--r--tests/layouts/align.typ4
-rw-r--r--tests/layouts/coma.typ6
-rw-r--r--tests/layouts/pagebreaks.typ6
9 files changed, 106 insertions, 14 deletions
diff --git a/src/func.rs b/src/func.rs
index 7925af2d..05bbe83d 100644
--- a/src/func.rs
+++ b/src/func.rs
@@ -116,6 +116,7 @@ pub enum Command<'a> {
Layout(&'a SyntaxTree),
Add(Layout),
AddMany(MultiLayout),
+ AddFlex(Layout),
SetAlignment(Alignment),
SetStyle(TextStyle),
FinishLayout,
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 470ac3ba..34c9b35a 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -40,6 +40,15 @@ pub struct Layout {
}
impl Layout {
+ /// Create an empty layout with the specified dimensions.
+ pub fn empty(width: Size, height: Size) -> Layout {
+ Layout {
+ dimensions: Size2D::new(width, height),
+ actions: vec![],
+ debug_render: true,
+ }
+ }
+
/// Serialize this layout into an output buffer.
pub fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()> {
writeln!(
diff --git a/src/layout/tree.rs b/src/layout/tree.rs
index 3a58115f..a0cb1434 100644
--- a/src/layout/tree.rs
+++ b/src/layout/tree.rs
@@ -124,6 +124,8 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
self.start_new_flex();
}
+ Command::AddFlex(layout) => self.flex.add(layout),
+
Command::SetAlignment(alignment) => {
self.finish_flex()?;
self.alignment = alignment;
diff --git a/src/library/mod.rs b/src/library/mod.rs
index d0c987a4..784ef204 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -5,6 +5,7 @@ use crate::func::Scope;
mod align;
mod boxed;
mod breaks;
+mod spacing;
mod styles;
/// Useful imports for creating your own functions.
@@ -20,6 +21,7 @@ pub mod prelude {
pub use align::AlignFunc;
pub use boxed::BoxFunc;
pub use breaks::{LinebreakFunc, PagebreakFunc};
+pub use spacing::{HorizontalSpaceFunc, VerticalSpaceFunc};
pub use styles::{BoldFunc, ItalicFunc, MonospaceFunc};
/// Create a scope with all standard functions.
@@ -27,15 +29,21 @@ pub fn std() -> Scope {
let mut std = Scope::new();
std.add::<AlignFunc>("align");
std.add::<BoxFunc>("box");
- std.add::<LinebreakFunc>("linebreak");
+
+ std.add::<LinebreakFunc>("line.break");
std.add::<LinebreakFunc>("n");
- std.add::<PagebreakFunc>("pagebreak");
+ std.add::<PagebreakFunc>("page.break");
+
+ std.add::<HorizontalSpaceFunc>("h");
+ std.add::<VerticalSpaceFunc>("v");
+
std.add::<BoldFunc>("bold");
std.add::<ItalicFunc>("italic");
std.add::<MonospaceFunc>("mono");
std
}
+/// Helpers for writing custom functions.
pub mod helpers {
use super::prelude::*;
diff --git a/src/library/spacing.rs b/src/library/spacing.rs
new file mode 100644
index 00000000..91288edc
--- /dev/null
+++ b/src/library/spacing.rs
@@ -0,0 +1,76 @@
+use std::marker::PhantomData;
+use super::prelude::*;
+use crate::size::Size;
+
+/// Adds vertical space.
+pub type VerticalSpaceFunc = SpaceFunc<SpaceVertical>;
+
+/// Adds horizontal space.
+pub type HorizontalSpaceFunc = SpaceFunc<SpaceHorizontal>;
+
+/// Adds generic space.
+#[derive(Debug, PartialEq)]
+pub struct SpaceFunc<F: SpaceFlow> {
+ spacing: Spacing,
+ _phantom: PhantomData<F>,
+}
+
+/// Absolute or font-relative spacing.
+#[derive(Debug, PartialEq)]
+enum Spacing {
+ Absolute(Size),
+ Relative(f32),
+}
+
+impl<F: SpaceFlow> Function for SpaceFunc<F> {
+ fn parse(header: &FuncHeader, body: Option<&str>, _: ParseContext) -> ParseResult<Self>
+ where Self: Sized {
+ if header.args.len() != 1 || !header.kwargs.is_empty() {
+ return err("align: expected exactly one positional argument");
+ }
+
+ let spacing = match header.args[0] {
+ Expression::Size(s) => Spacing::Absolute(s),
+ Expression::Number(f) => Spacing::Relative(f as f32),
+ _ => return err("space: expected size or number"),
+ };
+
+ if body.is_some() {
+ return err("space: expected no body");
+ }
+
+ Ok(SpaceFunc {
+ spacing,
+ _phantom: PhantomData,
+ })
+ }
+
+ fn layout(&self, ctx: LayoutContext) -> LayoutResult<CommandList> {
+ let space = match self.spacing {
+ Spacing::Absolute(s) => s,
+ Spacing::Relative(f) => Size::pt(f * ctx.style.font_size),
+ };
+
+ Ok(commands![F::cmd(space)])
+ }
+}
+
+pub trait SpaceFlow: std::fmt::Debug + PartialEq + 'static {
+ fn cmd(space: Size) -> Command<'static>;
+}
+
+#[derive(Debug, PartialEq)]
+pub struct SpaceVertical;
+impl SpaceFlow for SpaceVertical {
+ fn cmd(space: Size) -> Command<'static> {
+ Command::Add(Layout::empty(Size::zero(), space))
+ }
+}
+
+#[derive(Debug, PartialEq)]
+pub struct SpaceHorizontal;
+impl SpaceFlow for SpaceHorizontal {
+ fn cmd(space: Size) -> Command<'static> {
+ Command::AddFlex(Layout::empty(space, Size::zero()))
+ }
+}
diff --git a/src/parsing/mod.rs b/src/parsing/mod.rs
index cd886fb4..36920595 100644
--- a/src/parsing/mod.rs
+++ b/src/parsing/mod.rs
@@ -404,13 +404,13 @@ fn is_identifier(string: &str) -> bool {
let mut chars = string.chars();
match chars.next() {
- Some(c) if !UnicodeXID::is_xid_start(c) => return false,
+ Some(c) if c != '.' && !UnicodeXID::is_xid_start(c) => return false,
None => return false,
_ => (),
}
while let Some(c) = chars.next() {
- if !UnicodeXID::is_xid_continue(c) {
+ if c != '.' && !UnicodeXID::is_xid_continue(c) {
return false;
}
}
diff --git a/tests/layouts/align.typ b/tests/layouts/align.typ
index 68e5fab5..c971cb41 100644
--- a/tests/layouts/align.typ
+++ b/tests/layouts/align.typ
@@ -11,7 +11,7 @@
// Over multiple pages after the pervious 3-page run.
[align: left][Left: {lorem:80}]
-[pagebreak]
+[page.break]
// ---------------------------------- //
// Context-modifying align.
@@ -26,7 +26,7 @@ Right Again: {lorem:10}
// Reset context-modifier.
[align: left]
-[pagebreak]
+[page.break]
// ---------------------------------- //
// All in one line.
diff --git a/tests/layouts/coma.typ b/tests/layouts/coma.typ
index 7b3266a9..b56299ec 100644
--- a/tests/layouts/coma.typ
+++ b/tests/layouts/coma.typ
@@ -9,9 +9,7 @@
[align: right][*WiSe 2019/2020* [n] Week 1]
]
-
-// hack for more whitespace
-[box][]
+[v: 3mm]
[align: center][
*3. Ubungsblatt Computerorientierte Mathematik II* [n]
@@ -27,5 +25,3 @@ Ein _Binärbaum_ ist ein Wurzelbaum, in dem jeder Knoten ≤ 2 Kinder hat.
Die Tiefe eines Knotens _v_ ist die Länge des eindeutigen Weges von der Wurzel
zu _v_, und die Höhe von _v_ ist die Länge eines längsten (absteigenden) Weges
von _v_ zu einem Blatt. Die Höhe des Baumes ist die Höhe der Wurzel.
-
-
diff --git a/tests/layouts/pagebreaks.typ b/tests/layouts/pagebreaks.typ
index 8de361ab..3644f662 100644
--- a/tests/layouts/pagebreaks.typ
+++ b/tests/layouts/pagebreaks.typ
@@ -1,10 +1,10 @@
{size:150pt*200pt}
{lorem:100}
-[pagebreak]
-[pagebreak]
+[page.break]
+[page.break]
{lorem:20}
-[pagebreak]
+[page.break]
{lorem:150}