module Ribosome.Plugin.Watch where import Control.Lens (Lens') import qualified Control.Lens as Lens (at) import qualified Data.Map.Strict as Map (toList) import Data.MessagePack (Object(ObjectNil)) import Ribosome.Control.Lock (lockOrSkip) import Ribosome.Control.Monad.Ribo (MonadRibo, NvimE, pluginInternalL, pluginInternalModifyL) import Ribosome.Control.Ribosome (RibosomeInternal) import qualified Ribosome.Control.Ribosome as RibosomeInternal (watchedVariables) import Ribosome.Nvim.Api.IO (vimGetVar) import Ribosome.Nvim.Api.RpcCall (RpcError) data WatchedVariable m = WatchedVariable { WatchedVariable m -> Text wvName :: Text, WatchedVariable m -> Object -> m () wvHandler :: Object -> m () } watchedVariables :: Map Text (Object -> m ()) -> [WatchedVariable m] watchedVariables :: Map Text (Object -> m ()) -> [WatchedVariable m] watchedVariables = ((Text, Object -> m ()) -> WatchedVariable m) -> [(Text, Object -> m ())] -> [WatchedVariable m] forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap (Text, Object -> m ()) -> WatchedVariable m forall (m :: * -> *). (Text, Object -> m ()) -> WatchedVariable m create ([(Text, Object -> m ())] -> [WatchedVariable m]) -> (Map Text (Object -> m ()) -> [(Text, Object -> m ())]) -> Map Text (Object -> m ()) -> [WatchedVariable m] forall b c a. (b -> c) -> (a -> b) -> a -> c . Map Text (Object -> m ()) -> [(Text, Object -> m ())] forall k a. Map k a -> [(k, a)] Map.toList where create :: (Text, Object -> m ()) -> WatchedVariable m create (Text name, Object -> m () handler) = Text -> (Object -> m ()) -> WatchedVariable m forall (m :: * -> *). Text -> (Object -> m ()) -> WatchedVariable m WatchedVariable Text name Object -> m () handler storedVarLens :: Text -> Lens' RibosomeInternal (Maybe Object) storedVarLens :: Text -> Lens' RibosomeInternal (Maybe Object) storedVarLens Text name = (Map Text Object -> f (Map Text Object)) -> RibosomeInternal -> f RibosomeInternal forall c. HasRibosomeInternal c => Lens' c (Map Text Object) RibosomeInternal.watchedVariables ((Map Text Object -> f (Map Text Object)) -> RibosomeInternal -> f RibosomeInternal) -> ((Maybe Object -> f (Maybe Object)) -> Map Text Object -> f (Map Text Object)) -> (Maybe Object -> f (Maybe Object)) -> RibosomeInternal -> f RibosomeInternal forall b c a. (b -> c) -> (a -> b) -> a -> c . Index (Map Text Object) -> Lens' (Map Text Object) (Maybe (IxValue (Map Text Object))) forall m. At m => Index m -> Lens' m (Maybe (IxValue m)) Lens.at Text Index (Map Text Object) name runHandler :: MonadRibo m => WatchedVariable m -> Object -> m () runHandler :: WatchedVariable m -> Object -> m () runHandler (WatchedVariable Text name Object -> m () handler) Object new = do Lens' RibosomeInternal (Maybe Object) -> (Maybe Object -> Maybe Object) -> m () forall (m :: * -> *) a. MonadRibo m => Lens' RibosomeInternal a -> (a -> a) -> m () pluginInternalModifyL (Text -> Lens' RibosomeInternal (Maybe Object) storedVarLens Text name) (Maybe Object -> Maybe Object -> Maybe Object forall a b. a -> b -> a const (Object -> Maybe Object forall a. a -> Maybe a Just Object new)) Object -> m () handler Object new compareVar :: MonadRibo m => WatchedVariable m -> Maybe Object -> Object -> m () compareVar :: WatchedVariable m -> Maybe Object -> Object -> m () compareVar WatchedVariable m _ (Just Object old) Object new | Object old Object -> Object -> Bool forall a. Eq a => a -> a -> Bool == Object new = () -> m () forall (m :: * -> *) a. Monad m => a -> m a return () compareVar WatchedVariable m wv Maybe Object _ Object new = WatchedVariable m -> Object -> m () forall (m :: * -> *). MonadRibo m => WatchedVariable m -> Object -> m () runHandler WatchedVariable m wv Object new checkVar :: MonadRibo m => NvimE e m => WatchedVariable m -> m () checkVar :: WatchedVariable m -> m () checkVar wv :: WatchedVariable m wv@(WatchedVariable Text name Object -> m () _) = do Maybe Object old <- Lens' RibosomeInternal (Maybe Object) -> m (Maybe Object) forall (m :: * -> *) a. MonadRibo m => Lens' RibosomeInternal a -> m a pluginInternalL (Text -> Lens' RibosomeInternal (Maybe Object) storedVarLens Text name) Either () Object new <- (RpcError -> m (Either () Object)) -> m (Either () Object) -> m (Either () Object) forall e' e (m :: * -> *) a. MonadDeepError e e' m => (e' -> m a) -> m a -> m a catchAt @RpcError RpcError -> m (Either () Object) forall (m :: * -> *) p b. Monad m => p -> m (Either () b) recover (Object -> Either () Object forall a b. b -> Either a b Right (Object -> Either () Object) -> m Object -> m (Either () Object) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Text -> m Object forall (m :: * -> *) e a. (Nvim m, MonadDeepError e RpcError m, MsgpackDecode a) => Text -> m a vimGetVar Text name) (Object -> m ()) -> Either () Object -> m () forall (t :: * -> *) (f :: * -> *) a b. (Foldable t, Applicative f) => (a -> f b) -> t a -> f () traverse_ (WatchedVariable m -> Maybe Object -> Object -> m () forall (m :: * -> *). MonadRibo m => WatchedVariable m -> Maybe Object -> Object -> m () compareVar WatchedVariable m wv Maybe Object old) Either () Object new where recover :: p -> m (Either () b) recover p _ = Either () b -> m (Either () b) forall (m :: * -> *) a. Monad m => a -> m a return (() -> Either () b forall a b. a -> Either a b Left ()) handleWatcherRequest :: MonadRibo m => NvimE e m => [WatchedVariable m] -> [Object] -> m Object handleWatcherRequest :: [WatchedVariable m] -> [Object] -> m Object handleWatcherRequest [WatchedVariable m] variables [Object] _ = Object ObjectNil Object -> m () -> m Object forall (f :: * -> *) a b. Functor f => a -> f b -> f a <$ (WatchedVariable m -> m ()) -> [WatchedVariable m] -> m () forall (t :: * -> *) (f :: * -> *) a b. (Foldable t, Applicative f) => (a -> f b) -> t a -> f () traverse_ WatchedVariable m -> m () forall (m :: * -> *) e. (MonadRibo m, NvimE e m) => WatchedVariable m -> m () checkVar [WatchedVariable m] variables handleWatcherRequestSafe :: MonadBaseControl IO m => MonadRibo m => NvimE e m => [WatchedVariable m] -> [Object] -> m Object handleWatcherRequestSafe :: [WatchedVariable m] -> [Object] -> m Object handleWatcherRequestSafe [WatchedVariable m] variables [Object] o = Object ObjectNil Object -> m () -> m Object forall (f :: * -> *) a b. Functor f => a -> f b -> f a <$ Text -> m () -> m () forall (m :: * -> *). (MonadRibo m, MonadBaseControl IO m) => Text -> m () -> m () lockOrSkip Text "variable-watcher" (m Object -> m () forall (f :: * -> *) a. Functor f => f a -> f () void (m Object -> m ()) -> m Object -> m () forall a b. (a -> b) -> a -> b $ [WatchedVariable m] -> [Object] -> m Object forall (m :: * -> *) e. (MonadRibo m, NvimE e m) => [WatchedVariable m] -> [Object] -> m Object handleWatcherRequest [WatchedVariable m] variables [Object] o)