{-# LANGUAGE CPP        #-}
{- |
Module      :  Neovim.Context
Description :  The Neovim context
Copyright   :  (c) Sebastian Witte
License     :  Apache-2.0

Maintainer  :  woozletoff@gmail.com
Stability   :  experimental

-}
module Neovim.Context (
    newUniqueFunctionName,

    Neovim,
    NeovimException(..),
    exceptionToDoc,
    FunctionMap,
    FunctionMapEntry,
    mkFunctionMap,
    runNeovim,
    err,
    errOnInvalidResult,
    restart,
    quit,

    ask,
    asks,
    get,
    gets,
    put,
    modify,

    Doc,
    AnsiStyle,
    docToText,

    throwError,
    module Control.Monad.IO.Class,
#if __GLASGOW_HASKELL__ <= 710
    module Control.Applicative,
#endif
    ) where


import           Neovim.Classes
import           Neovim.Context.Internal      (FunctionMap, FunctionMapEntry,
                                               Neovim, mkFunctionMap,
                                               newUniqueFunctionName, runNeovim)
import           Neovim.Exceptions            (NeovimException (..), exceptionToDoc)

import qualified Neovim.Context.Internal      as Internal

#if __GLASGOW_HASKELL__ <= 710
import           Control.Applicative
#endif

import           Control.Concurrent           (putMVar)
import           Control.Exception
import           Control.Monad.Except
import           Control.Monad.IO.Class
import           Control.Monad.Reader
import           Control.Monad.State
import           Data.MessagePack             (Object)


-- | @'throw'@ specialized to a 'Pretty' value.
err :: Doc AnsiStyle -> Neovim env a
err :: Doc AnsiStyle -> Neovim env a
err = NeovimException -> Neovim env a
forall a e. Exception e => e -> a
throw (NeovimException -> Neovim env a)
-> (Doc AnsiStyle -> NeovimException)
-> Doc AnsiStyle
-> Neovim env a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc AnsiStyle -> NeovimException
ErrorMessage


errOnInvalidResult :: (NvimObject o)
                   => Neovim env (Either NeovimException Object)
                   -> Neovim env o
errOnInvalidResult :: Neovim env (Either NeovimException Object) -> Neovim env o
errOnInvalidResult Neovim env (Either NeovimException Object)
a = Neovim env (Either NeovimException Object)
a Neovim env (Either NeovimException Object)
-> (Either NeovimException Object -> Neovim env o) -> Neovim env o
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Left NeovimException
o ->
        (Doc AnsiStyle -> Neovim env o
forall env a. Doc AnsiStyle -> Neovim env a
err (Doc AnsiStyle -> Neovim env o)
-> (NeovimException -> Doc AnsiStyle)
-> NeovimException
-> Neovim env o
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NeovimException -> Doc AnsiStyle
exceptionToDoc) NeovimException
o

    Right Object
o -> case Object -> Either (Doc AnsiStyle) o
forall o. NvimObject o => Object -> Either (Doc AnsiStyle) o
fromObject Object
o of
        Left Doc AnsiStyle
e ->
            Doc AnsiStyle -> Neovim env o
forall env a. Doc AnsiStyle -> Neovim env a
err Doc AnsiStyle
e

        Right o
x ->
            o -> Neovim env o
forall (m :: * -> *) a. Monad m => a -> m a
return o
x



-- | Initiate a restart of the plugin provider.
restart :: Neovim env ()
restart :: Neovim env ()
restart = IO () -> Neovim env ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim env ())
-> (MVar StateTransition -> IO ())
-> MVar StateTransition
-> Neovim env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MVar StateTransition -> StateTransition -> IO ())
-> StateTransition -> MVar StateTransition -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip MVar StateTransition -> StateTransition -> IO ()
forall a. MVar a -> a -> IO ()
putMVar StateTransition
Internal.Restart (MVar StateTransition -> Neovim env ())
-> Neovim env (MVar StateTransition) -> Neovim env ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Config env -> MVar StateTransition)
-> Neovim env (MVar StateTransition)
forall env a. (Config env -> a) -> Neovim env a
Internal.asks' Config env -> MVar StateTransition
forall env. Config env -> MVar StateTransition
Internal.transitionTo


-- | Initiate the termination of the plugin provider.
quit :: Neovim env ()
quit :: Neovim env ()
quit = IO () -> Neovim env ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim env ())
-> (MVar StateTransition -> IO ())
-> MVar StateTransition
-> Neovim env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MVar StateTransition -> StateTransition -> IO ())
-> StateTransition -> MVar StateTransition -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip MVar StateTransition -> StateTransition -> IO ()
forall a. MVar a -> a -> IO ()
putMVar StateTransition
Internal.Quit (MVar StateTransition -> Neovim env ())
-> Neovim env (MVar StateTransition) -> Neovim env ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Config env -> MVar StateTransition)
-> Neovim env (MVar StateTransition)
forall env a. (Config env -> a) -> Neovim env a
Internal.asks' Config env -> MVar StateTransition
forall env. Config env -> MVar StateTransition
Internal.transitionTo