packages feed

brick 0.40 → 0.41

raw patch · 13 files changed

+178/−51 lines, 13 filesdep ~basedep ~vtyPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, vty

API changes (from Hackage documentation)

+ Brick.AttrMap: instance GHC.Generics.Generic Brick.AttrMap.AttrMap
+ Brick.AttrMap: instance GHC.Generics.Generic Brick.AttrMap.AttrName
+ Brick.BorderMap: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Brick.BorderMap.BorderMap a)
+ Brick.BorderMap: instance GHC.Generics.Generic (Brick.BorderMap.BorderMap a)
+ Brick.BorderMap: instance GHC.Read.Read a => GHC.Read.Read (Brick.BorderMap.BorderMap a)
+ Brick.Forms: listField :: forall s e n a. (Ord n, Show n, Eq a) => (s -> Vector a) -> Lens' s (Maybe a) -> (Bool -> a -> Widget n) -> Int -> n -> s -> FormFieldState s e n
+ Brick.Main: getRenderState :: EventM n (RenderState n)
+ Brick.Main: renderFinal :: AttrMap -> [Widget n] -> DisplayRegion -> ([CursorLocation n] -> Maybe (CursorLocation n)) -> RenderState n -> (RenderState n, Picture, Maybe (CursorLocation n), [Extent n])
+ Brick.Main: resetRenderState :: RenderState n -> RenderState n
+ Brick.Types: data RenderState n
+ Brick.Widgets.Border.Style: instance Control.DeepSeq.NFData Brick.Widgets.Border.Style.BorderStyle
+ Brick.Widgets.Border.Style: instance GHC.Generics.Generic Brick.Widgets.Border.Style.BorderStyle
+ Brick.Widgets.List: instance GHC.Generics.Generic (Brick.Widgets.List.List n e)
+ Brick.Widgets.List: listMoveToElement :: (Eq e) => e -> List n e -> List n e
+ Data.IMap: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Data.IMap.IMap a)
+ Data.IMap: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Data.IMap.Run a)
+ Data.IMap: instance GHC.Generics.Generic (Data.IMap.IMap a)
+ Data.IMap: instance GHC.Generics.Generic (Data.IMap.Run a)
+ Data.IMap: instance GHC.Read.Read a => GHC.Read.Read (Data.IMap.IMap a)
- Brick.BorderMap: eBottomL :: forall a_adTJ. Lens' (Edges a_adTJ) a_adTJ
+ Brick.BorderMap: eBottomL :: forall a_aidG. Lens' (Edges a_aidG) a_aidG
- Brick.BorderMap: eLeftL :: forall a_adTJ. Lens' (Edges a_adTJ) a_adTJ
+ Brick.BorderMap: eLeftL :: forall a_aidG. Lens' (Edges a_aidG) a_aidG
- Brick.BorderMap: eRightL :: forall a_adTJ. Lens' (Edges a_adTJ) a_adTJ
+ Brick.BorderMap: eRightL :: forall a_aidG. Lens' (Edges a_aidG) a_aidG
- Brick.BorderMap: eTopL :: forall a_adTJ. Lens' (Edges a_adTJ) a_adTJ
+ Brick.BorderMap: eTopL :: forall a_aidG. Lens' (Edges a_aidG) a_aidG
- Brick.Types: bordersL :: forall n_aAmL. Lens' (Result n_aAmL) (BorderMap DynBorder)
+ Brick.Types: bordersL :: forall n_aEnk. Lens' (Result n_aEnk) (BorderMap DynBorder)
- Brick.Types: cursorLocationL :: forall n_azMC. Lens' (CursorLocation n_azMC) Location
+ Brick.Types: cursorLocationL :: forall n_aD3s. Lens' (CursorLocation n_aD3s) Location
- Brick.Types: cursorLocationNameL :: forall n_azMC n_aAIi. Lens (CursorLocation n_azMC) (CursorLocation n_aAIi) (Maybe n_azMC) (Maybe n_aAIi)
+ Brick.Types: cursorLocationNameL :: forall n_aD3s n_aEZi. Lens (CursorLocation n_aD3s) (CursorLocation n_aEZi) (Maybe n_aD3s) (Maybe n_aEZi)
- Brick.Types: cursorsL :: forall n_aAmL. Lens' (Result n_aAmL) [CursorLocation n_aAmL]
+ Brick.Types: cursorsL :: forall n_aEnk. Lens' (Result n_aEnk) [CursorLocation n_aEnk]
- Brick.Types: eBottomL :: forall a_adTJ. Lens' (Edges a_adTJ) a_adTJ
+ Brick.Types: eBottomL :: forall a_aidG. Lens' (Edges a_aidG) a_aidG
- Brick.Types: eLeftL :: forall a_adTJ. Lens' (Edges a_adTJ) a_adTJ
+ Brick.Types: eLeftL :: forall a_aidG. Lens' (Edges a_aidG) a_aidG
- Brick.Types: eRightL :: forall a_adTJ. Lens' (Edges a_adTJ) a_adTJ
+ Brick.Types: eRightL :: forall a_aidG. Lens' (Edges a_aidG) a_aidG
- Brick.Types: eTopL :: forall a_adTJ. Lens' (Edges a_adTJ) a_adTJ
+ Brick.Types: eTopL :: forall a_aidG. Lens' (Edges a_aidG) a_aidG
- Brick.Types: extentsL :: forall n_aAmL. Lens' (Result n_aAmL) [Extent n_aAmL]
+ Brick.Types: extentsL :: forall n_aEnk. Lens' (Result n_aEnk) [Extent n_aEnk]
- Brick.Types: imageL :: forall n_aAmL. Lens' (Result n_aAmL) Image
+ Brick.Types: imageL :: forall n_aEnk. Lens' (Result n_aEnk) Image
- Brick.Types: visibilityRequestsL :: forall n_aAmL. Lens' (Result n_aAmL) [VisibilityRequest]
+ Brick.Types: visibilityRequestsL :: forall n_aEnk. Lens' (Result n_aEnk) [VisibilityRequest]
- Brick.Widgets.Dialog: dialogButtonsL :: forall a_a12D7 a_a12DO. Lens (Dialog a_a12D7) (Dialog a_a12DO) [(String, a_a12D7)] [(String, a_a12DO)]
+ Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1cIB a_a1cJi. Lens (Dialog a_a1cIB) (Dialog a_a1cJi) [(String, a_a1cIB)] [(String, a_a1cJi)]
- Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a12D7. Lens' (Dialog a_a12D7) (Maybe Int)
+ Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1cIB. Lens' (Dialog a_a1cIB) (Maybe Int)
- Brick.Widgets.Dialog: dialogTitleL :: forall a_a12D7. Lens' (Dialog a_a12D7) (Maybe String)
+ Brick.Widgets.Dialog: dialogTitleL :: forall a_a1cIB. Lens' (Dialog a_a1cIB) (Maybe String)
- Brick.Widgets.Dialog: dialogWidthL :: forall a_a12D7. Lens' (Dialog a_a12D7) Int
+ Brick.Widgets.Dialog: dialogWidthL :: forall a_a1cIB. Lens' (Dialog a_a1cIB) Int
- Brick.Widgets.Edit: editContentsL :: forall t_aYg8 n_aYg9 t_aYgS. Lens (Editor t_aYg8 n_aYg9) (Editor t_aYgS n_aYg9) (TextZipper t_aYg8) (TextZipper t_aYgS)
+ Brick.Widgets.Edit: editContentsL :: forall t_a18lw n_a18lx t_a18mg. Lens (Editor t_a18lw n_a18lx) (Editor t_a18mg n_a18lx) (TextZipper t_a18lw) (TextZipper t_a18mg)
- Brick.Widgets.List: listElementsL :: forall n_a179Q e_a179R e_a17jy. Lens (List n_a179Q e_a179R) (List n_a179Q e_a17jy) (Vector e_a179R) (Vector e_a17jy)
+ Brick.Widgets.List: listElementsL :: forall n_a1hjI e_a1hjJ e_a1hwd. Lens (List n_a1hjI e_a1hjJ) (List n_a1hjI e_a1hwd) (Vector e_a1hjJ) (Vector e_a1hwd)
- Brick.Widgets.List: listItemHeightL :: forall n_a179Q e_a179R. Lens' (List n_a179Q e_a179R) Int
+ Brick.Widgets.List: listItemHeightL :: forall n_a1hjI e_a1hjJ. Lens' (List n_a1hjI e_a1hjJ) Int
- Brick.Widgets.List: listNameL :: forall n_a179Q e_a179R n_a17jz. Lens (List n_a179Q e_a179R) (List n_a17jz e_a179R) n_a179Q n_a17jz
+ Brick.Widgets.List: listNameL :: forall n_a1hjI e_a1hjJ n_a1hwe. Lens (List n_a1hjI e_a1hjJ) (List n_a1hwe e_a1hjJ) n_a1hjI n_a1hwe
- Brick.Widgets.List: listSelectedL :: forall n_a179Q e_a179R. Lens' (List n_a179Q e_a179R) (Maybe Int)
+ Brick.Widgets.List: listSelectedL :: forall n_a1hjI e_a1hjJ. Lens' (List n_a1hjI e_a1hjJ) (Maybe Int)

Files

CHANGELOG.md view
@@ -2,6 +2,23 @@ Brick changelog --------------- +0.41+----++New features:+ * `Brick.Forms` got a new field constructor, `listField`, that provides+   a form field using a `List`.+ * `List`: added the `listMoveToElement` function for changing the list+   selection to the specified element, if it exists.++Package changes:+ * Now depends on vty >= 5.24.++Other changes:+ * `viewport`: fixed failable patterns for forward compatibility with+   GHC 8.6 (#183)+ * Add `Generic`, `NFData`, and `Read` instances for some types+ 0.40 ---- 
brick.cabal view
@@ -1,5 +1,5 @@ name:                brick-version:             0.40+version:             0.41 synopsis:            A declarative terminal user interface library description:   Write terminal applications painlessly with 'brick'! You write an@@ -87,7 +87,7 @@     Brick.Widgets.Internal    build-depends:       base <= 4.11.1.0,-                       vty >= 5.23.1,+                       vty >= 5.24,                        transformers,                        data-clist >= 0.1,                        dlist,
src/Brick/AttrMap.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveGeneric #-} -- | This module provides types and functions for managing an attribute -- map which maps attribute names ('AttrName') to attributes ('Attr'). -- This module is designed to be used with the 'OverloadedStrings'@@ -54,6 +55,7 @@ import Data.Maybe (catMaybes) import Data.List (inits) import Data.String (IsString(..))+import GHC.Generics (Generic)  import Graphics.Vty (Attr(..), MaybeDefault(..)) @@ -70,7 +72,7 @@ -- "header" <> "clock" <> "seconds" -- @ data AttrName = AttrName [String]-              deriving (Show, Read, Eq, Ord)+              deriving (Show, Read, Eq, Ord, Generic)  instance Sem.Semigroup AttrName where     (AttrName as) <> (AttrName bs) = AttrName $ as `mappend` bs@@ -85,7 +87,7 @@ -- | An attribute map which maps 'AttrName' values to 'Attr' values. data AttrMap = AttrMap Attr (M.Map AttrName Attr)              | ForceAttr Attr-             deriving Show+             deriving (Show, Generic)  -- | Create an attribute name from a string. attrName :: String -> AttrName
src/Brick/BorderMap.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-} module Brick.BorderMap     ( BorderMap     , Edges(..)@@ -18,6 +20,8 @@ import Brick.Types.Common (Edges(..), Location(..), eTopL, eBottomL, eRightL, eLeftL, origin) import Control.Applicative (liftA2) import Data.IMap (IMap, Run(Run))+import GHC.Generics+import Control.DeepSeq import Prelude hiding (lookup) import qualified Data.IMap as IM @@ -43,7 +47,7 @@ data BorderMap a = BorderMap     { _coordinates :: Edges Int     , _values :: Edges (IMap a)-    } deriving (Eq, Ord, Show, Functor)+    } deriving (Eq, Ord, Show, Functor, Read, Generic, NFData)  -- | Given a rectangle (specified as the coordinates of the top, left, bottom, -- and right sides), initialize an empty 'BorderMap'.
src/Brick/Forms.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-} -- | NOTE: This API is experimental and will probably change. Please try -- it out! Feedback is very much appreciated, and your patience in the -- face of breaking API changes is also appreciated!@@ -65,6 +66,7 @@   , editPasswordField   , radioField   , checkboxField+  , listField    -- * Advanced form field constructors   , editField@@ -82,10 +84,12 @@ #endif import Data.Maybe (isJust, isNothing) import Data.List (elemIndex)+import Data.Vector (Vector)  import Brick import Brick.Focus import Brick.Widgets.Edit+import Brick.Widgets.List import qualified Data.Text.Zipper as Z  import qualified Data.Text as T@@ -287,6 +291,50 @@        addAttr $        (str $ "[" <> (if val then "X" else " ") <> "] ") <+> txt label +-- | A form field for selecting a single choice from a set of possible+-- choices in a scrollable list. This uses a 'List' internally.+--+-- This field responds to the same input events that a 'List' does.+listField :: forall s e n a . (Ord n, Show n, Eq a)+          => (s -> Vector a)+          -- ^ Possible choices.+          -> Lens' s (Maybe a)+          -- ^ The state lens for the initially/finally selected+          -- element.+          -> (Bool -> a -> Widget n)+          -- ^ List item rendering function.+          -> Int+          -- ^ List item height in rows.+          -> n+          -- ^ The resource name for the input field.+          -> s+          -- ^ The initial form state.+          -> FormFieldState s e n+listField options stLens renderItem itemHeight name initialState =+    let optionsVector = options initialState+        initVal = initialState ^. customStLens++        customStLens :: Lens' s (List n a)+        customStLens = lens getList setList+            where+               getList s = let l = list name optionsVector itemHeight+                           in case s ^. stLens of+                               Nothing -> l+                               Just e -> listMoveToElement e l+               setList s l = s & stLens .~ (snd <$> listSelectedElement l)++        handleEvent (VtyEvent e) s = handleListEvent e s+        handleEvent _ s = return s++    in FormFieldState { formFieldState        = initVal+                      , formFields            = [ FormField name Just True+                                                            (renderList renderItem)+                                                            handleEvent+                                                ]+                      , formFieldLens         = customStLens+                      , formFieldRenderHelper = id+                      , formFieldConcat       = vBox+                      } -- | A form field for selecting a single choice from a set of possible -- choices. Each choice has an associated value and text label. --
src/Brick/Main.hs view
@@ -38,6 +38,11 @@   -- * Rendering cache management   , invalidateCacheEntry   , invalidateCache++  -- * Renderer internals (for benchmarking)+  , renderFinal+  , getRenderState+  , resetRenderState   ) where @@ -180,8 +185,7 @@               Nothing -> readBChan brickChan               Just uc -> readBrickEvent brickChan uc             runInner rs st = do-              (result, newRS) <- runVty vty readEvent app st (rs & observedNamesL .~ S.empty-                                                                 & clickableNamesL .~ mempty)+              (result, newRS) <- runVty vty readEvent app st (resetRenderState rs)               case result of                   SuspendAndResume act -> do                       killThread pid@@ -221,7 +225,8 @@                     run newVty newRS newAppState brickChan          emptyES = ES [] mempty-        eventRO = EventRO M.empty initialVty mempty+        emptyRS = RS M.empty mempty S.empty mempty mempty+        eventRO = EventRO M.empty initialVty mempty emptyRS     (st, eState) <- runStateT (runReaderT (runEventM (appStartEvent app initialAppState)) eventRO) emptyES     let initialRS = RS M.empty (esScrollRequests eState) S.empty mempty []     brickChan <- newBChan 20@@ -303,7 +308,7 @@         _ -> return (e, firstRS, exts)      let emptyES = ES [] mempty-        eventRO = EventRO (viewportMap nextRS) vty nextExts+        eventRO = EventRO (viewportMap nextRS) vty nextExts nextRS      (next, eState) <- runStateT (runReaderT (runEventM (appHandleEvent app appState e'))                                 eventRO) emptyES@@ -372,6 +377,14 @@ withVty :: Vty -> (Vty -> IO a) -> IO a withVty vty useVty = do     useVty vty `finally` shutdown vty++getRenderState :: EventM n (RenderState n)+getRenderState = EventM $ asks oldState++resetRenderState :: RenderState n -> RenderState n+resetRenderState s =+    s & observedNamesL .~ S.empty+      & clickableNamesL .~ mempty  renderApp :: Vty -> App s e n -> s -> RenderState n -> IO (RenderState n, [Extent n]) renderApp vty app appState rs = do
src/Brick/Types.hs view
@@ -76,6 +76,8 @@   , Padding(..)   , Direction(..) +  -- * Renderer internals (for benchmarking)+  , RenderState   ) where 
src/Brick/Types/Common.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TemplateHaskell #-}-+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-} module Brick.Types.Common   ( Location(..)   , locL@@ -12,6 +13,8 @@  import Brick.Types.TH (suffixLenses) import qualified Data.Semigroup as Sem+import GHC.Generics+import Control.DeepSeq import Lens.Micro (_1, _2) import Lens.Micro.Internal (Field1, Field2) @@ -19,7 +22,7 @@ data Location = Location { loc :: (Int, Int)                          -- ^ (Column, Row)                          }-                deriving (Show, Eq, Ord)+                deriving (Show, Eq, Ord, Read, Generic, NFData)  suffixLenses ''Location @@ -41,7 +44,7 @@     mappend = (Sem.<>)  data Edges a = Edges { eTop, eBottom, eLeft, eRight :: a }-    deriving (Eq, Ord, Read, Show, Functor)+    deriving (Eq, Ord, Read, Show, Functor, Generic, NFData)  suffixLenses ''Edges 
src/Brick/Types/Internal.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-} module Brick.Types.Internal   ( ScrollRequest(..)   , VisibilityRequest(..)@@ -58,6 +60,8 @@ import qualified Data.Set as S import qualified Data.Map as M import Graphics.Vty (Vty, Event, Button, Modifier, DisplayRegion, Image, Attr, emptyImage)+import GHC.Generics+import Control.DeepSeq (NFData)  import Brick.BorderMap (BorderMap) import qualified Brick.BorderMap as BM@@ -76,12 +80,13 @@                    | VScrollToEnd                    | SetTop Int                    | SetLeft Int+                   deriving (Read, Show, Generic, NFData)  data VisibilityRequest =     VR { vrPosition :: Location        , vrSize :: DisplayRegion        }-       deriving (Show, Eq)+       deriving (Show, Eq, Read, Generic, NFData)  -- | Describes the state of a viewport as it appears as its most recent -- rendering.@@ -93,7 +98,7 @@        , _vpSize :: DisplayRegion        -- ^ The size of the viewport.        }-       deriving Show+       deriving (Show, Read, Generic, NFData)  -- | The type of viewports that indicates the direction(s) in which a -- viewport is scrollable.@@ -120,12 +125,7 @@                        , extentSize      :: (Int, Int)                        , extentOffset    :: Location                        }-              deriving (Show)--data EventRO n = EventRO { eventViewportMap :: M.Map n Viewport-                         , eventVtyHandle :: Vty-                         , latestExtents :: [Extent n]-                         }+                       deriving (Show, Read, Generic, NFData)  -- | The type of actions to take upon completion of an event handler. data Next a = Continue a@@ -138,7 +138,7 @@                -- ^ Up/left                | Down                -- ^ Down/right-               deriving (Show, Eq)+               deriving (Show, Eq, Read, Generic, NFData)  -- | The class of types that behave like terminal locations. class TerminalLocation a where@@ -163,7 +163,7 @@                    , cursorLocationName :: !(Maybe n)                    -- ^ The name of the widget associated with the location                    }-                   deriving Show+                   deriving (Read, Show, Generic, NFData)  -- | A border character has four segments, one extending in each direction -- (horizontally and vertically) from the center of the character.@@ -175,7 +175,7 @@     -- ^ Does this segment want to connect to its neighbor?     , bsDraw :: Bool     -- ^ Should this segment be represented visually?-    } deriving (Eq, Ord, Read, Show)+    } deriving (Eq, Ord, Read, Show, Generic, NFData)  suffixLenses ''BorderSegment @@ -191,7 +191,7 @@     -- connections: only dynamic borders with equal 'Attr's will connect to     -- each other.     , dbSegments :: Edges BorderSegment-    } deriving (Eq, Read, Show)+    } deriving (Eq, Read, Show, Generic, NFData)  suffixLenses ''DynBorder @@ -224,7 +224,7 @@            -- ^ Places where we may rewrite the edge of the image when            -- placing this widget next to another one.            }-           deriving Show+           deriving (Show, Read, Generic, NFData)  suffixLenses ''Result @@ -252,7 +252,13 @@        , observedNames :: !(S.Set n)        , renderCache :: M.Map n (Result n)        , clickableNames :: [n]-       }+       } deriving (Read, Show, Generic, NFData)++data EventRO n = EventRO { eventViewportMap :: M.Map n Viewport+                         , eventVtyHandle :: Vty+                         , latestExtents :: [Extent n]+                         , oldState :: RenderState n+                         }  -- | The rendering context. This tells widgets how to render: how much -- space they have in which to render, which attribute they should use
src/Brick/Widgets/Border/Style.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-} -- | This module provides styles for borders as used in terminal -- applications. Your mileage may vary on some of the fancier styles -- due to varying support for some border characters in the fonts your@@ -21,6 +23,9 @@   ) where +import GHC.Generics+import Control.DeepSeq+ -- | A border style for use in any widget that needs to render borders -- in a consistent style. data BorderStyle =@@ -47,7 +52,7 @@                 , bsVertical :: Char                 -- ^ Vertical border character                 }-                deriving (Show, Read, Eq)+                deriving (Show, Read, Eq, Generic, NFData)  defaultBorderStyle :: BorderStyle defaultBorderStyle = unicode
src/Brick/Widgets/Core.hs view
@@ -1041,33 +1041,42 @@       reqs <- lift $ gets $ (^.rsScrollRequestsL)       let relevantRequests = snd <$> filter (\(n, _) -> n == vpname) reqs       when (not $ null relevantRequests) $ do-          Just vp <- lift $ gets $ (^.viewportMapL.to (M.lookup vpname))-          let updatedVp = applyRequests relevantRequests vp-              applyRequests [] v = v-              applyRequests (rq:rqs) v =-                  case typ of-                      Horizontal -> scrollTo typ rq (initialResult^.imageL) $ applyRequests rqs v-                      Vertical -> scrollTo typ rq (initialResult^.imageL) $ applyRequests rqs v-                      Both -> scrollTo Horizontal rq (initialResult^.imageL) $-                              scrollTo Vertical rq (initialResult^.imageL) $-                              applyRequests rqs v-          lift $ modify (& viewportMapL %~ (M.insert vpname updatedVp))-          return ()+          mVp <- lift $ gets $ (^.viewportMapL.to (M.lookup vpname))+          case mVp of+              Nothing -> error $ "BUG: viewport: viewport name " <> show vpname <> " absent from viewport map"+              Just vp -> do+                  let updatedVp = applyRequests relevantRequests vp+                      applyRequests [] v = v+                      applyRequests (rq:rqs) v =+                          case typ of+                              Horizontal -> scrollTo typ rq (initialResult^.imageL) $ applyRequests rqs v+                              Vertical -> scrollTo typ rq (initialResult^.imageL) $ applyRequests rqs v+                              Both -> scrollTo Horizontal rq (initialResult^.imageL) $+                                      scrollTo Vertical rq (initialResult^.imageL) $+                                      applyRequests rqs v+                  lift $ modify (& viewportMapL %~ (M.insert vpname updatedVp))        -- If the sub-rendering requested visibility, update the scroll       -- state accordingly       when (not $ null $ initialResult^.visibilityRequestsL) $ do-          Just vp <- lift $ gets $ (^.viewportMapL.to (M.lookup vpname))-          let rqs = initialResult^.visibilityRequestsL-              updateVp vp' rq = case typ of-                  Both -> scrollToView Horizontal rq $ scrollToView Vertical rq vp'-                  Horizontal -> scrollToView typ rq vp'-                  Vertical -> scrollToView typ rq vp'-          lift $ modify (& viewportMapL %~ (M.insert vpname $ foldl updateVp vp rqs))+          mVp <- lift $ gets $ (^.viewportMapL.to (M.lookup vpname))+          case mVp of+              Nothing -> error $ "BUG: viewport: viewport name " <> show vpname <> " absent from viewport map"+              Just vp -> do+                  let rqs = initialResult^.visibilityRequestsL+                      updateVp vp' rq = case typ of+                          Both -> scrollToView Horizontal rq $ scrollToView Vertical rq vp'+                          Horizontal -> scrollToView typ rq vp'+                          Vertical -> scrollToView typ rq vp'+                  lift $ modify (& viewportMapL %~ (M.insert vpname $ foldl updateVp vp rqs))        -- If the size of the rendering changes enough to make the       -- viewport offsets invalid, reset them-      Just vp <- lift $ gets $ (^.viewportMapL.to (M.lookup vpname))+      mVp <- lift $ gets $ (^.viewportMapL.to (M.lookup vpname))+      vp <- case mVp of+          Nothing -> error $ "BUG: viewport: viewport name " <> show vpname <> " absent from viewport map"+          Just v -> return v+       let img = initialResult^.imageL           fixTop v = if V.imageHeight img < v^.vpSize._2                    then v & vpTop .~ 0@@ -1082,7 +1091,10 @@       lift $ modify (& viewportMapL %~ (M.insert vpname (updateVp vp)))        -- Get the viewport state now that it has been updated.-      Just vpFinal <- lift $ gets (M.lookup vpname . (^.viewportMapL))+      mVpFinal <- lift $ gets (M.lookup vpname . (^.viewportMapL))+      vpFinal <- case mVpFinal of+          Nothing -> error $ "BUG: viewport: viewport name " <> show vpname <> " absent from viewport map"+          Just v -> return v        -- Then perform a translation of the sub-rendering to fit into the       -- viewport
src/Brick/Widgets/List.hs view
@@ -6,6 +6,7 @@ {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE DeriveGeneric #-} -- | This module provides a scrollable list type and functions for -- manipulating and rendering it. module Brick.Widgets.List@@ -38,6 +39,7 @@   -- * Manipulating a list   , listMoveBy   , listMoveTo+  , listMoveToElement   , listMoveUp   , listMoveDown   , listMoveByPages@@ -62,12 +64,14 @@ import Data.Foldable (Foldable) import Data.Traversable (Traversable) #endif+import Control.Applicative ((<|>))  import Lens.Micro ((^.), (&), (.~), (%~), _2) import Data.Maybe (fromMaybe) import Data.Monoid ((<>)) import Graphics.Vty (Event(..), Key(..), Modifier(..)) import qualified Data.Vector as V+import GHC.Generics (Generic)  import Brick.Types import Brick.Main (lookupViewport)@@ -92,7 +96,7 @@          -- ^ The list's name.          , listItemHeight :: Int          -- ^ The height of the list items.-         } deriving (Functor, Foldable, Traversable, Show)+         } deriving (Functor, Foldable, Traversable, Show, Generic)  suffixLenses ''List @@ -348,6 +352,13 @@     in l & listSelectedL .~ if len > 0                             then Just newSel                             else Nothing++-- | Set the selected index for a list to the index of the specified+-- element if it is in the list, or leave the list unmodified otherwise.+listMoveToElement :: (Eq e) => e -> List n e -> List n e+listMoveToElement e l =+    let i = V.elemIndex e (l^.listElementsL)+    in l & listSelectedL %~ (i <|>)  -- | Return a list's selected element, if any. listSelectedElement :: List n e -> Maybe (Int, e)
src/Data/IMap.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-} module Data.IMap     ( IMap     , Run(..)@@ -22,13 +24,15 @@ import Data.List (foldl') import Data.Monoid import Data.IntMap.Strict (IntMap)+import GHC.Generics+import Control.DeepSeq import Prelude hiding (lookup) import qualified Data.IntMap.Strict as IM  -- | Semantically, 'IMap' and 'IntMap' are identical; but 'IMap' is more -- efficient when large sequences of contiguous keys are mapped to the same -- value.-newtype IMap a = IMap { _runs :: IntMap (Run a) } deriving (Show, Functor)+newtype IMap a = IMap { _runs :: IntMap (Run a) } deriving (Show, Functor, Read, Generic, NFData)  {-# INLINE unsafeRuns #-} -- | This function is unsafe because 'IMap's that compare equal may split their@@ -72,7 +76,7 @@ data Run a = Run     { len :: !Int     , val :: !a-    } deriving (Eq, Ord, Read, Show, Functor)+    } deriving (Eq, Ord, Read, Show, Functor, Generic, NFData)  instance Foldable    Run where foldMap f r = f (val r) instance Traversable Run where sequenceA (Run n v) = Run n <$> v