From 28b5c55cd5ef59713239c73d03fa0051623513d3 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 13 Feb 2023 17:15:11 +0100 Subject: [PATCH] Configurable markers for nested lists --- library/src/layout/enum.rs | 2 +- library/src/layout/list.rs | 81 ++++++++++++++++++++++++++++--- library/src/layout/terms.rs | 4 +- tests/ref/layout/list-marker.png | Bin 0 -> 3769 bytes tests/ref/layout/list.png | Bin 20936 -> 19366 bytes tests/typ/layout/list-marker.typ | 34 +++++++++++++ tests/typ/layout/list.typ | 5 -- 7 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 tests/ref/layout/list-marker.png create mode 100644 tests/typ/layout/list-marker.typ diff --git a/library/src/layout/enum.rs b/library/src/layout/enum.rs index 9b7ea1996..866a6195f 100644 --- a/library/src/layout/enum.rs +++ b/library/src/layout/enum.rs @@ -150,7 +150,7 @@ impl EnumNode { /// The spacing between the items of a wide (non-tight) enumeration. /// - /// If set to `{auto}` uses the spacing [below blocks]($func/block.below). + /// If set to `{auto}`, uses the spacing [below blocks]($func/block.below). pub const SPACING: Smart = Smart::Auto; /// The numbers of parent items. diff --git a/library/src/layout/list.rs b/library/src/layout/list.rs index eab835cae..38816933c 100644 --- a/library/src/layout/list.rs +++ b/library/src/layout/list.rs @@ -76,16 +76,29 @@ pub struct ListNode { #[node] impl ListNode { - /// The marker which introduces each element. + /// The marker which introduces each item. + /// + /// Instead of plain content, you can also pass an array with multiple + /// markers that should be used for nested lists. If the list nesting depth + /// exceeds the number of markers, the last one is repeated. For total + /// control, you may pass a function that maps the list's nesting depth + /// (starting from `{0}`) to a desired marker. + /// + /// Default: `•` /// /// ```example /// #set list(marker: [--]) - /// /// - A more classic list /// - With en-dashes + /// + /// #set list(marker: ([•], [--])) + /// - Top-level + /// - Nested + /// - Items + /// - Items /// ``` #[property(referenced)] - pub const MARKER: Content = TextNode::packed('•'); + pub const MARKER: Marker = Marker::Content(vec![]); /// The indent of each item's marker. #[property(resolve)] @@ -97,9 +110,13 @@ impl ListNode { /// The spacing between the items of a wide (non-tight) list. /// - /// If set to `{auto}` uses the spacing [below blocks]($func/block.below). + /// If set to `{auto}`, uses the spacing [below blocks]($func/block.below). pub const SPACING: Smart = Smart::Auto; + /// The nesting depth. + #[property(skip, fold)] + const DEPTH: Depth = 0; + fn construct(_: &Vm, args: &mut Args) -> SourceResult { Ok(Self { tight: args.named("tight")?.unwrap_or(true), @@ -126,7 +143,6 @@ impl Layout for ListNode { styles: StyleChain, regions: Regions, ) -> SourceResult { - let marker = styles.get(Self::MARKER); let indent = styles.get(Self::INDENT); let body_indent = styles.get(Self::BODY_INDENT); let gutter = if self.tight { @@ -137,12 +153,17 @@ impl Layout for ListNode { .unwrap_or_else(|| styles.get(BlockNode::BELOW).amount) }; + let depth = styles.get(Self::DEPTH); + let marker = styles.get(Self::MARKER).resolve(vt.world(), depth)?; + let mut cells = vec![]; for (item, map) in self.items.iter() { cells.push(Content::empty()); cells.push(marker.clone()); cells.push(Content::empty()); - cells.push(item.clone().styled_with_map(map.clone())); + cells.push( + item.clone().styled_with_map(map.clone()).styled(Self::DEPTH, Depth), + ); } GridNode { @@ -158,3 +179,51 @@ impl Layout for ListNode { .layout(vt, styles, regions) } } + +/// A list's marker. +#[derive(Debug, Clone, Hash)] +pub enum Marker { + Content(Vec), + Func(Func), +} + +impl Marker { + /// Resolve the marker for the given depth. + fn resolve(&self, world: Tracked, depth: usize) -> SourceResult { + Ok(match self { + Self::Content(list) => list + .get(depth) + .or(list.last()) + .cloned() + .unwrap_or_else(|| TextNode::packed('•')), + Self::Func(func) => { + let args = Args::new(func.span(), [Value::Int(depth as i64)]); + func.call_detached(world, args)?.display() + } + }) + } +} + +castable! { + Marker, + v: Content => Self::Content(vec![v]), + array: Array => { + if array.len() == 0 { + Err("must contain at least one marker")?; + } + Self::Content(array.into_iter().map(Value::display).collect()) + }, + v: Func => Self::Func(v), +} + +#[derive(Debug, Clone, Hash)] +struct Depth; + +impl Fold for Depth { + type Output = usize; + + fn fold(self, mut outer: Self::Output) -> Self::Output { + outer += 1; + outer + } +} diff --git a/library/src/layout/terms.rs b/library/src/layout/terms.rs index b1d399dba..f2902b808 100644 --- a/library/src/layout/terms.rs +++ b/library/src/layout/terms.rs @@ -82,7 +82,7 @@ impl TermsNode { /// The spacing between the items of a wide (non-tight) term list. /// - /// If set to `{auto}` uses the spacing [below blocks]($func/block.below). + /// If set to `{auto}`, uses the spacing [below blocks]($func/block.below). pub const SPACING: Smart = Smart::Auto; fn construct(_: &Vm, args: &mut Args) -> SourceResult { @@ -171,7 +171,7 @@ castable! { let mut iter = array.into_iter(); let (term, description) = match (iter.next(), iter.next(), iter.next()) { (Some(a), Some(b), None) => (a.cast()?, b.cast()?), - _ => Err("array must contain exactly two entries")?, + _ => Err("term array must contain exactly two entries")?, }; Self { term, description } }, diff --git a/tests/ref/layout/list-marker.png b/tests/ref/layout/list-marker.png new file mode 100644 index 0000000000000000000000000000000000000000..cd0eab440a9699185f1844b92e4504b3f261abbb GIT binary patch literal 3769 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 delta 4143 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 diff --git a/tests/typ/layout/list-marker.typ b/tests/typ/layout/list-marker.typ new file mode 100644 index 000000000..0d223b58a --- /dev/null +++ b/tests/typ/layout/list-marker.typ @@ -0,0 +1,34 @@ +// Test list marker configuraiton. + +--- +// Test en-dash. +#set list(marker: [--]) +- A +- B + +--- +// Test that last item is repeated. +#set list(marker: ([--], [•])) +- A + - B + - C + +--- +// Test function. +#set list(marker: n => if n == 1 [--] else [•]) +- A +- B + - C + - D + - E +- F + +--- +// Test that bare hyphen doesn't lead to cycles and crashes. +#set list(marker: [-]) +- Bare hyphen is +- a bad marker + +--- +// Error: 19-21 must contain at least one marker +#set list(marker: ()) diff --git a/tests/typ/layout/list.typ b/tests/typ/layout/list.typ index 3fd9ddb1d..71ccfe351 100644 --- a/tests/typ/layout/list.typ +++ b/tests/typ/layout/list.typ @@ -44,11 +44,6 @@ _Shopping list_ - A with 2 spaces - B with 2 tabs ---- -#set list(marker: [-]) -- Bare hyphen -- is not a list - --- // Edge cases. -