brick 0.2.3 → 0.3
raw patch · 13 files changed
+70/−81 lines, 13 filesdep −DiffPVP ok
version bump matches the API change (PVP)
Dependencies removed: Diff
API changes (from Hackage documentation)
- Brick.Types: type EventM a = ReaderT (Map Name Viewport) (StateT EventState IO) a
+ Brick.Types: EventM :: ReaderT (Map Name Viewport) (StateT EventState IO) a -> EventM a
+ Brick.Types: [runEventM] :: EventM a -> ReaderT (Map Name Viewport) (StateT EventState IO) a
+ Brick.Types: instance GHC.Base.Applicative Brick.Types.EventM
+ Brick.Types: instance GHC.Base.Functor Brick.Types.EventM
+ Brick.Types: instance GHC.Base.Monad Brick.Types.EventM
+ Brick.Types: newtype EventM a
- Brick.Widgets.Dialog: dialogButtonsL :: Lens (Dialog a_aGHj) (Dialog a_aGHO) [(String, a_aGHj)] [(String, a_aGHO)]
+ Brick.Widgets.Dialog: dialogButtonsL :: forall a_aXQM a_aXRq. Lens (Dialog a_aXQM) (Dialog a_aXRq) [(String, a_aXQM)] [(String, a_aXRq)]
- Brick.Widgets.Dialog: dialogNameL :: Lens' (Dialog a_aGHj) Name
+ Brick.Widgets.Dialog: dialogNameL :: forall a_aXQM. Lens' (Dialog a_aXQM) Name
- Brick.Widgets.Dialog: dialogSelectedIndexL :: Lens' (Dialog a_aGHj) (Maybe Int)
+ Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_aXQM. Lens' (Dialog a_aXQM) (Maybe Int)
- Brick.Widgets.Dialog: dialogTitleL :: Lens' (Dialog a_aGHj) (Maybe String)
+ Brick.Widgets.Dialog: dialogTitleL :: forall a_aXQM. Lens' (Dialog a_aXQM) (Maybe String)
- Brick.Widgets.Dialog: dialogWidthL :: Lens' (Dialog a_aGHj) Int
+ Brick.Widgets.Dialog: dialogWidthL :: forall a_aXQM. Lens' (Dialog a_aXQM) Int
- Brick.Widgets.List: listElementsL :: Lens (List e_aMrE) (List e_aMsy) (Vector e_aMrE) (Vector e_aMsy)
+ Brick.Widgets.List: listElementsL :: forall e_a113M e_a114X. Lens (List e_a113M) (List e_a114X) (Vector e_a113M) (Vector e_a114X)
- Brick.Widgets.List: listItemHeightL :: Lens' (List e_aMrE) Int
+ Brick.Widgets.List: listItemHeightL :: forall e_a113M. Lens' (List e_a113M) Int
- Brick.Widgets.List: listNameL :: Lens' (List e_aMrE) Name
+ Brick.Widgets.List: listNameL :: forall e_a113M. Lens' (List e_a113M) Name
- Brick.Widgets.List: listReplace :: Eq e => Vector e -> List e -> List e
+ Brick.Widgets.List: listReplace :: Eq e => Vector e -> Maybe Int -> List e -> List e
- Brick.Widgets.List: listSelectedL :: Lens' (List e_aMrE) (Maybe Int)
+ Brick.Widgets.List: listSelectedL :: forall e_a113M. Lens' (List e_a113M) (Maybe Int)
Files
- CHANGELOG.md +17/−0
- README.md +1/−1
- brick.cabal +1/−2
- programs/LayerDemo.hs +1/−4
- programs/SuspendAndResumeDemo.hs +1/−1
- programs/ViewportScrollDemo.hs +0/−1
- src/Brick/Main.hs +13/−13
- src/Brick/Types.hs +7/−2
- src/Brick/Widgets/Center.hs +3/−2
- src/Brick/Widgets/Core.hs +8/−9
- src/Brick/Widgets/Internal.hs +1/−1
- src/Brick/Widgets/List.hs +15/−44
- src/Brick/Widgets/ProgressBar.hs +2/−1
CHANGELOG.md view
@@ -2,6 +2,23 @@ Brick changelog --------------- +0.3+---++API changes:+* Made EventM a newtype instead of a type alias+* List: listReplace now takes the new selected index and no longer does+element diffing++Package changes:+* Removed the dependency on the Diff package++Misc:+* Applied some hlint hints (thanks Markus Hauck <markus1189@gmail.com>)+* Fixed a typo in the README (thanks Markus Hauck <markus1189@gmail.com>)+* Improved the renderList documentation (thanks Profpatsch <mail@profpatsch.de>)+* Types: added an explicit import of Applicative for older GHCs+ 0.2.3 -----
README.md view
@@ -102,7 +102,7 @@ - Clearly describe the behavior you expected ... - - ... and include a mininal demonstration program that exhibits the+ - ... and include a minimal demonstration program that exhibits the behavior you actually observed. Contributing
brick.cabal view
@@ -1,5 +1,5 @@ name: brick-version: 0.2.3+version: 0.3 synopsis: A declarative terminal user interface library description: Write terminal applications painlessly with 'brick'! You write an@@ -80,7 +80,6 @@ vty >= 5.3.1, transformers, data-default,- Diff, containers, lens, vector,
programs/LayerDemo.hs view
@@ -8,12 +8,9 @@ import qualified Graphics.Vty as V import qualified Brick.Types as T-import Brick.Types (rowL, columnL)+import Brick.Types (rowL, columnL, Widget) import qualified Brick.Main as M import qualified Brick.Widgets.Border as B-import Brick.Types- ( Widget- ) import Brick.Widgets.Core ( translateBy , str
programs/SuspendAndResumeDemo.hs view
@@ -61,5 +61,5 @@ } main :: IO ()-main = do+main = void $ defaultMain theApp initialState
programs/ViewportScrollDemo.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-} module Main where
src/Brick/Main.hs view
@@ -53,7 +53,7 @@ , mkVty ) -import Brick.Types (Viewport, Direction, Widget, rowL, columnL, CursorLocation(..), cursorLocationNameL, Name(..), EventM)+import Brick.Types (Viewport, Direction, Widget, rowL, columnL, CursorLocation(..), cursorLocationNameL, Name(..), EventM(..)) import Brick.Types.Internal (ScrollRequest(..), RenderState(..), Next(..)) import Brick.Widgets.Internal (renderFinal) import Brick.AttrMap@@ -135,7 +135,7 @@ | InternalHalt a runWithNewVty :: IO Vty -> Chan e -> App s e -> RenderState -> s -> IO (InternalNext s)-runWithNewVty buildVty chan app initialRS initialSt = do+runWithNewVty buildVty chan app initialRS initialSt = withVty buildVty $ \vty -> do pid <- forkIO $ supplyVtyEvents vty (appLiftVtyEvent app) chan let runInner rs st = do@@ -174,7 +174,7 @@ newAppState <- action run newRS newAppState - (st, initialScrollReqs) <- runStateT (runReaderT (appStartEvent app initialAppState) M.empty) []+ (st, initialScrollReqs) <- runStateT (runReaderT (runEventM (appStartEvent app initialAppState)) M.empty) [] let initialRS = RS M.empty initialScrollReqs run initialRS st @@ -188,7 +188,7 @@ runVty vty chan app appState rs = do firstRS <- renderApp vty app appState rs e <- readChan chan- (next, scrollReqs) <- runStateT (runReaderT (appHandleEvent app appState e) (viewportMap rs)) []+ (next, scrollReqs) <- runStateT (runReaderT (runEventM (appHandleEvent app appState e)) (viewportMap rs)) [] return (next, firstRS { scrollRequests = scrollReqs }) -- | Given a viewport name, get the viewport's size and offset@@ -197,7 +197,7 @@ -- or because no rendering has occurred (e.g. in an 'appStartEvent' -- handler). lookupViewport :: Name -> EventM (Maybe Viewport)-lookupViewport = asks . M.lookup+lookupViewport = EventM . asks . M.lookup withVty :: IO Vty -> (Vty -> IO a) -> IO a withVty buildVty useVty = do@@ -276,14 +276,14 @@ viewportScroll :: Name -> ViewportScroll viewportScroll n = ViewportScroll { viewportName = n- , hScrollPage = \dir -> lift $ modify ((n, HScrollPage dir) :)- , hScrollBy = \i -> lift $ modify ((n, HScrollBy i) :)- , hScrollToBeginning = lift $ modify ((n, HScrollToBeginning) :)- , hScrollToEnd = lift $ modify ((n, HScrollToEnd) :)- , vScrollPage = \dir -> lift $ modify ((n, VScrollPage dir) :)- , vScrollBy = \i -> lift $ modify ((n, VScrollBy i) :)- , vScrollToBeginning = lift $ modify ((n, VScrollToBeginning) :)- , vScrollToEnd = lift $ modify ((n, VScrollToEnd) :)+ , hScrollPage = \dir -> EventM $ lift $ modify ((n, HScrollPage dir) :)+ , hScrollBy = \i -> EventM $ lift $ modify ((n, HScrollBy i) :)+ , hScrollToBeginning = EventM $ lift $ modify ((n, HScrollToBeginning) :)+ , hScrollToEnd = EventM $ lift $ modify ((n, HScrollToEnd) :)+ , vScrollPage = \dir -> EventM $ lift $ modify ((n, VScrollPage dir) :)+ , vScrollBy = \i -> EventM $ lift $ modify ((n, VScrollBy i) :)+ , vScrollToBeginning = EventM $ lift $ modify ((n, VScrollToBeginning) :)+ , vScrollToEnd = EventM $ lift $ modify ((n, VScrollToEnd) :) } -- | Continue running the event loop with the specified application
src/Brick/Types.hs view
@@ -1,6 +1,7 @@ -- | Basic types used by this library. {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Brick.Types ( -- * The Widget type@@ -22,7 +23,7 @@ , vpLeft -- * Event-handling types- , EventM+ , EventM(..) , Next , HandleEvent(..) , handleEventLensed@@ -66,6 +67,7 @@ ) where +import Control.Applicative import Control.Lens (_1, _2, to, (^.), (&), (.~), Lens') import Data.Monoid (Monoid(..)) import Control.Monad.Trans.State.Lazy@@ -111,7 +113,10 @@ -- | The monad in which event handlers run. Although it may be tempting -- to dig into the reader value yourself, just use -- 'Brick.Main.lookupViewport'.-type EventM a = ReaderT (M.Map Name Viewport) (StateT EventState IO) a+newtype EventM a =+ EventM { runEventM :: ReaderT (M.Map Name Viewport) (StateT EventState IO) a+ }+ deriving (Functor, Applicative, Monad) -- | Widget growth policies. These policies communicate to layout -- algorithms how a widget uses space when being rendered. These
src/Brick/Widgets/Center.hs view
@@ -15,6 +15,7 @@ where import Control.Lens ((^.), (&), (.~), to)+import Data.Maybe (fromMaybe) import Graphics.Vty (imageWidth, imageHeight, horizCat, charFill, vertCat) import Brick.Types@@ -30,7 +31,7 @@ -- to either side of the centered widget (defaults to space). hCenterWith :: Maybe Char -> Widget -> Widget hCenterWith mChar p =- let ch = maybe ' ' id mChar+ let ch = fromMaybe ' ' mChar in Widget Greedy (vSize p) $ do result <- render p c <- getContext@@ -60,7 +61,7 @@ -- widget (defaults to space). vCenterWith :: Maybe Char -> Widget -> Widget vCenterWith mChar p =- let ch = maybe ' ' id mChar+ let ch = fromMaybe ' ' mChar in Widget (hSize p) Greedy $ do result <- render p c <- getContext
src/Brick/Widgets/Core.hs view
@@ -65,8 +65,8 @@ where import Control.Applicative-import Control.Lens ((^.), (.~), (&), (%~), to, _1, _2, each, to, ix)-import Control.Monad (when)+import Control.Lens ((^.), (.~), (&), (%~), to, _1, _2, each, to, ix, Lens')+import Control.Monad ((>=>),when) import Control.Monad.Trans.State.Lazy import Control.Monad.Trans.Reader import Control.Monad.Trans.Class (lift)@@ -76,7 +76,6 @@ import qualified Data.Map as M import qualified Data.Function as DF import Data.List (sortBy, partition)-import Control.Lens (Lens') import qualified Graphics.Vty as V import Control.DeepSeq @@ -337,7 +336,7 @@ -- returned along with the translated cursor positions and visibility -- requests. renderBox :: BoxRenderer -> [Widget] -> Widget-renderBox br ws = do+renderBox br ws = Widget (maximum $ hSize <$> ws) (maximum $ vSize <$> ws) $ do c <- getContext @@ -389,7 +388,7 @@ -- and defers to the limited widget vertically. hLimit :: Int -> Widget -> Widget hLimit w p =- Widget Fixed (vSize p) $ do+ Widget Fixed (vSize p) $ withReaderT (& availWidthL .~ w) $ render $ cropToContext p -- | Limit the space available to the specified widget to the specified@@ -398,7 +397,7 @@ -- defers to the limited widget horizontally. vLimit :: Int -> Widget -> Widget vLimit h p =- Widget (hSize p) Fixed $ do+ Widget (hSize p) Fixed $ withReaderT (& availHeightL .~ h) $ render $ cropToContext p -- | When drawing the specified widget, set the current attribute used@@ -410,7 +409,7 @@ -- 'withDefAttr'. withAttr :: AttrName -> Widget -> Widget withAttr an p =- Widget (hSize p) (vSize p) $ do+ Widget (hSize p) (vSize p) $ withReaderT (& ctxAttrNameL .~ an) (render p) -- | Update the attribute map while rendering the specified widget: set@@ -426,7 +425,7 @@ -- the specified transformation. updateAttrMap :: (AttrMap -> AttrMap) -> Widget -> Widget updateAttrMap f p =- Widget (hSize p) (vSize p) $ do+ Widget (hSize p) (vSize p) $ withReaderT (& ctxAttrMapL %~ f) (render p) -- | When rendering the specified widget, force all attribute lookups@@ -554,7 +553,7 @@ release = case typ of Vertical -> vRelease Horizontal -> hRelease- Both -> \w -> vRelease w >>= hRelease+ Both ->vRelease >=> hRelease released = case release p of Just w -> w Nothing -> case typ of
src/Brick/Widgets/Internal.hs view
@@ -37,7 +37,7 @@ -- dimensions in the rendering context. cropToContext :: Widget -> Widget cropToContext p =- Widget (hSize p) (vSize p) $ (render p >>= cropResultToContext)+ Widget (hSize p) (vSize p) (render p >>= cropResultToContext) cropResultToContext :: Result -> RenderM Result cropResultToContext result = do
src/Brick/Widgets/List.hs view
@@ -36,9 +36,8 @@ import Control.Applicative ((<$>)) import Control.Lens ((^.), (&), (.~), _2)-import Data.Monoid ((<>)) import Data.Maybe (fromMaybe)-import qualified Data.Algorithm.Diff as D+import Data.Monoid ((<>)) import Graphics.Vty (Event(..), Key(..)) import qualified Data.Vector as V @@ -109,7 +108,12 @@ -- | Turn a list state value into a widget given an item drawing -- function.-renderList :: List e -> (Bool -> e -> Widget) -> Widget+renderList :: List e+ -- ^ The List to be rendered+ -> (Bool -> e -> Widget)+ -- ^ Rendering function, True for the selected element+ -> Widget+ -- ^ rendered widget renderList l drawElem = withDefAttr listAttr $ drawListElements l drawElem@@ -120,9 +124,7 @@ c <- getContext let es = V.slice start num (l^.listElementsL)- idx = case l^.listSelectedL of- Nothing -> 0- Just i -> i+ idx = fromMaybe 0 (l^.listSelectedL) start = max 0 $ idx - numPerHeight + 1 num = min (numPerHeight * 2) (V.length (l^.listElementsL) - start)@@ -184,20 +186,14 @@ in l & listSelectedL .~ (if V.null es' then Nothing else Just newSel) & listElementsL .~ es' --- | Replace the contents of a list with a new set of elements but--- preserve the currently selected index.-listReplace :: Eq e => V.Vector e -> List e -> List e-listReplace es' l | es' == l^.listElementsL = l- | otherwise =- let sel = fromMaybe 0 (l^.listSelectedL)- getNewSel es = case (V.null es, V.null es') of- (_, True) -> Nothing- (True, False) -> Just 0- (False, False) -> Just (maintainSel (V.toList es) (V.toList es') sel)- newSel = getNewSel (l^.listElementsL)-+-- | Replace the contents of a list with a new set of elements and+-- update the new selected index. If the specified selected index (via+-- 'Just') is not in the list bounds, zero is used instead.+listReplace :: Eq e => V.Vector e -> Maybe Int -> List e -> List e+listReplace es idx l =+ let newSel = clamp 0 (V.length es - 1) <$> idx in l & listSelectedL .~ newSel- & listElementsL .~ es'+ & listElementsL .~ es -- | Move the list selected index up by one. (Moves the cursor up, -- subtracts one from the index.)@@ -231,28 +227,3 @@ listSelectedElement l = do sel <- l^.listSelectedL return (sel, (l^.listElementsL) V.! sel)---- Assuming `xs` is an existing list that we want to update to match the--- state of `ys`. Given a selected index in `xs`, the goal is to compute--- the corresponding index in `ys`.-maintainSel :: (Eq e) => [e] -> [e] -> Int -> Int-maintainSel xs ys sel = let hunks = D.getDiff xs ys- in merge 0 sel hunks--merge :: (Eq e) => Int -> Int -> [D.Diff e] -> Int-merge _ sel [] = sel-merge idx sel (h:hs) | idx > sel = sel- | otherwise = case h of- D.Both _ _ -> merge sel (idx + 1) hs-- -- element removed in new list- D.First _ -> let newSel = if idx < sel- then sel - 1- else sel- in merge newSel idx hs-- -- element added in new list- D.Second _ -> let newSel = if idx <= sel- then sel + 1- else sel- in merge newSel (idx + 1) hs
src/Brick/Widgets/ProgressBar.hs view
@@ -9,6 +9,7 @@ where import Control.Lens ((^.))+import Data.Maybe (fromMaybe) import Data.Monoid import Brick.Types@@ -36,7 +37,7 @@ Widget Greedy Fixed $ do c <- getContext let barWidth = c^.availWidthL- label = maybe "" id mLabel+ label = fromMaybe "" mLabel labelWidth = length label spacesWidth = barWidth - labelWidth leftPart = replicate (spacesWidth `div` 2) ' '