natefaubion/purescript-dodo-printer

is it possible to print simple tables separated by space?

srghma opened this issue · 5 comments

text     text text
texttext text texttext

It would be non-trivial to support in a first class way. Like the linked ticket says, wadler/leijen style printing is not a general-purpose layout algorithm. dodo has experimental support for local overrides

-- | *EXPERIMENTAL:* modifies printing state and options locally for a document.
-- | This may change or be removed at any time.
locally :: forall a. (LocalOptions -> LocalOptions) -> Doc a -> Doc a
locally = Local
and also some context sensitivity
-- | Build a document based on the current layout position.
withPosition :: forall a. (Position -> Doc a) -> Doc a
withPosition = WithPosition
so in theory something might be possible. The difficult part is aligning things next to each other. You would probably have to completely bake the nested documents, split them on lines, and zip them back together. Doc annotations (like for ANSI colors) are handled in the renderer, and layout decisions are done dynamically while printing, so there's no current way to layout a Doc and get a Doc back. You could potentially write a Doc printer, that is, a printer that prints Docs back into Doc, or in some other intermediate boxes-like structure that you can manipulate back into the expected form.

You could potentially write a Doc printer, that is, a printer that prints Docs back into Doc, or in some other intermediate boxes-like structure that you can manipulate back into the expected form.

I've run some experiments, and I think this will work as long as you assume annotations are distributive. I'll try to tighten my implementation up over the next few days.

As an example, here it is working with ansi graphics:
Screen Shot 2022-02-05 at 1 18 30 PM

With some high-level code:

test :: Doc GraphicsParam
test = Box.toDoc do
  let
    a =
      heading
        (textBox 40 (Ansi.bold $ Dodo.text "Heading 1"))
        (textBox 40 (Ansi.italic para1))
    b =
      heading
        (textBox 60 (Ansi.bold $ Dodo.text "Heading 2"))
        (textBox 60 (Ansi.foreground Ansi.Yellow para1))

  a `hgutter 3` b