-- |Data types for Neovim mappings
module Ribosome.Data.Mapping where

import Data.MessagePack (Object)

import Ribosome.Host.Class.Msgpack.Decode (MsgpackDecode)
import Ribosome.Host.Class.Msgpack.Encode (MsgpackEncode)
import Ribosome.Host.Data.Event (EventName)
import Ribosome.Host.Data.RpcName (RpcName)

-- |The sequence of keys that triggers a mapping.
newtype MappingLhs =
  MappingLhs { MappingLhs -> Text
unMappingLhs :: Text }
  deriving stock (MappingLhs -> MappingLhs -> Bool
(MappingLhs -> MappingLhs -> Bool)
-> (MappingLhs -> MappingLhs -> Bool) -> Eq MappingLhs
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MappingLhs -> MappingLhs -> Bool
$c/= :: MappingLhs -> MappingLhs -> Bool
== :: MappingLhs -> MappingLhs -> Bool
$c== :: MappingLhs -> MappingLhs -> Bool
Eq, Int -> MappingLhs -> ShowS
[MappingLhs] -> ShowS
MappingLhs -> String
(Int -> MappingLhs -> ShowS)
-> (MappingLhs -> String)
-> ([MappingLhs] -> ShowS)
-> Show MappingLhs
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MappingLhs] -> ShowS
$cshowList :: [MappingLhs] -> ShowS
show :: MappingLhs -> String
$cshow :: MappingLhs -> String
showsPrec :: Int -> MappingLhs -> ShowS
$cshowsPrec :: Int -> MappingLhs -> ShowS
Show)
  deriving newtype (String -> MappingLhs
(String -> MappingLhs) -> IsString MappingLhs
forall a. (String -> a) -> IsString a
fromString :: String -> MappingLhs
$cfromString :: String -> MappingLhs
IsString, Eq MappingLhs
Eq MappingLhs
-> (MappingLhs -> MappingLhs -> Ordering)
-> (MappingLhs -> MappingLhs -> Bool)
-> (MappingLhs -> MappingLhs -> Bool)
-> (MappingLhs -> MappingLhs -> Bool)
-> (MappingLhs -> MappingLhs -> Bool)
-> (MappingLhs -> MappingLhs -> MappingLhs)
-> (MappingLhs -> MappingLhs -> MappingLhs)
-> Ord MappingLhs
MappingLhs -> MappingLhs -> Bool
MappingLhs -> MappingLhs -> Ordering
MappingLhs -> MappingLhs -> MappingLhs
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MappingLhs -> MappingLhs -> MappingLhs
$cmin :: MappingLhs -> MappingLhs -> MappingLhs
max :: MappingLhs -> MappingLhs -> MappingLhs
$cmax :: MappingLhs -> MappingLhs -> MappingLhs
>= :: MappingLhs -> MappingLhs -> Bool
$c>= :: MappingLhs -> MappingLhs -> Bool
> :: MappingLhs -> MappingLhs -> Bool
$c> :: MappingLhs -> MappingLhs -> Bool
<= :: MappingLhs -> MappingLhs -> Bool
$c<= :: MappingLhs -> MappingLhs -> Bool
< :: MappingLhs -> MappingLhs -> Bool
$c< :: MappingLhs -> MappingLhs -> Bool
compare :: MappingLhs -> MappingLhs -> Ordering
$ccompare :: MappingLhs -> MappingLhs -> Ordering
Ord)

-- |This ID type is intended to carry information about what buffer or other component triggered a mapping, if needed.
newtype MappingId =
  MappingId { MappingId -> Text
unMappingId :: Text }
  deriving stock (MappingId -> MappingId -> Bool
(MappingId -> MappingId -> Bool)
-> (MappingId -> MappingId -> Bool) -> Eq MappingId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MappingId -> MappingId -> Bool
$c/= :: MappingId -> MappingId -> Bool
== :: MappingId -> MappingId -> Bool
$c== :: MappingId -> MappingId -> Bool
Eq, Int -> MappingId -> ShowS
[MappingId] -> ShowS
MappingId -> String
(Int -> MappingId -> ShowS)
-> (MappingId -> String)
-> ([MappingId] -> ShowS)
-> Show MappingId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MappingId] -> ShowS
$cshowList :: [MappingId] -> ShowS
show :: MappingId -> String
$cshow :: MappingId -> String
showsPrec :: Int -> MappingId -> ShowS
$cshowsPrec :: Int -> MappingId -> ShowS
Show)
  deriving newtype (String -> MappingId
(String -> MappingId) -> IsString MappingId
forall a. (String -> a) -> IsString a
fromString :: String -> MappingId
$cfromString :: String -> MappingId
IsString, Eq MappingId
Eq MappingId
-> (MappingId -> MappingId -> Ordering)
-> (MappingId -> MappingId -> Bool)
-> (MappingId -> MappingId -> Bool)
-> (MappingId -> MappingId -> Bool)
-> (MappingId -> MappingId -> Bool)
-> (MappingId -> MappingId -> MappingId)
-> (MappingId -> MappingId -> MappingId)
-> Ord MappingId
MappingId -> MappingId -> Bool
MappingId -> MappingId -> Ordering
MappingId -> MappingId -> MappingId
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MappingId -> MappingId -> MappingId
$cmin :: MappingId -> MappingId -> MappingId
max :: MappingId -> MappingId -> MappingId
$cmax :: MappingId -> MappingId -> MappingId
>= :: MappingId -> MappingId -> Bool
$c>= :: MappingId -> MappingId -> Bool
> :: MappingId -> MappingId -> Bool
$c> :: MappingId -> MappingId -> Bool
<= :: MappingId -> MappingId -> Bool
$c<= :: MappingId -> MappingId -> Bool
< :: MappingId -> MappingId -> Bool
$c< :: MappingId -> MappingId -> Bool
compare :: MappingId -> MappingId -> Ordering
$ccompare :: MappingId -> MappingId -> Ordering
Ord, Object -> Either DecodeError MappingId
(Object -> Either DecodeError MappingId) -> MsgpackDecode MappingId
forall a. (Object -> Either DecodeError a) -> MsgpackDecode a
fromMsgpack :: Object -> Either DecodeError MappingId
$cfromMsgpack :: Object -> Either DecodeError MappingId
MsgpackDecode, MappingId -> Object
(MappingId -> Object) -> MsgpackEncode MappingId
forall a. (a -> Object) -> MsgpackEncode a
toMsgpack :: MappingId -> Object
$ctoMsgpack :: MappingId -> Object
MsgpackEncode)

-- |All possible variants of Neovim's @map@ commands, causing mappings to be registered for different modes.
data MapMode =
  -- |@:map@ – normal, visual, select and operator-pending
  MapDefault
  |
  -- |@:nmap@ – normal
  MapNormal
  |
  -- |@:map!@ – insert and cmdline
  MapInsertCmdline
  |
  -- |@:imap@ – insert
  MapInsert
  |
  -- |@:cmap@ – cmdline
  MapCmdline
  |
  -- |@:lmap@ – insert, cmdline, lang-arg
  MapLangArg
  |
  -- |@:xmap@ – visual
  MapVisual
  |
  -- |@:smap@ – select
  MapSelect
  |
  -- |@:vmap@ – visual and select
  MapVisualSelect
  |
  -- |@:omap@ – operator-pending
  MapOperator
  deriving stock (MapMode -> MapMode -> Bool
(MapMode -> MapMode -> Bool)
-> (MapMode -> MapMode -> Bool) -> Eq MapMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MapMode -> MapMode -> Bool
$c/= :: MapMode -> MapMode -> Bool
== :: MapMode -> MapMode -> Bool
$c== :: MapMode -> MapMode -> Bool
Eq, Int -> MapMode -> ShowS
[MapMode] -> ShowS
MapMode -> String
(Int -> MapMode -> ShowS)
-> (MapMode -> String) -> ([MapMode] -> ShowS) -> Show MapMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MapMode] -> ShowS
$cshowList :: [MapMode] -> ShowS
show :: MapMode -> String
$cshow :: MapMode -> String
showsPrec :: Int -> MapMode -> ShowS
$cshowsPrec :: Int -> MapMode -> ShowS
Show, Eq MapMode
Eq MapMode
-> (MapMode -> MapMode -> Ordering)
-> (MapMode -> MapMode -> Bool)
-> (MapMode -> MapMode -> Bool)
-> (MapMode -> MapMode -> Bool)
-> (MapMode -> MapMode -> Bool)
-> (MapMode -> MapMode -> MapMode)
-> (MapMode -> MapMode -> MapMode)
-> Ord MapMode
MapMode -> MapMode -> Bool
MapMode -> MapMode -> Ordering
MapMode -> MapMode -> MapMode
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MapMode -> MapMode -> MapMode
$cmin :: MapMode -> MapMode -> MapMode
max :: MapMode -> MapMode -> MapMode
$cmax :: MapMode -> MapMode -> MapMode
>= :: MapMode -> MapMode -> Bool
$c>= :: MapMode -> MapMode -> Bool
> :: MapMode -> MapMode -> Bool
$c> :: MapMode -> MapMode -> Bool
<= :: MapMode -> MapMode -> Bool
$c<= :: MapMode -> MapMode -> Bool
< :: MapMode -> MapMode -> Bool
$c< :: MapMode -> MapMode -> Bool
compare :: MapMode -> MapMode -> Ordering
$ccompare :: MapMode -> MapMode -> Ordering
Ord, Int -> MapMode
MapMode -> Int
MapMode -> [MapMode]
MapMode -> MapMode
MapMode -> MapMode -> [MapMode]
MapMode -> MapMode -> MapMode -> [MapMode]
(MapMode -> MapMode)
-> (MapMode -> MapMode)
-> (Int -> MapMode)
-> (MapMode -> Int)
-> (MapMode -> [MapMode])
-> (MapMode -> MapMode -> [MapMode])
-> (MapMode -> MapMode -> [MapMode])
-> (MapMode -> MapMode -> MapMode -> [MapMode])
-> Enum MapMode
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: MapMode -> MapMode -> MapMode -> [MapMode]
$cenumFromThenTo :: MapMode -> MapMode -> MapMode -> [MapMode]
enumFromTo :: MapMode -> MapMode -> [MapMode]
$cenumFromTo :: MapMode -> MapMode -> [MapMode]
enumFromThen :: MapMode -> MapMode -> [MapMode]
$cenumFromThen :: MapMode -> MapMode -> [MapMode]
enumFrom :: MapMode -> [MapMode]
$cenumFrom :: MapMode -> [MapMode]
fromEnum :: MapMode -> Int
$cfromEnum :: MapMode -> Int
toEnum :: Int -> MapMode
$ctoEnum :: Int -> MapMode
pred :: MapMode -> MapMode
$cpred :: MapMode -> MapMode
succ :: MapMode -> MapMode
$csucc :: MapMode -> MapMode
Enum)

instance Default MapMode where
  def :: MapMode
def =
    MapMode
MapNormal

-- |The character representing a map mode prefixing a @map@ command.
mapModePrefix :: MapMode -> Text
mapModePrefix :: MapMode -> Text
mapModePrefix = \case
  MapMode
MapDefault -> Text
""
  MapMode
MapNormal -> Text
"n"
  MapMode
MapInsertCmdline -> Text
""
  MapMode
MapInsert -> Text
"i"
  MapMode
MapCmdline -> Text
"c"
  MapMode
MapLangArg -> Text
"l"
  MapMode
MapVisual -> Text
"x"
  MapMode
MapSelect -> Text
"s"
  MapMode
MapVisualSelect -> Text
"v"
  MapMode
MapOperator -> Text
"o"

-- |The bang suffixing the insert+cmdline map cmd.
mapModeSuffix :: MapMode -> Text
mapModeSuffix :: MapMode -> Text
mapModeSuffix = \case
  MapMode
MapInsertCmdline -> Text
"!"
  MapMode
_ -> Text
""

-- |The character representing a map mode when passing it to an api function.
mapModeShortName :: MapMode -> Text
mapModeShortName :: MapMode -> Text
mapModeShortName MapMode
m =
  MapMode -> Text
mapModePrefix MapMode
m Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> MapMode -> Text
mapModeSuffix MapMode
m

-- |The action that should be performed when a mapping is triggered.
data MappingAction =
  -- |The name of the 'Ribosome.RpcHandler' that should be called when the mapping is triggered.
  MappingCall RpcName
  |
  -- |The event to publish when the mapping is triggered.
  MappingEvent EventName
  deriving stock (MappingAction -> MappingAction -> Bool
(MappingAction -> MappingAction -> Bool)
-> (MappingAction -> MappingAction -> Bool) -> Eq MappingAction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MappingAction -> MappingAction -> Bool
$c/= :: MappingAction -> MappingAction -> Bool
== :: MappingAction -> MappingAction -> Bool
$c== :: MappingAction -> MappingAction -> Bool
Eq, Int -> MappingAction -> ShowS
[MappingAction] -> ShowS
MappingAction -> String
(Int -> MappingAction -> ShowS)
-> (MappingAction -> String)
-> ([MappingAction] -> ShowS)
-> Show MappingAction
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MappingAction] -> ShowS
$cshowList :: [MappingAction] -> ShowS
show :: MappingAction -> String
$cshow :: MappingAction -> String
showsPrec :: Int -> MappingAction -> ShowS
$cshowsPrec :: Int -> MappingAction -> ShowS
Show)

-- |The configuration for a mapping that is specific to Neovim.
data MappingSpec =
  MappingSpec {
    -- |The key sequence that triggers the mapping.
    MappingSpec -> MappingLhs
lhs :: MappingLhs,
    -- |The modes in which the mapping should be installed.
    MappingSpec -> NonEmpty MapMode
mode :: NonEmpty MapMode
  }
  deriving stock (MappingSpec -> MappingSpec -> Bool
(MappingSpec -> MappingSpec -> Bool)
-> (MappingSpec -> MappingSpec -> Bool) -> Eq MappingSpec
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MappingSpec -> MappingSpec -> Bool
$c/= :: MappingSpec -> MappingSpec -> Bool
== :: MappingSpec -> MappingSpec -> Bool
$c== :: MappingSpec -> MappingSpec -> Bool
Eq, Int -> MappingSpec -> ShowS
[MappingSpec] -> ShowS
MappingSpec -> String
(Int -> MappingSpec -> ShowS)
-> (MappingSpec -> String)
-> ([MappingSpec] -> ShowS)
-> Show MappingSpec
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MappingSpec] -> ShowS
$cshowList :: [MappingSpec] -> ShowS
show :: MappingSpec -> String
$cshow :: MappingSpec -> String
showsPrec :: Int -> MappingSpec -> ShowS
$cshowsPrec :: Int -> MappingSpec -> ShowS
Show, Eq MappingSpec
Eq MappingSpec
-> (MappingSpec -> MappingSpec -> Ordering)
-> (MappingSpec -> MappingSpec -> Bool)
-> (MappingSpec -> MappingSpec -> Bool)
-> (MappingSpec -> MappingSpec -> Bool)
-> (MappingSpec -> MappingSpec -> Bool)
-> (MappingSpec -> MappingSpec -> MappingSpec)
-> (MappingSpec -> MappingSpec -> MappingSpec)
-> Ord MappingSpec
MappingSpec -> MappingSpec -> Bool
MappingSpec -> MappingSpec -> Ordering
MappingSpec -> MappingSpec -> MappingSpec
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MappingSpec -> MappingSpec -> MappingSpec
$cmin :: MappingSpec -> MappingSpec -> MappingSpec
max :: MappingSpec -> MappingSpec -> MappingSpec
$cmax :: MappingSpec -> MappingSpec -> MappingSpec
>= :: MappingSpec -> MappingSpec -> Bool
$c>= :: MappingSpec -> MappingSpec -> Bool
> :: MappingSpec -> MappingSpec -> Bool
$c> :: MappingSpec -> MappingSpec -> Bool
<= :: MappingSpec -> MappingSpec -> Bool
$c<= :: MappingSpec -> MappingSpec -> Bool
< :: MappingSpec -> MappingSpec -> Bool
$c< :: MappingSpec -> MappingSpec -> Bool
compare :: MappingSpec -> MappingSpec -> Ordering
$ccompare :: MappingSpec -> MappingSpec -> Ordering
Ord, (forall x. MappingSpec -> Rep MappingSpec x)
-> (forall x. Rep MappingSpec x -> MappingSpec)
-> Generic MappingSpec
forall x. Rep MappingSpec x -> MappingSpec
forall x. MappingSpec -> Rep MappingSpec x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MappingSpec x -> MappingSpec
$cfrom :: forall x. MappingSpec -> Rep MappingSpec x
Generic)

instance IsString MappingSpec where
  fromString :: String -> MappingSpec
fromString String
s =
    MappingLhs -> NonEmpty MapMode -> MappingSpec
MappingSpec (String -> MappingLhs
forall a. IsString a => String -> a
fromString String
s) [Item (NonEmpty MapMode)
forall a. Default a => a
def]

-- |This type associates a sequence of keys and a mode for a Neovim mapping with an RPC handler or event.
-- It is intended to be used with 'Ribosome.mappingFor' or 'Ribosome.eventMapping' and 'Ribosome.activateBufferMapping'.
data Mapping =
  Mapping {
    -- |The action to take when the mapping is triggered.
    Mapping -> MappingAction
action :: MappingAction,
    -- |The Neovim related configuration for the mapping, i.e. its key sequence and modes.
    Mapping -> MappingSpec
spec :: MappingSpec,
    -- |An optional string identifying the source of the mapping, for example when adding it to multiple buffers.
    Mapping -> Maybe MappingId
id :: Maybe MappingId,
    -- |Options like @remap@, @nowait@ or @desc@.
    Mapping -> Map Text Object
opts :: Map Text Object
  }
  deriving stock (Mapping -> Mapping -> Bool
(Mapping -> Mapping -> Bool)
-> (Mapping -> Mapping -> Bool) -> Eq Mapping
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Mapping -> Mapping -> Bool
$c/= :: Mapping -> Mapping -> Bool
== :: Mapping -> Mapping -> Bool
$c== :: Mapping -> Mapping -> Bool
Eq, Int -> Mapping -> ShowS
[Mapping] -> ShowS
Mapping -> String
(Int -> Mapping -> ShowS)
-> (Mapping -> String) -> ([Mapping] -> ShowS) -> Show Mapping
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Mapping] -> ShowS
$cshowList :: [Mapping] -> ShowS
show :: Mapping -> String
$cshow :: Mapping -> String
showsPrec :: Int -> Mapping -> ShowS
$cshowsPrec :: Int -> Mapping -> ShowS
Show, (forall x. Mapping -> Rep Mapping x)
-> (forall x. Rep Mapping x -> Mapping) -> Generic Mapping
forall x. Rep Mapping x -> Mapping
forall x. Mapping -> Rep Mapping x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Mapping x -> Mapping
$cfrom :: forall x. Mapping -> Rep Mapping x
Generic)