{-# LANGUAGE CPP #-}

-- | Provides the 'MonadEnv' typeclass.
--
-- @since 0.1
module Effects.System.Environment
  ( -- * Effect
    MonadEnv (..),
  )
where

import Control.Monad.Trans.Class (MonadTrans (lift))
import Control.Monad.Trans.Reader (ReaderT (runReaderT), ask)
import GHC.Stack (HasCallStack)
import System.Environment qualified as Env

{- ORMOLU_DISABLE -}

-- | Environment effects.
--
-- @since 0.1
class Monad m => MonadEnv m where
  -- | Lifted 'Env.getArgs'.
  --
  -- @since 0.1
  getArgs :: HasCallStack => m [String]

  -- | Lifted 'Env.getProgName'.
  --
  -- @since 0.1
  getProgName :: HasCallStack => m String

#if MIN_VERSION_base(4,17,0)
  -- | Lifted 'Env.executablePath'.
  --
  -- @since 0.1
  executablePath :: HasCallStack => Maybe (m (Maybe FilePath))
#endif

  -- | Lifted 'Env.getExecutablePath'.
  --
  -- @since 0.1
  getExecutablePath :: HasCallStack => m FilePath
  -- | Lifted 'Env.getEnv'.
  -- @since 0.1
  getEnv :: HasCallStack => String -> m String
  -- | Lifted 'Env.lookupEnv'.
  --
  -- @since 0.1
  lookupEnv :: HasCallStack => String -> m (Maybe String)
  -- | Lifted 'Env.setEnv'.
  --
  -- @since 0.1
  setEnv :: HasCallStack => String -> String -> m ()
  -- | Lifted 'Env.unsetEnv'.
  --
  -- @since 0.1
  unsetEnv :: HasCallStack => String -> m ()
  -- | Lifted 'Env.withArgs'.
  --
  -- @since 0.1
  withArgs :: HasCallStack => [String] -> m a -> m a
  -- | Lifted 'Env.withProgName'.
  --
  -- @since 0.1
  withProgName :: HasCallStack => String -> m a -> m a
  -- | Lifted 'Env.getEnvironment'.
  --
  -- @since 0.1
  getEnvironment :: HasCallStack => m [(String, String)]

-- | @since 0.1
instance MonadEnv IO where
  getArgs :: HasCallStack => IO [String]
getArgs = IO [String]
Env.getArgs
  {-# INLINEABLE getArgs #-}
  getProgName :: HasCallStack => IO String
getProgName = IO String
Env.getProgName
  {-# INLINEABLE getProgName #-}
#if MIN_VERSION_base(4,17,0)
  executablePath :: HasCallStack => Maybe (IO (Maybe String))
executablePath = Maybe (IO (Maybe String))
Env.executablePath
  {-# INLINEABLE executablePath #-}
#endif
  getExecutablePath :: HasCallStack => IO String
getExecutablePath = IO String
Env.getExecutablePath
  {-# INLINEABLE getExecutablePath #-}
  getEnv :: HasCallStack => String -> IO String
getEnv = String -> IO String
Env.getEnv
  {-# INLINEABLE getEnv #-}
  lookupEnv :: HasCallStack => String -> IO (Maybe String)
lookupEnv = String -> IO (Maybe String)
Env.lookupEnv
  {-# INLINEABLE lookupEnv #-}
  setEnv :: HasCallStack => String -> String -> IO ()
setEnv = String -> String -> IO ()
Env.setEnv
  {-# INLINEABLE setEnv #-}
  unsetEnv :: HasCallStack => String -> IO ()
unsetEnv = String -> IO ()
Env.unsetEnv
  {-# INLINEABLE unsetEnv #-}
  withArgs :: forall a. HasCallStack => [String] -> IO a -> IO a
withArgs = [String] -> IO a -> IO a
forall a. [String] -> IO a -> IO a
Env.withArgs
  {-# INLINEABLE withArgs #-}
  withProgName :: forall a. HasCallStack => String -> IO a -> IO a
withProgName = String -> IO a -> IO a
forall a. String -> IO a -> IO a
Env.withProgName
  {-# INLINEABLE withProgName #-}
  getEnvironment :: HasCallStack => IO [(String, String)]
getEnvironment = IO [(String, String)]
Env.getEnvironment
  {-# INLINEABLE getEnvironment #-}

-- | @since 0.1
instance MonadEnv m => MonadEnv (ReaderT env m) where
  getArgs :: HasCallStack => ReaderT env m [String]
getArgs = m [String] -> ReaderT env m [String]
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m [String]
forall (m :: * -> *). (MonadEnv m, HasCallStack) => m [String]
getArgs
  {-# INLINEABLE getArgs #-}
  getProgName :: HasCallStack => ReaderT env m String
getProgName = m String -> ReaderT env m String
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m String
forall (m :: * -> *). (MonadEnv m, HasCallStack) => m String
getProgName
  {-# INLINEABLE getProgName #-}
#if MIN_VERSION_base(4,17,0)
  executablePath :: HasCallStack => Maybe (ReaderT env m (Maybe String))
executablePath = (m (Maybe String) -> ReaderT env m (Maybe String))
-> Maybe (m (Maybe String)) -> Maybe (ReaderT env m (Maybe String))
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap m (Maybe String) -> ReaderT env m (Maybe String)
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift Maybe (m (Maybe String))
forall (m :: * -> *).
(MonadEnv m, HasCallStack) =>
Maybe (m (Maybe String))
executablePath
  {-# INLINEABLE executablePath #-}
#endif
  getExecutablePath :: HasCallStack => ReaderT env m String
getExecutablePath = m String -> ReaderT env m String
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m String
forall (m :: * -> *). (MonadEnv m, HasCallStack) => m String
getExecutablePath
  {-# INLINEABLE getExecutablePath #-}
  getEnv :: HasCallStack => String -> ReaderT env m String
getEnv = m String -> ReaderT env m String
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m String -> ReaderT env m String)
-> (String -> m String) -> String -> ReaderT env m String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> m String
forall (m :: * -> *).
(MonadEnv m, HasCallStack) =>
String -> m String
getEnv
  {-# INLINEABLE getEnv #-}
  lookupEnv :: HasCallStack => String -> ReaderT env m (Maybe String)
lookupEnv = m (Maybe String) -> ReaderT env m (Maybe String)
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe String) -> ReaderT env m (Maybe String))
-> (String -> m (Maybe String))
-> String
-> ReaderT env m (Maybe String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> m (Maybe String)
forall (m :: * -> *).
(MonadEnv m, HasCallStack) =>
String -> m (Maybe String)
lookupEnv
  {-# INLINEABLE lookupEnv #-}
  setEnv :: HasCallStack => String -> String -> ReaderT env m ()
setEnv String
x = m () -> ReaderT env m ()
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ReaderT env m ())
-> (String -> m ()) -> String -> ReaderT env m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> m ()
forall (m :: * -> *).
(MonadEnv m, HasCallStack) =>
String -> String -> m ()
setEnv String
x
  {-# INLINEABLE setEnv #-}
  unsetEnv :: HasCallStack => String -> ReaderT env m ()
unsetEnv = m () -> ReaderT env m ()
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ReaderT env m ())
-> (String -> m ()) -> String -> ReaderT env m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> m ()
forall (m :: * -> *). (MonadEnv m, HasCallStack) => String -> m ()
unsetEnv
  {-# INLINEABLE unsetEnv #-}
  withArgs :: forall a.
HasCallStack =>
[String] -> ReaderT env m a -> ReaderT env m a
withArgs [String]
x ReaderT env m a
m = ReaderT env m env
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask ReaderT env m env -> (env -> ReaderT env m a) -> ReaderT env m a
forall a b.
ReaderT env m a -> (a -> ReaderT env m b) -> ReaderT env m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \env
e -> m a -> ReaderT env m a
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ([String] -> m a -> m a
forall a. HasCallStack => [String] -> m a -> m a
forall (m :: * -> *) a.
(MonadEnv m, HasCallStack) =>
[String] -> m a -> m a
withArgs [String]
x (ReaderT env m a -> env -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT env m a
m env
e))
  {-# INLINEABLE withArgs #-}
  withProgName :: forall a.
HasCallStack =>
String -> ReaderT env m a -> ReaderT env m a
withProgName String
x ReaderT env m a
m = ReaderT env m env
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask ReaderT env m env -> (env -> ReaderT env m a) -> ReaderT env m a
forall a b.
ReaderT env m a -> (a -> ReaderT env m b) -> ReaderT env m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \env
e -> m a -> ReaderT env m a
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (String -> m a -> m a
forall a. HasCallStack => String -> m a -> m a
forall (m :: * -> *) a.
(MonadEnv m, HasCallStack) =>
String -> m a -> m a
withProgName String
x (ReaderT env m a -> env -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT env m a
m env
e))
  {-# INLINEABLE withProgName #-}
  getEnvironment :: HasCallStack => ReaderT env m [(String, String)]
getEnvironment = m [(String, String)] -> ReaderT env m [(String, String)]
forall (m :: * -> *) a. Monad m => m a -> ReaderT env m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m [(String, String)]
forall (m :: * -> *).
(MonadEnv m, HasCallStack) =>
m [(String, String)]
getEnvironment
  {-# INLINEABLE getEnvironment #-}

{- ORMOLU_ENABLE -}