hob-0.0.1.0: src/lib/Hob/Context.hs
module Hob.Context (
App,
Context(..),
PreviewCommandHandler(..),
CommandHandler(..),
CommandMatcher(..),
KeyboardBinding,
KeyCommandMatcher,
TextCommandMatcher,
Mode(..),
Event(..),
Editor(..),
EditorList(..),
initContext,
runOnEditor,
enterMode,
exitLastMode,
activeModes,
deferredRunner,
registerEventHandler,
emitEvent,
createMatcherForPrefix,
createMatcherForCommand,
createMatcherForKeyBinding,
fromContext,
runApp,
getActiveCommands,
) where
import Control.Concurrent.MVar
import Control.Monad.Reader
import Graphics.UI.Gtk (postGUIAsync)
import GtkExtras.LargeTreeStore as LTS (TreeStore)
import Hob.Context.CommandMatcher
import Hob.Context.Editor
import Hob.Context.Events
import Hob.Context.FileContext
import Hob.Context.StyleContext
import Hob.Context.Types
import Hob.Context.UiContext
import Hob.DirectoryTree
initContext :: StyleContext -> FileContext -> UiContext -> LTS.TreeStore DirectoryTreeElement -> CommandMatcher -> IO Context
initContext styleCtx fileCtx uiCtx treeModel initCommands = do
actionSync <- newMVar True
deferredMessagesRef <- newMVar []
bus <- initEventBus
editorList <- initEditors
initialisedIdGenerator <- initIdGenerator
let ctx = Context styleCtx fileCtx uiCtx treeModel initCommands editorList (messageRunner actionSync deferredMessagesRef) bus initialisedIdGenerator
return ctx
where
messageRunner actionSync deferredMessagesRef ctx message = do
queueMessage deferredMessagesRef message
sync <- tryTakeMVar actionSync
case sync of
Just _ -> flushMessageQueue deferredMessagesRef ctx >> putMVar actionSync True
Nothing -> return()
flushMessageQueue deferredMessagesRef ctx = do
messages <- swapMVar deferredMessagesRef []
unless (null messages) $ foldM runMessage ctx messages >>= flushMessageQueue deferredMessagesRef
queueMessage deferredMessagesRef message = modifyMVar_ deferredMessagesRef (\messages -> return $ messages ++ [message])
runApp :: Context -> App a -> IO a
runApp ctx appSteps = runReaderT appSteps ctx
runMessage :: Context -> Message -> IO Context
runMessage ctx (AppAction action) = runApp ctx action >> return ctx
deferredRunner :: Context -> App() -> IO()
deferredRunner ctx actions = postGUIAsync $ messageLoop ctx ctx $ AppAction actions
initIdGenerator :: IO (IO Int)
initIdGenerator = do
generatorStorage <- newMVar 0
return $ do
lastGeneratdId <- takeMVar generatorStorage
let newId = lastGeneratdId + 1
putMVar generatorStorage newId
return newId