on develop help sign in
Reflex host for Graphics.Vty
commit2916af8e63adf23aa1e4288dde0eb2961ca15a60 authorAli Abrar <aliabrar@gmail.com> dateSun 25 Feb 2018, 16:58 (9 years ago)
3 files changed+100
Setup.hs+2 reflex-vty.cabal+29 src/Reflex/Vty.hs+69
Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
reflex-vty.cabalnew file+29
@@ -0,0 +1,29 @@
1+-- Initial reflex-vty.cabal generated by cabal init. For further
2+-- documentation, see http: //haskell.org/cabal/users-guide/
3+
4+name: reflex-vty
5+version: 0.1.0.0
6+-- synopsis:
7+-- description:
8+license: BSD3
9+license-file: LICENSE
10+author: Ali Abrar
11+maintainer: aliabrar@gmail.com
12+-- copyright:
13+-- category:
14+build-type: Simple
15+extra-source-files: ChangeLog.md
16+cabal-version: >=1.10
17+
18+library
19+ exposed-modules: Reflex.Vty
20+ -- other-modules:
21+ -- other-extensions:
22+ build-depends:
23+ base,
24+ dependent-sum,
25+ mtl,
26+ reflex,
27+ vty
28+ hs-source-dirs: src
29+ default-language: Haskell2010
src/Reflex/Vty.hsnew file+69
@@ -0,0 +1,69 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE MultiParamTypeClasses #-}
3+{-# LANGUAGE RankNTypes #-}
4+
5+module Reflex.Vty where
6+
7+import Reflex
8+import Reflex.Host.Class
9+import Control.Concurrent (forkIO)
10+import Control.Monad (forever)
11+import Control.Monad.Fix
12+import Control.Monad.Identity (Identity(..))
13+import Control.Monad.IO.Class (liftIO)
14+import Data.IORef (readIORef)
15+import Data.Dependent.Sum (DSum ((:=>)))
16+import System.IO (hSetEcho, hSetBuffering, stdin, BufferMode (NoBuffering))
17+
18+import qualified Graphics.Vty as V
19+
20+data VtyResult t = VtyResult
21+ { _vtyResult_picture :: Behavior t V.Picture
22+ , _vtyResult_refresh :: Event t ()
23+ , _vtyResult_shutdown :: Event t ()
24+ }
25+
26+type VtyApp t m = (Reflex t, MonadHold t m, MonadFix m) => Event t (V.Event) -> m (VtyResult t)
27+
28+host
29+ :: (forall t m. VtyApp t m)
30+ -> IO ()
31+host vtyGuest = runSpiderHost $ do
32+ cfg <- liftIO V.standardIOConfig
33+ vty <- liftIO $ V.mkVty cfg
34+
35+ (e, eTriggerRef) <- newEventWithTriggerRef
36+ r <- runHostFrame $ vtyGuest e
37+ shutdown <- subscribeEvent $ _vtyResult_shutdown r
38+
39+ fix $ \loop -> do
40+ vtyEvent <- liftIO $ V.nextEvent vty
41+ mETrigger <- liftIO $ readIORef eTriggerRef
42+ next <- case mETrigger of
43+ Nothing -> return loop
44+ Just eTrigger ->
45+ fireEventsAndRead [eTrigger :=> Identity vtyEvent] $ do
46+ readEvent shutdown >>= \case
47+ Nothing -> return loop
48+ Just _ -> return $ liftIO $ V.shutdown vty
49+ output <- runHostFrame $ sample $ _vtyResult_picture r
50+ liftIO $ V.update vty output
51+ next
52+
53+guest :: VtyApp t m
54+guest e = do
55+ let shutdown = fforMaybe e $ \case
56+ V.EvKey V.KEsc _ -> Just ()
57+ _ -> Nothing
58+ picture <- hold V.emptyPicture $ V.picForImage . V.string mempty . show <$> e
59+ return $ VtyResult
60+ { _vtyResult_picture = picture
61+ , _vtyResult_refresh = never
62+ , _vtyResult_shutdown = shutdown
63+ }
64+
65+main :: IO ()
66+main = do
67+ hSetEcho stdin False
68+ hSetBuffering stdin NoBuffering
69+ host guest