autolib-todoc
Safe HaskellNone
LanguageHaskell98

Text.PrettyPrint.Dent

Description

super simple pretty printer:

Abstract: the only option of formatting is to increase indentation by a fixed amount.

Application: this is mainly used for pretty-printing Haskell data literals (records, tuples, lists).

Design goals:

  1. for parenthesized (by {}[]() ) sub-structure, the opening paren, separators (;,), closing paren should be in the same column
  2. the location (distance to left margin) of that column should only depend on the semantic nesting level of sub-structures (and not on the width of the layout of elements of sub-structures)
  3. small sub-structures should be put on one line (if they fit)

Example:

( Leftist 
    { tree = Branch 
        { left = Branch { left = Leaf, key = 4, right = Leaf }
        , key = 3
        , right = Leaf 
        }
    , refs = listToFM [ ( Ref 13, [ 0 ] ), ( Ref 17, [ ] ) ] 
    }
, [ Any, Any ]
)

Realisation (concept)

  1. there is a layout element nest (that is called for each opening delimiter) that increases the semantic indentation (for its scope)
  2. there is a layout element skip that compares semantic indentation s with current indentation (position of write-head on line) c, and if s < c (the head is too far ahead), it will insert a line-break, and advance to position s (by inserting white space)

This is used in combinator

l </> r = (l <> " ") <> nest 2 (skip <> r)

that is applied for each block: 'pretty (1,2,3)' is

vcat [ "(" </> 1, "," </> 2, "," </> 3, ")" ]

and 'pretty (Foo {bar = B})' is

"Foo" </> vcat [ "{" </> "bar" <+> "=" <+> "B", "}" ]

Note that we might have a named record instead of B, starting with 'B / ...', so the skip happens *after* the constructor name. This is applied in the example above.

  1. We want the full layout process to be lazy (do not build the full document when we only want some prefix).
ghci> L.take 10  $  renderT $ toDoc $ replicate 1000000 ()
"[ ( )\n, ( "
(0.00 secs, 1,169,104 bytes)

There is just one place where the algorithm has to consider alternative layouts: the group operator will make a layout without line breaks, if that fits on the current line. For that decision (does it fit?) we need to determine the size of the sub-document quickly. We use a representation of natural numbers, see type Size below, with lazy addition and comparison.

Synopsis

Documentation

data Doc Source #

Instances

Instances details
ToDoc Doc Source # 
Instance details

Defined in Autolib.ToDoc.Manual

Methods

toDocPrec :: Int -> Doc -> Doc Source #

toDocList :: [Doc] -> Doc Source #

Monoid Doc Source # 
Instance details

Defined in Autolib.Multilingual.Doc

Methods

mempty :: Doc #

mappend :: Doc -> Doc -> Doc #

mconcat :: [Doc] -> Doc #

Monoid Doc Source # 
Instance details

Defined in Text.PrettyPrint.Dent

Methods

mempty :: Doc #

mappend :: Doc -> Doc -> Doc #

mconcat :: [Doc] -> Doc #

Semigroup Doc Source # 
Instance details

Defined in Autolib.Multilingual.Doc

Methods

(<>) :: Doc -> Doc -> Doc #

sconcat :: NonEmpty Doc -> Doc #

stimes :: Integral b => b -> Doc -> Doc #

Semigroup Doc Source # 
Instance details

Defined in Text.PrettyPrint.Dent

Methods

(<>) :: Doc -> Doc -> Doc #

sconcat :: NonEmpty Doc -> Doc #

stimes :: Integral b => b -> Doc -> Doc #

IsString Doc Source # 
Instance details

Defined in Text.PrettyPrint.Dent

Methods

fromString :: String -> Doc #

Show Doc Source # 
Instance details

Defined in Autolib.Multilingual.Doc

Methods

showsPrec :: Int -> Doc -> ShowS #

show :: Doc -> String #

showList :: [Doc] -> ShowS #

Container Doc String Source # 
Instance details

Defined in Autolib.ToDoc.Xml

renderCompact :: Doc -> SimpleDoc Source #

renderWide :: Doc -> SimpleDoc Source #

renderPretty :: p1 -> p2 -> Doc -> SimpleDoc Source #

renderFlat :: Doc -> SimpleDoc Source #

(<+>) :: Doc -> Doc -> Doc Source #

concatenate with separating space

(<$$>) :: Doc -> Doc -> Doc Source #

concatenate with line break or (flat layout) no space

(<//>) :: Doc -> Doc -> Doc Source #

concatenate with line break or (flat layout) separating space

vcat :: [Doc] -> Doc Source #

concatenate vertically. in flat layout, concatenate horizontally (no separating space)

hcat :: [Doc] -> Doc Source #

concatenate horizontally (no separating space)

cat :: [Doc] -> Doc Source #

hsep :: [Doc] -> Doc Source #

concatenate horizontally (with separating space)

vsep :: [Doc] -> Doc Source #

concatenate vertically. in flat layout, concatenate horizontally (with separating space)

sep :: [Doc] -> Doc Source #

concatenate horizontally (with separating space)

fill :: p -> a -> a Source #

fillBreak :: p -> a -> a Source #

align :: a -> a Source #

nest :: Integral a => a -> Doc -> Doc Source #

encloseSep :: Semigroup a => a -> a -> a -> a Source #

char :: IsString a => Char -> a Source #