Search code examples
haskellpretty-print

Optional spaces and multiple alternatives in wl-pprint-extras


Is there a good/accepted way to get more than two alternative layouts, specifically in a way which supports optional spaces?

In particular, I might want to print a list in one of three ways:

[1, 2, 3, 4, 5]

[1,2,3,4,5]

[ 1
, 2
, 3
, 4
, 5
]

in that order of preference.


Solution

  • You can try one alternatives before another with group and flatAlt.

    (<|>) :: Doc e -> Doc e -> Doc e
    a <|> b = group $ flatAlt b a
    
    infixl 5 <|>
    

    We'll define your three examples.

    {-# LANGUAGE OverloadedStrings #-}
    
    import Text.PrettyPrint.Free
    import System.IO
    
    items = map char ['1'..'5']
    
    widest = brackets . hcat . punctuate ", " $ items
    wide   = brackets . hcat . punctuate ","  $ items
    skinny = brackets . hcat . punctuate "," . map (\x -> " " <> x <> linebreak) $ items
    

    The widest of these that fits on the screen, widestFits, can be defined in terms of <|> which we defined above.

    widestFits = widest <|> wide <|> skinny
    

    We will try pretty printing these on three documents, one wide enough to hold the widest example, one only wide enough to hold the wide example, and one that can't hold either.

    main = do
        displayIO stdout $ renderPretty 1.0 15 widestFits
        putStrLn ""
        displayIO stdout $ renderPretty 1.0 14 widestFits   
        putStrLn "" 
        displayIO stdout $ renderPretty 1.0 10 widestFits
        putStrLn "
    

    This results in the desired output.

    [1, 2, 3, 4, 5]
    [1,2,3,4,5]
    [ 1
    , 2
    , 3
    , 4
    , 5
    ]