packages feed

termbox-tea 0.1.0.1 → 1.0.0

raw patch · 5 files changed

+422/−288 lines, 5 filesdep ~basedep ~termboxnew-component:exe:termbox-tea-example-demonew-component:exe:termbox-tea-example-quick-startPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, termbox

API changes (from Hackage documentation)

- Termbox.Tea: cell :: Pos -> Cell -> Scene
- Termbox.Tea: data Cell
+ Termbox.Tea: at :: Pos -> Image -> Image
+ Termbox.Tea: atCol :: Int -> Image -> Image
+ Termbox.Tea: atRow :: Int -> Image -> Image
+ Termbox.Tea: data () => Image
+ Termbox.Tea: image :: Image -> Scene
- Termbox.Tea: KeyChar :: Char -> Key
+ Termbox.Tea: KeyChar :: !Char -> Key
- Termbox.Tea: bg :: Color -> Cell -> Cell
+ Termbox.Tea: bg :: Color -> Image -> Image
- Termbox.Tea: blink :: Cell -> Cell
+ Termbox.Tea: blink :: Image -> Image
- Termbox.Tea: bold :: Cell -> Cell
+ Termbox.Tea: bold :: Image -> Image
- Termbox.Tea: char :: Char -> Cell
+ Termbox.Tea: char :: Char -> Image
- Termbox.Tea: cursor :: Pos -> Scene
+ Termbox.Tea: cursor :: Pos -> Scene -> Scene
- Termbox.Tea: data Color
+ Termbox.Tea: data () => Color
- Termbox.Tea: data Event e
+ Termbox.Tea: data () => Event e
- Termbox.Tea: data InitError
+ Termbox.Tea: data () => InitError
- Termbox.Tea: data Key
+ Termbox.Tea: data () => Key
- Termbox.Tea: data Mouse
+ Termbox.Tea: data () => Mouse
- Termbox.Tea: data MouseButton
+ Termbox.Tea: data () => MouseButton
- Termbox.Tea: data Pos
+ Termbox.Tea: data () => Pos
- Termbox.Tea: data Scene
+ Termbox.Tea: data () => Scene
- Termbox.Tea: data Size
+ Termbox.Tea: data () => Size
- Termbox.Tea: fg :: Color -> Cell -> Cell
+ Termbox.Tea: fg :: Color -> Image -> Image
- Termbox.Tea: fill :: Color -> Scene
+ Termbox.Tea: fill :: Color -> Scene -> Scene
- Termbox.Tea: underline :: Cell -> Cell
+ Termbox.Tea: underline :: Image -> Image

Files

CHANGELOG.md view
@@ -1,7 +1,11 @@-## [0.1.0.1] - 2023-10-15+## [1.0.0] - November 5, 2023 +- Update to `termbox-2.0.0`++## [0.1.0.1] - October 15, 2023+ - Support GHC 9.8 -## [0.1.0] - 2022-11-03+## [0.1.0] - November 3, 2022  - Initial release
examples/Demo.hs view
@@ -1,11 +1,21 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE ImportQualifiedPost #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NumericUnderscores #-}+{-# LANGUAGE OverloadedRecordDot #-}+ module Main (main) where  import Control.Concurrent (threadDelay)-import Control.Concurrent.MVar-import Control.Monad (forever)+import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, takeMVar)+import Control.Monad (forever, guard)+import Data.Function ((&)) import GHC.Clock (getMonotonicTime)-import qualified Ki-import qualified Termbox.Tea as Termbox+import Ki qualified+import Termbox.Tea qualified as Termbox import Text.Printf (printf)  main :: IO ()@@ -26,21 +36,28 @@             render,             finished           }-  case result of-    Left err -> print err-    Right _state -> pure ()+  putStrLn case result of+    Left err -> "Termbox program failed to initialize: " ++ show err+    Right state -> "Final state: " ++ show state  data State = State-  { elapsed :: Double,-    lastKey :: Maybe Termbox.Key,-    bright :: Bool+  { elapsed :: !Double,+    terminalSize :: !Termbox.Size,+    lastKey :: !(Maybe Termbox.Key),+    lastMouse :: !(Maybe Termbox.Mouse),+    cursor :: !(Maybe (Termbox.Pos, Double)),+    bright :: !Bool   }+  deriving stock (Show)  initialize :: Termbox.Size -> State-initialize _size =+initialize terminalSize =   State     { elapsed = 0,+      terminalSize,       lastKey = Nothing,+      lastMouse = Nothing,+      cursor = Nothing,       bright = False     } @@ -50,167 +67,134 @@     t1 <- takeMVar timeVar     pure (t1 - t0) -handleEvent :: State -> Termbox.Event Double -> IO State-handleEvent State {elapsed, lastKey, bright} = \case+handleEvent :: (Applicative m) => State -> Termbox.Event Double -> m State+handleEvent state = \case   Termbox.EventKey key ->     pure-      State-        { elapsed,-          lastKey = Just key,+      state+        { lastKey = Just key,           bright =             case key of-              Termbox.KeyChar '*' -> not bright-              _ -> bright+              Termbox.KeyChar '*' -> not state.bright+              _ -> state.bright         }-  Termbox.EventUser elapsed1 ->+  Termbox.EventMouse mouse ->     pure-      State-        { elapsed = elapsed1,-          lastKey,-          bright+      state+        { lastMouse = Just mouse,+          cursor =+            case mouse.button of+              Termbox.ReleaseClick -> Just (mouse.pos, state.elapsed + 1)+              _ -> state.cursor         }-  _ ->+  Termbox.EventResize terminalSize -> pure state {terminalSize}+  Termbox.EventUser elapsed ->     pure-      State+      state         { elapsed,-          lastKey,-          bright+          cursor = do+            (pos, erase) <- state.cursor+            guard (erase > elapsed)+            Just (pos, erase)         }  render :: State -> Termbox.Scene-render State {elapsed, lastKey, bright} =-  renderBox Termbox.Pos {row = 1, col = 2} $-    vcat-      [ string "Welcome to Termbox. Try typing, clicking, and resizing the terminal!",-        string " ",-        hcat-          [ string "Elapsed time: ",-            string (map Termbox.char (printf "%.1fs" elapsed))-          ],-        hcat-          [ string "Latest key press: ",-            case lastKey of-              Nothing -> emptyBox-              Just event -> string (map (Termbox.bold . Termbox.char) (show event))-          ],-        string " ",-        string "default red green yellow blue magenta cyan white",-        hcat-          [ rect-              Rect-                { size = Termbox.Size {width = 7, height = 2},-                  color = brighten Termbox.defaultColor-                },-            string " ",-            rect-              Rect-                { size = Termbox.Size {width = 3, height = 2},-                  color = brighten Termbox.red-                },-            string " ",-            rect-              Rect-                { size = Termbox.Size {width = 5, height = 2},-                  color = brighten Termbox.green-                },-            string " ",-            rect-              Rect-                { size = Termbox.Size {width = 6, height = 2},-                  color = brighten Termbox.yellow-                },-            string " ",-            rect-              Rect-                { size = Termbox.Size {width = 4, height = 2},-                  color = brighten Termbox.blue-                },-            string " ",-            rect-              Rect-                { size = Termbox.Size {width = 7, height = 2},-                  color = brighten Termbox.magenta-                },-            string " ",-            rect-              Rect-                { size = Termbox.Size {width = 4, height = 2},-                  color = brighten Termbox.cyan-                },-            string " ",-            rect-              Rect-                { size = Termbox.Size {width = 5, height = 2},-                  color = brighten Termbox.white-                },-            string " ",-            vcat-              [ string ("Press " ++ [Termbox.bold (Termbox.char '*')] ++ " to toggle brightness."),-                string-                  ( let selected = map (Termbox.bg (Termbox.gray 20) . Termbox.fg (Termbox.gray 0))-                     in if bright-                          then "normal " ++ selected "bright"-                          else selected "normal" ++ " bright"-                  )-              ]-          ],-        string " ",-        string "color 0 .. color 215",-        vcat-          ( map-              ( \is ->-                  hcat-                    ( map-                        ( \i ->-                            acat-                              [ rect-                                  Rect-                                    { size = Termbox.Size {width = 4, height = 2},-                                      color = Termbox.color i-                                    },-                                string (map (Termbox.bg (Termbox.color i) . Termbox.char) (show i))-                              ]-                        )-                        is-                    )-              )-              (chunksOf 24 [0 .. 215])-          ),-        string " ",-        string "gray 0 .. gray 23",-        hcat-          ( map-              ( \i ->-                  acat-                    [ rect-                        Rect-                          { size = Termbox.Size {width = 4, height = 2},-                            color = Termbox.gray i-                          },-                      string (map (Termbox.bg (Termbox.gray i) . Termbox.char) (show i))-                    ]-              )-              [0 .. 23]-          ),-        string " ",-        hcat-          [ string (map Termbox.bold "This text is bold."),-            string " ",-            string (map Termbox.underline "This text is underlined."),-            string " ",-            string (map Termbox.blink "This text is blinking (maybe).")-          ],-        string " ",-        hcat-          [ string "Press ",-            string (map Termbox.bold "Esc"),-            string " to quit!"-          ]-      ]+render state =+  vcat+    [ string "Welcome to Termbox. Try typing, clicking, and resizing the terminal!",+      string " ",+      hcat+        [ string "Elapsed time: ",+          string (printf "%.1fs" state.elapsed)+        ],+      hcat [string "Terminal size: ", string (show state.terminalSize)],+      hcat+        [ string "Latest key press: ",+          case state.lastKey of+            Nothing -> emptyBox+            Just event -> string (show event) & boldBox+        ],+      hcat+        [ string "Latest mouse click: ",+          case state.lastMouse of+            Nothing -> emptyBox+            Just event -> string (show event) & boldBox+        ],+      string " ",+      hcat+        [ let selected = bgBox (Termbox.gray 20) . fgBox (Termbox.gray 0)+           in vcat+                if state.bright+                  then [string " ", string "normal", selected (string "bright")]+                  else [string " ", selected (string "normal"), string "bright"],+          string " ",+          vcat+            [ string "default red green yellow blue magenta cyan white",+              hcat+                [ rect Termbox.Size {width = 7, height = 2} (brighten Termbox.defaultColor),+                  string " ",+                  rect Termbox.Size {width = 3, height = 2} (brighten Termbox.red),+                  string " ",+                  rect Termbox.Size {width = 5, height = 2} (brighten Termbox.green),+                  string " ",+                  rect Termbox.Size {width = 6, height = 2} (brighten Termbox.yellow),+                  string " ",+                  rect Termbox.Size {width = 4, height = 2} (brighten Termbox.blue),+                  string " ",+                  rect Termbox.Size {width = 7, height = 2} (brighten Termbox.magenta),+                  string " ",+                  rect Termbox.Size {width = 4, height = 2} (brighten Termbox.cyan),+                  string " ",+                  rect Termbox.Size {width = 5, height = 2} (brighten Termbox.white),+                  string " ",+                  hcat [string "Press ", boldBox (string "*"), string " to toggle brightness."]+                ]+            ]+        ],+      string " ",+      string "color 0 .. color 215",+      vcat $+        chunksOf 24 [0 .. 215] & map \is ->+          hcat $+            is & map \i ->+              acat+                [ rect Termbox.Size {width = 4, height = 2} (Termbox.color i),+                  string (show i) & bgBox (Termbox.color i)+                ],+      string " ",+      string "gray 0 .. gray 23",+      hcat $+        [0 .. 23] & map \i ->+          acat+            [ rect (Termbox.Size {width = 4, height = 2}) (Termbox.gray i),+              string (show i) & bgBox (Termbox.gray i)+            ],+      string " ",+      hcat+        [ string "This text is bold." & boldBox,+          string " ",+          string "This text is underlined." & underlineBox,+          string " ",+          string "This text is blinking (maybe)." & blinkBox+        ],+      string " ",+      hcat+        [ string "Press ",+          string "Esc" & boldBox,+          string " to quit!"+        ]+    ]+    & boxImage+    & Termbox.at Termbox.Pos {row = 1, col = 2}+    & Termbox.image+    & case state.cursor of+      Nothing -> id+      Just (pos, _) -> Termbox.cursor pos+    & Termbox.fill (Termbox.gray 4)   where     brighten :: Termbox.Color -> Termbox.Color     brighten =-      if bright+      if state.bright         then Termbox.bright         else id @@ -221,68 +205,71 @@     _ -> False  data Box-  = Box !Termbox.Size Content--data Content-  = E-  | O !Termbox.Cell-  | A !Box !Box-  | H !Box !Box-  | V !Box !Box+  = Box !Termbox.Size !Termbox.Image  emptyBox :: Box emptyBox =-  Box (Termbox.Size 0 0) E+  Box (Termbox.Size 0 0) mempty -one :: Termbox.Cell -> Box-one cell =-  Box (Termbox.Size 1 1) (O cell) -- assume it's not an empty cell *shrug*+boxImage :: Box -> Termbox.Image+boxImage (Box _size image) =+  image +fgBox :: Termbox.Color -> Box -> Box+fgBox color (Box size image) =+  Box size (Termbox.fg color image)++bgBox :: Termbox.Color -> Box -> Box+bgBox color (Box size image) =+  Box size (Termbox.bg color image)++boldBox :: Box -> Box+boldBox (Box size image) =+  Box size (Termbox.bold image)++underlineBox :: Box -> Box+underlineBox (Box size image) =+  Box size (Termbox.underline image)++blinkBox :: Box -> Box+blinkBox (Box size image) =+  Box size (Termbox.blink image)++one :: Char -> Box+one char =+  Box (Termbox.Size 1 1) (Termbox.char char)+ acat :: [Box] -> Box acat =   foldr f emptyBox   where     f :: Box -> Box -> Box-    f box1@(Box (Termbox.Size w1 h1) _) box2@(Box (Termbox.Size w2 h2) _) =-      Box (Termbox.Size (max w1 w2) (max h1 h2)) (A box1 box2)+    f (Box (Termbox.Size w1 h1) i1) (Box (Termbox.Size w2 h2) i2) =+      Box (Termbox.Size (max w1 w2) (max h1 h2)) (i1 <> i2)  hcat :: [Box] -> Box hcat =   foldr f emptyBox   where     f :: Box -> Box -> Box-    f box1@(Box (Termbox.Size w1 h1) _) box2@(Box (Termbox.Size w2 h2) _) =-      Box (Termbox.Size (w1 + w2) (max h1 h2)) (H box1 box2)+    f (Box (Termbox.Size w1 h1) i1) (Box (Termbox.Size w2 h2) i2) =+      Box (Termbox.Size (w1 + w2) (max h1 h2)) (i1 <> Termbox.atCol w1 i2)  vcat :: [Box] -> Box vcat =   foldr f emptyBox   where     f :: Box -> Box -> Box-    f box1@(Box (Termbox.Size w1 h1) _) box2@(Box (Termbox.Size w2 h2) _) =-      Box (Termbox.Size (max w1 w2) (h1 + h2)) (V box1 box2)--renderBox :: Termbox.Pos -> Box -> Termbox.Scene-renderBox pos (Box _ content) =-  case content of-    E -> mempty-    O cell -> Termbox.cell pos cell-    A box1 box2 -> renderBox pos box1 <> renderBox pos box2-    H box1@(Box (Termbox.Size w1 _) _) box2 -> renderBox pos box1 <> renderBox (Termbox.posRight w1 pos) box2-    V box1@(Box (Termbox.Size _ h1) _) box2 -> renderBox pos box1 <> renderBox (Termbox.posDown h1 pos) box2+    f (Box (Termbox.Size w1 h1) i1) (Box (Termbox.Size w2 h2) i2) =+      Box (Termbox.Size (max w1 w2) (h1 + h2)) (i1 <> Termbox.atRow h1 i2) -string :: [Termbox.Cell] -> Box+string :: [Char] -> Box string =   hcat . map one -data Rect = Rect-  { size :: Termbox.Size,-    color :: Termbox.Color-  }--rect :: Rect -> Box-rect Rect {size = Termbox.Size {width, height}, color} =-  vcat (replicate height (string (replicate width (Termbox.bg color (Termbox.char ' ')))))+rect :: Termbox.Size -> Termbox.Color -> Box+rect Termbox.Size {width, height} color =+  bgBox color (vcat (replicate height (string (replicate width ' '))))  chunksOf :: Int -> [a] -> [[a]] chunksOf n = \case
+ examples/QuickStart.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE ImportQualifiedPost #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedRecordDot #-}++import Data.Foldable (fold)+import Data.Function ((&))+import Data.Void (Void)+import Termbox.Tea qualified as Termbox++main :: IO ()+main = do+  result <-+    Termbox.run+      Termbox.Program+        { initialize,+          pollEvent,+          handleEvent,+          render,+          finished+        }+  putStrLn case result of+    Left err -> "Termbox program failed to initialize: " ++ show err+    Right state -> "Final state: " ++ show state++data MyState = MyState+  { keysPressed :: !Int,+    pressedEsc :: !Bool+  }+  deriving stock (Show)++initialize :: Termbox.Size -> MyState+initialize _size =+  MyState+    { keysPressed = 0,+      pressedEsc = False+    }++pollEvent :: Maybe (IO Void)+pollEvent =+  Nothing++handleEvent :: MyState -> Termbox.Event Void -> IO MyState+handleEvent state = \case+  Termbox.EventKey key ->+    pure+      MyState+        { keysPressed = state.keysPressed + 1,+          pressedEsc =+            case key of+              Termbox.KeyEsc -> True+              _ -> False+        }+  _ -> pure state++render :: MyState -> Termbox.Scene+render state =+  fold+    [ string ("Number of keys pressed: " ++ show state.keysPressed),+      fold+        [ string "Press",+          string "Esc" & Termbox.bold & Termbox.atCol 6,+          string "to quit." & Termbox.atCol 10+        ]+        & Termbox.atRow 2+    ]+    & Termbox.at Termbox.Pos {row = 2, col = 4}+    & Termbox.image++finished :: MyState -> Bool+finished state =+  state.pressedEsc++string :: [Char] -> Termbox.Image+string chars =+  zip [0 ..] chars & foldMap \(i, char) ->+    Termbox.char char & Termbox.atCol i
src/Termbox/Tea.hs view
@@ -6,47 +6,46 @@ -- -- * @<https://hackage.haskell.org/package/termbox-banana termbox-banana>@, a @reactive-banana@ FRP interface. ----- This module is intended to be imported qualified.--- -- ==== __👉 Quick start example__ -- -- This @termbox@ program displays the number of keys pressed. -- -- @+-- {-\# LANGUAGE BlockArguments \#-} -- {-\# LANGUAGE DerivingStrategies \#-} -- {-\# LANGUAGE DuplicateRecordFields \#-} -- {-\# LANGUAGE ImportQualifiedPost \#-} -- {-\# LANGUAGE LambdaCase \#-}+-- {-\# LANGUAGE NamedFieldPuns \#-} -- {-\# LANGUAGE OverloadedRecordDot \#-}--- {-\# LANGUAGE OverloadedStrings \#-}--- {-\# LANGUAGE NoFieldSelectors \#-} -- -- import Data.Foldable (fold)+-- import Data.Function ((&)) -- import Data.Void (Void) -- import Termbox.Tea qualified as Termbox -- -- main :: IO () -- main = do---   result <-+--   result \<- --     Termbox.'run'---       Termbox.'Termbox.Tea.Program'+--       Termbox.'Program' --         { initialize, --           pollEvent, --           handleEvent, --           render, --           finished --         }---   case result of---     Left err -\> putStrLn (\"Termbox program failed to initialize: \" ++ show err)---     Right state -\> putStrLn (\"Final state: \" ++ show state)+--   putStrLn case result of+--     Left err -\> \"Termbox program failed to initialize: \" ++ show err+--     Right state -\> \"Final state: \" ++ show state -- -- data MyState = MyState---   { keysPressed :: Int,---     pressedEsc :: Bool+--   { keysPressed :: !Int,+--     pressedEsc :: !Bool --   } --   deriving stock (Show) ----- initialize :: Termbox.'Termbox.Tea.Size' -\> MyState+-- initialize :: Termbox.'Size' -\> MyState -- initialize _size = --   MyState --     { keysPressed = 0,@@ -57,113 +56,167 @@ -- pollEvent = --   Nothing ----- handleEvent :: MyState -\> Termbox.'Termbox.Tea.Event' Void -\> IO MyState+-- handleEvent :: MyState -\> Termbox.'Event' Void -\> IO MyState -- handleEvent state = \\case---   Termbox.'Termbox.Tea.EventKey' key -\>+--   Termbox.'EventKey' key -\> --     pure --       MyState --         { keysPressed = state.keysPressed + 1, --           pressedEsc = --             case key of---               Termbox.'Termbox.Tea.KeyEsc' -\> True+--               Termbox.'KeyEsc' -\> True --               _ -\> False --         } --   _ -\> pure state ----- render :: MyState -\> Termbox.'Termbox.Tea.Scene'+-- render :: MyState -\> Termbox.'Scene' -- render state = --   fold---     [ string---         Termbox.'Termbox.Tea.Pos' {row = 2, col = 4}---         (\"Number of keys pressed: \" ++ map Termbox.'Termbox.Tea.char' (show state.keysPressed))---     , string---         Termbox.'Termbox.Tea.Pos' {row = 4, col = 4}---         (\"Press \" ++ map (Termbox.'Termbox.Tea.bold' . Termbox.'Termbox.Tea.char') \"Esc\" ++ \" to quit.\")+--     [ string (\"Number of keys pressed: \" ++ show state.keysPressed),+--       fold+--         [ string \"Press\",+--           string \"Esc\" & Termbox.'bold' & Termbox.'atCol' 6,+--           string \"to quit.\" & Termbox.'atCol' 10+--         ]+--         & Termbox.'atRow' 2 --     ]+--     & Termbox.'at' Termbox.'Pos' {row = 2, col = 4}+--     & Termbox.'image' -- -- finished :: MyState -\> Bool -- finished state = --   state.pressedEsc ----- string :: Termbox.'Termbox.Tea.Pos' -\> [Termbox.'Termbox.Tea.Cell'] -\> Termbox.'Termbox.Tea.Scene'--- string pos cells =---   foldMap (\\(i, cell) -\> Termbox.'Termbox.Tea.cell' (Termbox.'Termbox.Tea.posRight' i pos) cell) (zip [0 ..] cells)+-- string :: [Char] -\> Termbox.'Image'+-- string chars =+--   zip [0 ..] chars & foldMap \\(i, char) -\>+--     Termbox.char char & Termbox.atCol i -- @ module Termbox.Tea   ( -- * Main     Program (..),     run,-    Termbox.InitError (..),+    InitError (..),      -- * Terminal contents      -- ** Scene-    Termbox.Scene,-    Termbox.cell,-    Termbox.fill,-    Termbox.cursor,+    Scene,+    image,+    fill,+    cursor, -    -- ** Cell-    Termbox.Cell,-    Termbox.char,-    Termbox.fg,-    Termbox.bg,-    Termbox.bold,-    Termbox.underline,-    Termbox.blink,+    -- ** Image+    Image,+    char, +    -- *** Color+    fg,+    bg,++    -- *** Style+    bold,+    underline,+    blink,++    -- *** Translation+    at,+    atRow,+    atCol,+     -- ** Colors-    Termbox.Color,+    Color,      -- *** Basic colors-    Termbox.defaultColor,-    Termbox.red,-    Termbox.green,-    Termbox.yellow,-    Termbox.blue,-    Termbox.magenta,-    Termbox.cyan,-    Termbox.white,-    Termbox.bright,+    defaultColor,+    red,+    green,+    yellow,+    blue,+    magenta,+    cyan,+    white,+    bright,      -- *** 216 miscellaneous colors-    Termbox.color,+    color,      -- *** 24 monochrome colors-    Termbox.gray,+    gray,      -- * Event handling-    Termbox.Event (..),-    Termbox.Key (..),-    Termbox.Mouse (..),-    Termbox.MouseButton (..),+    Event (..),+    Key (..),+    Mouse (..),+    MouseButton (..),      -- * Miscellaneous types-    Termbox.Pos (..),-    Termbox.posUp,-    Termbox.posDown,-    Termbox.posLeft,-    Termbox.posRight,-    Termbox.Size (..),+    Pos (..),+    posUp,+    posDown,+    posLeft,+    posRight,+    Size (..),   ) where -import Control.Concurrent.MVar+import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar) import Control.Monad (forever) import qualified Ki-import qualified Termbox+import Termbox+  ( Color,+    Event (..),+    Image,+    InitError (..),+    Key (..),+    Mouse (..),+    MouseButton (..),+    Pos (..),+    Scene,+    Size (..),+    at,+    atCol,+    atRow,+    bg,+    blink,+    blue,+    bold,+    bright,+    char,+    color,+    cursor,+    cyan,+    defaultColor,+    fg,+    fill,+    getSize,+    gray,+    green,+    image,+    magenta,+    poll,+    posDown,+    posLeft,+    posRight,+    posUp,+    red,+    underline,+    white,+    yellow,+  )+import qualified Termbox (render, run)  -- | A @termbox@ program, parameterized by state __@s@__. data Program s = forall e.   Program   { -- | The initial state, given the initial terminal size.-    initialize :: Termbox.Size -> s,+    initialize :: Size -> s,     -- | Poll for a user event. Every value that this @IO@ action returns is provided to @handleEvent@.     pollEvent :: Maybe (IO e),     -- | Handle an event.-    handleEvent :: s -> Termbox.Event e -> IO s,+    handleEvent :: s -> Event e -> IO s,     -- | Render the current state.-    render :: s -> Termbox.Scene,+    render :: s -> Scene,     -- | Is the current state finished?     finished :: s -> Bool   }@@ -172,15 +225,15 @@ -- -- @run@ either: -----   * Returns immediately with an 'Termbox.Tea.InitError'.+--   * Returns immediately with an @InitError@. --   * Returns the final state, once it's @finished@.-run :: Program s -> IO (Either Termbox.InitError s)+run :: Program s -> IO (Either InitError s) run program =   Termbox.run (run_ program)  run_ :: Program s -> IO s run_ Program {initialize, pollEvent, handleEvent, render, finished} = do-  state0 <- initialize <$> Termbox.getSize+  state0 <- initialize <$> getSize    let loop0 doPoll =         let loop s0 =@@ -194,7 +247,7 @@          in loop    case pollEvent of-    Nothing -> loop0 Termbox.poll state0+    Nothing -> loop0 poll state0     Just pollEvent1 -> do       eventVar <- newEmptyMVar @@ -202,7 +255,7 @@         Ki.fork_ scope do           forever do             event <- pollEvent1-            putMVar eventVar (Termbox.EventUser event)+            putMVar eventVar (EventUser event)          Ki.fork_ scope do           forever do
termbox-tea.cabal view
@@ -18,9 +18,9 @@ name: termbox-tea synopsis: termbox + The Elm Architecture tested-with: GHC == 9.4.7, GHC == 9.6.3, GHC == 9.8.1-version: 0.1.0.1+version: 1.0.0 -extra-source-files:+extra-doc-files:   CHANGELOG.md  source-repository head@@ -33,25 +33,6 @@   manual: True  common component-  default-extensions:-    BlockArguments-    CApiFFI-    DeriveAnyClass-    DeriveFunctor-    DeriveGeneric-    DerivingStrategies-    DerivingVia-    DuplicateRecordFields-    ExistentialQuantification-    FlexibleInstances-    GeneralizedNewtypeDeriving-    InstanceSigs-    LambdaCase-    NamedFieldPuns-    NumericUnderscores-    OverloadedStrings-    PatternSynonyms-    TypeApplications   default-language: Haskell2010   ghc-options:     -Weverything@@ -77,12 +58,31 @@   import: component   build-depends:     base ^>= 4.13 || ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17 || ^>= 4.18 || ^>= 4.19,-    termbox ^>= 1.1.0,+    termbox ^>= 2.0.0,     ki ^>= 1.0,+  default-extensions:+    BlockArguments+    CApiFFI+    DeriveAnyClass+    DeriveFunctor+    DeriveGeneric+    DerivingStrategies+    DerivingVia+    DuplicateRecordFields+    ExistentialQuantification+    FlexibleInstances+    GeneralizedNewtypeDeriving+    InstanceSigs+    LambdaCase+    NamedFieldPuns+    NumericUnderscores+    OverloadedStrings+    PatternSynonyms+    TypeApplications   exposed-modules: Termbox.Tea   hs-source-dirs: src -executable termbox-example-demo+executable termbox-tea-example-demo   import: component   if !flag(build-examples)     buildable: False@@ -95,3 +95,13 @@     -threaded   hs-source-dirs: examples   main-is: Demo.hs++executable termbox-tea-example-quick-start+  import: component+  if !flag(build-examples)+    buildable: False+  build-depends:+    base,+    termbox-tea,+  hs-source-dirs: examples+  main-is: QuickStart.hs