module CHR.Pretty
(
module CHR.Pretty.Simple
, PP_DocL
, (>-|-<)
, (>-#-<)
, ppListSep, ppListSepV, ppListSepVV
, ppCurlys
, ppPacked
, ppPackedWithStrings
, ppParens
, ppCurly
, ppBrackets
, ppVBar
, ppBlock, ppBlockH
, ppBlock'
, ppBlockWithStrings
, ppBlockWithStrings'
, ppBlockWithStringsH
, ppParensCommasBlock
, ppCurlysBlock
, ppCurlysSemisBlock
, ppCurlysCommasBlock
, ppParensSemisBlock
, ppBracketsCommasBlock
, ppParensCommasBlockH
, ppCurlysBlockH
, ppCurlysSemisBlockH
, ppCurlysCommasBlockH
, ppParensSemisBlockH
, ppBracketsCommasBlockH
, ppBracketsCommasV
, ppVertically
, ppCommas, ppCommas'
, ppSemis, ppSemis'
, ppSpaces
, ppCurlysCommas, ppCurlysCommas', ppCurlysCommasWith
, ppCurlysSemis, ppCurlysSemis'
, ppParensSpaces
, ppParensCommas, ppParensCommas'
, ppBracketsCommas
, ppBracketsCommas'
, ppHorizontally
, ppListSepFill
, ppMbPre, ppMbPost
, ppListPre, ppListPost
, ppDots, ppMb, ppUnless, ppWhen
, showPP
, hPutWidthPPLn, putWidthPPLn
, hPutPPLn, putPPLn
, hPutPPFile, putPPFile
)
where
import CHR.Pretty.Simple
import System.IO
import Data.List
import Data.Word
import qualified Data.Set as Set
type PP_DocL = [PP_Doc]
ppListSep :: (PP s, PP c, PP o, PP a) => o -> c -> s -> [a] -> PP_Doc
ppListSep = ppListSepWith pp
ppListSepWith :: (PP s, PP c, PP o) => (a->PP_Doc) -> o -> c -> s -> [a] -> PP_Doc
ppListSepWith ppa o c s pps = o >|< hlist (intersperse (pp s) (map ppa pps)) >|< c
ppListSepFill :: (PP s, PP c, PP o, PP a) => o -> c -> s -> [a] -> PP_Doc
ppListSepFill o c s pps
= l pps
where l [] = o >|< c
l [p] = o >|< pp p >|< c
l (p:ps) = hlist ((o >|< pp p) : map (s >|<) ps) >|< c
ppBlock'' :: (PP ocs, PP a) => Bool -> ocs -> ocs -> ocs -> ocs -> [a] -> [PP_Doc]
ppBlock'' _ osngl _ c _ [] = [osngl >|< c]
ppBlock'' _ osngl o c _ [a] | isSingleLine x = [osngl >|< x >|< c]
| otherwise = [o >|< x] ++ [pp c]
where x = pp a
ppBlock'' hori osngl o c s aa@(a:as)
| hori && all isSingleLine xx = [osngl >|< x >|< hlist (map (s >|<) xs) >|< c]
| otherwise = [o >|< x] ++ map (s >|<) xs ++ [pp c]
where xx@(x:xs) = map pp aa
ppBlock' :: (PP ocs, PP a) => ocs -> ocs -> ocs -> ocs -> [a] -> [PP_Doc]
ppBlock' = ppBlock'' False
ppBlockH' :: (PP ocs, PP a) => ocs -> ocs -> ocs -> ocs -> [a] -> [PP_Doc]
ppBlockH' = ppBlock'' True
ppBlock :: (PP ocs, PP a) => ocs -> ocs -> ocs -> [a] -> PP_Doc
ppBlock o c s = vlist . ppBlock' o o c s
ppBlockH :: (PP ocs, PP a) => ocs -> ocs -> ocs -> [a] -> PP_Doc
ppBlockH o c s = vlist . ppBlockH' o o c s
ppBlockWithStrings'' :: (PP a) => Bool -> String -> String -> String -> [a] -> [PP_Doc]
ppBlockWithStrings'' hori o c s = ppBlock'' hori o (pad o) c (pad s)
where l = maximum $ map length [o,s]
pad s = s ++ replicate (l length s) ' '
ppBlockWithStrings' :: (PP a) => String -> String -> String -> [a] -> [PP_Doc]
ppBlockWithStrings' = ppBlockWithStrings'' False
ppBlockWithStringsH' :: (PP a) => String -> String -> String -> [a] -> [PP_Doc]
ppBlockWithStringsH' = ppBlockWithStrings'' True
ppBlockWithStrings :: (PP a) => String -> String -> String -> [a] -> PP_Doc
ppBlockWithStrings o c s = vlist . ppBlockWithStrings' o c s
ppBlockWithStringsH :: (PP a) => String -> String -> String -> [a] -> PP_Doc
ppBlockWithStringsH o c s = vlist . ppBlockWithStringsH' o c s
ppCommas :: PP a => [a] -> PP_Doc
ppCommas = ppListSep "" "" ","
ppCommas' :: PP a => [a] -> PP_Doc
ppCommas' = ppListSep "" "" ", "
ppSemis :: PP a => [a] -> PP_Doc
ppSemis = ppListSep "" "" ";"
ppSemis' :: PP a => [a] -> PP_Doc
ppSemis' = ppListSep "" "" "; "
ppSpaces :: PP a => [a] -> PP_Doc
ppSpaces = ppListSep "" "" " "
ppCurlysBlock :: PP a => [a] -> PP_Doc
ppCurlysBlock = ppBlockWithStrings "{" "}" " "
ppCurlysBlockH :: PP a => [a] -> PP_Doc
ppCurlysBlockH = ppBlockWithStringsH "{" "}" " "
ppCurlysSemisBlock :: PP a => [a] -> PP_Doc
ppCurlysSemisBlock = ppBlockWithStrings "{" "}" "; "
ppCurlysSemisBlockH :: PP a => [a] -> PP_Doc
ppCurlysSemisBlockH = ppBlockWithStringsH "{" "}" "; "
ppCurlysCommasBlock :: PP a => [a] -> PP_Doc
ppCurlysCommasBlock = ppBlockWithStrings "{" "}" ", "
ppCurlysCommasBlockH :: PP a => [a] -> PP_Doc
ppCurlysCommasBlockH = ppBlockWithStringsH "{" "}" ", "
ppParensSemisBlock :: PP a => [a] -> PP_Doc
ppParensSemisBlock = ppBlockWithStrings "(" ")" "; "
ppParensSemisBlockH :: PP a => [a] -> PP_Doc
ppParensSemisBlockH = ppBlockWithStringsH "(" ")" "; "
ppParensCommasBlock :: PP a => [a] -> PP_Doc
ppParensCommasBlock = ppBlockWithStrings "(" ")" ", "
ppParensCommasBlockH :: PP a => [a] -> PP_Doc
ppParensCommasBlockH = ppBlockWithStringsH "(" ")" ", "
ppBracketsCommasV, ppBracketsCommasBlock, ppBracketsCommasBlockH :: PP a => [a] -> PP_Doc
ppBracketsCommasBlock = ppBlockWithStrings "[" "]" ", "
ppBracketsCommasBlockH = ppBlockWithStringsH "[" "]" ", "
ppBracketsCommasV = ppBracketsCommasBlock
ppBracketsCommas :: PP a => [a] -> PP_Doc
ppBracketsCommas = ppListSep "[" "]" ","
ppBracketsCommas' :: PP a => [a] -> PP_Doc
ppBracketsCommas' = ppListSep "[" "]" ", "
ppParensSpaces :: PP a => [a] -> PP_Doc
ppParensSpaces = ppListSep "(" ")" " "
ppParensCommas :: PP a => [a] -> PP_Doc
ppParensCommas = ppListSep "(" ")" ","
ppParensCommas' :: PP a => [a] -> PP_Doc
ppParensCommas' = ppListSep "(" ")" ", "
ppCurlysCommas :: PP a => [a] -> PP_Doc
ppCurlysCommas = ppListSep "{" "}" ","
ppCurlysCommasWith :: PP a => (a->PP_Doc) -> [a] -> PP_Doc
ppCurlysCommasWith ppa = ppListSepWith ppa "{" "}" ","
ppCurlysCommas' :: PP a => [a] -> PP_Doc
ppCurlysCommas' = ppListSep "{" "}" ", "
ppCurlysSemis :: PP a => [a] -> PP_Doc
ppCurlysSemis = ppListSep "{" "}" ";"
ppCurlysSemis' :: PP a => [a] -> PP_Doc
ppCurlysSemis' = ppListSep "{" "}" "; "
ppListSepV' :: (PP s, PP c, PP o, PP a) => (forall x y . (PP x, PP y) => x -> y -> PP_Doc) -> o -> c -> s -> [a] -> PP_Doc
ppListSepV' aside o c s pps
= l pps
where l [] = o `aside` c
l [p] = o `aside` p `aside` c
l (p:ps) = vlist ([o `aside` p] ++ map (s `aside`) (init ps) ++ [s `aside` last ps `aside` c])
ppListSepV :: (PP s, PP c, PP o, PP a) => o -> c -> s -> [a] -> PP_Doc
ppListSepV = ppListSepV' (>|<)
ppListSepVV :: (PP s, PP c, PP o, PP a) => o -> c -> s -> [a] -> PP_Doc
ppListSepVV = ppListSepV' (>-<)
ppVertically :: [PP_Doc] -> PP_Doc
ppVertically = vlist
ppHorizontally :: [PP_Doc] -> PP_Doc
ppHorizontally = hlist
ppPacked :: (PP o, PP c, PP p) => o -> c -> p -> PP_Doc
ppPacked o c pp
= o >|< pp >|< c
ppPackedWithStrings :: (PP p) => String -> String -> p -> PP_Doc
ppPackedWithStrings o c x = ppBlockWithStrings o c "" [x]
ppParens, ppBrackets, ppCurly, ppCurlys, ppVBar :: PP p => p -> PP_Doc
ppParens = ppPackedWithStrings "(" ")"
ppBrackets = ppPackedWithStrings "[" "]"
ppCurly = ppPackedWithStrings "{" "}"
ppCurlys = ppCurly
ppVBar = ppPackedWithStrings "|" "|"
infixr 2 >-|-<, >-#-<
aside :: (PP a, PP b) => String -> a -> b -> PP_Doc
aside sep l r | isSingleLine l' && isSingleLine r' = l' >|< sep >|< r'
| otherwise = l' >-< sep >|< r'
where l' = pp l
r' = pp r
(>-|-<) :: (PP a, PP b) => a -> b -> PP_Doc
(>-|-<) = aside ""
(>-#-<) :: (PP a, PP b) => a -> b -> PP_Doc
(>-#-<) = aside " "
maybeNull :: r -> ([a] -> r) -> [a] -> r
maybeNull n f l = if null l then n else f l
ppMbPre :: (PP x, PP r) => (a -> x) -> Maybe a -> r -> PP_Doc
ppMbPre p = maybe pp (\v rest -> p v >#< rest)
ppMbPost :: (PP x, PP r) => (a -> x) -> Maybe a -> r -> PP_Doc
ppMbPost p = maybe pp (\v rest -> rest >#< p v)
ppListPre :: (PP x, PP r) => ([a] -> x) -> [a] -> r -> PP_Doc
ppListPre p = maybeNull pp (\l rest -> p l >#< rest)
ppListPost :: (PP x, PP r) => ([a] -> x) -> [a] -> r -> PP_Doc
ppListPost p = maybeNull pp (\l rest -> p l >#< rest)
ppUnless :: PP x => Bool -> x -> PP_Doc
ppUnless b x = if b then empty else pp x
ppWhen :: PP x => Bool -> x -> PP_Doc
ppWhen b x = if b then pp x else empty
ppDots :: PP a => [a] -> PP_Doc
ppDots = ppListSep "" "" "."
ppMb :: PP a => Maybe a -> PP_Doc
ppMb = maybe empty pp
instance PP a => PP (Maybe a) where
pp = maybe (pp "?") pp
instance PP a => PP (Set.Set a) where
pp = ppCurlysCommasBlockH . Set.toList
instance PP Bool where
pp = pp . show
instance PP Word32 where
pp = pp . show
instance PP () where
pp _ = pp "()"
instance (PP a, PP b) => PP (a,b) where
pp (a,b) = "(" >|< a >-|-< "," >|< b >-|-< ")"
instance (PP a, PP b, PP c) => PP (a,b,c) where
pp (a,b,c) = "(" >|< a >-|-< "," >|< b >-|-< "," >|< c >-|-< ")"
showPP :: PP a => a -> String
showPP x = disp (pp x) 1000 ""
hPutLn :: Handle -> Int -> PP_Doc -> IO ()
hPutLn h w pp
= hPutStrLn h (disp pp w "")
hPutWidthPPLn :: Handle -> Int -> PP_Doc -> IO ()
hPutWidthPPLn h w pp = hPutLn h w pp
putWidthPPLn :: Int -> PP_Doc -> IO ()
putWidthPPLn = hPutWidthPPLn stdout
hPutPPLn :: Handle -> PP_Doc -> IO ()
hPutPPLn h = hPutWidthPPLn h 4000
putPPLn :: PP_Doc -> IO ()
putPPLn = hPutPPLn stdout
hPutPPFile :: Handle -> PP_Doc -> Int -> IO ()
hPutPPFile h pp wid
= hPutLn h wid pp
putPPFile :: String -> PP_Doc -> Int -> IO ()
putPPFile fn pp wid
= do { h <- openFile fn WriteMode
; hPutPPFile h pp wid
; hClose h
}