termbox-banana 1.0.0 → 2.0.0
raw patch · 5 files changed
+228/−94 lines, 5 filesdep +termbox-bananadep ~basedep ~reactive-bananadep ~termboxnew-component:exe:termbox-banana-example-quick-startPVP ok
version bump matches the API change (PVP)
Dependencies added: termbox-banana
Dependency ranges changed: base, reactive-banana, termbox
API changes (from Hackage documentation)
- Termbox.Banana: cell :: Pos -> Cell -> Scene
- Termbox.Banana: data Cell
+ Termbox.Banana: at :: Pos -> Image -> Image
+ Termbox.Banana: atCol :: Int -> Image -> Image
+ Termbox.Banana: atRow :: Int -> Image -> Image
+ Termbox.Banana: data () => Image
+ Termbox.Banana: image :: Image -> Scene
- Termbox.Banana: KeyChar :: Char -> Key
+ Termbox.Banana: KeyChar :: !Char -> Key
- Termbox.Banana: bg :: Color -> Cell -> Cell
+ Termbox.Banana: bg :: Color -> Image -> Image
- Termbox.Banana: blink :: Cell -> Cell
+ Termbox.Banana: blink :: Image -> Image
- Termbox.Banana: bold :: Cell -> Cell
+ Termbox.Banana: bold :: Image -> Image
- Termbox.Banana: char :: Char -> Cell
+ Termbox.Banana: char :: Char -> Image
- Termbox.Banana: cursor :: Pos -> Scene
+ Termbox.Banana: cursor :: Pos -> Scene -> Scene
- Termbox.Banana: data Color
+ Termbox.Banana: data () => Color
- Termbox.Banana: data InitError
+ Termbox.Banana: data () => InitError
- Termbox.Banana: data Key
+ Termbox.Banana: data () => Key
- Termbox.Banana: data Mouse
+ Termbox.Banana: data () => Mouse
- Termbox.Banana: data MouseButton
+ Termbox.Banana: data () => MouseButton
- Termbox.Banana: data Pos
+ Termbox.Banana: data () => Pos
- Termbox.Banana: data Scene
+ Termbox.Banana: data () => Scene
- Termbox.Banana: data Size
+ Termbox.Banana: data () => Size
- Termbox.Banana: fg :: Color -> Cell -> Cell
+ Termbox.Banana: fg :: Color -> Image -> Image
- Termbox.Banana: fill :: Color -> Scene
+ Termbox.Banana: fill :: Color -> Scene -> Scene
- Termbox.Banana: underline :: Cell -> Cell
+ Termbox.Banana: underline :: Image -> Image
Files
- CHANGELOG.md +11/−7
- LICENSE +1/−1
- examples/QuickStart.hs +53/−0
- src/Termbox/Banana.hs +119/−65
- termbox-banana.cabal +44/−21
CHANGELOG.md view
@@ -1,36 +1,40 @@-## [1.0.0] - 2022-11-03+## [2.0.0] - November 5, 2023 +- Update to `termbox-2.0.0`++## [1.0.0] - November 2, 2022+ - Rework `run` type - Bump to `termbox-1.1.0`, whose API changes are visible here, too -## [0.4.0] - 2022-07-16+## [0.4.0] - July 16, 2022 - Parameterize `TermboxEvent` (now `Event`) by user event - Add `Program` type alias for readability - Remove `TermboxEvent` alias - Drop GHC 8.2 support -## [0.3.1] - 2022-04-02+## [0.3.1] - April 2, 2022 - Remove example executables -## [0.3.0] - 2020-09-20+## [0.3.0] - September 20, 2020 - Support GHC 8.8, GHC 8.10 - Depend on `termbox ==0.3` - Remove `Scene` -## [0.2.0] - 2019-06-28+## [0.2.0] - June 29, 2019 - Add `run` - Rename `main` to `run_` - Bump `termbox` lower bound -## [0.1.1] - 2019-04-19+## [0.1.1] - April 19, 2019 - Remov unnecessary `stm` dependency - Bump `base` upper bound -## [0.1.0] - 2018-07-22+## [0.1.0] - July 22, 2018 - Initial release
LICENSE view
@@ -1,4 +1,4 @@-Copyright 2018-2022 Mitchell Rosen+Copyright 2018-2023 Mitchell Rosen Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ examples/QuickStart.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE ImportQualifiedPost #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedRecordDot #-}++module Main (main) where++import Data.Foldable (fold)+import Data.Function ((&))+import Reactive.Banana ((<@>))+import Reactive.Banana qualified as Banana+import Termbox.Banana qualified as Termbox++main :: IO ()+main = do+ result <- Termbox.run network+ putStrLn case result of+ Left err -> "Termbox program failed to initialize: " ++ show err+ Right state -> "Final state: " ++ show state++network :: (Banana.MonadMoment m) => Termbox.Inputs -> m (Termbox.Outputs Int)+network inputs = do+ keysPressed <- Banana.accumB 0 ((+ 1) <$ inputs.keys)+ pure+ Termbox.Outputs+ { scene = render <$> keysPressed,+ done = Banana.filterJust (isDone <$> keysPressed <@> inputs.keys)+ }+ where+ isDone :: Int -> Termbox.Key -> Maybe Int+ isDone n = \case+ Termbox.KeyEsc -> Just n+ _ -> Nothing++render :: Int -> Termbox.Scene+render keysPressed =+ fold+ [ string ("Number of keys pressed: " ++ show 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++string :: [Char] -> Termbox.Image+string chars =+ zip [0 ..] chars & foldMap \(i, char) ->+ Termbox.char char & Termbox.atCol i
src/Termbox/Banana.hs view
@@ -6,116 +6,130 @@ -- -- * @<https://hackage.haskell.org/package/termbox-tea termbox-tea>@, an Elm Architecture interface. ----- This module is intended to be imported qualified.--- -- ==== __👉 Quick start example__ -- -- This @termbox@ program displays the number of keys pressed. -- -- @+-- {-\# LANGUAGE BlockArguments \#-} -- {-\# LANGUAGE DuplicateRecordFields \#-} -- {-\# LANGUAGE ImportQualifiedPost \#-} -- {-\# LANGUAGE LambdaCase \#-} -- {-\# LANGUAGE OverloadedRecordDot \#-}--- {-\# LANGUAGE OverloadedStrings \#-}--- {-\# LANGUAGE NoFieldSelectors \#-} --+-- module Main (main) where+-- -- import Data.Foldable (fold)+-- import Data.Function ((&)) -- import Reactive.Banana ((\<\@\>)) -- import Reactive.Banana qualified as Banana -- import Termbox.Banana qualified as Termbox -- -- main :: IO ()--- main =--- Termbox.'run' network \>\>= \\case--- Left err -\> putStrLn (\"Termbox program failed to initialize: \" ++ show err)--- Right n -\> putStrLn (\"Pressed \" ++ show n ++ \" keys.\")+-- main = do+-- result \<- Termbox.'run' network+-- putStrLn case result of+-- Left err -\> \"Termbox program failed to initialize: \" ++ show err+-- Right state -\> \"Final state: \" ++ show state ----- network :: Banana.MonadMoment m =\> Termbox.'Inputs' -\> m (Termbox.'Outputs' Int)+-- network :: (Banana.MonadMoment m) =\> Termbox.'Inputs' -\> m (Termbox.'Outputs' Int) -- network inputs = do--- keysPressed <- Banana.accumB 0 ((+ 1) \<$ inputs.keys)+-- keysPressed \<- Banana.accumB 0 ((+ 1) \<$ inputs.keys) -- pure -- Termbox.'Outputs' -- { scene = render \<$\> keysPressed, -- done = Banana.filterJust (isDone \<$\> keysPressed \<\@\> inputs.keys) -- } -- where--- isDone :: Int -\> Termbox.'Termbox.Banana.Key' -\> Maybe Int+-- isDone :: Int -\> Termbox.'Key' -\> Maybe Int -- isDone n = \\case--- Termbox.'Termbox.Banana.KeyEsc' -\> Just n+-- Termbox.'KeyEsc' -\> Just n -- _ -\> Nothing ----- render :: Int -\> Termbox.'Termbox.Banana.Scene'+-- render :: Int -\> Termbox.'Scene' -- render keysPressed = -- fold--- [ string--- Termbox.'Termbox.Banana.Pos' {row = 2, col = 4}--- (\"Number of keys pressed: \" ++ map Termbox.'Termbox.Banana.char' (show keysPressed)),--- string--- Termbox.'Termbox.Banana.Pos' {row = 4, col = 4}--- (\"Press \" ++ map (Termbox.'Termbox.Banana.bold' . Termbox.'Termbox.Banana.char') \"Esc\" ++ \" to quit.\")+-- [ string (\"Number of keys pressed: \" ++ show 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' ----- string :: Termbox.'Termbox.Banana.Pos' -\> [Termbox.'Termbox.Banana.Cell'] -\> Termbox.'Termbox.Banana.Scene'--- string pos cells =--- foldMap (\\(i, cell) -\> Termbox.'Termbox.Banana.cell' (Termbox.'Termbox.Banana.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.Banana ( -- * Main Inputs (..), Outputs (..), 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.Key (..),- Termbox.Mouse (..),- Termbox.MouseButton (..),+ Key (..),+ Mouse (..),+ MouseButton (..), -- * Miscellaneous types- Termbox.Pos (..),- Termbox.posUp,- Termbox.posDown,- Termbox.posLeft,- Termbox.posRight,- Termbox.Size (..),+ Pos (..),+ posUp,+ posDown,+ posLeft,+ posRight,+ Size (..), ) where @@ -124,24 +138,64 @@ import Data.Void (Void) import qualified Reactive.Banana as Banana import qualified Reactive.Banana.Frameworks as Banana-import qualified Termbox+import Termbox+ ( Color,+ 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 (Event (..), render, run) -- | The inputs to a @termbox@ FRP network. data Inputs = Inputs { -- | The initial terminal size.- initialSize :: !Termbox.Size,+ initialSize :: !Size, -- | Key events.- keys :: !(Banana.Event Termbox.Key),+ keys :: !(Banana.Event Key), -- | Resize events.- resizes :: !(Banana.Event Termbox.Size),+ resizes :: !(Banana.Event Size), -- | Mouse events.- mouses :: !(Banana.Event Termbox.Mouse)+ mouses :: !(Banana.Event Mouse) } -- | The outputs from a @termbox@ FRP network. data Outputs a = Outputs { -- | The scene to render.- scene :: !(Banana.Behavior Termbox.Scene),+ scene :: !(Banana.Behavior Scene), -- | The events of arbitrary values, on the first of which is relevant, which causes 'run' to return. -- -- /Note/: Wrapping this event in 'Banana.once' is not necessary, as this library does so internally.@@ -158,13 +212,13 @@ -- | The FRP network. (Inputs -> Banana.MomentIO (Outputs a)) -> -- | The result of the FRP network.- IO (Either Termbox.InitError a)+ IO (Either InitError a) run program = Termbox.run (run_ program) run_ :: (Inputs -> Banana.MomentIO (Outputs a)) -> IO a run_ program = do- initialSize <- Termbox.getSize+ initialSize <- getSize doneVar <- newEmptyMVar (keysAddHandler, fireKey) <- Banana.newAddHandler@@ -191,7 +245,7 @@ Banana.actuate network let loop = do- Termbox.poll @Void >>= \case+ poll @Void >>= \case Termbox.EventKey key -> fireKey key Termbox.EventResize size -> fireResize size Termbox.EventMouse mouse -> fireMouse mouse
termbox-banana.cabal view
@@ -1,49 +1,42 @@ cabal-version: 2.4 author: Mitchell Rosen-bug-reports: https://github.com/mitchellwrosen/termbox-banana/issues+bug-reports: https://github.com/termbox/termbox-haskell/issues build-type: Simple category: User Interfaces-copyright: (c) 2018-2022, Mitchell Rosen+copyright: (c) 2018-2023, Mitchell Rosen description: This package provides a @reactive-banana@ FRP interface to @termbox@ programs. . See also: . * @<https://hackage.haskell.org/package/termbox-tea termbox-tea>@ for an Elm Architecture interface.-homepage: https://github.com/mitchellwrosen/termbox-banana+homepage: https://github.com/termbox/termbox-haskell license: BSD-3-Clause license-file: LICENSE maintainer: Mitchell Rosen <mitchellwrosen@gmail.com> name: termbox-banana synopsis: termbox + reactive-banana-tested-with: GHC == 9.0.2, GHC == 9.2.4, GHC == 9.4.2-version: 1.0.0+tested-with: GHC == 9.2.7, GHC == 9.4.4, GHC == 9.6.1+version: 2.0.0 -extra-source-files:+extra-doc-files: CHANGELOG.md source-repository head type: git- location: git://github.com/mitchellwrosen/termbox-banana.git+ location: git://github.com/awkward-squad/termbox.git+ subdir: termbox-banana -library- build-depends:- base ^>= 4.13 || ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17,- reactive-banana ^>= 1.3,- termbox ^>= 1.1.0,- default-extensions:- BlockArguments- DerivingStrategies- GeneralizedNewtypeDeriving- InstanceSigs- LambdaCase- NamedFieldPuns- TypeApplications+flag build-examples+ default: False+ manual: True++common component default-language: Haskell2010- exposed-modules: Termbox.Banana ghc-options: -Weverything+ -Wno-all-missed-specialisations -Wno-implicit-prelude -Wno-missing-import-lists -Wno-missing-local-signatures@@ -57,4 +50,34 @@ if impl(ghc >= 9.2) ghc-options: -Wno-missing-kind-signatures+ if impl(ghc >= 9.8)+ ghc-options:+ -Wno-missing-role-annotations++library+ import: component+ build-depends:+ base ^>= 4.13 || ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17 || ^>= 4.18 || ^>= 4.19,+ reactive-banana ^>= 1.3,+ termbox ^>= 2.0.0,+ default-extensions:+ BlockArguments+ DerivingStrategies+ GeneralizedNewtypeDeriving+ InstanceSigs+ LambdaCase+ NamedFieldPuns+ TypeApplications+ exposed-modules: Termbox.Banana hs-source-dirs: src++executable termbox-banana-example-quick-start+ import: component+ if !flag(build-examples)+ buildable: False+ build-depends:+ base,+ reactive-banana,+ termbox-banana,+ hs-source-dirs: examples+ main-is: QuickStart.hs