prettyprinter
prettyprinter copied to clipboard
`space`s not collapsed
The following snippet
putStrLn . renderString . layoutPretty defaultLayoutOptions $
pretty "a" <+> mempty <+> pretty "b"
gives this output:
a b
(two spaces between a
and b
). Most of the time I want spaces to collapse i.e. to have
x <> space <> space === x <> space
because I often write things like x <+> (if b then y else mempty) <+> z
and I want to have one space between x
and z
when b
is False
. I think, pretty
(the library) works this way.
With the current behaviour I have to structure my pretty-printers in a weird non-compositional way. Is it maybe possible to add a layoutCollapseSpaces :: Bool
option to LayoutOptions
?
I've never used pretty
but according to "A prettier printer" it has different concatenation primitives than the Wadler/Leijen style pretty-printers, so it might behave as you desire here.
Is it maybe possible to add a
layoutCollapseSpaces :: Bool
option toLayoutOptions
?
Maybe, but it seems tricky to avoid collapsing subsequent spaces when they were intentionally inserted.
I think a better alternative might be to use something like this variant of hsep
:
hsep' :: [Doc ann] -> Doc ann
hsep' = hsep . filter (not . isEmpty)
where
isEmpty Empty = True
isEmpty _ = False
hsep' [x, if b then y else mempty, z]
… or you could use a variant of <+>
:
(<++>) :: Doc ann -> Doc ann -> Doc ann
Empty <++> y = y
x <++> Empty = x
x <++> y = x <> Char ' ' <> y
infixr 6 <++>
For reference, there's an old SO question regarding zero-height documents. IMHO that's a related problem where a solution could also involve filtering out the empty documents.
EDIT: wl-pprint
has the same problem.
Thank you!
The solution that you proposed works for me.
Feel free to close the issue if you don't think it's worth keeping it open.
Since there are multiple people who have trouble with the handling of empty documents, I'll keep this open to discuss possible solutions.
The problem is that <+>
is not concatenation, but »put a space between these, no matter what«. We could do something similar to what GHC does – remove duplicate empty lines etc – but that brings its own complexities. For example, it’s a priori not possible to decide whether a document is empty (it might be layout-dependent, e.g. using pageWidth
). So double whitespace collapse would need to be a special case in the layouter and only happen when the user requests it in some way.
I think it’s easier to solve this at the individual user’s level; these little, superficially convenient and desirable features usually result in loads of very subtle special cases that differ for each user anyway, so there is no one size fits all way of making the library »smart«.
After stumbling across GHC's prettyprinter
plans I found a related discussion in https://github.com/quchen/prettyprinter/issues/34.