{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} module GLuaFixer.Effects.Logging where import Control.Monad.IO.Class (liftIO) import Data.Maybe (isJust) import Effectful (Dispatch (Dynamic), DispatchOf, Eff, Effect, IOE, (:>)) import Effectful.Dispatch.Dynamic (interpret, send) import qualified Effectful.Environment as Env import GLuaFixer.LintMessage (LintMessage, LogFormat (..), LogFormatChoice (..), formatLintMessage) import System.IO (hPutStrLn, stderr) -- | The effect for emitting lint messages to the right channel data Logging :: Effect where -- | Emit a single lint message in the given format EmitLintMessage :: LogFormat -> LintMessage -> Logging m () -- | Find out which logging format to use GetLogFormat :: LogFormatChoice -> Logging m LogFormat -- | Print a string in stdout PutStrLnStdOut :: String -> Logging m () -- | Print a string in stdout PutStrStdOut :: String -> Logging m () -- | Print a string in stderr PutStrLnStdError :: String -> Logging m () type instance DispatchOf Logging = Dynamic putStrLnStdError :: Logging :> es => String -> Eff es () putStrLnStdError str = send $ PutStrLnStdError str putStrStdOut :: Logging :> es => String -> Eff es () putStrStdOut str = send $ PutStrStdOut str putStrLnStdOut :: Logging :> es => String -> Eff es () putStrLnStdOut str = send $ PutStrLnStdOut str getLogFormat :: Logging :> es => LogFormatChoice -> Eff es LogFormat getLogFormat logFormatChoice = send $ GetLogFormat logFormatChoice emitLintMessage :: Logging :> es => LogFormat -> LintMessage -> Eff es () emitLintMessage logFormat lintMessage = send $ EmitLintMessage logFormat lintMessage -- | Run the logging in IO runLoggingIO :: (IOE :> es, Env.Environment :> es) => Eff (Logging : es) a -> Eff es a runLoggingIO = interpret $ \_ -> \case EmitLintMessage logFormat lintMessage -> case logFormat of StandardLogFormat -> liftIO $ putStrLn $ formatLintMessage StandardLogFormat lintMessage GithubLogFormat -> do liftIO $ putStrLn $ formatLintMessage GithubLogFormat lintMessage liftIO $ putStrLn $ formatLintMessage StandardLogFormat lintMessage GetLogFormat (LogFormatChoice format) -> pure format GetLogFormat AutoLogFormatChoice -> do actionsExists <- isJust <$> Env.lookupEnv "GITHUB_ACTIONS" workflowExists <- isJust <$> Env.lookupEnv "GITHUB_WORKFLOW" pure $ if actionsExists && workflowExists then GithubLogFormat else StandardLogFormat PutStrLnStdOut str -> liftIO $ putStrLn str PutStrStdOut str -> liftIO $ putStr str PutStrLnStdError str -> liftIO $ hPutStrLn stderr str runLoggingPureNoop :: Eff (Logging : es) a -> Eff es a runLoggingPureNoop = interpret $ \_ -> \case EmitLintMessage _ _ -> pure () GetLogFormat (LogFormatChoice format) -> pure format GetLogFormat AutoLogFormatChoice -> pure StandardLogFormat PutStrLnStdOut _ -> pure () PutStrStdOut _ -> pure () PutStrLnStdError _ -> pure ()