-- |API functions for registers.
module Ribosome.Api.Register where

import Ribosome.Data.Register (Register)
import qualified Ribosome.Data.Register as Register (Register (..))
import Ribosome.Data.RegisterType (RegisterType)
import qualified Ribosome.Data.RegisterType as RegisterType (RegisterType (..))
import Ribosome.Host.Api.Effect (vimCallFunction)
import Ribosome.Host.Class.Msgpack.Array (msgpackArray)
import Ribosome.Host.Class.Msgpack.Decode (MsgpackDecode)
import Ribosome.Host.Class.Msgpack.Encode (MsgpackEncode (toMsgpack))
import Ribosome.Host.Effect.Rpc (Rpc)

-- |The special register referring to the primary X11 selection.
starRegister :: Register
starRegister :: Register
starRegister =
  Text -> Register
Register.Special Text
"*"

-- |The special register referring to the clipboard X11 selection.
plusRegister :: Register
plusRegister :: Register
plusRegister =
  Text -> Register
Register.Special Text
"+"

-- |The special register referring to the unnamed register.
unnamedRegister :: Register
unnamedRegister :: Register
unnamedRegister =
  Text -> Register
Register.Special Text
"\""

-- |Set a Neovim register's contents, using the specified type.
--
-- A register's type determines whether the contents are supposed to be pasted as lines or characters, for example.
setregAs ::
  Member Rpc r =>
  MsgpackEncode a =>
  RegisterType ->
  Register ->
  a ->
  Sem r ()
setregAs :: forall (r :: EffectRow) a.
(Member Rpc r, MsgpackEncode a) =>
RegisterType -> Register -> a -> Sem r ()
setregAs RegisterType
regType Register
register a
text =
  Text -> [Object] -> Sem r ()
forall a (r :: EffectRow).
(Member Rpc r, MsgpackDecode a) =>
Text -> [Object] -> Sem r a
vimCallFunction Text
"setreg" (Register -> a -> RegisterType -> [Object]
forall a. MsgpackArray a => a
msgpackArray Register
register a
text RegisterType
regType)

-- |Set a Neovim register's contents as inline characters.
setreg ::
  Member Rpc r =>
  Register ->
  Text ->
  Sem r ()
setreg :: forall (r :: EffectRow).
Member Rpc r =>
Register -> Text -> Sem r ()
setreg =
  RegisterType -> Register -> Text -> Sem r ()
forall (r :: EffectRow) a.
(Member Rpc r, MsgpackEncode a) =>
RegisterType -> Register -> a -> Sem r ()
setregAs RegisterType
RegisterType.Character

-- |Set a Neovim register's contents as whole lines.
setregLine ::
  Member Rpc r =>
  Register ->
  [Text] ->
  Sem r ()
setregLine :: forall (r :: EffectRow).
Member Rpc r =>
Register -> [Text] -> Sem r ()
setregLine =
  RegisterType -> Register -> [Text] -> Sem r ()
forall (r :: EffectRow) a.
(Member Rpc r, MsgpackEncode a) =>
RegisterType -> Register -> a -> Sem r ()
setregAs RegisterType
RegisterType.Line

-- |Get the type of a register's contents.
getregtype ::
  Member Rpc r =>
  Register ->
  Sem r RegisterType
getregtype :: forall (r :: EffectRow).
Member Rpc r =>
Register -> Sem r RegisterType
getregtype Register
register =
  Text -> [Object] -> Sem r RegisterType
forall a (r :: EffectRow).
(Member Rpc r, MsgpackDecode a) =>
Text -> [Object] -> Sem r a
vimCallFunction Text
"getregtype" [Register -> Object
forall a. MsgpackEncode a => a -> Object
toMsgpack Register
register]

-- |Get a Neovim register's contents, using the specified type.
--
-- A register's type determines whether the contents are supposed to be pasted as lines or characters, for example.
getregAs ::
  Member Rpc r =>
  MsgpackDecode a =>
  Bool ->
  Register ->
  Sem r a
getregAs :: forall (r :: EffectRow) a.
(Member Rpc r, MsgpackDecode a) =>
Bool -> Register -> Sem r a
getregAs Bool
list Register
register =
  Text -> [Object] -> Sem r a
forall a (r :: EffectRow).
(Member Rpc r, MsgpackDecode a) =>
Text -> [Object] -> Sem r a
vimCallFunction Text
"getreg" (Register -> Int -> Bool -> [Object]
forall a. MsgpackArray a => a
msgpackArray Register
register (Int
0 :: Int) Bool
list)

-- |Get a Neovim register's contents as inline characters.
getreg ::
  Member Rpc r =>
  Register ->
  Sem r (Either [Text] Text)
getreg :: forall (r :: EffectRow).
Member Rpc r =>
Register -> Sem r (Either [Text] Text)
getreg Register
register =
  RegisterType -> Sem r (Either [Text] Text)
withType (RegisterType -> Sem r (Either [Text] Text))
-> Sem r RegisterType -> Sem r (Either [Text] Text)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Register -> Sem r RegisterType
forall (r :: EffectRow).
Member Rpc r =>
Register -> Sem r RegisterType
getregtype Register
register
  where
    withType :: RegisterType -> Sem r (Either [Text] Text)
withType RegisterType
RegisterType.Line =
      [Text] -> Either [Text] Text
forall a b. a -> Either a b
Left ([Text] -> Either [Text] Text)
-> Sem r [Text] -> Sem r (Either [Text] Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Bool -> Register -> Sem r [Text]
forall (r :: EffectRow) a.
(Member Rpc r, MsgpackDecode a) =>
Bool -> Register -> Sem r a
getregAs Bool
True Register
register
    withType RegisterType
_ =
      Text -> Either [Text] Text
forall a b. b -> Either a b
Right (Text -> Either [Text] Text)
-> Sem r Text -> Sem r (Either [Text] Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Bool -> Register -> Sem r Text
forall (r :: EffectRow) a.
(Member Rpc r, MsgpackDecode a) =>
Bool -> Register -> Sem r a
getregAs Bool
False Register
register

-- |Get a Neovim register's contents as whole lines.
getregLines ::
  Member Rpc r =>
  Register ->
  Sem r [Text]
getregLines :: forall (r :: EffectRow). Member Rpc r => Register -> Sem r [Text]
getregLines =
  Bool -> Register -> Sem r [Text]
forall (r :: EffectRow) a.
(Member Rpc r, MsgpackDecode a) =>
Bool -> Register -> Sem r a
getregAs Bool
True