{-# LANGUAGE FlexibleContexts #-}

{- |
Module                  : Iris.Colour.Formatting
Copyright               : (c) 2022 Dmitrii Kovanikov
SPDX-License-Identifier : MPL-2.0
Maintainer              : Dmitrii Kovanikov <kovanikov@gmail.com>
Stability               : Experimental
Portability             : Portable

Helper functions to print with colouring.

@since 0.0.0.0
-}
module Iris.Colour.Formatting (
    putStdoutColouredLn,
    putStderrColouredLn,
    putStdoutColoured,
    putStderrColoured,
) where

import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.Reader (MonadReader)
import Data.Text (Text)
import qualified Data.Text.IO as T
import System.IO (stderr)

import Iris.Colour.Mode (ColourMode (..))
import Iris.Env (CliEnv (..), asksCliEnv)

import qualified Data.Text.IO as TIO

{- | Print 'Text' to 'System.IO.stdout' by providing a custom
formatting function.

This works especially well with the @colourista@ package:

@
'putStdoutColouredLn'
    (Colourista.formatWith [Colourista.bold, Colourista.green])
    "my message"
@

@since 0.0.0.0
-}
putStdoutColouredLn
    :: ( MonadReader (CliEnv cmd appEnv) m
       , MonadIO m
       )
    => (Text -> Text)
    -> Text
    -> m ()
putStdoutColouredLn :: forall cmd appEnv (m :: * -> *).
(MonadReader (CliEnv cmd appEnv) m, MonadIO m) =>
(Text -> Text) -> Text -> m ()
putStdoutColouredLn Text -> Text
formatWithColour Text
str = do
    ColourMode
colourMode <- forall cmd appEnv (m :: * -> *) field.
MonadReader (CliEnv cmd appEnv) m =>
(CliEnv cmd appEnv -> field) -> m field
asksCliEnv forall cmd appEnv. CliEnv cmd appEnv -> ColourMode
cliEnvStdoutColourMode
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Text -> IO ()
T.putStrLn forall a b. (a -> b) -> a -> b
$ case ColourMode
colourMode of
        ColourMode
DisableColour -> Text
str
        ColourMode
EnableColour -> Text -> Text
formatWithColour Text
str

{- | Print 'Text' to 'System.IO.stderr' by providing a custom
formatting function.

This works especially well with the @colourista@ package:

@
'putStderrColouredLn'
    (Colourista.formatWith [Colourista.bold, Colourista.green])
    "my message"
@

@since 0.0.0.0
-}
putStderrColouredLn
    :: ( MonadReader (CliEnv cmd appEnv) m
       , MonadIO m
       )
    => (Text -> Text)
    -> Text
    -> m ()
putStderrColouredLn :: forall cmd appEnv (m :: * -> *).
(MonadReader (CliEnv cmd appEnv) m, MonadIO m) =>
(Text -> Text) -> Text -> m ()
putStderrColouredLn Text -> Text
formatWithColour Text
str = do
    ColourMode
colourMode <- forall cmd appEnv (m :: * -> *) field.
MonadReader (CliEnv cmd appEnv) m =>
(CliEnv cmd appEnv -> field) -> m field
asksCliEnv forall cmd appEnv. CliEnv cmd appEnv -> ColourMode
cliEnvStderrColourMode
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Handle -> Text -> IO ()
T.hPutStrLn Handle
stderr forall a b. (a -> b) -> a -> b
$ case ColourMode
colourMode of
        ColourMode
DisableColour -> Text
str
        ColourMode
EnableColour -> Text -> Text
formatWithColour Text
str

{- | Print 'Text' to 'System.IO.stdout' by providing a custom
formatting function. Doesn't breaks output line that differs from
`putStdoutColouredLn`

This works especially well with the @colourista@ package:

@
'putStdoutColoured'
    (Colourista.formatWith [Colourista.bold, Colourista.green])
    "my message"
@

@since 0.1.0.0
-}
putStdoutColoured
    :: ( MonadReader (CliEnv cmd appEnv) m
       , MonadIO m
       )
    => (Text -> Text)
    -> Text
    -> m ()
putStdoutColoured :: forall cmd appEnv (m :: * -> *).
(MonadReader (CliEnv cmd appEnv) m, MonadIO m) =>
(Text -> Text) -> Text -> m ()
putStdoutColoured Text -> Text
formatWithColour Text
str = do
    ColourMode
colourMode <- forall cmd appEnv (m :: * -> *) field.
MonadReader (CliEnv cmd appEnv) m =>
(CliEnv cmd appEnv -> field) -> m field
asksCliEnv forall cmd appEnv. CliEnv cmd appEnv -> ColourMode
cliEnvStdoutColourMode
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Text -> IO ()
TIO.putStr forall a b. (a -> b) -> a -> b
$ case ColourMode
colourMode of
        ColourMode
DisableColour -> Text
str
        ColourMode
EnableColour -> Text -> Text
formatWithColour Text
str

{- | Print 'Text' to 'System.IO.stderr' by providing a custom
formatting function. Doesn't breaks output line that differs from
`putStderrColouredLn`

This works especially well with the @colourista@ package:

@
'putStderrColoured'
    (Colourista.formatWith [Colourista.bold, Colourista.green])
    "my message"
@

@since 0.1.0.0
-}
putStderrColoured
    :: ( MonadReader (CliEnv cmd appEnv) m
       , MonadIO m
       )
    => (Text -> Text)
    -> Text
    -> m ()
putStderrColoured :: forall cmd appEnv (m :: * -> *).
(MonadReader (CliEnv cmd appEnv) m, MonadIO m) =>
(Text -> Text) -> Text -> m ()
putStderrColoured Text -> Text
formatWithColour Text
str = do
    ColourMode
colourMode <- forall cmd appEnv (m :: * -> *) field.
MonadReader (CliEnv cmd appEnv) m =>
(CliEnv cmd appEnv -> field) -> m field
asksCliEnv forall cmd appEnv. CliEnv cmd appEnv -> ColourMode
cliEnvStderrColourMode
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Handle -> Text -> IO ()
TIO.hPutStr Handle
stderr forall a b. (a -> b) -> a -> b
$ case ColourMode
colourMode of
        ColourMode
DisableColour -> Text
str
        ColourMode
EnableColour -> Text -> Text
formatWithColour Text
str