printcess-0.1.0.0: src/Printcess/PrettyPrinting.hs
module Printcess.PrettyPrinting (
-- * Overview
-- $overview
-- * Example
-- $example
-- * Rendering
pretty,
prettyPrint,
-- * Config
Config,
cMaxLineWidth, cIndentChar, cIndentDepth, cIndentAfterBreaks,
cInitIndent, cInitPrecedence,
defConfig,
-- * Type Class
Pretty(..),
-- * Monad
PrettyM,
-- * Sequencing
(+>), (~>), (\>),
-- * Indentation
indentedByChars, indentedBy, indented,
block, block',
-- * Associativity & Fixity
assocL, assocR, assocN,
left, right, inner, AssocAnn(..),
-- * Folding @Pretty@ Things
betweenEach, beforeEach, afterEach,
ppList, ppListMap, ppMap,
-- * Other combinators
bar, titleBar,
-- * Constants
nl, sp,
-- * Lifted Type Classes
Pretty1(..), Pretty2(..),
-- * Reexports
State, (.=),
) where
import Control.Monad.State.Strict
import Control.Lens
import Printcess.Config
import Printcess.Core
import Printcess.Combinators
{- $overview
The main features of the @printcess@ pretty printing library are
* /Indentation/. Printing-actions are relative to the indentation level
of their context. Special actions can be used to control the indentation
level. Indentation is automatically inserted after newlines.
* /Automatic parenthesizing of mixfix operators/.
Special printing-actions can be used to specify the associativity
and fixity of operators and to mark the positions of their arguments.
This makes it easy to print for example @"λx. λy. x y (x y)"@
instead of @"(λx. (λy. ((x y) (x y))))"@.
* /Automatic line breaks after exceeding a maximum line width/.
A maximum line width can be specified, after which lines are
automatically broken. If the break point is inside a word,
it is moved to the left until a white space character is reached.
This avoids splitting identifiers into two.
-}
{- $example
In this section, a small example is presented, which pretty prints a
lambda calculus expression.
First we define an abstract syntax tree for lambda calculus expressions.
> data Expr
> = EVar String
> | EAbs String Expr
> | EApp Expr Expr
Then we make @Expr@ an instance of the 'Pretty' type class, which
declares one method 'pp'. This method takes an @Expr@ and returns a
'PrettyM' @()@ action, which describes how to 'pretty' print the @Expr@.
> instance Pretty Expr where
> pp (EVar x) = pp x
> pp (EApp e1 e2) = assocL 9 $ L e1 ~> R e2
> pp (EAbs x e) = assocR 0 $ "λ" +> I x +> "." ~> R e
We print
* a variable @EVar x@ by printing the identifier 'String' @x@.
* a function application @EApp e1 e2@ as a left-associative operator of
fixity 9 ('assocL' @9@), where e1 is the left argument ('L') and @e2@ is
the right argument ('R'). The ('~>') combinator separates its first
argument with a space from its second argument.
* a function abstraction @EAbs x e@ as a right-associative operator of
fixity 0 ('assocR' @0@), where @x@ is an inner
argument ('I') and @e@ is the right argument ('R').
The ('+>') combinator behaves as ('~>'), but without inserting a space.
Then we define a simple test expression @e1@ representing @λx. λy. x y (x y)@
> e1 :: Expr
> e1 = EAbs "x" $ EAbs "y" $ EApp (EApp (EVar "x") (EVar "y"))
> (EApp (EVar "x") (EVar "y"))
and pretty print it to 'String' using the 'pretty' function
> s1, s2 :: String
> s1 = pretty defConfig e1 -- evaluates to "λx. λy. x y (x y)"
> s2 = pretty (cMaxLineWidth .= Just 12) e1 -- evaluates to "λx. λy. x y
> -- (x y)"
-}