module System.Log.Format where
import System.Log.Log (Log)
import System.Log.Data (Lvl(Lvl), Msg(Msg), Loc(Loc), Time(Time), LocData(LocData), LevelData(LevelData), readData, DataOf, Lookup)
import Data.Time.Clock (UTCTime)
import Data.Time.Format (formatTime, defaultTimeLocale)
import Text.PrettyPrint.ANSI.Leijen
newtype Formatter a = Formatter { runFormatter :: Log a -> Doc }
mapFormatter f (Formatter a) = Formatter (f a)
instance Show (Formatter a) where
show _ = "Formatter"
class FormatterBuilder a b where
buildFormatter :: a -> Formatter b
(<:>) :: (FormatterBuilder a c, FormatterBuilder b c) => a -> b -> Formatter c
(<:>) a b = concatFormatters (buildFormatter a) (buildFormatter b)
concatFormatters :: Formatter a -> Formatter a -> Formatter a
concatFormatters (Formatter f) (Formatter g) = Formatter (\s -> f s <> g s)
instance (PPrint (DataOf seg), Lookup seg (Log a)) => FormatterBuilder seg a where
buildFormatter a = Formatter $ pprint . readData a
instance (a~b) => FormatterBuilder (Formatter a) b where
buildFormatter = id
instance FormatterBuilder String a where
buildFormatter a = Formatter $ const (text a)
instance FormatterBuilder Doc a where
buildFormatter a = Formatter $ const a
class PPrint a where
pprint :: a -> Doc
instance PPrint String where
pprint = text
instance Pretty a => PPrint a where
pprint = pretty
instance Pretty LevelData where
pretty (LevelData _ name) = text name
instance Pretty LocData where
pretty (LocData _ _ m (l,_) _) = text (m ++ ":" ++ show l)
instance Pretty UTCTime where
pretty = text . formatTime defaultTimeLocale "%c"
defaultFormatter = colorLvlFormatter ("[" <:> Lvl <:> "] ") <:> Msg
defaultTimeFormatter = colorLvlFormatter ("[" <:> Lvl <:> "] ") <:> Time <:> ": " <:> Msg
defaultFormatterTH = colorLvlFormatter ("[" <:> Lvl <:> "] ") <:> Loc <:> ": " <:> Msg
colorLvlFormatter f = Formatter (\s -> let (LevelData pr _) = readData Lvl s in lvlColor pr $ runFormatter f s)
lvlColor lvl
| lvl == 0 = id
| lvl <= 2 = green
| lvl == 3 = yellow
| otherwise = red