-- | Provides an interface for 'ReaderT' rather than 'InputT'.
--
-- @since 0.8.4.0
module System.Console.Haskeline.ReaderT
    ( -- * ReaderT
      -- $reader
      toReaderT,
      fromReaderT,
      InputTEnv,
      mapInputTEnv,
    ) where

import Control.Monad.Trans.Reader (ReaderT (ReaderT, runReaderT))
import Data.IORef (IORef)
import System.Console.Haskeline.Command.KillRing (KillRing)
import System.Console.Haskeline.History (History)
import System.Console.Haskeline.InputT(
                         InputT(InputT),
                         Settings(
                            Settings,
                            autoAddHistory,
                            complete,
                            historyFile
                            )
                         )
import System.Console.Haskeline.Prefs (Prefs)
import System.Console.Haskeline.Term (RunTerm)


-- $reader
--
-- These functions expose the 'InputT' type in terms of ordinary 'ReaderT'.
-- This allows for easier integration with applications that do not use a
-- concrete monad transformer stack, or do not want to commit to having
-- 'InputT' in the stack.

-- | The abstract environment used by 'InputT', for 'ReaderT'
-- usage.
--
-- @since 0.8.4.0
data InputTEnv m = MkInputTEnv
    { forall (m :: * -> *). InputTEnv m -> RunTerm
runTerm :: RunTerm,
      forall (m :: * -> *). InputTEnv m -> IORef History
history :: IORef History,
      forall (m :: * -> *). InputTEnv m -> IORef KillRing
killRing :: IORef KillRing,
      forall (m :: * -> *). InputTEnv m -> Prefs
prefs :: Prefs,
      forall (m :: * -> *). InputTEnv m -> Settings m
settings :: Settings m
    }

-- | Maps the environment.
--
-- @since 0.8.4.0
mapInputTEnv :: (forall x. m x -> n x) -> InputTEnv m -> InputTEnv n
mapInputTEnv :: forall (m :: * -> *) (n :: * -> *).
(forall x. m x -> n x) -> InputTEnv m -> InputTEnv n
mapInputTEnv forall x. m x -> n x
f (MkInputTEnv RunTerm
t IORef History
h IORef KillRing
k Prefs
p Settings m
s) =
    MkInputTEnv
        { runTerm :: RunTerm
runTerm = RunTerm
t,
          history :: IORef History
history = IORef History
h,
          killRing :: IORef KillRing
killRing = IORef KillRing
k,
          prefs :: Prefs
prefs = Prefs
p,
          settings :: Settings n
settings = Settings n
settings'
        }
    where
        settings' :: Settings n
settings' = Settings
            { complete :: CompletionFunc n
complete = m (FilePath, [Completion]) -> n (FilePath, [Completion])
forall x. m x -> n x
f (m (FilePath, [Completion]) -> n (FilePath, [Completion]))
-> ((FilePath, FilePath) -> m (FilePath, [Completion]))
-> CompletionFunc n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Settings m -> (FilePath, FilePath) -> m (FilePath, [Completion])
forall (m :: * -> *). Settings m -> CompletionFunc m
complete Settings m
s,
              historyFile :: Maybe FilePath
historyFile = Settings m -> Maybe FilePath
forall (m :: * -> *). Settings m -> Maybe FilePath
historyFile Settings m
s,
              autoAddHistory :: Bool
autoAddHistory = Settings m -> Bool
forall (m :: * -> *). Settings m -> Bool
autoAddHistory Settings m
s
            }

-- | Maps an 'InputT' to a 'ReaderT'. Useful for lifting 'InputT' functions
-- into some other reader-like monad.
--
-- __Examples:__
--
-- @
-- import System.Console.Haskeline qualified as H
--
-- runApp :: ReaderT (InputTEnv IO) IO ()
-- runApp = do
--   input <- toReaderT (H.getInputLine "Enter your name: ")
--   ...
-- @
--
-- @
-- -- MTL-style polymorphism
-- class MonadHaskeline m where
--   getInputLine :: String -> m (Maybe String)
--
-- -- AppT is the core type over ReaderT.
-- instance MonadHaskeline (AppT m) where
--   getInputLine = lift . toReaderT . H.getInputLine
--
-- runApp :: (MonadHaskeline m) => m ()
-- runApp = do
--   input <- getInputLine "Enter your name: "
--   ...
-- @
--
-- @since 0.8.4.0
toReaderT :: InputT m a -> ReaderT (InputTEnv m) m a
toReaderT :: forall (m :: * -> *) a. InputT m a -> ReaderT (InputTEnv m) m a
toReaderT (InputT ReaderT
  RunTerm
  (ReaderT
     (IORef History)
     (ReaderT
        (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
  a
rdr) = (InputTEnv m -> m a) -> ReaderT (InputTEnv m) m a
(InputTEnv m -> m a) -> ReaderT (InputTEnv m) m a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT ((InputTEnv m -> m a) -> ReaderT (InputTEnv m) m a)
-> (InputTEnv m -> m a) -> ReaderT (InputTEnv m) m a
forall a b. (a -> b) -> a -> b
$ \InputTEnv m
st ->
    Settings m -> ReaderT (Settings m) m a -> m a
forall env (m :: * -> *) a. env -> ReaderT env m a -> m a
usingReaderT (InputTEnv m -> Settings m
forall (m :: * -> *). InputTEnv m -> Settings m
settings InputTEnv m
st)
        (ReaderT (Settings m) m a -> m a)
-> (ReaderT
      RunTerm
      (ReaderT
         (IORef History)
         (ReaderT
            (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
      a
    -> ReaderT (Settings m) m a)
-> ReaderT
     RunTerm
     (ReaderT
        (IORef History)
        (ReaderT
           (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
     a
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Prefs
-> ReaderT Prefs (ReaderT (Settings m) m) a
-> ReaderT (Settings m) m a
forall env (m :: * -> *) a. env -> ReaderT env m a -> m a
usingReaderT (InputTEnv m -> Prefs
forall (m :: * -> *). InputTEnv m -> Prefs
prefs InputTEnv m
st)
        (ReaderT Prefs (ReaderT (Settings m) m) a
 -> ReaderT (Settings m) m a)
-> (ReaderT
      RunTerm
      (ReaderT
         (IORef History)
         (ReaderT
            (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
      a
    -> ReaderT Prefs (ReaderT (Settings m) m) a)
-> ReaderT
     RunTerm
     (ReaderT
        (IORef History)
        (ReaderT
           (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
     a
-> ReaderT (Settings m) m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef KillRing
-> ReaderT
     (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a
-> ReaderT Prefs (ReaderT (Settings m) m) a
forall env (m :: * -> *) a. env -> ReaderT env m a -> m a
usingReaderT (InputTEnv m -> IORef KillRing
forall (m :: * -> *). InputTEnv m -> IORef KillRing
killRing InputTEnv m
st)
        (ReaderT
   (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a
 -> ReaderT Prefs (ReaderT (Settings m) m) a)
-> (ReaderT
      RunTerm
      (ReaderT
         (IORef History)
         (ReaderT
            (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
      a
    -> ReaderT
         (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a)
-> ReaderT
     RunTerm
     (ReaderT
        (IORef History)
        (ReaderT
           (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
     a
-> ReaderT Prefs (ReaderT (Settings m) m) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef History
-> ReaderT
     (IORef History)
     (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
     a
-> ReaderT
     (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a
forall env (m :: * -> *) a. env -> ReaderT env m a -> m a
usingReaderT (InputTEnv m -> IORef History
forall (m :: * -> *). InputTEnv m -> IORef History
history InputTEnv m
st)
        (ReaderT
   (IORef History)
   (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
   a
 -> ReaderT
      (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a)
-> (ReaderT
      RunTerm
      (ReaderT
         (IORef History)
         (ReaderT
            (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
      a
    -> ReaderT
         (IORef History)
         (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
         a)
-> ReaderT
     RunTerm
     (ReaderT
        (IORef History)
        (ReaderT
           (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
     a
-> ReaderT
     (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RunTerm
-> ReaderT
     RunTerm
     (ReaderT
        (IORef History)
        (ReaderT
           (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
     a
-> ReaderT
     (IORef History)
     (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
     a
forall env (m :: * -> *) a. env -> ReaderT env m a -> m a
usingReaderT (InputTEnv m -> RunTerm
forall (m :: * -> *). InputTEnv m -> RunTerm
runTerm InputTEnv m
st)
        (ReaderT
   RunTerm
   (ReaderT
      (IORef History)
      (ReaderT
         (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
   a
 -> m a)
-> ReaderT
     RunTerm
     (ReaderT
        (IORef History)
        (ReaderT
           (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
     a
-> m a
forall a b. (a -> b) -> a -> b
$ ReaderT
  RunTerm
  (ReaderT
     (IORef History)
     (ReaderT
        (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
  a
rdr

-- | Maps a 'ReaderT' to an 'InputT'. Allows defining an application in terms
-- of 'ReaderT'.
--
-- __Examples:__
--
-- @
-- import System.Console.Haskeline qualified as H
--
-- -- Could be generalized to MonadReader, effects libraries.
-- runApp :: ReaderT (InputTEnv IO) IO ()
--
-- main :: IO ()
-- main = H.runInputT H.defaultSettings $ fromReaderT runApp
-- @
--
-- @since 0.8.4.0
fromReaderT :: ReaderT (InputTEnv m) m a -> InputT m a
fromReaderT :: forall (m :: * -> *) a. ReaderT (InputTEnv m) m a -> InputT m a
fromReaderT (ReaderT InputTEnv m -> m a
onEnv) = ReaderT
  RunTerm
  (ReaderT
     (IORef History)
     (ReaderT
        (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
  a
-> InputT m a
ReaderT
  RunTerm
  (ReaderT
     (IORef History)
     (ReaderT
        (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
  a
-> InputT m a
forall (m :: * -> *) a.
ReaderT
  RunTerm
  (ReaderT
     (IORef History)
     (ReaderT
        (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
  a
-> InputT m a
InputT (ReaderT
   RunTerm
   (ReaderT
      (IORef History)
      (ReaderT
         (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
   a
 -> InputT m a)
-> ReaderT
     RunTerm
     (ReaderT
        (IORef History)
        (ReaderT
           (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
     a
-> InputT m a
forall a b. (a -> b) -> a -> b
$ (RunTerm
 -> ReaderT
      (IORef History)
      (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
      a)
-> ReaderT
     RunTerm
     (ReaderT
        (IORef History)
        (ReaderT
           (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
     a
(RunTerm
 -> ReaderT
      (IORef History)
      (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
      a)
-> ReaderT
     RunTerm
     (ReaderT
        (IORef History)
        (ReaderT
           (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
     a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT
    ((RunTerm
  -> ReaderT
       (IORef History)
       (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
       a)
 -> ReaderT
      RunTerm
      (ReaderT
         (IORef History)
         (ReaderT
            (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
      a)
-> (RunTerm
    -> ReaderT
         (IORef History)
         (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
         a)
-> ReaderT
     RunTerm
     (ReaderT
        (IORef History)
        (ReaderT
           (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m))))
     a
forall a b. (a -> b) -> a -> b
$ \RunTerm
runTerm' -> (IORef History
 -> ReaderT
      (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a)
-> ReaderT
     (IORef History)
     (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
     a
(IORef History
 -> ReaderT
      (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a)
-> ReaderT
     (IORef History)
     (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
     a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT
    ((IORef History
  -> ReaderT
       (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a)
 -> ReaderT
      (IORef History)
      (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
      a)
-> (IORef History
    -> ReaderT
         (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a)
-> ReaderT
     (IORef History)
     (ReaderT (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)))
     a
forall a b. (a -> b) -> a -> b
$ \IORef History
history' -> (IORef KillRing -> ReaderT Prefs (ReaderT (Settings m) m) a)
-> ReaderT
     (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a
(IORef KillRing -> ReaderT Prefs (ReaderT (Settings m) m) a)
-> ReaderT
     (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT
    ((IORef KillRing -> ReaderT Prefs (ReaderT (Settings m) m) a)
 -> ReaderT
      (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a)
-> (IORef KillRing -> ReaderT Prefs (ReaderT (Settings m) m) a)
-> ReaderT
     (IORef KillRing) (ReaderT Prefs (ReaderT (Settings m) m)) a
forall a b. (a -> b) -> a -> b
$ \IORef KillRing
killRing' -> (Prefs -> ReaderT (Settings m) m a)
-> ReaderT Prefs (ReaderT (Settings m) m) a
(Prefs -> ReaderT (Settings m) m a)
-> ReaderT Prefs (ReaderT (Settings m) m) a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT
    ((Prefs -> ReaderT (Settings m) m a)
 -> ReaderT Prefs (ReaderT (Settings m) m) a)
-> (Prefs -> ReaderT (Settings m) m a)
-> ReaderT Prefs (ReaderT (Settings m) m) a
forall a b. (a -> b) -> a -> b
$ \Prefs
prefs' -> (Settings m -> m a) -> ReaderT (Settings m) m a
(Settings m -> m a) -> ReaderT (Settings m) m a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT
    ((Settings m -> m a) -> ReaderT (Settings m) m a)
-> (Settings m -> m a) -> ReaderT (Settings m) m a
forall a b. (a -> b) -> a -> b
$ \Settings m
settings' ->
        InputTEnv m -> m a
onEnv (RunTerm
-> IORef History
-> IORef KillRing
-> Prefs
-> Settings m
-> InputTEnv m
forall (m :: * -> *).
RunTerm
-> IORef History
-> IORef KillRing
-> Prefs
-> Settings m
-> InputTEnv m
MkInputTEnv RunTerm
runTerm' IORef History
history' IORef KillRing
killRing' Prefs
prefs' Settings m
settings')

usingReaderT :: env -> ReaderT env m a -> m a
usingReaderT :: forall env (m :: * -> *) a. env -> ReaderT env m a -> m a
usingReaderT = (ReaderT env m a -> env -> m a) -> env -> ReaderT env m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT env m a -> env -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT