{- | Module : $Header$ Description : Pretty printing Copyright : (c) 2013 - 2014 Björn Peemöller 2016 Finn Teegen License : BSD-3-clause Maintainer : bjp@informatik.uni-kiel.de Stability : stable Portability : portable This module re-exports the well known pretty printing combinators from Hughes and Peyton-Jones. In addition, it re-exports the type class 'Pretty' for pretty printing arbitrary types. -} {-# LANGUAGE CPP #-} module Curry.Base.Pretty ( module Curry.Base.Pretty , module Text.PrettyPrint ) where #if __GLASGOW_HASKELL__ >= 804 import Prelude hiding ((<>)) #endif import Text.PrettyPrint -- | Pretty printing class. -- The precedence level is used in a similar way as in the 'Show' class. -- Minimal complete definition is either 'pPrintPrec' or 'pPrint'. class Pretty a where -- | Pretty-print something in isolation. pPrint :: a -> Doc pPrint = pPrintPrec 0 -- | Pretty-print something in a precedence context. pPrintPrec :: Int -> a -> Doc pPrintPrec _ = pPrint -- |Pretty-print a list. pPrintList :: [a] -> Doc pPrintList = brackets . fsep . punctuate comma . map (pPrintPrec 0) #if __GLASGOW_HASKELL__ >= 707 {-# MINIMAL pPrintPrec | pPrint #-} #endif -- | Pretty print a value to a 'String'. prettyShow :: Pretty a => a -> String prettyShow = render . pPrint -- | Parenthesize an value if the boolean is true. parenIf :: Bool -> Doc -> Doc parenIf False = id parenIf True = parens -- | Pretty print a value if the boolean is true ppIf :: Bool -> Doc -> Doc ppIf True = id ppIf False = const empty -- | Pretty print a 'Maybe' value for the 'Just' constructor only maybePP :: (a -> Doc) -> Maybe a -> Doc maybePP pp = maybe empty pp -- | A blank line. blankLine :: Doc blankLine = text "" -- |Above with a blank line in between. If one of the documents is empty, -- then the other document is returned. ($++$) :: Doc -> Doc -> Doc d1 $++$ d2 | isEmpty d1 = d2 | isEmpty d2 = d1 | otherwise = d1 $+$ blankLine $+$ d2 -- |Above with overlapping, but with a space in between. If one of the -- documents is empty, then the other document is returned. ($-$) :: Doc -> Doc -> Doc d1 $-$ d2 | isEmpty d1 = d2 | isEmpty d2 = d1 | otherwise = d1 $$ space $$ d2 -- | Seperate a list of 'Doc's by a 'blankLine'. sepByBlankLine :: [Doc] -> Doc sepByBlankLine = foldr ($++$) empty -- |A '.' character. dot :: Doc dot = char '.' -- |Precedence of function application appPrec :: Int appPrec = 10 -- |A left arrow @<-@. larrow :: Doc larrow = text "<-" -- |A right arrow @->@. rarrow :: Doc rarrow = text "->" -- |A double arrow @=>@. darrow :: Doc darrow = text "=>" -- |A back quote @`@. backQuote :: Doc backQuote = char '`' -- |A backslash @\@. backsl :: Doc backsl = char '\\' -- |A vertical bar @|@. vbar :: Doc vbar = char '|' -- |Set a document in backquotes. bquotes :: Doc -> Doc bquotes doc = backQuote <> doc <> backQuote -- |Set a document in backquotes if the condition is @True@. bquotesIf :: Bool -> Doc -> Doc bquotesIf b doc = if b then bquotes doc else doc -- |Seperate a list of documents by commas list :: [Doc] -> Doc list = fsep . punctuate comma . filter (not . isEmpty) -- | Instance for 'Int' instance Pretty Int where pPrint = int -- | Instance for 'Integer' instance Pretty Integer where pPrint = integer -- | Instance for 'Float' instance Pretty Float where pPrint = float -- | Instance for 'Double' instance Pretty Double where pPrint = double -- | Instance for '()' instance Pretty () where pPrint _ = text "()" -- | Instance for 'Bool' instance Pretty Bool where pPrint = text . show -- | Instance for 'Ordering' instance Pretty Ordering where pPrint = text . show -- | Instance for 'Char' instance Pretty Char where pPrint = char pPrintList = text . show -- | Instance for 'Maybe' instance (Pretty a) => Pretty (Maybe a) where pPrintPrec _ Nothing = text "Nothing" pPrintPrec p (Just x) = parenIf (p > appPrec) $ text "Just" <+> pPrintPrec (appPrec + 1) x -- | Instance for 'Either' instance (Pretty a, Pretty b) => Pretty (Either a b) where pPrintPrec p (Left x) = parenIf (p > appPrec) $ text "Left" <+> pPrintPrec (appPrec + 1) x pPrintPrec p (Right x) = parenIf (p > appPrec) $ text "Right" <+> pPrintPrec (appPrec + 1) x -- | Instance for '[]' instance (Pretty a) => Pretty [a] where pPrintPrec _ xs = pPrintList xs -- | Instance for '(,)' instance (Pretty a, Pretty b) => Pretty (a, b) where pPrintPrec _ (a, b) = parens $ fsep $ punctuate comma [pPrint a, pPrint b] -- | Instance for '(,,)' instance (Pretty a, Pretty b, Pretty c) => Pretty (a, b, c) where pPrintPrec _ (a, b, c) = parens $ fsep $ punctuate comma [pPrint a, pPrint b, pPrint c] -- | Instance for '(,,,)' instance (Pretty a, Pretty b, Pretty c, Pretty d) => Pretty (a, b, c, d) where pPrintPrec _ (a, b, c, d) = parens $ fsep $ punctuate comma [pPrint a, pPrint b, pPrint c, pPrint d] -- | Instance for '(,,,,)' instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e) => Pretty (a, b, c, d, e) where pPrintPrec _ (a, b, c, d, e) = parens $ fsep $ punctuate comma [pPrint a, pPrint b, pPrint c, pPrint d, pPrint e] -- | Instance for '(,,,,,)' instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e, Pretty f) => Pretty (a, b, c, d, e, f) where pPrintPrec _ (a, b, c, d, e, f) = parens $ fsep $ punctuate comma [pPrint a, pPrint b, pPrint c, pPrint d, pPrint e, pPrint f] -- | Instance for '(,,,,,,)' instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e, Pretty f, Pretty g) => Pretty (a, b, c, d, e, f, g) where pPrintPrec _ (a, b, c, d, e, f, g) = parens $ fsep $ punctuate comma [pPrint a, pPrint b, pPrint c, pPrint d, pPrint e, pPrint f, pPrint g] -- | Instance for '(,,,,,,,)' instance (Pretty a, Pretty b, Pretty c, Pretty d, Pretty e, Pretty f, Pretty g, Pretty h) => Pretty (a, b, c, d, e, f, g, h) where pPrintPrec _ (a, b, c, d, e, f, g, h) = parens $ fsep $ punctuate comma [pPrint a, pPrint b, pPrint c, pPrint d, pPrint e, pPrint f, pPrint g, pPrint h]