ribosome-host-0.9.9.9: lib/Ribosome/Host/RegisterHandlers.hs
module Ribosome.Host.RegisterHandlers where
import qualified Data.Text as Text
import Exon (exon)
import qualified Polysemy.Log as Log
import Ribosome.Host.Api.Autocmd (autocmd)
import Ribosome.Host.Api.Data (nvimCommand, nvimCreateUserCommand)
import Ribosome.Host.Class.Msgpack.Encode (toMsgpack)
import Ribosome.Host.Data.ChannelId (ChannelId (ChannelId))
import Ribosome.Host.Data.Execution (Execution (Async, Sync))
import Ribosome.Host.Data.Report (Report, resumeReport)
import Ribosome.Host.Data.Request (RpcMethod (RpcMethod))
import Ribosome.Host.Data.RpcCall (RpcCall)
import Ribosome.Host.Data.RpcError (RpcError, rpcError)
import Ribosome.Host.Data.RpcHandler (RpcHandler (RpcHandler), rpcMethod)
import Ribosome.Host.Data.RpcName (RpcName (RpcName))
import qualified Ribosome.Host.Data.RpcType as RpcType
import Ribosome.Host.Data.RpcType (CommandArgs (CommandArgs), CommandOptions (CommandOptions), RpcType, completionValue)
import qualified Ribosome.Host.Effect.Rpc as Rpc
import Ribosome.Host.Effect.Rpc (Rpc)
registerFailed ::
Member Log r =>
RpcError ->
Sem r ()
registerFailed e =
Log.error [exon|Registering rpc handlers failed: #{rpcError e}|]
trigger :: Execution -> Text
trigger = \case
Sync -> "rpcrequest"
Async -> "rpcnotify"
rpcCall ::
ChannelId ->
RpcMethod ->
Execution ->
Maybe Text ->
Text
rpcCall (ChannelId i) (RpcMethod method) exec args =
[exon|call('#{trigger exec}', [#{show i}, '#{method}']#{foldMap appendArgs args})|]
where
appendArgs a =
[exon| + #{a}|]
registerType ::
ChannelId ->
RpcMethod ->
RpcName ->
Execution ->
RpcType ->
RpcCall ()
registerType i method (RpcName name) exec = \case
RpcType.Function ->
nvimCommand [exon|function! #{name}(...) range
return #{rpcCall i method exec (Just "a:000")}
endfunction|]
RpcType.Command (CommandOptions options comp) (CommandArgs args) ->
nvimCreateUserCommand name [exon|call #{rpcCall i method exec (Just argsText)}|] (options <> foldMap compOpt comp)
where
compOpt c =
[("complete", toMsgpack (completionValue c))]
argsText =
[exon|[#{Text.intercalate ", " args}]|]
RpcType.Autocmd events options ->
void (autocmd events options [exon|call #{rpcCall i method exec Nothing}|])
registerHandler ::
ChannelId ->
RpcHandler r ->
RpcCall ()
registerHandler i (RpcHandler tpe name exec _) =
registerType i (rpcMethod tpe name) name exec tpe
registerHandlers ::
Members [Rpc !! RpcError, Log] r =>
[RpcHandler r] ->
Sem (Stop Report : r) ()
registerHandlers defs = do
i <- resumeReport Rpc.channelId
Rpc.sync (foldMap (registerHandler i) defs) !! registerFailed