Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Text.PrettyPrint.HughesPJ.fsep behaviour in Text.PrettyPrint.Leijen?

I am switching from H to L

import qualified Text.PrettyPrint.HughesPJ as H
import qualified Text.PrettyPrint.Leijen as L

and I have problems translating H.fsep ("paragraph fill").

This is what I want:

H.fsep  $ map ( \ d -> H.parens $ H.fsep $ replicate 4 d ) $ map (H.text . show) [1..10]

(1 1 1 1) (2 2 2 2) (3 3 3 3) (4 4 4 4) (5 5 5 5) (6 6 6 6)
(7 7 7 7) (8 8 8 8) (9 9 9 9) (10 10 10 10)

But I only get this:

 L.fillSep  $ map ( \ d -> L.parens $ L.fillSep $ replicate 4 d ) $ map (L.text . show) [1..10]

(1 1 1 1) (2 2 2 2) (3 3 3 3) (4
4 4 4) (5 5 5 5) (6 6 6 6) (7 7
7 7) (8 8 8 8) (9 9 9 9) (10 10
10 10)

(the formatting of the inner documents is not respected) or this:

 L.fillSep  $ map ( \ d -> L.parens $ L.align $ L.fillSep $ replicate 4 d ) $ map (L.text . show) [1..10]

(1 1 1 1) (2 2 2 2) (3 3 3 3) (4
                               4 4 4) (5 5 5 5) (6 6 6 6) (7 7
                                                           7 7) (8 8 8 8) (9 9 9
                                                                           9)
(10 10 10 10)

which is ugly.

like image 363
d8d0d65b3f7cf42 Avatar asked Feb 08 '14 19:02

d8d0d65b3f7cf42


1 Answers

A simple solution is to use hsep inside the parentheses

λ> L.fillSep $ map (\d -> L.parens $ L.hsep $ replicate 4 d) $ map (L.text . show) [1..10]
(1 1 1 1) (2 2 2 2) (3 3 3 3)
(4 4 4 4) (5 5 5 5) (6 6 6 6)
(7 7 7 7) (8 8 8 8) (9 9 9 9)
(10 10 10 10)

But that means that the inner document will always be printed horizontally.

Here is a function that is closer to the HughesPJ behavior:

fsep :: [L.Doc] -> L.Doc
fsep = foldl1 (\x y -> x L.<> (L.group $ L.line L.<> y))

λ> fsep $ map (\d -> L.parens $ L.fillSep $ replicate 4 d) $ map (L.text . show) [1..10]
(1 1 1 1) (2 2 2 2) (3 3 3 3)
(4 4 4 4) (5 5 5 5) (6 6 6 6)
(7 7 7 7) (8 8 8 8) (9 9 9 9)
(10 10 10 10)

What group does is put the output on a single line by changing all lines to space if the resulting output fits on the current line, while keeping the original formating otherwise. So fsep outputs the start of a list, and if the next item completely fits on the same line, then it is appended to that line. Otherwise a newline is inserted before the next list element.

In general, I often find it easier to control the output by using group manually, instead of relying on softline and </>.

like image 175
Twan van Laarhoven Avatar answered Sep 30 '22 16:09

Twan van Laarhoven