termbox 1.0.0 → 1.1.0
raw patch · 9 files changed
+160/−555 lines, 9 filesdep −kidep −termboxdep ~basePVP ok
version bump matches the API change (PVP)
Dependencies removed: ki, termbox
Dependency ranges changed: base
API changes (from Hackage documentation)
- Termbox: Program :: (Size -> s) -> Maybe (IO e) -> (s -> Event e -> IO s) -> (s -> Scene) -> (s -> Bool) -> Program s
- Termbox: [$sel:finished:Program] :: Program s -> s -> Bool
- Termbox: [$sel:handleEvent:Program] :: Program s -> s -> Event e -> IO s
- Termbox: [$sel:initialize:Program] :: Program s -> Size -> s
- Termbox: [$sel:pollEvent:Program] :: Program s -> Maybe (IO e)
- Termbox: [$sel:render:Program] :: Program s -> s -> Scene
- Termbox: data Program s
- Termbox: instance GHC.Exception.Type.Exception Termbox.InitError
- Termbox: instance GHC.Show.Show Termbox.InitError
- Termbox: pattern MouseLeft :: Mouse
- Termbox: pattern MouseMiddle :: Mouse
- Termbox: pattern MouseRelease :: Mouse
- Termbox: pattern MouseRight :: Mouse
- Termbox: pattern MouseWheelDown :: Mouse
- Termbox: pattern MouseWheelUp :: Mouse
+ Termbox: Mouse :: !MouseButton -> !Pos -> Mouse
+ Termbox: [$sel:button:Mouse] :: Mouse -> !MouseButton
+ Termbox: [$sel:pos:Mouse] :: Mouse -> !Pos
+ Termbox: data MouseButton
+ Termbox: finalize :: IO ()
+ Termbox: getSize :: IO Size
+ Termbox: initialize :: IO (Either InitError ())
+ Termbox: pattern LeftClick :: MouseButton
+ Termbox: pattern MiddleClick :: MouseButton
+ Termbox: pattern ReleaseClick :: MouseButton
+ Termbox: pattern RightClick :: MouseButton
+ Termbox: pattern WheelDown :: MouseButton
+ Termbox: pattern WheelUp :: MouseButton
+ Termbox: poll :: IO (Event e)
+ Termbox: render :: Scene -> IO ()
- Termbox: EventMouse :: !Mouse -> !Pos -> Event e
+ Termbox: EventMouse :: !Mouse -> Event e
- Termbox: run :: Program s -> IO (Either InitError s)
+ Termbox: run :: IO a -> IO (Either InitError a)
Files
- CHANGELOG.md +11/−1
- examples/Demo.hs +0/−292
- src/Termbox.hs +22/−198
- src/Termbox/Internal/Event.hs +18/−9
- src/Termbox/Internal/Main.hs +51/−0
- src/Termbox/Internal/Mouse.hs +40/−30
- src/Termbox/Internal/Scene.hs +4/−4
- src/Termbox/Internal/Size.hs +9/−0
- termbox.cabal +5/−21
CHANGELOG.md view
@@ -1,4 +1,10 @@-## [1.0.0] - Unreleased+## [1.1.0] - 2022-11-03++- Split off Elm Architecture wrapper into `termbox-tea` package, and expose `run`/`initialize`/`finalize` instead.+- Rename `Mouse` to `MouseButton`, rename its constructors, and add `Mouse` type (`MouseButton` + `Pos`)++## [1.0.0] - 2022-10-25+ - Rework `run`; add `Program` record of callbacks - Add user events to `Event` type - Overhaul `Attr`+`Cell`+`Cells`+`Cursor` API; now it's `Cell`+`Color`+`Scene`@@ -14,6 +20,7 @@ - Drop support for GHC < 8.8 ## [0.3.0] - 2020-09-20+ - Add `Cells` and `Cursor` types - Export `Termbox.Internal` module that roughly corresponds to the C library - Add a few arguments to the action provided to `run`@@ -29,9 +36,11 @@ - Remove support for GHC < 8.2 ## [0.2.0.1] - 2020-06-27+ - Bump `base` upper bound ## [0.2.0] - 2019-06-21+ - Add `getCells` function - Add `run` function - Rename `size` to `getSize`@@ -41,4 +50,5 @@ - Remove `buffer` function ## [0.1.0] - 2018-07-18+ - Initial release
− examples/Demo.hs
@@ -1,292 +0,0 @@-module Main (main) where--import Control.Concurrent (threadDelay)-import Control.Concurrent.MVar-import Control.Monad (forever)-import GHC.Clock (getMonotonicTime)-import qualified Ki-import qualified Termbox-import Text.Printf (printf)--main :: IO ()-main = do- t0 <- getMonotonicTime- result <-- Ki.scoped \scope -> do- timeVar <- newEmptyMVar- Ki.fork_ scope do- forever do- threadDelay 100_000- getMonotonicTime >>= putMVar timeVar- Termbox.run- Termbox.Program- { initialize,- pollEvent = pollEvent t0 timeVar,- handleEvent,- render,- finished- }- case result of- Left err -> print err- Right _state -> pure ()--data State = State- { elapsed :: Double,- lastKey :: Maybe Termbox.Key,- bright :: Bool- }--initialize :: Termbox.Size -> State-initialize _size =- State- { elapsed = 0,- lastKey = Nothing,- bright = False- }--pollEvent :: Double -> MVar Double -> Maybe (IO Double)-pollEvent t0 timeVar =- Just do- t1 <- takeMVar timeVar- pure (t1 - t0)--handleEvent :: State -> Termbox.Event Double -> IO State-handleEvent State {elapsed, lastKey, bright} = \case- Termbox.EventKey key ->- pure- State- { elapsed,- lastKey = Just key,- bright =- case key of- Termbox.KeyChar '*' -> not bright- _ -> bright- }- Termbox.EventUser elapsed1 ->- pure- State- { elapsed = elapsed1,- lastKey,- bright- }- _ ->- pure- State- { elapsed,- lastKey,- bright- }--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!"- ]- ]- where- brighten :: Termbox.Color -> Termbox.Color- brighten =- if bright- then Termbox.bright- else id--finished :: State -> Bool-finished State {lastKey} =- case lastKey of- Just Termbox.KeyEsc -> True- _ -> False--data Box- = Box !Termbox.Size Content--data Content- = E- | O !Termbox.Cell- | A !Box !Box- | H !Box !Box- | V !Box !Box--emptyBox :: Box-emptyBox =- Box (Termbox.Size 0 0) E--one :: Termbox.Cell -> Box-one cell =- Box (Termbox.Size 1 1) (O cell) -- assume it's not an empty cell *shrug*--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)--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)--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--string :: [Termbox.Cell] -> 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 ' ')))))--chunksOf :: Int -> [a] -> [[a]]-chunksOf n = \case- [] -> []- xs ->- let (ys, zs) = splitAt n xs- in ys : chunksOf n zs
src/Termbox.hs view
@@ -1,111 +1,25 @@ -- |--- -- This module provides a high-level wrapper around @termbox@, a simple C library for writing text-based user -- interfaces: <https://github.com/termbox/termbox> ----- This module is intended to be imported qualified.------ ==== __👉 Quick start example__------ This @termbox@ program displays the number of keys pressed.------ @--- {-\# LANGUAGE DerivingStrategies \#-}--- {-\# LANGUAGE DuplicateRecordFields \#-}--- {-\# LANGUAGE ImportQualifiedPost \#-}--- {-\# LANGUAGE LambdaCase \#-}--- {-\# LANGUAGE OverloadedRecordDot \#-}--- {-\# LANGUAGE OverloadedStrings \#-}--- {-\# LANGUAGE NoFieldSelectors \#-}------ import Data.Foldable (fold)--- import Data.Void (Void)--- import Termbox qualified------ main :: IO ()--- main = do--- result <---- Termbox.'run'--- Termbox.'Program'--- { initialize,--- pollEvent,--- handleEvent,--- handleEventError,--- render,--- finished--- }--- case result of--- Left err -> putStrLn ("Termbox program failed to initialize: " ++ show err)--- Right state -> putStrLn ("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------ handleEventError :: MyState -> IO MyState--- handleEventError state =--- pure state------ render :: MyState -> Termbox.'Scene'--- render state =--- fold--- [ string--- Termbox.'Pos' {row = 2, col = 4}--- ("Number of keys pressed: " ++ map Termbox.'char' (show state.keysPressed))--- , string--- Termbox.'Pos' {row = 4, col = 4}--- ("Press " ++ map (Termbox.'bold' . Termbox.'char') "Esc" ++ " to quit.")--- ]+-- You may prefer to use one of the following interfaces instead: ----- finished :: MyState -> Bool--- finished state =--- state.pressedEsc+-- * @<https://hackage.haskell.org/package/termbox-banana termbox-banana>@, a @reactive-banana@ FRP interface.+-- * @<https://hackage.haskell.org/package/termbox-tea termbox-tea>@, an Elm Architecture interface. ----- string :: Termbox.'Pos' -> [Termbox.'Cell'] -> Termbox.'Scene'--- string pos cells =--- foldMap--- (\\(i, cell) ->--- Termbox.'cell'--- Termbox.'Pos' {row = pos.row, col = pos.col + i}--- cell)--- (zip [0 ..] cells)--- @+-- This module is intended to be imported qualified. module Termbox- ( -- * Termbox- Program (..),+ ( -- * Main run,+ initialize,+ finalize, InitError (..), -- * Terminal contents -- ** Scene Scene,+ render, cell, fill, cursor,@@ -155,6 +69,8 @@ KeyCtrlUnderscore ), Mouse (..),+ MouseButton (..),+ poll, -- * Miscellaneous types Pos (..),@@ -163,14 +79,10 @@ posLeft, posRight, Size (..),+ getSize, ) where -import Control.Concurrent.MVar-import Control.Exception-import Control.Monad (forever)-import qualified Ki-import qualified Termbox.Bindings.Hs import Termbox.Internal.Cell (Cell, bg, blink, bold, char, fg, underline) import Termbox.Internal.Color ( Color,@@ -200,106 +112,18 @@ pattern KeyCtrlM, pattern KeyCtrlUnderscore, )+import Termbox.Internal.Main (InitError (..), finalize, initialize, run) import Termbox.Internal.Mouse- ( Mouse- ( MouseLeft,- MouseMiddle,- MouseRelease,- MouseRight,- MouseWheelDown,- MouseWheelUp+ ( Mouse (..),+ MouseButton+ ( LeftClick,+ MiddleClick,+ ReleaseClick,+ RightClick,+ WheelDown,+ WheelUp ), ) import Termbox.Internal.Pos (Pos (..), posDown, posLeft, posRight, posUp)-import Termbox.Internal.Scene (Scene, cell, cursor, drawScene, fill)-import Termbox.Internal.Size (Size (..))---- | @termbox@ initialization errors.-data InitError- = FailedToOpenTTY- | PipeTrapError- | UnsupportedTerminal- deriving stock (Show)--instance Exception InitError---- | A @termbox@ program, parameterized by state __@s@__.-data Program s = forall e. Program- { -- | The initial state, given the initial terminal size.- 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 -> Event e -> IO s,- -- | Render the current state.- render :: s -> Scene,- -- | Is the current state finished?- finished :: s -> Bool- }---- | Run a @termbox@ program.------ Either returns immediately with an 'InitError', or once the program state is finished with the final state.-run :: Program s -> IO (Either InitError s)-run program = do- mask \unmask ->- Termbox.Bindings.Hs.tb_init >>= \case- Left err ->- (pure . Left) case err of- Termbox.Bindings.Hs.TB_EFAILED_TO_OPEN_TTY -> FailedToOpenTTY- Termbox.Bindings.Hs.TB_EPIPE_TRAP_ERROR -> PipeTrapError- Termbox.Bindings.Hs.TB_EUNSUPPORTED_TERMINAL -> UnsupportedTerminal- Right () -> do- result <- unmask (runProgram program) `onException` shutdown- shutdown- pure (Right result)--runProgram :: Program s -> IO s-runProgram Program {initialize, pollEvent, handleEvent, render, finished} = do- _ <- Termbox.Bindings.Hs.tb_select_input_mode Termbox.Bindings.Hs.TB_INPUT_MOUSE- _ <- Termbox.Bindings.Hs.tb_select_output_mode Termbox.Bindings.Hs.TB_OUTPUT_256- width <- Termbox.Bindings.Hs.tb_width- height <- Termbox.Bindings.Hs.tb_height-- let state0 =- initialize Size {width, height}-- let loop0 doPoll =- let loop s0 =- if finished s0- then pure s0- else do- drawScene (render s0)- event <- doPoll- s1 <- handleEvent s0 event- loop s1- in loop-- case pollEvent of- Nothing -> loop0 pollIgnoringErrors state0- Just pollEvent1 -> do- eventVar <- newEmptyMVar-- Ki.scoped \scope -> do- Ki.fork_ scope do- forever do- event <- pollEvent1- putMVar eventVar (EventUser event)-- Ki.fork_ scope do- forever do- event <- pollIgnoringErrors- putMVar eventVar event-- loop0 (takeMVar eventVar) state0--pollIgnoringErrors :: IO (Event e)-pollIgnoringErrors =- poll >>= \case- Left () -> pollIgnoringErrors- Right event -> pure event--shutdown :: IO ()-shutdown = do- _ <- Termbox.Bindings.Hs.tb_select_output_mode Termbox.Bindings.Hs.TB_OUTPUT_NORMAL- Termbox.Bindings.Hs.tb_shutdown+import Termbox.Internal.Scene (Scene, cell, cursor, fill, render)+import Termbox.Internal.Size (Size (..), getSize)
src/Termbox/Internal/Event.hs view
@@ -8,7 +8,7 @@ import GHC.Generics (Generic) import qualified Termbox.Bindings.Hs import Termbox.Internal.Key (Key (KeyChar), parseKey)-import Termbox.Internal.Mouse (Mouse (Mouse))+import Termbox.Internal.Mouse (Mouse (..), MouseButton (..)) import Termbox.Internal.Pos (Pos (..)) import Termbox.Internal.Size (Size (..)) import Prelude hiding (mod)@@ -20,14 +20,20 @@ | -- | Resize event EventResize !Size | -- | Mouse event- EventMouse !Mouse !Pos+ EventMouse !Mouse | -- | User event EventUser !e deriving stock (Eq, Generic, Show) --- Block until an Event arrives.-poll :: IO (Either () (Event e))-poll = do+-- | Poll for an event.+poll :: IO (Event e)+poll =+ poll_ >>= \case+ Left () -> poll+ Right event -> pure event++poll_ :: IO (Either () (Event e))+poll_ = do result <- Termbox.Bindings.Hs.tb_poll_event pure (parseEvent <$> result) @@ -54,8 +60,11 @@ } Termbox.Bindings.Hs.TB_EVENT_MOUSE -> EventMouse- (Mouse key)- Pos- { row = fromIntegral @Int32 @Int y,- col = fromIntegral @Int32 @Int x+ Mouse+ { button = MouseButton key,+ pos =+ Pos+ { row = fromIntegral @Int32 @Int y,+ col = fromIntegral @Int32 @Int x+ } }
+ src/Termbox/Internal/Main.hs view
@@ -0,0 +1,51 @@+module Termbox.Internal.Main+ ( run,+ initialize,+ finalize,+ InitError (..),+ )+where++import Control.Exception (Exception, mask, onException)+import qualified Termbox.Bindings.Hs++-- | @termbox@ initialization errors.+data InitError+ = FailedToOpenTTY+ | PipeTrapError+ | UnsupportedTerminal+ deriving anyclass (Exception)+ deriving stock (Show)++-- | Initialize a @termbox@ program, and if that succeeds, run the provided action, then finalize the @termbox@ program.+run :: IO a -> IO (Either InitError a)+run action =+ mask \unmask ->+ initialize >>= \case+ Left err -> pure (Left err)+ Right () -> do+ result <- unmask action `onException` finalize+ finalize+ pure (Right result)++-- | Initialize a @termbox@ program.+--+-- If @initialize@ succeeds, it must be paired with a call to 'finalize'.+initialize :: IO (Either InitError ())+initialize =+ Termbox.Bindings.Hs.tb_init >>= \case+ Left err ->+ (pure . Left) case err of+ Termbox.Bindings.Hs.TB_EFAILED_TO_OPEN_TTY -> FailedToOpenTTY+ Termbox.Bindings.Hs.TB_EPIPE_TRAP_ERROR -> PipeTrapError+ Termbox.Bindings.Hs.TB_EUNSUPPORTED_TERMINAL -> UnsupportedTerminal+ Right () -> do+ _ <- Termbox.Bindings.Hs.tb_select_input_mode Termbox.Bindings.Hs.TB_INPUT_MOUSE+ _ <- Termbox.Bindings.Hs.tb_select_output_mode Termbox.Bindings.Hs.TB_OUTPUT_256+ pure (Right ())++-- | Shut down a @termbox@ program.+finalize :: IO ()+finalize = do+ _ <- Termbox.Bindings.Hs.tb_select_output_mode Termbox.Bindings.Hs.TB_OUTPUT_NORMAL+ Termbox.Bindings.Hs.tb_shutdown
src/Termbox/Internal/Mouse.hs view
@@ -1,48 +1,58 @@ module Termbox.Internal.Mouse- ( Mouse- ( Mouse,- MouseLeft,- MouseMiddle,- MouseRelease,- MouseRight,- MouseWheelUp,- MouseWheelDown+ ( Mouse (..),+ MouseButton+ ( MouseButton,+ LeftClick,+ MiddleClick,+ RightClick,+ ReleaseClick,+ WheelDown,+ WheelUp ), ) where +import GHC.Generics (Generic) import qualified Termbox.Bindings.Hs+import Termbox.Internal.Pos (Pos) -- | A mouse event.-newtype Mouse- = Mouse Termbox.Bindings.Hs.Tb_key+data Mouse = Mouse+ { button :: !MouseButton,+ pos :: !Pos+ }+ deriving stock (Eq, Generic, Ord, Show)++-- | A mouse button.+newtype MouseButton+ = MouseButton Termbox.Bindings.Hs.Tb_key deriving stock (Eq, Ord) -instance Show Mouse where+instance Show MouseButton where show = \case- MouseLeft -> "MouseLeft"- MouseMiddle -> "MouseMiddle"- MouseRelease -> "MouseRelease"- MouseRight -> "MouseRight"- MouseWheelDown -> "MouseWheelDown"- MouseWheelUp -> "MouseWheelUp"+ LeftClick -> "LeftClick"+ MiddleClick -> "MiddleClick"+ ReleaseClick -> "ReleaseClick"+ RightClick -> "RightClick"+ WheelDown -> "WheelDown"+ WheelUp -> "WheelUp" -pattern MouseLeft :: Mouse-pattern MouseLeft = Mouse Termbox.Bindings.Hs.TB_KEY_MOUSE_LEFT+pattern LeftClick :: MouseButton+pattern LeftClick = MouseButton Termbox.Bindings.Hs.TB_KEY_MOUSE_LEFT -pattern MouseMiddle :: Mouse-pattern MouseMiddle = Mouse Termbox.Bindings.Hs.TB_KEY_MOUSE_MIDDLE+pattern MiddleClick :: MouseButton+pattern MiddleClick = MouseButton Termbox.Bindings.Hs.TB_KEY_MOUSE_MIDDLE -pattern MouseRelease :: Mouse-pattern MouseRelease = Mouse Termbox.Bindings.Hs.TB_KEY_MOUSE_RELEASE+pattern RightClick :: MouseButton+pattern RightClick = MouseButton Termbox.Bindings.Hs.TB_KEY_MOUSE_RIGHT -pattern MouseRight :: Mouse-pattern MouseRight = Mouse Termbox.Bindings.Hs.TB_KEY_MOUSE_RIGHT+pattern ReleaseClick :: MouseButton+pattern ReleaseClick = MouseButton Termbox.Bindings.Hs.TB_KEY_MOUSE_RELEASE -pattern MouseWheelDown :: Mouse-pattern MouseWheelDown = Mouse Termbox.Bindings.Hs.TB_KEY_MOUSE_WHEEL_DOWN+pattern WheelDown :: MouseButton+pattern WheelDown = MouseButton Termbox.Bindings.Hs.TB_KEY_MOUSE_WHEEL_DOWN -pattern MouseWheelUp :: Mouse-pattern MouseWheelUp = Mouse Termbox.Bindings.Hs.TB_KEY_MOUSE_WHEEL_UP+pattern WheelUp :: MouseButton+pattern WheelUp = MouseButton Termbox.Bindings.Hs.TB_KEY_MOUSE_WHEEL_UP -{-# COMPLETE MouseLeft, MouseMiddle, MouseRelease, MouseRight, MouseWheelDown, MouseWheelUp #-}+{-# COMPLETE LeftClick, MiddleClick, ReleaseClick, RightClick, WheelDown, WheelUp #-}
src/Termbox/Internal/Scene.hs view
@@ -1,6 +1,6 @@ module Termbox.Internal.Scene ( Scene,- drawScene,+ render, cell, fill, cursor,@@ -43,9 +43,9 @@ draw1 color } --- Draw a scene.-drawScene :: Scene -> IO ()-drawScene Scene {sceneFill, sceneDraw} = do+-- | Render a scene.+render :: Scene -> IO ()+render Scene {sceneFill, sceneDraw} = do let background = case sceneFill of Nothing -> Termbox.Bindings.Hs.TB_DEFAULT
src/Termbox/Internal/Size.hs view
@@ -1,9 +1,11 @@ module Termbox.Internal.Size ( Size (..),+ getSize, ) where import GHC.Generics (Generic)+import qualified Termbox.Bindings.Hs -- | A terminal size. data Size = Size@@ -11,3 +13,10 @@ height :: {-# UNPACK #-} !Int } deriving stock (Eq, Generic, Ord, Show)++-- | Get the current terminal size.+getSize :: IO Size+getSize = do+ width <- Termbox.Bindings.Hs.tb_width+ height <- Termbox.Bindings.Hs.tb_height+ pure Size {width, height}
termbox.cabal view
@@ -11,16 +11,18 @@ . See also: .+ * @<https://hackage.haskell.org/package/termbox-banana termbox-banana>@ for a @reactive-banana@ FRP interface.+ * @<https://hackage.haskell.org/package/termbox-tea termbox-tea>@ for an Elm Architecture interface. * @<https://hackage.haskell.org/package/termbox-bindings-hs termbox-bindings-hs>@ for lower-level bindings. * @<https://hackage.haskell.org/package/termbox-bindings-c termbox-bindings-c>@ for even lower-level bindings. homepage: https://github.com/termbox/termbox-haskell-license-file: LICENSE license: BSD-3-Clause+license-file: LICENSE maintainer: Mitchell Rosen <mitchellwrosen@gmail.com> name: termbox synopsis: termbox tested-with: GHC == 9.0.2, GHC == 9.2.4, GHC == 9.4.2-version: 1.0.0+version: 1.1.0 extra-source-files: CHANGELOG.md@@ -29,10 +31,6 @@ type: git location: git://github.com/termbox/termbox-haskell.git -flag build-examples- default: False- manual: True- common component default-extensions: BlockArguments@@ -76,7 +74,6 @@ build-depends: base ^>= 4.13 || ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17, termbox-bindings-hs ^>= 0.1,- ki ^>= 1.0, exposed-modules: Termbox hs-source-dirs: src other-modules:@@ -84,21 +81,8 @@ Termbox.Internal.Color Termbox.Internal.Event Termbox.Internal.Key+ Termbox.Internal.Main Termbox.Internal.Mouse Termbox.Internal.Pos Termbox.Internal.Size Termbox.Internal.Scene--executable termbox-example-demo- import: component- if !flag(build-examples)- buildable: False- build-depends:- base,- ki ^>= 1.0,- termbox,- ghc-options:- -rtsopts- -threaded- hs-source-dirs: examples- main-is: Demo.hs