on develop help sign in
Add more comments from the reflex-vty host
3e36d45Carlo Nucera
src/Reflex/Host/Headless.hs+46−7
@@ -48,28 +48,67 @@ runHeadlessApp
48 -- closed at the first occurrence of the resulting 'Event'.
48 -- closed at the first occurrence of the resulting 'Event'.
49 -> IO ()
49 -> IO ()
50runHeadlessApp guest =
50runHeadlessApp guest =
51+ -- We are using the 'Spider' implementation of reflex. Running the host
52+ -- allows us to take actions on the FRP timeline. The scoped type signature
53+ -- specifies that our host runs on the Global timeline.
54+ -- For more information, see 'Reflex.Spider.Internal.runSpiderHost'.
51 (runSpiderHost :: SpiderHost Global a -> IO a) $ do
55 (runSpiderHost :: SpiderHost Global a -> IO a) $ do
56+ -- Create the "post-build" event and associated trigger. This event fires
57+ -- once, when the application starts.
52 (postBuild, postBuildTriggerRef) <- newEventWithTriggerRef
58 (postBuild, postBuildTriggerRef) <- newEventWithTriggerRef
59+ -- Create a queue to which we will write 'Event's that need to be
60+ -- processed.
53 events <- liftIO newChan
61 events <- liftIO newChan
62+ -- Run the "guest" application, providing the appropriate context. We'll
63+ -- return the result of the action, and a 'FireCommand' that will be used to
64+ -- trigger events.
54 (result, fc@(FireCommand fire)) <- do
65 (result, fc@(FireCommand fire)) <- do
55− hostPerformEventT $
66+ hostPerformEventT $ -- Allows the guest app to run
67+ -- 'performEvent', so that actions
68+ -- (e.g., IO actions) can be run when
69+ -- 'Event's fire.
70+
56− flip runPostBuildT postBuild $
71+ flip runPostBuildT postBuild $ -- Allows the guest app to access to
72+ -- a "post-build" 'Event'
73+
57− flip runTriggerEventT events $
74+ flip runTriggerEventT events $ -- Allows the guest app to create new
75+ -- events and triggers and write
76+ -- those triggers to a channel from
77+ -- which they will be read and
78+ -- processed.
58 guest
79 guest
80+
81+ -- Read the trigger reference for the post-build event. This will be
82+ -- 'Nothing' if the guest application hasn't subscribed to this event.
59 mPostBuildTrigger <- readRef postBuildTriggerRef
83 mPostBuildTrigger <- readRef postBuildTriggerRef
84+
85+ -- When there is a subscriber to the post-build event, fire the event.
60 forM_ mPostBuildTrigger $ \postBuildTrigger ->
86 forM_ mPostBuildTrigger $ \postBuildTrigger ->
61 fire [postBuildTrigger :=> Identity ()] $ return ()
87 fire [postBuildTrigger :=> Identity ()] $ return ()
88+
89+ -- Subscribe to an 'Event' of that the guest application can use to
90+ -- request application shutdown. We'll check whether this 'Event' is firing
91+ -- to determine whether to terminate.
62 shutdown <- subscribeEvent result
92 shutdown <- subscribeEvent result
93+
94+ -- The main application loop. We wait for new events and fire those that
95+ -- have subscribers. If we detect a shutdown request, the application
96+ -- terminates.
63 fix $ \loop -> do
97 fix $ \loop -> do
98+ -- Read the next event (blocking).
64 ers <- liftIO $ readChan events
99 ers <- liftIO $ readChan events
100+ stop <- do
101+ -- Fire events that have subscribers.
65− stop <- fireEventTriggerRefs fc ers $ readEvent shutdown >>= \case
102+ fireEventTriggerRefs fc ers $
103+ -- Check if the shutdown 'Event' is firing.
104+ readEvent shutdown >>= \case
66− Nothing -> return False
105+ Nothing -> return False
67− Just _ -> return True
106+ Just _ -> return True
68 if or stop
107 if or stop
69 then return ()
108 then return ()
70 else loop
109 else loop
71 where
110 where
72− -- | Use the given 'FireCommand' to fire events that have subscribers
111+ -- Use the given 'FireCommand' to fire events that have subscribers
73 -- and call the callback for the 'TriggerInvocation' of each.
112 -- and call the callback for the 'TriggerInvocation' of each.
74 fireEventTriggerRefs
113 fireEventTriggerRefs
75 :: (MonadIO m)
114 :: (MonadIO m)