summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-02-24 18:47:43 +0100
committerLaurenz <laurmaedje@gmail.com>2022-02-24 19:15:11 +0100
commit49c0bac44dda8be643480df2c4e68623eeec91bd (patch)
tree6f697031013e4259bdfefc7977edc8d9d683e823 /src
parent90132b0d658f1b2a5df75eb458150e6782b2c30c (diff)
First-line indents
Co-Authored-By: Martin Haug <mhaug@live.de>
Diffstat (limited to 'src')
-rw-r--r--src/eval/collapse.rs5
-rw-r--r--src/eval/styles.rs16
-rw-r--r--src/eval/template.rs30
-rw-r--r--src/library/par.rs3
4 files changed, 53 insertions, 1 deletions
diff --git a/src/eval/collapse.rs b/src/eval/collapse.rs
index ef8a5255..31581986 100644
--- a/src/eval/collapse.rs
+++ b/src/eval/collapse.rs
@@ -67,6 +67,11 @@ impl<'a, T: Merge> CollapsingBuilder<'a, T> {
self.staged.push((item, styles, None));
}
+ /// Iterate over the contained items.
+ pub fn items(&self) -> impl DoubleEndedIterator<Item = &T> {
+ self.builder.items().chain(self.staged.iter().map(|(item, ..)| item))
+ }
+
/// Return the finish style vec and the common prefix chain.
pub fn finish(mut self) -> (StyleVec<T>, StyleChain<'a>) {
self.flush(false);
diff --git a/src/eval/styles.rs b/src/eval/styles.rs
index bd1f808f..8e7bd4b6 100644
--- a/src/eval/styles.rs
+++ b/src/eval/styles.rs
@@ -547,6 +547,17 @@ impl<T> StyleVec<T> {
.flat_map(|(map, count)| std::iter::repeat(map).take(*count));
self.items().zip(styles)
}
+
+ /// Insert an element in the front. The element will share the style of the
+ /// current first element.
+ ///
+ /// This method has no effect if the vector is empty.
+ pub fn push_front(&mut self, item: T) {
+ if !self.maps.is_empty() {
+ self.items.insert(0, item);
+ self.maps[0].1 += 1;
+ }
+ }
}
impl<T> Default for StyleVec<T> {
@@ -601,6 +612,11 @@ impl<'a, T> StyleVecBuilder<'a, T> {
Some((item, chain))
}
+ /// Iterate over the contained items.
+ pub fn items(&self) -> std::slice::Iter<'_, T> {
+ self.items.iter()
+ }
+
/// Finish building, returning a pair of two things:
/// - a style vector of items with the non-shared styles
/// - a shared prefix chain of styles that apply to all items
diff --git a/src/eval/template.rs b/src/eval/template.rs
index a9e1262f..fb624600 100644
--- a/src/eval/template.rs
+++ b/src/eval/template.rs
@@ -445,8 +445,36 @@ impl<'a> Builder<'a> {
/// Finish the currently built paragraph.
fn finish_par(&mut self, styles: StyleChain<'a>) {
- let (par, shared) = std::mem::take(&mut self.par).finish();
+ let (mut par, shared) = std::mem::take(&mut self.par).finish();
if !par.is_empty() {
+ // Paragraph indent should only apply if the paragraph starts with
+ // text and follows directly after another paragraph.
+ let indent = shared.get(ParNode::INDENT);
+ if !indent.is_zero()
+ && par
+ .items()
+ .find_map(|child| match child {
+ ParChild::Spacing(_) => None,
+ ParChild::Text(_) => Some(true),
+ ParChild::Node(_) => Some(false),
+ })
+ .unwrap_or_default()
+ && self
+ .flow
+ .items()
+ .rev()
+ .find_map(|child| match child {
+ FlowChild::Leading => None,
+ FlowChild::Parbreak => None,
+ FlowChild::Node(node) => Some(node.is::<ParNode>()),
+ FlowChild::Spacing(_) => Some(false),
+ FlowChild::Colbreak => Some(false),
+ })
+ .unwrap_or_default()
+ {
+ par.push_front(ParChild::Spacing(SpacingKind::Linear(indent)))
+ }
+
let node = ParNode(par).pack();
self.flow.supportive(FlowChild::Node(node), shared);
}
diff --git a/src/library/par.rs b/src/library/par.rs
index e5122166..cc5dd9b6 100644
--- a/src/library/par.rs
+++ b/src/library/par.rs
@@ -36,6 +36,8 @@ impl ParNode {
pub const LEADING: Linear = Relative::new(0.65).into();
/// The extra spacing between paragraphs (dependent on scaled font size).
pub const SPACING: Linear = Relative::new(0.55).into();
+ /// The indent the first line of a consecutive paragraph should have.
+ pub const INDENT: Linear = Linear::zero();
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
// The paragraph constructor is special: It doesn't create a paragraph
@@ -75,6 +77,7 @@ impl ParNode {
styles.set_opt(Self::ALIGN, align);
styles.set_opt(Self::LEADING, args.named("leading")?);
styles.set_opt(Self::SPACING, args.named("spacing")?);
+ styles.set_opt(Self::INDENT, args.named("indent")?);
Ok(())
}