summaryrefslogtreecommitdiff
path: root/src/library/spacing.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/library/spacing.rs')
-rw-r--r--src/library/spacing.rs103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/library/spacing.rs b/src/library/spacing.rs
new file mode 100644
index 00000000..6c818292
--- /dev/null
+++ b/src/library/spacing.rs
@@ -0,0 +1,103 @@
+use super::*;
+use ContentKind::*;
+
+
+function! {
+ /// `line.break`, `n`: Ends the current line.
+ #[derive(Debug, Default, Clone, PartialEq)]
+ pub struct LineBreakFunc;
+
+ parse(default)
+ layout(self, ctx, errors) { vec![FinishLine] }
+}
+
+function! {
+ /// `par.break`: Ends the current paragraph.
+ ///
+ /// self has the same effect as two subsequent newlines.
+ #[derive(Debug, Default, Clone, PartialEq)]
+ pub struct ParBreakFunc;
+
+ parse(default)
+ layout(self, ctx, errors) { vec![BreakParagraph] }
+}
+
+function! {
+ /// `page.break`: Ends the current page.
+ #[derive(Debug, Default, Clone, PartialEq)]
+ pub struct PageBreakFunc;
+
+ parse(default)
+ layout(self, ctx, errors) { vec![BreakPage] }
+}
+
+function! {
+ /// `word.spacing`, `line.spacing`, `par.spacing`: The spacing between
+ /// words, lines or paragraphs as a multiple of the font size.
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct ContentSpacingFunc {
+ body: Option<SyntaxModel>,
+ content: ContentKind,
+ spacing: Option<f32>,
+ }
+
+ type Meta = ContentKind;
+
+ parse(header, body, ctx, errors, decos, meta) {
+ ContentSpacingFunc {
+ body: body!(opt: body, ctx, errors, decos),
+ content: meta,
+ spacing: header.args.pos.get::<f64>(errors)
+ .map(|num| num as f32)
+ .or_missing(errors, header.name.span, "spacing"),
+ }
+ }
+
+ layout(self, ctx, errors) {
+ styled(&self.body, ctx, self.spacing, |t, s| match self.content {
+ Word => t.word_spacing_scale = s,
+ Line => t.line_spacing_scale = s,
+ Paragraph => t.paragraph_spacing_scale = s,
+ })
+ }
+}
+
+/// The different kinds of content that can be spaced.
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum ContentKind {
+ Word,
+ Line,
+ Paragraph,
+}
+
+function! {
+ /// `spacing`, `h`, `v`: Adds spacing along an axis.
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct SpacingFunc {
+ spacing: Option<(AxisKey, FSize)>,
+ }
+
+ type Meta = Option<SpecificAxis>;
+
+ parse(header, body, ctx, errors, decos, meta) {
+ body!(nope: body, errors);
+ SpacingFunc {
+ spacing: if let Some(axis) = meta {
+ header.args.pos.get::<FSize>(errors)
+ .map(|s| (AxisKey::Specific(axis), s))
+ } else {
+ header.args.key.get_with_key::<AxisKey, FSize>(errors)
+ }.or_missing(errors, header.name.span, "spacing"),
+ }
+ }
+
+ layout(self, ctx, errors) {
+ if let Some((axis, spacing)) = self.spacing {
+ let axis = axis.to_generic(ctx.axes);
+ let spacing = spacing.scaled(ctx.style.text.font_size());
+ vec![AddSpacing(spacing, SpacingKind::Hard, axis)]
+ } else {
+ vec![]
+ }
+ }
+}