module Neovim.RPC.FunctionCall (
acall,
acall',
scall,
scall',
atomically',
wait,
wait',
waitErr,
waitErr',
respond,
) where
import Neovim.Classes
import Neovim.Context
import Neovim.Plugin.IPC
import Neovim.Plugin.IPC.Internal
import Control.Applicative
import Control.Concurrent.STM
import Control.Monad.Reader as R
import Data.MessagePack
import Data.Monoid
import Data.Text
unexpectedException :: String -> err -> a
unexpectedException fn _ = error $
"Function threw an exception even though it was declared not to throw one: "
<> fn
withIgnoredException :: (Functor f, NvimObject result)
=> Text
-> f (Either err result)
-> f result
withIgnoredException fn = fmap (either ((unexpectedException . unpack) fn) id)
acall :: (NvimObject result)
=> Text
-> [Object]
-> Neovim r st (STM (Either Object result))
acall fn parameters = do
q <- eventQueue
mv <- liftIO newEmptyTMVarIO
timestamp <- liftIO getCurrentTime
atomically' . writeTQueue q . SomeMessage $ FunctionCall fn parameters mv timestamp
return $ convertObject <$> readTMVar mv
where
convertObject = \case
Left e -> Left e
Right o -> case fromObject o of
Left e -> Left (toObject e)
Right r -> Right r
acall' :: (NvimObject result)
=> Text
-> [Object]
-> Neovim r st (STM result)
acall' fn parameters = withIgnoredException fn <$> acall fn parameters
scall :: (NvimObject result)
=> Text
-> [Object]
-> Neovim r st (Either Object result)
scall fn parameters = acall fn parameters >>= atomically'
scall' :: NvimObject result => Text -> [Object] -> Neovim r st result
scall' fn = withIgnoredException fn . scall fn
atomically' :: (MonadIO io) => STM result -> io result
atomically' = liftIO . atomically
wait :: Neovim r st (STM result) -> Neovim r st result
wait = (=<<) atomically'
wait' :: Neovim r st (STM result) -> Neovim r st ()
wait' = void . wait
waitErr :: (Show e)
=> String
-> Neovim r st (STM (Either e result))
-> Neovim r st result
waitErr loc act = wait act >>= either (err . (loc++) . show) return
waitErr' :: (Show e)
=> String
-> Neovim r st (STM (Either e result))
-> Neovim r st ()
waitErr' loc = void . waitErr loc
respond :: (NvimObject result) => Request -> Either String result -> Neovim r st ()
respond Request{..} result = do
q <- eventQueue
atomically' . writeTQueue q . SomeMessage $ uncurry (Response reqId) oResult
where
oResult = case result of
Left e -> (toObject e, toObject ())
Right r -> (toObject (), toObject r)