{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module Neovim.Plugin (
startPluginThreads,
wrapPlugin,
NeovimPlugin,
Plugin (..),
Synchronous (..),
CommandOption (..),
addAutocmd,
registerPlugin,
registerFunctionality,
getProviderName,
) where
import Neovim.API.String
( nvim_err_writeln, nvim_get_api_info, vim_call_function )
import Neovim.Classes
( (<+>),
Doc,
AnsiStyle,
Pretty(pretty),
NvimObject(toObject, fromObject),
Dictionary,
(+:) )
import Neovim.Context
( MonadIO(liftIO),
NeovimException,
newUniqueFunctionName,
runNeovim,
FunctionMapEntry,
Neovim,
err )
import Neovim.Context.Internal (
FunctionType (..),
runNeovimInternal,
)
import qualified Neovim.Context.Internal as Internal
import Neovim.Plugin.Classes
( HasFunctionName(nvimMethod),
FunctionName(..),
NeovimEventId(NeovimEventId),
Synchronous(..),
CommandOption(..),
CommandOptions(getCommandOptions),
AutocmdOptions(AutocmdOptions),
FunctionalityDescription(..),
NvimMethod(..) )
import Neovim.Plugin.IPC.Classes
( Notification(Notification),
Request(Request),
Message(fromMessage),
SomeMessage,
readSomeMessage )
import Neovim.Plugin.Internal
( NeovimPlugin(..),
Plugin(..),
getDescription,
getFunction,
wrapPlugin )
import Neovim.RPC.FunctionCall ( respond )
import Control.Monad (foldM, void)
import Data.Foldable (forM_)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Either (rights)
import Data.MessagePack ( Object )
import Data.Text (Text)
import Data.Traversable (forM)
import System.Log.Logger ( debugM, errorM )
import UnliftIO.Async (Async, async, race)
import UnliftIO.Concurrent (threadDelay)
import UnliftIO.Exception (SomeException, catch, try)
import UnliftIO.STM
( TVar,
putTMVar,
takeTMVar,
tryReadTMVar,
modifyTVar,
TQueue,
atomically,
newTQueueIO,
newTVarIO,
readTVarIO )
import Prelude
logger :: String
logger :: String
logger = String
"Neovim.Plugin"
startPluginThreads ::
Internal.Config () ->
[Neovim () NeovimPlugin] ->
IO (Either (Doc AnsiStyle) ([FunctionMapEntry], [Async ()]))
startPluginThreads :: Config ()
-> [Neovim () NeovimPlugin]
-> IO (Either (Doc AnsiStyle) ([FunctionMapEntry], [Async ()]))
startPluginThreads Config ()
cfg = (([FunctionMapEntry], [Async ()])
-> IO ([FunctionMapEntry], [Async ()]))
-> Config ()
-> Neovim () ([FunctionMapEntry], [Async ()])
-> IO (Either (Doc AnsiStyle) ([FunctionMapEntry], [Async ()]))
forall a env.
(a -> IO a)
-> Config env -> Neovim env a -> IO (Either (Doc AnsiStyle) a)
runNeovimInternal ([FunctionMapEntry], [Async ()])
-> IO ([FunctionMapEntry], [Async ()])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Config ()
cfg (Neovim () ([FunctionMapEntry], [Async ()])
-> IO (Either (Doc AnsiStyle) ([FunctionMapEntry], [Async ()])))
-> ([Neovim () NeovimPlugin]
-> Neovim () ([FunctionMapEntry], [Async ()]))
-> [Neovim () NeovimPlugin]
-> IO (Either (Doc AnsiStyle) ([FunctionMapEntry], [Async ()]))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([FunctionMapEntry], [Async ()])
-> Neovim () NeovimPlugin
-> Neovim () ([FunctionMapEntry], [Async ()]))
-> ([FunctionMapEntry], [Async ()])
-> [Neovim () NeovimPlugin]
-> Neovim () ([FunctionMapEntry], [Async ()])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM ([FunctionMapEntry], [Async ()])
-> Neovim () NeovimPlugin
-> Neovim () ([FunctionMapEntry], [Async ()])
go ([], [])
where
go ::
([FunctionMapEntry], [Async ()]) ->
Neovim () NeovimPlugin ->
Neovim () ([FunctionMapEntry], [Async ()])
go :: ([FunctionMapEntry], [Async ()])
-> Neovim () NeovimPlugin
-> Neovim () ([FunctionMapEntry], [Async ()])
go ([FunctionMapEntry]
es, [Async ()]
tids) Neovim () NeovimPlugin
iop = do
NeovimPlugin Plugin env
p <- Neovim () NeovimPlugin
iop
([FunctionMapEntry]
es', Async ()
tid) <- Plugin env -> Neovim () ([FunctionMapEntry], Async ())
forall env anyEnv.
Plugin env -> Neovim anyEnv ([FunctionMapEntry], Async ())
registerStatefulFunctionality Plugin env
p
([FunctionMapEntry], [Async ()])
-> Neovim () ([FunctionMapEntry], [Async ()])
forall a. a -> Neovim () a
forall (m :: * -> *) a. Monad m => a -> m a
return ([FunctionMapEntry]
es [FunctionMapEntry] -> [FunctionMapEntry] -> [FunctionMapEntry]
forall a. [a] -> [a] -> [a]
++ [FunctionMapEntry]
es', Async ()
tid Async () -> [Async ()] -> [Async ()]
forall a. a -> [a] -> [a]
: [Async ()]
tids)
registerWithNeovim :: FunctionalityDescription -> Neovim anyEnv Bool
registerWithNeovim :: forall anyEnv. FunctionalityDescription -> Neovim anyEnv Bool
registerWithNeovim = \case
func :: FunctionalityDescription
func@(Function (F Text
functionName) Synchronous
s) -> do
Either String Int
pName <- Neovim anyEnv (Either String Int)
forall env. Neovim env (Either String Int)
getProviderName
let (String
defineFunction, Object
host) =
(String -> (String, Object))
-> (Int -> (String, Object))
-> Either String Int
-> (String, Object)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either
(\String
n -> (String
"remote#define#FunctionOnHost", String -> Object
forall o. NvimObject o => o -> Object
toObject String
n))
(\Int
c -> (String
"remote#define#FunctionOnChannel", Int -> Object
forall o. NvimObject o => o -> Object
toObject Int
c))
Either String Int
pName
reportError :: NeovimException -> Neovim anyEnv Bool
reportError (NeovimException
e :: NeovimException) = do
IO () -> Neovim anyEnv ()
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim anyEnv ())
-> (String -> IO ()) -> String -> Neovim anyEnv ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> IO ()
errorM String
logger (String -> Neovim anyEnv ()) -> String -> Neovim anyEnv ()
forall a b. (a -> b) -> a -> b
$
String
"Failed to register function: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
functionName String -> String -> String
forall a. [a] -> [a] -> [a]
++ NeovimException -> String
forall a. Show a => a -> String
show NeovimException
e
Bool -> Neovim anyEnv Bool
forall a. a -> Neovim anyEnv a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
logSuccess :: Neovim anyEnv Bool
logSuccess = do
IO () -> Neovim anyEnv ()
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim anyEnv ())
-> (String -> IO ()) -> String -> Neovim anyEnv ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> IO ()
debugM String
logger (String -> Neovim anyEnv ()) -> String -> Neovim anyEnv ()
forall a b. (a -> b) -> a -> b
$
String
"Registered function: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
functionName
Bool -> Neovim anyEnv Bool
forall a. a -> Neovim anyEnv a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
(Neovim anyEnv Bool
-> (NeovimException -> Neovim anyEnv Bool) -> Neovim anyEnv Bool)
-> (NeovimException -> Neovim anyEnv Bool)
-> Neovim anyEnv Bool
-> Neovim anyEnv Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip Neovim anyEnv Bool
-> (NeovimException -> Neovim anyEnv Bool) -> Neovim anyEnv Bool
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> (e -> m a) -> m a
catch NeovimException -> Neovim anyEnv Bool
reportError (Neovim anyEnv Bool -> Neovim anyEnv Bool)
-> Neovim anyEnv Bool -> Neovim anyEnv Bool
forall a b. (a -> b) -> a -> b
$ do
Neovim anyEnv Object -> Neovim anyEnv ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Neovim anyEnv Object -> Neovim anyEnv ())
-> Neovim anyEnv Object -> Neovim anyEnv ()
forall a b. (a -> b) -> a -> b
$
String -> [Object] -> Neovim anyEnv Object
forall env. String -> [Object] -> Neovim env Object
vim_call_function String
defineFunction ([Object] -> Neovim anyEnv Object)
-> [Object] -> Neovim anyEnv Object
forall a b. (a -> b) -> a -> b
$
Object
host Object -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: NvimMethod -> Text
nvimMethodName (FunctionalityDescription -> NvimMethod
forall a. HasFunctionName a => a -> NvimMethod
nvimMethod FunctionalityDescription
func) Text -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: Synchronous
s Synchronous -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: Text
functionName Text -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: (Dictionary
forall k a. Map k a
Map.empty :: Dictionary) Dictionary -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: []
Neovim anyEnv Bool
logSuccess
cmd :: FunctionalityDescription
cmd@(Command (F Text
functionName) CommandOptions
copts) -> do
let sync :: Synchronous
sync = case CommandOptions -> [CommandOption]
getCommandOptions CommandOptions
copts of
(CmdSync Synchronous
s : [CommandOption]
_) -> Synchronous
s
[CommandOption]
_ -> Synchronous
Sync
Either String Int
pName <- Neovim anyEnv (Either String Int)
forall env. Neovim env (Either String Int)
getProviderName
let (String
defineFunction, Object
host) =
(String -> (String, Object))
-> (Int -> (String, Object))
-> Either String Int
-> (String, Object)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either
(\String
n -> (String
"remote#define#CommandOnHost", String -> Object
forall o. NvimObject o => o -> Object
toObject String
n))
(\Int
c -> (String
"remote#define#CommandOnChannel", Int -> Object
forall o. NvimObject o => o -> Object
toObject Int
c))
Either String Int
pName
reportError :: NeovimException -> Neovim anyEnv Bool
reportError (NeovimException
e :: NeovimException) = do
IO () -> Neovim anyEnv ()
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim anyEnv ())
-> (String -> IO ()) -> String -> Neovim anyEnv ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> IO ()
errorM String
logger (String -> Neovim anyEnv ()) -> String -> Neovim anyEnv ()
forall a b. (a -> b) -> a -> b
$
String
"Failed to register command: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
functionName String -> String -> String
forall a. [a] -> [a] -> [a]
++ NeovimException -> String
forall a. Show a => a -> String
show NeovimException
e
Bool -> Neovim anyEnv Bool
forall a. a -> Neovim anyEnv a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
logSuccess :: Neovim anyEnv Bool
logSuccess = do
IO () -> Neovim anyEnv ()
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim anyEnv ())
-> (String -> IO ()) -> String -> Neovim anyEnv ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> IO ()
debugM String
logger (String -> Neovim anyEnv ()) -> String -> Neovim anyEnv ()
forall a b. (a -> b) -> a -> b
$
String
"Registered command: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
functionName
Bool -> Neovim anyEnv Bool
forall a. a -> Neovim anyEnv a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
(Neovim anyEnv Bool
-> (NeovimException -> Neovim anyEnv Bool) -> Neovim anyEnv Bool)
-> (NeovimException -> Neovim anyEnv Bool)
-> Neovim anyEnv Bool
-> Neovim anyEnv Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip Neovim anyEnv Bool
-> (NeovimException -> Neovim anyEnv Bool) -> Neovim anyEnv Bool
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> (e -> m a) -> m a
catch NeovimException -> Neovim anyEnv Bool
reportError (Neovim anyEnv Bool -> Neovim anyEnv Bool)
-> Neovim anyEnv Bool -> Neovim anyEnv Bool
forall a b. (a -> b) -> a -> b
$ do
Neovim anyEnv Object -> Neovim anyEnv ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Neovim anyEnv Object -> Neovim anyEnv ())
-> Neovim anyEnv Object -> Neovim anyEnv ()
forall a b. (a -> b) -> a -> b
$
String -> [Object] -> Neovim anyEnv Object
forall env. String -> [Object] -> Neovim env Object
vim_call_function String
defineFunction ([Object] -> Neovim anyEnv Object)
-> [Object] -> Neovim anyEnv Object
forall a b. (a -> b) -> a -> b
$
Object
host Object -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: NvimMethod -> Text
nvimMethodName (FunctionalityDescription -> NvimMethod
forall a. HasFunctionName a => a -> NvimMethod
nvimMethod FunctionalityDescription
cmd) Text -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: Synchronous
sync Synchronous -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: Text
functionName Text -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: CommandOptions
copts CommandOptions -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: []
Neovim anyEnv Bool
logSuccess
Autocmd Text
acmdType (F Text
functionName) Synchronous
sync AutocmdOptions
opts -> do
Either String Int
pName <- Neovim anyEnv (Either String Int)
forall env. Neovim env (Either String Int)
getProviderName
let (String
defineFunction, Object
host) =
(String -> (String, Object))
-> (Int -> (String, Object))
-> Either String Int
-> (String, Object)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either
(\String
n -> (String
"remote#define#AutocmdOnHost", String -> Object
forall o. NvimObject o => o -> Object
toObject String
n))
(\Int
c -> (String
"remote#define#AutocmdOnChannel", Int -> Object
forall o. NvimObject o => o -> Object
toObject Int
c))
Either String Int
pName
reportError :: NeovimException -> Neovim anyEnv Bool
reportError (NeovimException
e :: NeovimException) = do
IO () -> Neovim anyEnv ()
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim anyEnv ())
-> (String -> IO ()) -> String -> Neovim anyEnv ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> IO ()
errorM String
logger (String -> Neovim anyEnv ()) -> String -> Neovim anyEnv ()
forall a b. (a -> b) -> a -> b
$
String
"Failed to register autocmd: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
functionName String -> String -> String
forall a. [a] -> [a] -> [a]
++ NeovimException -> String
forall a. Show a => a -> String
show NeovimException
e
Bool -> Neovim anyEnv Bool
forall a. a -> Neovim anyEnv a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
logSuccess :: Neovim anyEnv Bool
logSuccess = do
IO () -> Neovim anyEnv ()
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim anyEnv ())
-> (String -> IO ()) -> String -> Neovim anyEnv ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> IO ()
debugM String
logger (String -> Neovim anyEnv ()) -> String -> Neovim anyEnv ()
forall a b. (a -> b) -> a -> b
$
String
"Registered autocmd: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
functionName
Bool -> Neovim anyEnv Bool
forall a. a -> Neovim anyEnv a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
(Neovim anyEnv Bool
-> (NeovimException -> Neovim anyEnv Bool) -> Neovim anyEnv Bool)
-> (NeovimException -> Neovim anyEnv Bool)
-> Neovim anyEnv Bool
-> Neovim anyEnv Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip Neovim anyEnv Bool
-> (NeovimException -> Neovim anyEnv Bool) -> Neovim anyEnv Bool
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> (e -> m a) -> m a
catch NeovimException -> Neovim anyEnv Bool
reportError (Neovim anyEnv Bool -> Neovim anyEnv Bool)
-> Neovim anyEnv Bool -> Neovim anyEnv Bool
forall a b. (a -> b) -> a -> b
$ do
Neovim anyEnv Object -> Neovim anyEnv ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Neovim anyEnv Object -> Neovim anyEnv ())
-> Neovim anyEnv Object -> Neovim anyEnv ()
forall a b. (a -> b) -> a -> b
$
String -> [Object] -> Neovim anyEnv Object
forall env. String -> [Object] -> Neovim env Object
vim_call_function String
defineFunction ([Object] -> Neovim anyEnv Object)
-> [Object] -> Neovim anyEnv Object
forall a b. (a -> b) -> a -> b
$
Object
host Object -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: Text
functionName Text -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: Synchronous
sync Synchronous -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: Text
acmdType Text -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: AutocmdOptions
opts AutocmdOptions -> [Object] -> [Object]
forall o. NvimObject o => o -> [Object] -> [Object]
+: []
Neovim anyEnv Bool
logSuccess
getProviderName :: Neovim env (Either String Int)
getProviderName :: forall env. Neovim env (Either String Int)
getProviderName = do
TMVar (Either String Int)
mp <- (Config env -> TMVar (Either String Int))
-> Neovim env (TMVar (Either String Int))
forall env a. (Config env -> a) -> Neovim env a
Internal.asks' Config env -> TMVar (Either String Int)
forall env. Config env -> TMVar (Either String Int)
Internal.providerName
(IO (Maybe (Either String Int))
-> Neovim env (Maybe (Either String Int))
forall a. IO a -> Neovim env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe (Either String Int))
-> Neovim env (Maybe (Either String Int)))
-> (TMVar (Either String Int) -> IO (Maybe (Either String Int)))
-> TMVar (Either String Int)
-> Neovim env (Maybe (Either String Int))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. STM (Maybe (Either String Int)) -> IO (Maybe (Either String Int))
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM (Maybe (Either String Int)) -> IO (Maybe (Either String Int)))
-> (TMVar (Either String Int) -> STM (Maybe (Either String Int)))
-> TMVar (Either String Int)
-> IO (Maybe (Either String Int))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TMVar (Either String Int) -> STM (Maybe (Either String Int))
forall a. TMVar a -> STM (Maybe a)
tryReadTMVar) TMVar (Either String Int)
mp Neovim env (Maybe (Either String Int))
-> (Maybe (Either String Int) -> Neovim env (Either String Int))
-> Neovim env (Either String Int)
forall a b. Neovim env a -> (a -> Neovim env b) -> Neovim env b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Just Either String Int
p ->
Either String Int -> Neovim env (Either String Int)
forall a. a -> Neovim env a
forall (m :: * -> *) a. Monad m => a -> m a
return Either String Int
p
Maybe (Either String Int)
Nothing -> do
[Object]
api <- Neovim env [Object]
forall env. Neovim env [Object]
nvim_get_api_info
case [Object]
api of
[] -> Doc AnsiStyle -> Neovim env (Either String Int)
forall env a. Doc AnsiStyle -> Neovim env a
err Doc AnsiStyle
"empty nvim_get_api_info"
(Object
i : [Object]
_) -> do
case Object -> Either (Doc AnsiStyle) Int
forall o. NvimObject o => Object -> Either (Doc AnsiStyle) o
fromObject Object
i :: Either (Doc AnsiStyle) Int of
Left Doc AnsiStyle
_ ->
Doc AnsiStyle -> Neovim env (Either String Int)
forall env a. Doc AnsiStyle -> Neovim env a
err (Doc AnsiStyle -> Neovim env (Either String Int))
-> Doc AnsiStyle -> Neovim env (Either String Int)
forall a b. (a -> b) -> a -> b
$
Doc AnsiStyle
"Expected an integral value as the first"
Doc AnsiStyle -> Doc AnsiStyle -> Doc AnsiStyle
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc AnsiStyle
"argument of nvim_get_api_info"
Right Int
channelId -> do
IO () -> Neovim env ()
forall a. IO a -> Neovim env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim env ()) -> (Int -> IO ()) -> Int -> Neovim env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM () -> IO ()) -> (Int -> STM ()) -> Int -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TMVar (Either String Int) -> Either String Int -> STM ()
forall a. TMVar a -> a -> STM ()
putTMVar TMVar (Either String Int)
mp (Either String Int -> STM ())
-> (Int -> Either String Int) -> Int -> STM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Either String Int
forall a b. b -> Either a b
Right (Int -> Neovim env ()) -> Int -> Neovim env ()
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
channelId
Either String Int -> Neovim env (Either String Int)
forall a. a -> Neovim env a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String Int -> Neovim env (Either String Int))
-> (Int -> Either String Int)
-> Int
-> Neovim env (Either String Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Either String Int
forall a b. b -> Either a b
Right (Int -> Neovim env (Either String Int))
-> Int -> Neovim env (Either String Int)
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
channelId
registerFunctionality ::
FunctionalityDescription ->
([Object] -> Neovim env Object) ->
Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
registerFunctionality :: forall env.
FunctionalityDescription
-> ([Object] -> Neovim env Object)
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
registerFunctionality FunctionalityDescription
d [Object] -> Neovim env Object
f = do
(Config env -> Maybe (PluginSettings env))
-> Neovim env (Maybe (PluginSettings env))
forall env a. (Config env -> a) -> Neovim env a
Internal.asks' Config env -> Maybe (PluginSettings env)
forall env. Config env -> Maybe (PluginSettings env)
Internal.pluginSettings Neovim env (Maybe (PluginSettings env))
-> (Maybe (PluginSettings env)
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
forall a b. Neovim env a -> (a -> Neovim env b) -> Neovim env b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe (PluginSettings env)
Nothing -> do
let msg :: String
msg = String
"Cannot register functionality in this context."
IO () -> Neovim env ()
forall a. IO a -> Neovim env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim env ()) -> IO () -> Neovim env ()
forall a b. (a -> b) -> a -> b
$ String -> String -> IO ()
errorM String
logger String
msg
Either (Doc AnsiStyle) FunctionMapEntry
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
forall a. a -> Neovim env a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either (Doc AnsiStyle) FunctionMapEntry
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> Either (Doc AnsiStyle) FunctionMapEntry
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
forall a b. (a -> b) -> a -> b
$ Doc AnsiStyle -> Either (Doc AnsiStyle) FunctionMapEntry
forall a b. a -> Either a b
Left (Doc AnsiStyle -> Either (Doc AnsiStyle) FunctionMapEntry)
-> Doc AnsiStyle -> Either (Doc AnsiStyle) FunctionMapEntry
forall a b. (a -> b) -> a -> b
$ String -> Doc AnsiStyle
forall ann. String -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty String
msg
Just (Internal.StatefulSettings FunctionalityDescription
-> ([Object] -> Neovim env Object)
-> TQueue SomeMessage
-> TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env (Maybe FunctionMapEntry)
reg TQueue SomeMessage
q TVar (Map NvimMethod ([Object] -> Neovim env Object))
m) ->
FunctionalityDescription
-> ([Object] -> Neovim env Object)
-> TQueue SomeMessage
-> TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env (Maybe FunctionMapEntry)
reg FunctionalityDescription
d [Object] -> Neovim env Object
f TQueue SomeMessage
q TVar (Map NvimMethod ([Object] -> Neovim env Object))
m Neovim env (Maybe FunctionMapEntry)
-> (Maybe FunctionMapEntry
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
forall a b. Neovim env a -> (a -> Neovim env b) -> Neovim env b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Just FunctionMapEntry
e -> do
Either (Doc AnsiStyle) FunctionMapEntry
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
forall a. a -> Neovim env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either (Doc AnsiStyle) FunctionMapEntry
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> Either (Doc AnsiStyle) FunctionMapEntry
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
forall a b. (a -> b) -> a -> b
$ FunctionMapEntry -> Either (Doc AnsiStyle) FunctionMapEntry
forall a b. b -> Either a b
Right FunctionMapEntry
e
Maybe FunctionMapEntry
Nothing ->
Either (Doc AnsiStyle) FunctionMapEntry
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
forall a. a -> Neovim env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either (Doc AnsiStyle) FunctionMapEntry
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> Either (Doc AnsiStyle) FunctionMapEntry
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
forall a b. (a -> b) -> a -> b
$ Doc AnsiStyle -> Either (Doc AnsiStyle) FunctionMapEntry
forall a b. a -> Either a b
Left Doc AnsiStyle
""
registerInGlobalFunctionMap :: FunctionMapEntry -> Neovim env ()
registerInGlobalFunctionMap :: forall env. FunctionMapEntry -> Neovim env ()
registerInGlobalFunctionMap FunctionMapEntry
e = do
IO () -> Neovim env ()
forall a. IO a -> Neovim env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim env ())
-> (String -> IO ()) -> String -> Neovim env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> IO ()
debugM String
logger (String -> Neovim env ()) -> String -> Neovim env ()
forall a b. (a -> b) -> a -> b
$ String
"Adding function to global function map." String -> String -> String
forall a. [a] -> [a] -> [a]
++ FunctionalityDescription -> String
forall a. Show a => a -> String
show (FunctionMapEntry -> FunctionalityDescription
forall a b. (a, b) -> a
fst FunctionMapEntry
e)
TMVar FunctionMap
funMap <- (Config env -> TMVar FunctionMap) -> Neovim env (TMVar FunctionMap)
forall env a. (Config env -> a) -> Neovim env a
Internal.asks' Config env -> TMVar FunctionMap
forall env. Config env -> TMVar FunctionMap
Internal.globalFunctionMap
IO () -> Neovim env ()
forall a. IO a -> Neovim env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim env ())
-> (STM () -> IO ()) -> STM () -> Neovim env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM () -> Neovim env ()) -> STM () -> Neovim env ()
forall a b. (a -> b) -> a -> b
$ do
FunctionMap
m <- TMVar FunctionMap -> STM FunctionMap
forall a. TMVar a -> STM a
takeTMVar TMVar FunctionMap
funMap
TMVar FunctionMap -> FunctionMap -> STM ()
forall a. TMVar a -> a -> STM ()
putTMVar TMVar FunctionMap
funMap (FunctionMap -> STM ()) -> FunctionMap -> STM ()
forall a b. (a -> b) -> a -> b
$ NvimMethod -> FunctionMapEntry -> FunctionMap -> FunctionMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert ((FunctionalityDescription -> NvimMethod
forall a. HasFunctionName a => a -> NvimMethod
nvimMethod (FunctionalityDescription -> NvimMethod)
-> (FunctionMapEntry -> FunctionalityDescription)
-> FunctionMapEntry
-> NvimMethod
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FunctionMapEntry -> FunctionalityDescription
forall a b. (a, b) -> a
fst) FunctionMapEntry
e) FunctionMapEntry
e FunctionMap
m
IO () -> Neovim env ()
forall a. IO a -> Neovim env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim env ())
-> (String -> IO ()) -> String -> Neovim env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> IO ()
debugM String
logger (String -> Neovim env ()) -> String -> Neovim env ()
forall a b. (a -> b) -> a -> b
$ String
"Added function to global function map." String -> String -> String
forall a. [a] -> [a] -> [a]
++ FunctionalityDescription -> String
forall a. Show a => a -> String
show (FunctionMapEntry -> FunctionalityDescription
forall a b. (a, b) -> a
fst FunctionMapEntry
e)
registerPlugin ::
(FunctionMapEntry -> Neovim env ()) ->
FunctionalityDescription ->
([Object] -> Neovim env Object) ->
TQueue SomeMessage ->
TVar (Map NvimMethod ([Object] -> Neovim env Object)) ->
Neovim env (Maybe FunctionMapEntry)
registerPlugin :: forall env.
(FunctionMapEntry -> Neovim env ())
-> FunctionalityDescription
-> ([Object] -> Neovim env Object)
-> TQueue SomeMessage
-> TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env (Maybe FunctionMapEntry)
registerPlugin FunctionMapEntry -> Neovim env ()
reg FunctionalityDescription
d [Object] -> Neovim env Object
f TQueue SomeMessage
q TVar (Map NvimMethod ([Object] -> Neovim env Object))
tm =
FunctionalityDescription -> Neovim env Bool
forall anyEnv. FunctionalityDescription -> Neovim anyEnv Bool
registerWithNeovim FunctionalityDescription
d Neovim env Bool
-> (Bool -> Neovim env (Maybe FunctionMapEntry))
-> Neovim env (Maybe FunctionMapEntry)
forall a b. Neovim env a -> (a -> Neovim env b) -> Neovim env b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> do
let n :: NvimMethod
n = FunctionalityDescription -> NvimMethod
forall a. HasFunctionName a => a -> NvimMethod
nvimMethod FunctionalityDescription
d
e :: FunctionMapEntry
e = (FunctionalityDescription
d, TQueue SomeMessage -> FunctionType
Stateful TQueue SomeMessage
q)
IO () -> Neovim env ()
forall a. IO a -> Neovim env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Neovim env ())
-> ((Map NvimMethod ([Object] -> Neovim env Object)
-> Map NvimMethod ([Object] -> Neovim env Object))
-> IO ())
-> (Map NvimMethod ([Object] -> Neovim env Object)
-> Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM () -> IO ())
-> ((Map NvimMethod ([Object] -> Neovim env Object)
-> Map NvimMethod ([Object] -> Neovim env Object))
-> STM ())
-> (Map NvimMethod ([Object] -> Neovim env Object)
-> Map NvimMethod ([Object] -> Neovim env Object))
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> (Map NvimMethod ([Object] -> Neovim env Object)
-> Map NvimMethod ([Object] -> Neovim env Object))
-> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar TVar (Map NvimMethod ([Object] -> Neovim env Object))
tm ((Map NvimMethod ([Object] -> Neovim env Object)
-> Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env ())
-> (Map NvimMethod ([Object] -> Neovim env Object)
-> Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env ()
forall a b. (a -> b) -> a -> b
$ NvimMethod
-> ([Object] -> Neovim env Object)
-> Map NvimMethod ([Object] -> Neovim env Object)
-> Map NvimMethod ([Object] -> Neovim env Object)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert NvimMethod
n [Object] -> Neovim env Object
f
FunctionMapEntry -> Neovim env ()
reg FunctionMapEntry
e
Maybe FunctionMapEntry -> Neovim env (Maybe FunctionMapEntry)
forall a. a -> Neovim env a
forall (m :: * -> *) a. Monad m => a -> m a
return (FunctionMapEntry -> Maybe FunctionMapEntry
forall a. a -> Maybe a
Just FunctionMapEntry
e)
Bool
False ->
Maybe FunctionMapEntry -> Neovim env (Maybe FunctionMapEntry)
forall a. a -> Neovim env a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe FunctionMapEntry
forall a. Maybe a
Nothing
addAutocmd ::
Text ->
Synchronous ->
AutocmdOptions ->
Neovim env () ->
Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
addAutocmd :: forall env.
Text
-> Synchronous
-> AutocmdOptions
-> Neovim env ()
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
addAutocmd Text
event Synchronous
s opts :: AutocmdOptions
opts@AutocmdOptions{} Neovim env ()
f = do
FunctionName
n <- Neovim env FunctionName
forall env. Neovim env FunctionName
newUniqueFunctionName
FunctionalityDescription
-> ([Object] -> Neovim env Object)
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
forall env.
FunctionalityDescription
-> ([Object] -> Neovim env Object)
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
registerFunctionality (Text
-> FunctionName
-> Synchronous
-> AutocmdOptions
-> FunctionalityDescription
Autocmd Text
event FunctionName
n Synchronous
s AutocmdOptions
opts) (\[Object]
_ -> () -> Object
forall o. NvimObject o => o -> Object
toObject (() -> Object) -> Neovim env () -> Neovim env Object
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Neovim env ()
f)
registerStatefulFunctionality ::
Plugin env ->
Neovim anyEnv ([FunctionMapEntry], Async ())
registerStatefulFunctionality :: forall env anyEnv.
Plugin env -> Neovim anyEnv ([FunctionMapEntry], Async ())
registerStatefulFunctionality (Plugin{environment :: forall env. Plugin env -> env
environment = env
env, exports :: forall env. Plugin env -> [ExportedFunctionality env]
exports = [ExportedFunctionality env]
fs}) = do
TQueue SomeMessage
messageQueue <- IO (TQueue SomeMessage) -> Neovim anyEnv (TQueue SomeMessage)
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (TQueue SomeMessage)
forall (m :: * -> *) a. MonadIO m => m (TQueue a)
newTQueueIO
TVar (Map NvimMethod ([Object] -> Neovim env Object))
route <- IO (TVar (Map NvimMethod ([Object] -> Neovim env Object)))
-> Neovim
anyEnv (TVar (Map NvimMethod ([Object] -> Neovim env Object)))
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (TVar (Map NvimMethod ([Object] -> Neovim env Object)))
-> Neovim
anyEnv (TVar (Map NvimMethod ([Object] -> Neovim env Object))))
-> IO (TVar (Map NvimMethod ([Object] -> Neovim env Object)))
-> Neovim
anyEnv (TVar (Map NvimMethod ([Object] -> Neovim env Object)))
forall a b. (a -> b) -> a -> b
$ Map NvimMethod ([Object] -> Neovim env Object)
-> IO (TVar (Map NvimMethod ([Object] -> Neovim env Object)))
forall (m :: * -> *) a. MonadIO m => a -> m (TVar a)
newTVarIO Map NvimMethod ([Object] -> Neovim env Object)
forall k a. Map k a
Map.empty
TVar [Notification -> Neovim env ()]
subscribers <- IO (TVar [Notification -> Neovim env ()])
-> Neovim anyEnv (TVar [Notification -> Neovim env ()])
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (TVar [Notification -> Neovim env ()])
-> Neovim anyEnv (TVar [Notification -> Neovim env ()]))
-> IO (TVar [Notification -> Neovim env ()])
-> Neovim anyEnv (TVar [Notification -> Neovim env ()])
forall a b. (a -> b) -> a -> b
$ [Notification -> Neovim env ()]
-> IO (TVar [Notification -> Neovim env ()])
forall (m :: * -> *) a. MonadIO m => a -> m (TVar a)
newTVarIO []
Config anyEnv
cfg <- Neovim anyEnv (Config anyEnv)
forall env. Neovim env (Config env)
Internal.ask'
let startupConfig :: Config env
startupConfig =
Config anyEnv
cfg
{ Internal.customConfig = env
, Internal.pluginSettings =
Just $
Internal.StatefulSettings
(registerPlugin (\FunctionMapEntry
_ -> () -> Neovim env ()
forall a. a -> Neovim env a
forall (m :: * -> *) a. Monad m => a -> m a
return ()))
messageQueue
route
}
Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry]
res <- IO
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry])
-> Neovim
anyEnv
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry])
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry])
-> Neovim
anyEnv
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry]))
-> ((ExportedFunctionality env
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> IO
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry]))
-> (ExportedFunctionality env
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> Neovim
anyEnv
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Either (Doc AnsiStyle) FunctionMapEntry]
-> IO [Either (Doc AnsiStyle) FunctionMapEntry])
-> Config env
-> Neovim env [Either (Doc AnsiStyle) FunctionMapEntry]
-> IO
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry])
forall a env.
(a -> IO a)
-> Config env -> Neovim env a -> IO (Either (Doc AnsiStyle) a)
runNeovimInternal [Either (Doc AnsiStyle) FunctionMapEntry]
-> IO [Either (Doc AnsiStyle) FunctionMapEntry]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Config env
startupConfig (Neovim env [Either (Doc AnsiStyle) FunctionMapEntry]
-> IO
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry]))
-> ((ExportedFunctionality env
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> Neovim env [Either (Doc AnsiStyle) FunctionMapEntry])
-> (ExportedFunctionality env
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> IO
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ExportedFunctionality env]
-> (ExportedFunctionality env
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> Neovim env [Either (Doc AnsiStyle) FunctionMapEntry]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [ExportedFunctionality env]
fs ((ExportedFunctionality env
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> Neovim
anyEnv
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry]))
-> (ExportedFunctionality env
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry))
-> Neovim
anyEnv
(Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry])
forall a b. (a -> b) -> a -> b
$ \ExportedFunctionality env
f ->
FunctionalityDescription
-> ([Object] -> Neovim env Object)
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
forall env.
FunctionalityDescription
-> ([Object] -> Neovim env Object)
-> Neovim env (Either (Doc AnsiStyle) FunctionMapEntry)
registerFunctionality (ExportedFunctionality env -> FunctionalityDescription
forall env. ExportedFunctionality env -> FunctionalityDescription
getDescription ExportedFunctionality env
f) (ExportedFunctionality env -> [Object] -> Neovim env Object
forall env.
ExportedFunctionality env -> [Object] -> Neovim env Object
getFunction ExportedFunctionality env
f)
[FunctionMapEntry]
es <- case Either (Doc AnsiStyle) [Either (Doc AnsiStyle) FunctionMapEntry]
res of
Left Doc AnsiStyle
e -> Doc AnsiStyle -> Neovim anyEnv [FunctionMapEntry]
forall env a. Doc AnsiStyle -> Neovim env a
err Doc AnsiStyle
e
Right [Either (Doc AnsiStyle) FunctionMapEntry]
a -> [FunctionMapEntry] -> Neovim anyEnv [FunctionMapEntry]
forall a. a -> Neovim anyEnv a
forall (m :: * -> *) a. Monad m => a -> m a
return ([FunctionMapEntry] -> Neovim anyEnv [FunctionMapEntry])
-> [FunctionMapEntry] -> Neovim anyEnv [FunctionMapEntry]
forall a b. (a -> b) -> a -> b
$ [Either (Doc AnsiStyle) FunctionMapEntry] -> [FunctionMapEntry]
forall a b. [Either a b] -> [b]
rights [Either (Doc AnsiStyle) FunctionMapEntry]
a
let pluginThreadConfig :: Config env
pluginThreadConfig =
Config anyEnv
cfg
{ Internal.customConfig = env
, Internal.pluginSettings =
Just $
Internal.StatefulSettings
(registerPlugin registerInGlobalFunctionMap)
messageQueue
route
}
Async ()
tid <- IO (Async ()) -> Neovim anyEnv (Async ())
forall a. IO a -> Neovim anyEnv a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Async ()) -> Neovim anyEnv (Async ()))
-> (Neovim env () -> IO (Async ()))
-> Neovim env ()
-> Neovim anyEnv (Async ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO () -> IO (Async ())
forall (m :: * -> *) a. MonadUnliftIO m => m a -> m (Async a)
async (IO () -> IO (Async ()))
-> (Neovim env () -> IO ()) -> Neovim env () -> IO (Async ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Either (Doc AnsiStyle) ()) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (Either (Doc AnsiStyle) ()) -> IO ())
-> (Neovim env () -> IO (Either (Doc AnsiStyle) ()))
-> Neovim env ()
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Config env -> Neovim env () -> IO (Either (Doc AnsiStyle) ())
forall a env.
NFData a =>
Config env -> Neovim env a -> IO (Either (Doc AnsiStyle) a)
runNeovim Config env
pluginThreadConfig (Neovim env () -> Neovim anyEnv (Async ()))
-> Neovim env () -> Neovim anyEnv (Async ())
forall a b. (a -> b) -> a -> b
$ do
TQueue SomeMessage
-> TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> TVar [Notification -> Neovim env ()]
-> Neovim env ()
forall env.
TQueue SomeMessage
-> TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> TVar [Notification -> Neovim env ()]
-> Neovim env ()
listeningThread TQueue SomeMessage
messageQueue TVar (Map NvimMethod ([Object] -> Neovim env Object))
route TVar [Notification -> Neovim env ()]
subscribers
([FunctionMapEntry], Async ())
-> Neovim anyEnv ([FunctionMapEntry], Async ())
forall a. a -> Neovim anyEnv a
forall (m :: * -> *) a. Monad m => a -> m a
return ([FunctionMapEntry]
es, Async ()
tid)
where
executeFunction ::
([Object] -> Neovim env Object) ->
[Object] ->
Neovim env (Either String Object)
executeFunction :: forall env.
([Object] -> Neovim env Object)
-> [Object] -> Neovim env (Either String Object)
executeFunction [Object] -> Neovim env Object
f [Object]
args =
Neovim env Object -> Neovim env (Either SomeException Object)
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> m (Either e a)
try ([Object] -> Neovim env Object
f [Object]
args) Neovim env (Either SomeException Object)
-> (Either SomeException Object
-> Neovim env (Either String Object))
-> Neovim env (Either String Object)
forall a b. Neovim env a -> (a -> Neovim env b) -> Neovim env b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Left SomeException
e -> Either String Object -> Neovim env (Either String Object)
forall a. a -> Neovim env a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String Object -> Neovim env (Either String Object))
-> (String -> Either String Object)
-> String
-> Neovim env (Either String Object)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Either String Object
forall a b. a -> Either a b
Left (String -> Neovim env (Either String Object))
-> String -> Neovim env (Either String Object)
forall a b. (a -> b) -> a -> b
$ SomeException -> String
forall a. Show a => a -> String
show (SomeException
e :: SomeException)
Right Object
res -> Either String Object -> Neovim env (Either String Object)
forall a. a -> Neovim env a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String Object -> Neovim env (Either String Object))
-> Either String Object -> Neovim env (Either String Object)
forall a b. (a -> b) -> a -> b
$ Object -> Either String Object
forall a b. b -> Either a b
Right Object
res
killAfterSeconds :: Word -> Neovim anyEnv ()
killAfterSeconds :: forall anyEnv. Word -> Neovim anyEnv ()
killAfterSeconds Word
seconds = Int -> Neovim anyEnv ()
forall (m :: * -> *). MonadIO m => Int -> m ()
threadDelay (Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
seconds Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
1000 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
1000)
timeoutAndLog :: Word -> FunctionName -> Neovim anyEnv String
timeoutAndLog :: forall anyEnv. Word -> FunctionName -> Neovim anyEnv String
timeoutAndLog Word
seconds FunctionName
functionName = do
Word -> Neovim anyEnv ()
forall anyEnv. Word -> Neovim anyEnv ()
killAfterSeconds Word
seconds
String -> Neovim anyEnv String
forall a. a -> Neovim anyEnv a
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Neovim anyEnv String)
-> (Doc Any -> String) -> Doc Any -> Neovim anyEnv String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc Any -> String
forall a. Show a => a -> String
show (Doc Any -> Neovim anyEnv String)
-> Doc Any -> Neovim anyEnv String
forall a b. (a -> b) -> a -> b
$
FunctionName -> Doc Any
forall a ann. Pretty a => a -> Doc ann
forall ann. FunctionName -> Doc ann
pretty FunctionName
functionName Doc Any -> Doc Any -> Doc Any
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc Any
"has been aborted after"
Doc Any -> Doc Any -> Doc Any
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Word -> Doc Any
forall ann. Word -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Word
seconds
Doc Any -> Doc Any -> Doc Any
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc Any
"seconds"
listeningThread ::
TQueue SomeMessage ->
TVar (Map NvimMethod ([Object] -> Neovim env Object)) ->
TVar [Notification -> Neovim env ()] ->
Neovim env ()
listeningThread :: forall env.
TQueue SomeMessage
-> TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> TVar [Notification -> Neovim env ()]
-> Neovim env ()
listeningThread TQueue SomeMessage
q TVar (Map NvimMethod ([Object] -> Neovim env Object))
route TVar [Notification -> Neovim env ()]
subscribers = do
SomeMessage
msg <- TQueue SomeMessage -> Neovim env SomeMessage
forall (m :: * -> *).
MonadIO m =>
TQueue SomeMessage -> m SomeMessage
readSomeMessage TQueue SomeMessage
q
Maybe Request -> (Request -> Neovim env ()) -> Neovim env ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (SomeMessage -> Maybe Request
forall message. Message message => SomeMessage -> Maybe message
fromMessage SomeMessage
msg) ((Request -> Neovim env ()) -> Neovim env ())
-> (Request -> Neovim env ()) -> Neovim env ()
forall a b. (a -> b) -> a -> b
$ \req :: Request
req@(Request fun :: FunctionName
fun@(F Text
methodName) Int64
_ [Object]
args) -> do
let method :: NvimMethod
method = Text -> NvimMethod
NvimMethod Text
methodName
Map NvimMethod ([Object] -> Neovim env Object)
route' <- IO (Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env (Map NvimMethod ([Object] -> Neovim env Object))
forall a. IO a -> Neovim env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env (Map NvimMethod ([Object] -> Neovim env Object)))
-> IO (Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env (Map NvimMethod ([Object] -> Neovim env Object))
forall a b. (a -> b) -> a -> b
$ TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> IO (Map NvimMethod ([Object] -> Neovim env Object))
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO TVar (Map NvimMethod ([Object] -> Neovim env Object))
route
Maybe ([Object] -> Neovim env Object)
-> (([Object] -> Neovim env Object) -> Neovim env ())
-> Neovim env ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (NvimMethod
-> Map NvimMethod ([Object] -> Neovim env Object)
-> Maybe ([Object] -> Neovim env Object)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup NvimMethod
method Map NvimMethod ([Object] -> Neovim env Object)
route') ((([Object] -> Neovim env Object) -> Neovim env ())
-> Neovim env ())
-> (([Object] -> Neovim env Object) -> Neovim env ())
-> Neovim env ()
forall a b. (a -> b) -> a -> b
$ \[Object] -> Neovim env Object
f -> do
Request -> Either String Object -> Neovim env ()
forall result env.
NvimObject result =>
Request -> Either String result -> Neovim env ()
respond Request
req (Either String Object -> Neovim env ())
-> (Either String (Either String Object) -> Either String Object)
-> Either String (Either String Object)
-> Neovim env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Either String Object)
-> (Either String Object -> Either String Object)
-> Either String (Either String Object)
-> Either String Object
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Either String Object
forall a b. a -> Either a b
Left Either String Object -> Either String Object
forall a. a -> a
id
(Either String (Either String Object) -> Neovim env ())
-> Neovim env (Either String (Either String Object))
-> Neovim env ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Neovim env String
-> Neovim env (Either String Object)
-> Neovim env (Either String (Either String Object))
forall (m :: * -> *) a b.
MonadUnliftIO m =>
m a -> m b -> m (Either a b)
race
(Word -> FunctionName -> Neovim env String
forall anyEnv. Word -> FunctionName -> Neovim anyEnv String
timeoutAndLog Word
10 FunctionName
fun)
(([Object] -> Neovim env Object)
-> [Object] -> Neovim env (Either String Object)
forall env.
([Object] -> Neovim env Object)
-> [Object] -> Neovim env (Either String Object)
executeFunction [Object] -> Neovim env Object
f [Object]
args)
Maybe Notification
-> (Notification -> Neovim env ()) -> Neovim env ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (SomeMessage -> Maybe Notification
forall message. Message message => SomeMessage -> Maybe message
fromMessage SomeMessage
msg) ((Notification -> Neovim env ()) -> Neovim env ())
-> (Notification -> Neovim env ()) -> Neovim env ()
forall a b. (a -> b) -> a -> b
$ \notification :: Notification
notification@(Notification (NeovimEventId Text
methodName) [Object]
args) -> do
let method :: NvimMethod
method = Text -> NvimMethod
NvimMethod Text
methodName
Map NvimMethod ([Object] -> Neovim env Object)
route' <- IO (Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env (Map NvimMethod ([Object] -> Neovim env Object))
forall a. IO a -> Neovim env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env (Map NvimMethod ([Object] -> Neovim env Object)))
-> IO (Map NvimMethod ([Object] -> Neovim env Object))
-> Neovim env (Map NvimMethod ([Object] -> Neovim env Object))
forall a b. (a -> b) -> a -> b
$ TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> IO (Map NvimMethod ([Object] -> Neovim env Object))
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO TVar (Map NvimMethod ([Object] -> Neovim env Object))
route
Maybe ([Object] -> Neovim env Object)
-> (([Object] -> Neovim env Object) -> Neovim env ())
-> Neovim env ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (NvimMethod
-> Map NvimMethod ([Object] -> Neovim env Object)
-> Maybe ([Object] -> Neovim env Object)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup NvimMethod
method Map NvimMethod ([Object] -> Neovim env Object)
route') ((([Object] -> Neovim env Object) -> Neovim env ())
-> Neovim env ())
-> (([Object] -> Neovim env Object) -> Neovim env ())
-> Neovim env ()
forall a b. (a -> b) -> a -> b
$ \[Object] -> Neovim env Object
f ->
Neovim env (Async ()) -> Neovim env ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Neovim env (Async ()) -> Neovim env ())
-> (Neovim env () -> Neovim env (Async ()))
-> Neovim env ()
-> Neovim env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Neovim env () -> Neovim env (Async ())
forall (m :: * -> *) a. MonadUnliftIO m => m a -> m (Async a)
async (Neovim env () -> Neovim env ()) -> Neovim env () -> Neovim env ()
forall a b. (a -> b) -> a -> b
$ do
Either String Object
result <- (String -> Either String Object)
-> (Either String Object -> Either String Object)
-> Either String (Either String Object)
-> Either String Object
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Either String Object
forall a b. a -> Either a b
Left Either String Object -> Either String Object
forall a. a -> a
id (Either String (Either String Object) -> Either String Object)
-> Neovim env (Either String (Either String Object))
-> Neovim env (Either String Object)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Neovim env String
-> Neovim env (Either String Object)
-> Neovim env (Either String (Either String Object))
forall (m :: * -> *) a b.
MonadUnliftIO m =>
m a -> m b -> m (Either a b)
race
(Word -> FunctionName -> Neovim env String
forall anyEnv. Word -> FunctionName -> Neovim anyEnv String
timeoutAndLog Word
600 (Text -> FunctionName
F Text
methodName))
(([Object] -> Neovim env Object)
-> [Object] -> Neovim env (Either String Object)
forall env.
([Object] -> Neovim env Object)
-> [Object] -> Neovim env (Either String Object)
executeFunction [Object] -> Neovim env Object
f [Object]
args)
case Either String Object
result of
Left String
message ->
String -> Neovim env ()
forall env. String -> Neovim env ()
nvim_err_writeln String
message
Right Object
_ ->
() -> Neovim env ()
forall a. a -> Neovim env a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
[Notification -> Neovim env ()]
subscribers' <- IO [Notification -> Neovim env ()]
-> Neovim env [Notification -> Neovim env ()]
forall a. IO a -> Neovim env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [Notification -> Neovim env ()]
-> Neovim env [Notification -> Neovim env ()])
-> IO [Notification -> Neovim env ()]
-> Neovim env [Notification -> Neovim env ()]
forall a b. (a -> b) -> a -> b
$ TVar [Notification -> Neovim env ()]
-> IO [Notification -> Neovim env ()]
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO TVar [Notification -> Neovim env ()]
subscribers
[Notification -> Neovim env ()]
-> ((Notification -> Neovim env ()) -> Neovim env (Async ()))
-> Neovim env ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Notification -> Neovim env ()]
subscribers' (((Notification -> Neovim env ()) -> Neovim env (Async ()))
-> Neovim env ())
-> ((Notification -> Neovim env ()) -> Neovim env (Async ()))
-> Neovim env ()
forall a b. (a -> b) -> a -> b
$ \Notification -> Neovim env ()
subscriber ->
Neovim env () -> Neovim env (Async ())
forall (m :: * -> *) a. MonadUnliftIO m => m a -> m (Async a)
async (Neovim env () -> Neovim env (Async ()))
-> Neovim env () -> Neovim env (Async ())
forall a b. (a -> b) -> a -> b
$ Neovim env (Either () ()) -> Neovim env ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Neovim env (Either () ()) -> Neovim env ())
-> Neovim env (Either () ()) -> Neovim env ()
forall a b. (a -> b) -> a -> b
$ Neovim env () -> Neovim env () -> Neovim env (Either () ())
forall (m :: * -> *) a b.
MonadUnliftIO m =>
m a -> m b -> m (Either a b)
race (Notification -> Neovim env ()
subscriber Notification
notification) (Word -> Neovim env ()
forall anyEnv. Word -> Neovim anyEnv ()
killAfterSeconds Word
10)
TQueue SomeMessage
-> TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> TVar [Notification -> Neovim env ()]
-> Neovim env ()
forall env.
TQueue SomeMessage
-> TVar (Map NvimMethod ([Object] -> Neovim env Object))
-> TVar [Notification -> Neovim env ()]
-> Neovim env ()
listeningThread TQueue SomeMessage
q TVar (Map NvimMethod ([Object] -> Neovim env Object))
route TVar [Notification -> Neovim env ()]
subscribers