rasa-0.1.0.0: src/Rasa.hs
{-# language ExistentialQuantification, Rank2Types, ScopedTypeVariables #-}
module Rasa (rasa) where
import Rasa.Internal.Editor
import Rasa.Internal.Action
import Rasa.Internal.Events
import Rasa.Internal.Scheduler
import Control.Lens
import Control.Concurrent.Async
import Control.Monad
import Control.Monad.State
import Control.Monad.Reader
import Data.Default (def)
import Data.Foldable
-- | The main function to run rasa.
--
-- @rasa eventProviders extensions@
--
-- This should be imported by a user-config and called with extension event providers and extension event hooks as
-- arguments. e.g.:
--
-- > rasa [slateEvent] $ do
-- > cursor
-- > vim
rasa :: [Action [Keypress]] -> Scheduler () -> IO ()
rasa eventProviders scheduler =
evalAction def hooks $ do
dispatchEvent Init
eventLoop eventProviders
dispatchEvent Exit
where hooks = getHooks scheduler
-- | This is the main event loop, it runs recursively forever until something
-- sets 'Rasa.Editor.exiting'. It runs the pre-event hooks, then listens for an
-- event from the event providers, then runs the post event hooks and repeats.
eventLoop :: [Action [Keypress]] -> Action ()
eventLoop eventProviders = do
dispatchEvent BeforeRender
dispatchEvent OnRender
dispatchEvent AfterRender
dispatchEvent BeforeEvent
currentEditor <- get
hooks <- ask
-- This is a little weird, but I think it needs to be this way to execute providers in parallel
asyncEventProviders <- liftIO $ traverse (async.evalAction currentEditor hooks) eventProviders
(_, nextEvents) <- liftIO $ waitAny asyncEventProviders
traverse_ dispatchEvent nextEvents
isExiting <- use exiting
unless isExiting $ eventLoop eventProviders