diff --git a/logic.typ b/logic.typ index ab96944..987f2f0 100644 --- a/logic.typ +++ b/logic.typ @@ -127,33 +127,71 @@ } } -#let alternatives( - start: 1, - position: bottom + left, - repeat-last: false, - ..children -) = { +#let alternatives-match(subslides-contents, position: bottom + left) = { + let subslides-contents = if type(subslides-contents) == "dictionary" { + subslides-contents.pairs() + } else { + subslides-contents + } + + let subslides = subslides-contents.map(it => it.first()) + let contents = subslides-contents.map(it => it.last()) style(styles => { - let sizes = children.pos().map(c => measure(c, styles)) + let sizes = contents.map(c => measure(c, styles)) let max-width = calc.max(..sizes.map(sz => sz.width)) let max-height = calc.max(..sizes.map(sz => sz.height)) - for (idx, child) in children.pos().enumerate() { - let last = idx == children.pos().len() - 1 - let visible-subslides = if last and repeat-last { - (beginning: start + idx) - } else { - start + idx - } - - only(visible-subslides, box( + for (subslides, content) in subslides-contents { + only(subslides, box( width: max-width, height: max-height, - align(position, child) + align(position, content) )) } }) } +#let alternatives( + start: 1, + repeat-last: false, + ..args +) = { + let contents = args.pos() + let kwargs = args.named() + let subslides = range(start, start + contents.len()) + if repeat-last { + subslides.last() = (beginning: subslides.last()) + } + alternatives-match(subslides.zip(contents), ..kwargs) +} + +#let alternatives-fn( + start: 1, + end: none, + count: none, + ..kwargs, + fn +) = { + let end = if end == none { + if count == none { + panic("You must specify either end or count.") + } else { + start + count + } + } else { + end + } + + let subslides = range(start, end) + let contents = subslides.map(fn) + alternatives-match(subslides.zip(contents), ..kwargs.named()) +} + +#let alternatives-cases(cases, fn, ..kwargs) = { + let idcs = range(cases.len()) + let contents = idcs.map(fn) + alternatives-match(cases.zip(contents), ..kwargs.named()) +} + #let line-by-line(start: 1, mode: "invisible", body) = { let items = if repr(body.func()) == "sequence" { body.children diff --git a/polylux.typ b/polylux.typ index be2774c..5d85221 100644 --- a/polylux.typ +++ b/polylux.typ @@ -1,5 +1,5 @@ #import "themes/themes.typ" #import "logic.typ" -#import "logic.typ": polylux-slide, uncover, only, alternatives, one-by-one, line-by-line, pause, enable-handout-mode +#import "logic.typ": polylux-slide, uncover, only, alternatives, alternatives-match, alternatives-fn, alternatives-cases, one-by-one, line-by-line, pause, enable-handout-mode #import "helpers.typ" #import "helpers.typ": polylux-outline, fit-to-height, pdfpc diff --git a/tests/alternatives.typ b/tests/alternatives.typ index 5a87554..39febea 100644 --- a/tests/alternatives.typ +++ b/tests/alternatives.typ @@ -11,3 +11,31 @@ #uncover(5)[You can go now.] ] + +#polylux-slide[ + == Test that `alternatives-match` works + + #alternatives-match(position: center, ( + "-2": [beginning], + "3, 5": [main part], + "4": [short break], + "6-" : [end] + )) + + #uncover("1-8")[I am always here, for technical reasons.] +] + +#polylux-slide[ + == Test that `alternatives-cases` works + + #alternatives-cases(("1,3,4", "2,5", "6"), case => { + set text(fill: lime) if case == 1 + lorem(10) + }) +] + +#polylux-slide[ + == Test that `alternatives-fn` works + + #alternatives-fn(count: 5, subslide => numbering("(i)", subslide)) +]