{-# LANGUAGE TypeSynonymInstances, ScopedTypeVariables #-} -- | Pretty printing utils. module BuildBox.Pretty ( module Text.PrettyPrint , Pretty(..) , pprPSecTime , pprFloatTime , pprFloatSR , pprFloatRef , padRc, padR , padLc, padL , blank) where import Text.PrettyPrint import Data.Time -- Things that can be pretty printed class Pretty a where ppr :: a -> Doc -- Basic instances instance Pretty Doc where ppr = id instance Pretty String where ppr = text instance Pretty Float where ppr = text . show instance Pretty Int where ppr = int instance Pretty Integer where ppr = text . show instance Pretty UTCTime where ppr = text . show -- To handle type defaulting ten12i :: Integer ten12i = 10^(12 :: Integer) -- | Print a number of picoseconds as a time. pprPSecTime :: Integer -> Doc pprPSecTime psecs = text (show (psecs `quot` ten12i)) <> text "." <> (text $ (take 3 $ render $ padRc 12 '0' $ text $ show $ psecs `rem` ten12i)) -- | Print a float number of seconds as a time. pprFloatTime :: Float -> Doc pprFloatTime stime = let (secs :: Integer, frac :: Float) = properFraction stime msecs = frac * 1000 in text (show secs) <> text "." <> (padRc 3 '0' $ text $ show $ ((round $ msecs) :: Integer) ) -- | Pretty print a signed float, with a percentage change relative to a reference figure. -- Comes out like @0.235( +5)@ for a +5 percent swing. pprFloatRef :: Float -> Float -> Doc pprFloatRef stime stimeRef = let diff = ((stime - stimeRef) / stimeRef )*100 in pprFloatTime stime <> parens (padR 4 $ pprFloatSR diff) -- | Print a float number of seconds, rounding it and, prefixing with @+@ or @-@ appropriately. pprFloatSR :: Float -> Doc pprFloatSR p | p == 0 = text "----" | p > 0 = text "+" <> (ppr $ (round p :: Integer)) | otherwise = text "-" <> (ppr $ (round (negate p) :: Integer)) -- | Right justify a doc, padding with a given character. padRc :: Int -> Char -> Doc -> Doc padRc n c str = (text $ replicate (n - length (render str)) c) <> str -- | Right justify a string with spaces. padR :: Int -> Doc -> Doc padR n str = padRc n ' ' str -- | Left justify a string, padding with a given character. padLc :: Int -> Char -> Doc -> Doc padLc n c str = str <> (text $ replicate (n - length (render str)) c) -- | Left justify a string with spaces. padL :: Int -> Doc -> Doc padL n str = padLc n ' ' str -- | Blank text. This is different different from `empty` because it comes out a a newline when used in a `vcat`. blank :: Doc blank = ppr ""