That's awesome Alex :D I sort of agree that using step directly is not the prettiest. That leads to two things: (1) maybe the Automaton library should have a "run" function for lists and (2) we can do a higher level API on top of this.
You can do safe blocks as follows:
data Blocks = Block (Int,Int) Blocks | Rest
chunk : Blocks -> Text -> [Element]
This ensures that every sequence of blocks is sure to get all the text. You can even do some syntax tricks to make this nicer:
(>>) = Block
blocks = (100,200) >> (300,200) >> Rest
main = flow right (chunk blocks myText)
That's all a bit weird though because the Blocks ADT is basically a list where cons is Block and nil is Rest. So the API could just be
chunk : [(Int,Int)] -> Text -> [Element]
chunk [] myText == [<all the text>]
chunk [(100,100)] myText == [<small block>, <everything else>]
I'm not sure if it is necessary to have the automaton library be public facing. Can you think of use cases that are not covered by the idea presented here? Maybe you want to do some complex layout that depends on what has happened so far?
I think the big thing is to figure out how to make Text expressive enough to make this nice. Like some way to unify markdown blocks and Text or something. Let's start a thread about this when someone has the first insight :)