module Ribosome.Config.Setting where

import Ribosome.Control.Monad.Ribo (MonadRibo, Nvim, NvimE, pluginName)
import Ribosome.Data.Setting (Setting(Setting))
import Ribosome.Data.SettingError (SettingError)
import qualified Ribosome.Data.SettingError as SettingError (SettingError(..))
import Ribosome.Msgpack.Decode (MsgpackDecode)
import Ribosome.Msgpack.Encode (MsgpackEncode(toMsgpack))
import Ribosome.Nvim.Api.IO
import Ribosome.Nvim.Api.RpcCall (RpcError)
import qualified Ribosome.Nvim.Api.RpcCall as RpcError (RpcError(..))

settingVariableName ::
  (MonadRibo m) =>
  Setting a ->
  m Text
settingVariableName :: Setting a -> m Text
settingVariableName (Setting Text
settingName Bool
False Maybe a
_) =
  Text -> m Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
settingName
settingVariableName (Setting Text
settingName Bool
True Maybe a
_) = do
  Text
name <- m Text
forall (m :: * -> *). MonadRibo m => m Text
pluginName
  return $ Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
settingName

settingRaw :: (MonadRibo m, Nvim m, MsgpackDecode a, MonadDeepError e RpcError m) => Setting a -> m a
settingRaw :: Setting a -> m a
settingRaw Setting a
s =
  Text -> m a
forall (m :: * -> *) e a.
(Nvim m, MonadDeepError e RpcError m, MsgpackDecode a) =>
Text -> m a
vimGetVar (Text -> m a) -> m Text -> m a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Setting a -> m Text
forall (m :: * -> *) a. MonadRibo m => Setting a -> m Text
settingVariableName Setting a
s

setting ::
   e m a.
  NvimE e m =>
  MonadRibo m =>
  MonadDeepError e SettingError m =>
  MsgpackDecode a =>
  Setting a ->
  m a
setting :: Setting a -> m a
setting s :: Setting a
s@(Setting Text
n Bool
_ Maybe a
fallback') =
  (RpcError -> m a) -> m a -> m a
forall e' e (m :: * -> *) a.
MonadDeepError e e' m =>
(e' -> m a) -> m a -> m a
catchAt RpcError -> m a
handleError (m a -> m a) -> m a -> m a
forall a b. (a -> b) -> a -> b
$ Setting a -> m a
forall (m :: * -> *) a e.
(MonadRibo m, Nvim m, MsgpackDecode a,
 MonadDeepError e RpcError m) =>
Setting a -> m a
settingRaw Setting a
s
  where
    handleError :: RpcError -> m a
handleError (RpcError.Nvim RpcCall
_ NeovimException
_) =
      case Maybe a
fallback' of
        (Just a
fb) -> a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
fb
        Maybe a
Nothing -> SettingError -> m a
forall e e' (m :: * -> *) a. MonadDeepError e e' m => e' -> m a
throwHoist (SettingError -> m a) -> SettingError -> m a
forall a b. (a -> b) -> a -> b
$ Text -> SettingError
SettingError.Unset Text
n
    handleError RpcError
a =
      RpcError -> m a
forall e e' (m :: * -> *) a. MonadDeepError e e' m => e' -> m a
throwHoist RpcError
a

data SettingOrError =
  Sett SettingError
  |
  Rpc RpcError

deepPrisms ''SettingOrError

settingOr ::
  (MonadIO m, Nvim m, MonadRibo m, MsgpackDecode a) =>
  a ->
  Setting a ->
  m a
settingOr :: a -> Setting a -> m a
settingOr a
a =
  (a -> Either SettingOrError a -> a
forall b a. b -> Either a b -> b
fromRight a
a (Either SettingOrError a -> a)
-> m (Either SettingOrError a) -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) (m (Either SettingOrError a) -> m a)
-> (Setting a -> m (Either SettingOrError a)) -> Setting a -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExceptT SettingOrError m a -> m (Either SettingOrError a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT SettingOrError m a -> m (Either SettingOrError a))
-> (Setting a -> ExceptT SettingOrError m a)
-> Setting a
-> m (Either SettingOrError a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e (m :: * -> *) a.
(NvimE e m, MonadRibo m, MonadDeepError e SettingError m,
 MsgpackDecode a) =>
Setting a -> m a
forall (m :: * -> *) a.
(NvimE SettingOrError m, MonadRibo m,
 MonadDeepError SettingOrError SettingError m, MsgpackDecode a) =>
Setting a -> m a
setting @SettingOrError

settingMaybe ::
  (MonadIO m, Nvim m, MonadRibo m, MsgpackDecode a) =>
  Setting a ->
  m (Maybe a)
settingMaybe :: Setting a -> m (Maybe a)
settingMaybe =
  (Either SettingOrError a -> Maybe a
forall l r. Either l r -> Maybe r
rightToMaybe (Either SettingOrError a -> Maybe a)
-> m (Either SettingOrError a) -> m (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) (m (Either SettingOrError a) -> m (Maybe a))
-> (Setting a -> m (Either SettingOrError a))
-> Setting a
-> m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExceptT SettingOrError m a -> m (Either SettingOrError a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT SettingOrError m a -> m (Either SettingOrError a))
-> (Setting a -> ExceptT SettingOrError m a)
-> Setting a
-> m (Either SettingOrError a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e (m :: * -> *) a.
(NvimE e m, MonadRibo m, MonadDeepError e SettingError m,
 MsgpackDecode a) =>
Setting a -> m a
forall (m :: * -> *) a.
(NvimE SettingOrError m, MonadRibo m,
 MonadDeepError SettingOrError SettingError m, MsgpackDecode a) =>
Setting a -> m a
setting @SettingOrError

updateSetting ::
  (MonadRibo m, Nvim m, MonadDeepError e RpcError m, MsgpackEncode a) =>
  Setting a ->
  a ->
  m ()
updateSetting :: Setting a -> a -> m ()
updateSetting Setting a
s a
a =
  (Text -> Object -> m ()
forall (m :: * -> *) e a.
(Nvim m, MonadDeepError e RpcError m, MsgpackDecode a) =>
Text -> Object -> m a
`vimSetVar` a -> Object
forall a. MsgpackEncode a => a -> Object
toMsgpack a
a) (Text -> m ()) -> m Text -> m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Setting a -> m Text
forall (m :: * -> *) a. MonadRibo m => Setting a -> m Text
settingVariableName Setting a
s