andreasKroepelin / polylux

A package for creating slides in Typst
https://polylux.dev/book
MIT License
1.18k stars 55 forks source link

Composability, nesting and avoiding exlicit subslide numbering #103

Open donRumata03 opened 1 year ago

donRumata03 commented 1 year ago

Currently, functions for handling presence of content at subslides (such as alternatives, one-by-one, etc.) are bounded to subslide indexes from 1, which is a serious problem for composability. For instance, consider this code:

    #alternatives[First option][
        Common text for second option
        #one-by-one[2][3][4]
    ]

one would expect this to firstly show First option and then uncover the variants of the second one one-by-one. But alternatives constrain the scope of the second option to just the second slide. Moreover, both 3 and 4 are already uncovered by that time because one-by-one counts relative to 1, not to the index at which the parent would decide.

Ideally, the language should be expressive enough to mitigate the necessity of explicit numbering for arbitrarily complex «content flow control» logic.

Another use-case would be

#alternatives[
    One alternative
][
    Another alternative
    #alternatives[Sub-alternative 1][Sub-alternative 2]
]

which should probably render as… expected.

So, I wonder if it would be possible to implement something like this. Probably, at every recursion level of polylux invocation the whole content tree should traversed and the relative indexes of «transient» objects (the ones created by one of those helper functions) should be shifted. Also, given a top-level instance (could it be polylux-slide?), we could traverse the tree to root (collecting offsets and nodes) and then from root (propagating the offsets down to leafs).

Obviously, that sounds like a breaking change, so functions with different names could be used (or a semver-compatible version increase could be made). Anyway, the mainstream code with just one of those primitives per slide wouldn't be affected.

As an intermediate solution, some interoperation of the primitives can be handled by users if the blocks would return an index at which it ended its counting. For example, one could write (with imaginary syntax):

#let (content, next_index) = #fancy-alternatives[…][…]…
#content
#one-by-one(start: next_index)[…][…][…]

but the latter approach is clearly pretty limited.