packages feed

sarsi-0.0.2.0: sarsi-nvim/NVIM/Client.hs

module NVIM.Client where

-- | A primitive NVIM RPC synchronous client.

import Data.Binary.Machine (streamGet)
import Data.Binary.Put (runPut)
import Data.ByteString (hGetSome, hPut)
import Data.ByteString.Lazy (toStrict)
import Data.Machine ((<~), asParts, auto, final, run, source)
import Data.MessagePack.Object (Object(..), toObject)
import Data.MessagePack.RPC (Answer(..), Request(..), Message(..), getMessage, putRequest)
import Data.Text (Text)
import System.IO (Handle, stdin, stdout)
import qualified Data.Text as Text
import qualified Data.Vector as Vector

data Command = VimCommand [Object] | VimCallFunction Text [Object]

runCommand :: Command -> IO Answer
runCommand = runCommandWith stdin stdout

runCommandWith :: Handle -> Handle -> Command -> IO Answer
runCommandWith hIn hOut cmd = do
  hPut hOut $ toStrict $ runPut $ putRequest $ mkRequest cmd
  xs <- hGetSome hIn 1024
  let ys = run $ final <~ asParts <~ auto unpack <~ streamGet getMessage <~ source [xs]
  return $ mkAnswer $ ys
    where
      mkAnswer [a] = a
      mkAnswer _   = Error $ ObjectStr $ Text.pack "No RPC answer received."
      mkRequest (VimCommand xs) =
        Request 0 (Text.pack "vim_command") $ Vector.fromList xs
      mkRequest (VimCallFunction m xs) =
        Request 0 (Text.pack "vim_call_function") $ Vector.fromList $
          [ toObject m
          , toObject $ Vector.fromList xs ]
      unpack (Right (Response _ a)) = [a]
      unpack _                      = []