{-| This module provides functions that generate hslogger functions using Template Haskell. -} module System.Log.Logger.TH (deriveLoggers) where import qualified Language.Haskell.TH as TH import qualified System.Log.Logger as HSL {-| Generate hslogger functions for a list of priorities. Example usage: > module Foo.Bar ( ... ) where > > import System.Log.Logger.TH (deriveLoggers) > import qualified System.Log.Logger as HSL > > $(deriveLoggers "HSL" [HSL.DEBUG, HSL.INFO]) Used this way, @deriveLoggers@ would generate the following functions: > infoM :: String -> IO () > infoM s = HSL.infoM "Foo.Bar" ((++) "Foo.Bar: " s) > > debugM :: String -> IO () > debugM s = HSL.debugM "Foo.Bar" ((++) "Foo.Bar: " s) The other hslogger priorities follow the same pattern. So > infoM "hi there" would generate the INFO-level log event > Foo.Bar: hi there Notes: * "System.Log.Logger" must be imported qualified, and the qualifier must match the qualifier given to @deriveLoggers@. * Don't forget to enable Template Haskell preprocessing: specify the pragma @LANGUAGE TemplateHaskell@ at the top of your source file or @extensions: TemplateHaskell@ in your cabal file, etc. -} deriveLoggers :: String -- ^ Must match qualifier on import of "System.Log.Logger". -> [HSL.Priority] -- ^ List of priorities for which to generate logging functions. -> TH.Q [TH.Dec] deriveLoggers qualifier priorities = fmap TH.loc_module TH.location >>= \moduleName -> fmap concat (mapM (deriveLogger qualifier moduleName) priorities) -- ---------------------------------------- deriveLogger :: String -> String -> HSL.Priority -> TH.Q [TH.Dec] deriveLogger qualifier moduleName priority = code where code = do sig <- TH.sigD th_f [t| String -> IO () |] body <- TH.funD th_f [ TH.clause [TH.varP th_s] (TH.normalB (TH.appE (TH.appE (TH.varE th_h) (TH.stringE moduleName) ) (TH.appE (TH.appE (TH.varE '(++)) (TH.stringE prefix) ) (TH.varE th_s) ) ) ) [] ] return [sig, body] where th_s = TH.mkName "s" th_f = TH.mkName functionName th_h = TH.mkName (qualifier ++ "." ++ functionName) prefix = moduleName ++ ": " functionName = case priority of HSL.DEBUG -> "debugM" HSL.INFO -> "infoM" HSL.NOTICE -> "noticeM" HSL.WARNING -> "warningM" HSL.ERROR -> "errorM" HSL.CRITICAL -> "criticalM" HSL.ALERT -> "alertM" HSL.EMERGENCY -> "emergencyM"