Skip to content

The (break-group).nest-break pattern¤

Consider the following (from the methods example).

from wadler_lindig import BreakDoc as Brk, TextDoc as Txt, pprint


doc = (
    Txt("begin")
    + (
        Brk(" ")
        + (Txt("stmt;") + Brk(" ") + Txt("stmt;") + Brk(" ") + Txt("stmt;")).group()
    ).nest(3)
    + Brk(" ")
    + Txt("end")
)
pprint(doc, width=25)
pprint(doc, width=15)
begin
   stmt; stmt; stmt;
end
begin
   stmt;
   stmt;
   stmt;
end

Patterns of this form are very common: we have a beginning statement, then some indented content, and then an ending statement. The indented content should be laid out horizontally, or if there isn't enough space, vertically. The pattern being used here is this:

(Brk("") + (foo + bar + baz).group()).nest(indent) + Brk("")

This is the (break-group).nest-break pattern. This is clearest to understand working backwards:

  • the final break puts the closing statement (e.g. end) on a new line if laid out vertically.
  • the nest ensures that the contents are indented if they are laid out vertically.
    • the group (inside the nest) ensures that the contents have a chance to lay themselves out horizontally if possible (even if the overall pattern is laid out vertically).
    • the first break (also inside the nest!) puts the beginning statement on a new line if laid out vertically. This has to be inside the nest so that this first newline is inserted with the right amount of indentation after it.

Finally note that the grouped content itself should typically use breaks to separate each item. wl.join(wl.comma, ...) is a common way to do this.


Here are a few more examples that use this pattern. First a list:

my_list = ["foo", "bar", "qux"]
pprint(my_list, width=20, indent=1)
pprint(my_list, width=15, indent=1)
[
 'foo', 'bar', 'qux'
]
[
 'foo',
 'bar',
 'qux'
]

And now a dataclass:

from dataclasses import dataclass


@dataclass
class MyDataclass:
    x: int
    y: str
    z: float


my_dataclass = MyDataclass(x=3, y="hello world", z=3.14)
pprint(my_dataclass, width=30)
pprint(my_dataclass, width=20)
MyDataclass(
  x=3, y='hello world', z=3.14
)
MyDataclass(
  x=3,
  y='hello world',
  z=3.14
)

And now if you've made it this far through all the examples, here's a useful trick: wadler_lindig.bracketed offers a simple API for creating the (break-group).nest-break pattern for you.