packages feed

ribosome-0.4.0.0: lib/Ribosome/Api/Buffer.hs

module Ribosome.Api.Buffer where

import Data.MessagePack (Object)
import qualified Data.Text as Text (null)
import System.FilePath ((</>))

import Ribosome.Api.Atomic (atomicAs)
import Ribosome.Api.Path (nvimCwd)
import Ribosome.Control.Monad.Ribo (NvimE)
import Ribosome.Msgpack.Encode (toMsgpack)
import Ribosome.Msgpack.Error (DecodeError)
import Ribosome.Nvim.Api.Data (Buffer)
import qualified Ribosome.Nvim.Api.Data as ApiData (bufferGetName)
import Ribosome.Nvim.Api.IO (
  bufferGetLines,
  bufferGetName,
  bufferGetNumber,
  bufferGetOption,
  bufferIsValid,
  bufferSetLines,
  nvimWinSetBuf,
  vimCallFunction,
  vimCommand,
  vimGetBuffers,
  vimGetCurrentBuffer,
  vimGetCurrentWindow,
  )
import Ribosome.Nvim.Api.RpcCall (RpcError, syncRpcCall)

edit :: NvimE e m => FilePath -> m ()
edit path = vimCommand $ "silent! edit " <> toText path

nvimCallBool :: NvimE e m => Text -> [Object] -> m Bool
nvimCallBool =
  vimCallFunction

buflisted :: NvimE e m => Buffer -> m Bool
buflisted buf = do
  catchAs @RpcError False do
    num <- bufferGetNumber buf
    nvimCallBool "buflisted" [toMsgpack num]

bufferContent :: NvimE e m => Buffer -> m [Text]
bufferContent buffer =
  bufferGetLines buffer 0 (-1) False

currentBufferContent :: NvimE e m => m [Text]
currentBufferContent =
  bufferContent =<< vimGetCurrentBuffer

setBufferContent :: NvimE e m => Buffer -> [Text] -> m ()
setBufferContent buffer =
  bufferSetLines buffer 0 (-1) False

setBufferLine :: NvimE e m => Buffer -> Int -> Text -> m ()
setBufferLine buffer line text =
  bufferSetLines buffer line (line + 1) False [text]

setCurrentBufferContent ::
  NvimE e m =>
  [Text] ->
  m ()
setCurrentBufferContent content = do
  buffer <- vimGetCurrentBuffer
  setBufferContent buffer content

withBufferNumber ::
  NvimE e m =>
  (Int -> m ()) ->
  Buffer ->
  m ()
withBufferNumber run buffer =
  whenM (bufferIsValid buffer) (run =<< bufferGetNumber buffer)

closeBuffer ::
  NvimE e m =>
  Buffer ->
  m ()
closeBuffer =
  withBufferNumber del
  where
    del number =
      vimCommand ("silent! bdelete! " <> show number)

wipeBuffer ::
  NvimE e m =>
  Buffer ->
  m ()
wipeBuffer =
  withBufferNumber wipe
  where
    wipe number =
      vimCommand ("silent! bwipeout! " <> show number)

unloadBuffer ::
  NvimE e m =>
  Buffer ->
  m ()
unloadBuffer =
  withBufferNumber unload
  where
    unload number =
      vimCommand ("silent! bunload! " <> show number)

addBuffer ::
  NvimE e m =>
  Text ->
  m ()
addBuffer path =
  vimCommand ("badd " <> path)

buffersAndNames ::
  MonadIO m =>
  MonadDeepError e DecodeError m =>
  NvimE e m =>
  m [(Buffer, Text)]
buffersAndNames = do
  buffers <- vimGetBuffers
  names <- atomicAs (syncRpcCall . ApiData.bufferGetName <$> buffers)
  return (zip buffers names)

bufferForFile ::
  MonadIO m =>
  MonadDeepError e DecodeError m =>
  NvimE e m =>
  Text ->
  m (Maybe Buffer)
bufferForFile target = do
  cwd <- nvimCwd
  fmap fst . find sameBuffer . fmap (second (toText . absolute cwd . toString)) <$> buffersAndNames
  where
    sameBuffer (_, name) = name == target
    absolute dir ('.' : '/' : rest) =
      dir </> rest
    absolute _ p@('/' : _) =
      p
    absolute dir path =
      dir </> path

currentBufferName ::
  NvimE e m =>
  m Text
currentBufferName =
  bufferGetName =<< vimGetCurrentBuffer

setCurrentBuffer ::
  NvimE e m =>
  Buffer ->
  m ()
setCurrentBuffer buf = do
  win <- vimGetCurrentWindow
  nvimWinSetBuf win buf

bufferIsFile ::
  NvimE e m =>
  Buffer ->
  m Bool
bufferIsFile buf =
  Text.null <$> bufferGetOption buf "buftype"

bufferCount ::
  NvimE e m =>
  m Natural
bufferCount =
  fromIntegral . length <$> vimGetBuffers