{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE FlexibleContexts #-}
module Distribution.Utils.LogProgress (
LogProgress,
runLogProgress,
warnProgress,
infoProgress,
dieProgress,
addProgressCtx,
) where
import Prelude ()
import Distribution.Compat.Prelude
import Distribution.Utils.Progress
import Distribution.Verbosity
import Distribution.Simple.Utils
import Text.PrettyPrint
type CtxMsg = Doc
type LogMsg = Doc
type ErrMsg = Doc
data LogEnv = LogEnv {
le_verbosity :: Verbosity,
le_context :: [CtxMsg]
}
newtype LogProgress a = LogProgress { unLogProgress :: LogEnv -> Progress LogMsg ErrMsg a }
instance Functor LogProgress where
fmap f (LogProgress m) = LogProgress (fmap (fmap f) m)
instance Applicative LogProgress where
pure x = LogProgress (pure (pure x))
LogProgress f <*> LogProgress x = LogProgress $ \r -> f r `ap` x r
instance Monad LogProgress where
return = pure
LogProgress m >>= f = LogProgress $ \r -> m r >>= \x -> unLogProgress (f x) r
runLogProgress :: Verbosity -> LogProgress a -> NoCallStackIO a
runLogProgress verbosity (LogProgress m) =
foldProgress step_fn fail_fn return (m env)
where
env = LogEnv {
le_verbosity = verbosity,
le_context = []
}
step_fn :: LogMsg -> NoCallStackIO a -> NoCallStackIO a
step_fn doc go = do
putStrLn (render doc)
go
fail_fn :: Doc -> NoCallStackIO a
fail_fn doc = do
dieNoWrap verbosity (render doc)
warnProgress :: Doc -> LogProgress ()
warnProgress s = LogProgress $ \env ->
when (le_verbosity env >= normal) $
stepProgress $
hang (text "Warning:") 4 (formatMsg (le_context env) s)
infoProgress :: Doc -> LogProgress ()
infoProgress s = LogProgress $ \env ->
when (le_verbosity env >= verbose) $
stepProgress s
dieProgress :: Doc -> LogProgress a
dieProgress s = LogProgress $ \env ->
failProgress $
hang (text "Error:") 4 (formatMsg (le_context env) s)
formatMsg :: [CtxMsg] -> Doc -> Doc
formatMsg ctx doc = doc $$ vcat ctx
addProgressCtx :: CtxMsg -> LogProgress a -> LogProgress a
addProgressCtx s (LogProgress m) = LogProgress $ \env ->
m env { le_context = s : le_context env }