packages feed

ribosome-host-0.9.9.9: lib/Ribosome/Host/Modify.hs

-- |Modify 'RpcCall' constructors that contain calls to @nvim_command@.
--
-- See @:h :command-modifiers@.
module Ribosome.Host.Modify where

import Data.MessagePack (Object (ObjectString))
import Exon (exon)

import Ribosome.Host.Api.Data (Buffer, Window)
import Ribosome.Host.Api.Effect (
  nvimBufGetNumber,
  nvimGetCurrentBuf,
  nvimGetCurrentWin,
  nvimSetCurrentBuf,
  nvimWinGetNumber,
  vimSetCurrentWindow,
  )
import Ribosome.Host.Data.Request (Request (Request))
import Ribosome.Host.Data.RpcCall (RpcCall (RpcCallRequest))
import qualified Ribosome.Host.Effect.Rpc as Rpc
import Ribosome.Host.Effect.Rpc (Rpc)

-- |Modify an 'RpcCall' constructor if it contains a request for @nvim_command@ by prefixing it with the given string.
modifyCall :: Text -> RpcCall a -> RpcCall a
modifyCall modifier = \case
  RpcCallRequest (Request "nvim_command" [ObjectString cmd]) ->
    RpcCallRequest (Request "nvim_command" [ObjectString [exon|#{encodeUtf8 modifier} #{cmd}|]])
  c ->
    c

-- |Prefix all @nvim_commands@ called in an action with the given string.
modifyCmd ::
  Member Rpc r =>
  Text ->
  Sem r a ->
  Sem r a
modifyCmd modifier =
  interceptH \case
    Rpc.Sync call ->
      pureT =<< Rpc.sync (modifyCall modifier call)
    Rpc.Async call use ->
      pureT =<< Rpc.async (modifyCall modifier call) (\ r -> void (runTSimple (use r)))
    Rpc.Notify call ->
      pureT =<< Rpc.notify (modifyCall modifier call)
    Rpc.ChannelId ->
      pureT =<< Rpc.channelId

-- |Prefix all @nvim_commands@ called in an action with @silent@.
silent ::
  Member Rpc r =>
  Sem r a ->
  Sem r a
silent =
  modifyCmd "silent"

-- |Prefix all @nvim_commands@ called in an action with @silent!@.
silentBang ::
  Member Rpc r =>
  Sem r a ->
  Sem r a
silentBang =
  modifyCmd "silent!"

-- |Prefix all @nvim_commands@ called in an action with @noautocmd@.
noautocmd ::
  Member Rpc r =>
  Sem r a ->
  Sem r a
noautocmd =
  modifyCmd "noautocmd"

-- |Prefix all @nvim_commands@ called in an action with @windo N@ where @N@ is the number of the given window.
windo ::
  Member Rpc r =>
  Window ->
  Sem r a ->
  Sem r a
windo win ma = do
  previous <- nvimGetCurrentWin
  number <- nvimWinGetNumber win
  a <- modifyCmd [exon|#{show number}windo|] ma
  when (previous /= win) (vimSetCurrentWindow previous)
  pure a

-- |Prefix all @nvim_commands@ called in an action with @bufdo N@ where @N@ is the number of the given buffer.
bufdo ::
  Member Rpc r =>
  Buffer ->
  Sem r a ->
  Sem r a
bufdo buf ma = do
  previous <- nvimGetCurrentBuf
  number <- nvimBufGetNumber buf
  a <- modifyCmd [exon|#{show number}bufdo|] ma
  when (previous /= buf) (nvimSetCurrentBuf previous)
  pure a