brick 0.63 → 0.64
raw patch · 16 files changed
+162/−76 lines, 16 filesdep ~text-zipperdep ~vtyPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: text-zipper, vty
API changes (from Hackage documentation)
+ Brick.Main: continueWithoutRedraw :: s -> EventM n (Next s)
+ Brick.Types: [cursorLocationVisible] :: CursorLocation n -> !Bool
+ Brick.Widgets.Core: putCursor :: n -> Location -> Widget n -> Widget n
- Brick.Types: CursorLocation :: !Location -> !Maybe n -> CursorLocation n
+ Brick.Types: CursorLocation :: !Location -> !Maybe n -> !Bool -> CursorLocation n
- Brick.Types: bordersL :: forall n_axXs. Lens' (Result n_axXs) (BorderMap DynBorder)
+ Brick.Types: bordersL :: forall n_axZ5. Lens' (Result n_axZ5) (BorderMap DynBorder)
- Brick.Types: cursorLocationL :: forall n_awIU. Lens' (CursorLocation n_awIU) Location
+ Brick.Types: cursorLocationL :: forall n_awIW. Lens' (CursorLocation n_awIW) Location
- Brick.Types: cursorLocationNameL :: forall n_awIU n_ayB0. Lens (CursorLocation n_awIU) (CursorLocation n_ayB0) (Maybe n_awIU) (Maybe n_ayB0)
+ Brick.Types: cursorLocationNameL :: forall n_awIW n_ayCD. Lens (CursorLocation n_awIW) (CursorLocation n_ayCD) (Maybe n_awIW) (Maybe n_ayCD)
- Brick.Types: cursorsL :: forall n_axXs. Lens' (Result n_axXs) [CursorLocation n_axXs]
+ Brick.Types: cursorsL :: forall n_axZ5. Lens' (Result n_axZ5) [CursorLocation n_axZ5]
- Brick.Types: extentsL :: forall n_axXs. Lens' (Result n_axXs) [Extent n_axXs]
+ Brick.Types: extentsL :: forall n_axZ5. Lens' (Result n_axZ5) [Extent n_axZ5]
- Brick.Types: imageL :: forall n_axXs. Lens' (Result n_axXs) Image
+ Brick.Types: imageL :: forall n_axZ5. Lens' (Result n_axZ5) Image
- Brick.Types: visibilityRequestsL :: forall n_axXs. Lens' (Result n_axXs) [VisibilityRequest]
+ Brick.Types: visibilityRequestsL :: forall n_axZ5. Lens' (Result n_axZ5) [VisibilityRequest]
- Brick.Widgets.Dialog: dialogButtonsL :: forall a_a19Tc a_a19TQ. Lens (Dialog a_a19Tc) (Dialog a_a19TQ) [(String, a_a19Tc)] [(String, a_a19TQ)]
+ Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1alG a_a1amk. Lens (Dialog a_a1alG) (Dialog a_a1amk) [(String, a_a1alG)] [(String, a_a1amk)]
- Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a19Tc. Lens' (Dialog a_a19Tc) (Maybe Int)
+ Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1alG. Lens' (Dialog a_a1alG) (Maybe Int)
- Brick.Widgets.Dialog: dialogTitleL :: forall a_a19Tc. Lens' (Dialog a_a19Tc) (Maybe String)
+ Brick.Widgets.Dialog: dialogTitleL :: forall a_a1alG. Lens' (Dialog a_a1alG) (Maybe String)
- Brick.Widgets.Dialog: dialogWidthL :: forall a_a19Tc. Lens' (Dialog a_a19Tc) Int
+ Brick.Widgets.Dialog: dialogWidthL :: forall a_a1alG. Lens' (Dialog a_a1alG) Int
- Brick.Widgets.Edit: editContentsL :: forall t_a14oN n_a14oO t_a14ps. Lens (Editor t_a14oN n_a14oO) (Editor t_a14ps n_a14oO) (TextZipper t_a14oN) (TextZipper t_a14ps)
+ Brick.Widgets.Edit: editContentsL :: forall t_a14CC n_a14CD t_a14Dh. Lens (Editor t_a14CC n_a14CD) (Editor t_a14Dh n_a14CD) (TextZipper t_a14CC) (TextZipper t_a14Dh)
- Brick.Widgets.Edit: handleEditorEvent :: (DecodeUtf8 t, Eq t, Monoid t) => Event -> Editor t n -> EventM n (Editor t n)
+ Brick.Widgets.Edit: handleEditorEvent :: (DecodeUtf8 t, Eq t, GenericTextZipper t) => Event -> Editor t n -> EventM n (Editor t n)
- Brick.Widgets.FileBrowser: fileBrowserEntryFilterL :: forall n_a1k03. Lens' (FileBrowser n_a1k03) (Maybe (FileInfo -> Bool))
+ Brick.Widgets.FileBrowser: fileBrowserEntryFilterL :: forall n_a1kyM. Lens' (FileBrowser n_a1kyM) (Maybe (FileInfo -> Bool))
- Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1k03. Lens' (FileBrowser n_a1k03) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1kyM. Lens' (FileBrowser n_a1kyM) (FileInfo -> Bool)
- Brick.Widgets.List: listElementsL :: forall n_a1ePt t_a1ePu e_a1ePv t_a1f3A e_a1f3B. Lens (GenericList n_a1ePt t_a1ePu e_a1ePv) (GenericList n_a1ePt t_a1f3A e_a1f3B) (t_a1ePu e_a1ePv) (t_a1f3A e_a1f3B)
+ Brick.Widgets.List: listElementsL :: forall n_a1foc t_a1fod e_a1foe t_a1fCj e_a1fCk. Lens (GenericList n_a1foc t_a1fod e_a1foe) (GenericList n_a1foc t_a1fCj e_a1fCk) (t_a1fod e_a1foe) (t_a1fCj e_a1fCk)
- Brick.Widgets.List: listItemHeightL :: forall n_a1ePt t_a1ePu e_a1ePv. Lens' (GenericList n_a1ePt t_a1ePu e_a1ePv) Int
+ Brick.Widgets.List: listItemHeightL :: forall n_a1foc t_a1fod e_a1foe. Lens' (GenericList n_a1foc t_a1fod e_a1foe) Int
- Brick.Widgets.List: listNameL :: forall n_a1ePt t_a1ePu e_a1ePv n_a1f3C. Lens (GenericList n_a1ePt t_a1ePu e_a1ePv) (GenericList n_a1f3C t_a1ePu e_a1ePv) n_a1ePt n_a1f3C
+ Brick.Widgets.List: listNameL :: forall n_a1foc t_a1fod e_a1foe n_a1fCl. Lens (GenericList n_a1foc t_a1fod e_a1foe) (GenericList n_a1fCl t_a1fod e_a1foe) n_a1foc n_a1fCl
- Brick.Widgets.List: listSelectedL :: forall n_a1ePt t_a1ePu e_a1ePv. Lens' (GenericList n_a1ePt t_a1ePu e_a1ePv) (Maybe Int)
+ Brick.Widgets.List: listSelectedL :: forall n_a1foc t_a1fod e_a1foe. Lens' (GenericList n_a1foc t_a1fod e_a1foe) (Maybe Int)
Files
- CHANGELOG.md +25/−3
- README.md +2/−0
- brick.cabal +3/−3
- docs/guide.rst +13/−6
- programs/ReadmeDemo.hs +4/−4
- src/Brick/AttrMap.hs +1/−1
- src/Brick/Focus.hs +1/−1
- src/Brick/Forms.hs +8/−8
- src/Brick/Main.hs +40/−14
- src/Brick/Types/Internal.hs +4/−0
- src/Brick/Widgets/Core.hs +36/−28
- src/Brick/Widgets/Edit.hs +21/−3
- src/Brick/Widgets/FileBrowser.hs +2/−2
- src/Brick/Widgets/List.hs +1/−1
- src/Brick/Widgets/ProgressBar.hs +0/−1
- tests/List.hs +1/−1
CHANGELOG.md view
@@ -2,6 +2,28 @@ Brick changelog --------------- +0.64+----++API changes:+ * Added `Brick.Main.continueWithoutRedraw`, an alternative to+ `Brick.Main.continue` that does not trigger a screen redraw. See the+ Haddock and User Guide for details.+ * Added `Brick.Widgets.Core.putCursor` to support Vty's new (as of+ 5.33) API for placing cursors without visually representing+ them. This change also updated `Brick.Forms.renderCheckbox` and+ `Brick.Forms.renderRadio` to use `putCursor`.++Other improvements:+ * `Brick.Widgets.Edit` now supports a few more Emacs-style keybindings+ (thanks Mario Lang):+ * `M-b` and `M-f` to navigate by word+ * `C-b` and `C-f` for consistency+ * `M-d` to delete word under cursor+ * `C-t` to transpose previous character with current character+ * `M-<` and `M->` to goto-beginning-of-file and end of file,+ respectively+ 0.63 ---- @@ -501,14 +523,14 @@ * The Forms API got two new functions, `setFormConcat` and `setFieldConcat`, used for controlling the previously hard-coded concatenation behavior of form fields. These are optional and both- concatentation settings default to their former hard-coded values,+ concatenation settings default to their former hard-coded values, `vBox` (#172). 0.36.1 ------ Package changes:- * Raiseed upper bound to support GHC 8.4.2 (#171)+ * Raised upper bound to support GHC 8.4.2 (#171) Other changes: * Improved List accessor documentation (thanks liam <liam@magicseaweed.com>)@@ -522,7 +544,7 @@ * Dynamic border support: adjacent widgets that use borders can make those borders seamlessly connect to each other! Thanks so much to Daniel Wagner for this feature! Please see- `programs/DynamicBorderDemo.hs` for a demonstraton. Also see the+ `programs/DynamicBorderDemo.hs` for a demonstration. Also see the "Joinable Borders" section of the User Guide. 0.35.1
README.md view
@@ -76,6 +76,8 @@ | [`pboy`](https://github.com/2mol/pboy) | A tiny PDF organizer | | [`hyahtzee2`](https://github.com/DamienCassou/hyahtzee2#readme) | Famous Yahtzee dice game | | [`brewsage`](https://github.com/gerdreiss/brewsage#readme) | A TUI for Homebrew |+| [`sandwich`](https://codedownio.github.io/sandwich/) | A test framework with a TUI interface |+| [`youbrick`](https://github.com/florentc/youbrick) | A feed aggregator and launcher for Youtube channels | These third-party packages also extend `brick`:
brick.cabal view
@@ -1,5 +1,5 @@ name: brick-version: 0.63+version: 0.64 synopsis: A declarative terminal user interface library description: Write terminal user interfaces (TUIs) painlessly with 'brick'! You@@ -115,7 +115,7 @@ Brick.Widgets.Internal build-depends: base < 4.16.0.0,- vty >= 5.31,+ vty >= 5.33, transformers, data-clist >= 0.1, directory >= 1.2.5.0,@@ -131,7 +131,7 @@ contravariant, stm >= 2.4.3, text,- text-zipper >= 0.7.1,+ text-zipper >= 0.11, template-haskell, deepseq >= 1.3 && < 1.5, unix,
docs/guide.rst view
@@ -221,11 +221,18 @@ the corresponding types in ``App`` and ``EventM``. The return value type ``Next s`` value describes what should happen-after the event handler is finished. We have three choices:+after the event handler is finished. We have four choices: * ``Brick.Main.continue s``: continue executing the event loop with the specified application state ``s`` as the next value. Commonly this is where you'd modify the state based on the event and return it.+* ``Brick.Main.continueWithoutRedraw s``: continue executing the event+ loop with the specified application state ``s`` as the next value, but+ unlike ``continue``, do not redraw the screen using the new state.+ This is a faster version of ``continue`` since it doesn't redraw the+ screen; it just leaves up the previous screen contents. This function+ is only useful when you know that your state change won't cause+ anything on the screen to change. When in doubt, use ``continue``. * ``Brick.Main.halt s``: halt the event loop and return the final application state value ``s``. This state value is returned to the caller of ``defaultMain`` or ``customMain`` where it can be used prior@@ -533,7 +540,7 @@ appAttrMap: Managing Attributes ------------------------------- -In ``brick`` we use an *attribute map* to assign attibutes to elements+In ``brick`` we use an *attribute map* to assign attributes to elements of the interface. Rather than specifying specific attributes when drawing a widget (e.g. red-on-black text) we specify an *attribute name* that is an abstract name for the kind of thing we are drawing, e.g.@@ -784,7 +791,7 @@ follows: * The application provides a default theme built in to the program.-* The application customizes the them by loading theme customizations+* The application customizes the theme by loading theme customizations from a user-specified customization file. * The application can save new customizations to files for later re-loading.@@ -934,12 +941,12 @@ mExtent <- Brick.Main.lookupExtent FooBox case mExtent of Nothing -> ...- Just (Extent _ upperLeft (width, height) offset) -> ...+ Just (Extent _ upperLeft (width, height)) -> ... Paste Support ============= -Some terminal emulators support "bracketed paste" support. This feature+Some terminal emulators support "bracketed paste" mode. This feature enables OS-level paste operations to send the pasted content as a single chunk of data and bypass the usual input processing that the application does. This enables more secure handling of pasted data since@@ -1352,7 +1359,7 @@ to initialize all of the form fields. Each form field will use the lens provided to extract the initial value from the ``UserInfo`` record, convert it into an appropriate state type for the field in question, and-later validate that state and convert it back into the approprate type+later validate that state and convert it back into the appropriate type for storage in ``UserInfo``. The form value itself -- of type ``Form`` -- must be stored in your
programs/ReadmeDemo.hs view
@@ -1,9 +1,9 @@ module Main where -import Brick-import Brick.Widgets.Center-import Brick.Widgets.Border-import Brick.Widgets.Border.Style+import Brick (Widget, simpleMain, (<+>), str, withBorderStyle)+import Brick.Widgets.Center (center)+import Brick.Widgets.Border (borderWithLabel, vBorder)+import Brick.Widgets.Border.Style (unicode) ui :: Widget () ui =
src/Brick/AttrMap.hs view
@@ -17,7 +17,7 @@ -- Attribute names are mapped to attributes, but some attributes may -- be partial (specify only a foreground or background color). When -- attribute name lookups occur, the attribute corresponding to a more--- specific name ('parent <> child' as above) is sucessively merged with+-- specific name ('parent <> child' as above) is successively merged with -- the parent attribute ('parent' as above) all the way to the "root" -- of the attribute map, the map's default attribute. In this way, more -- specific attributes inherit what they don't specify from more general
src/Brick/Focus.hs view
@@ -60,7 +60,7 @@ -> (Bool -> a -> b) -- ^ A function that takes a value and its focus state. -> a- -- ^ The wiget state value that we need to check for focus.+ -- ^ The widget state value that we need to check for focus. -> b -- ^ The rest of the computation. withFocusRing ring f a = f (focusGetCurrent ring == Just (getName a)) a
src/Brick/Forms.hs view
@@ -124,12 +124,12 @@ -- ^ A validation function converting this field's state -- into a value of your choosing. @Nothing@ indicates a -- validation failure. For example, this might validate- -- an 'Editor' state value by parsing its text contents s- -- aan integer and return 'Maybe' 'Int'. This is for pure- -- avalue validation; if additional validation is required- -- a(e.g. via 'IO'), use this field's state value in an- -- aexternal validation routine and use 'setFieldValid' to- -- afeed the result back into the form.+ -- an 'Editor' state value by parsing its text contents as+ -- an integer and return 'Maybe' 'Int'. This is for pure+ -- value validation; if additional validation is required+ -- (e.g. via 'IO'), use this field's state value in an+ -- external validation routine and use 'setFieldValid' to+ -- feed the result back into the form. , formFieldExternallyValid :: Bool -- ^ Whether the field is valid according to an external -- validation source. Defaults to always being 'True' and@@ -349,7 +349,7 @@ renderCheckbox :: Char -> Char -> Char -> T.Text -> n -> Bool -> Bool -> Widget n renderCheckbox lb check rb label n foc val = let addAttr = if foc then withDefAttr focusedFormInputAttr else id- csr = if foc then showCursor n (Location (1,0)) else id+ csr = if foc then putCursor n (Location (1,0)) else id in clickable n $ addAttr $ csr $ (txt $ T.singleton lb <> (if val then T.singleton check else " ") <>@@ -478,7 +478,7 @@ then withDefAttr focusedFormInputAttr else id isSet = val == cur- csr = if foc then showCursor name (Location (1,0)) else id+ csr = if foc then putCursor name (Location (1,0)) else id in clickable name $ addAttr $ csr $ hBox [ txt $ T.singleton lb
src/Brick/Main.hs view
@@ -10,6 +10,7 @@ -- * Event handler functions , continue+ , continueWithoutRedraw , halt , suspendAndResume , lookupViewport@@ -114,7 +115,8 @@ -- ^ This function takes the current application state and an -- event and returns an action to be taken and a corresponding -- transformed application state. Possible options are- -- 'continue', 'suspendAndResume', and 'halt'.+ -- 'continue', 'continueWithoutRedraw', 'suspendAndResume', and+ -- 'halt'. , appStartEvent :: s -> EventM n s -- ^ This function gets called once just prior to the first -- drawing of your application. Here is where you can make@@ -191,8 +193,8 @@ let readEvent = case mUserChan of Nothing -> readBChan brickChan Just uc -> readBrickEvent brickChan uc- runInner rs st = do- (result, newRS) <- runVty vty readEvent app st (resetRenderState rs)+ runInner rs es draw st = do+ (result, newRS, newExtents) <- runVty vty readEvent app st (resetRenderState rs) es draw case result of SuspendAndResume act -> do killThread pid@@ -200,8 +202,10 @@ Halt s -> do killThread pid return $ InternalHalt s- Continue s -> runInner newRS s- runInner initialRS initialSt+ Continue s -> runInner newRS newExtents True s+ ContinueWithoutRedraw s ->+ runInner newRS newExtents False s+ runInner initialRS mempty True initialSt -- | The custom event loop entry point to use when the simpler ones -- don't permit enough control. Returns the final application state@@ -293,9 +297,14 @@ -> App s e n -> s -> RenderState n- -> IO (Next s, RenderState n)-runVty vty readEvent app appState rs = do- (firstRS, exts) <- renderApp vty app appState rs+ -> [Extent n]+ -> Bool+ -> IO (Next s, RenderState n, [Extent n])+runVty vty readEvent app appState rs prevExtents draw = do+ (firstRS, exts) <- case draw of+ True -> renderApp vty app appState rs+ False -> return (rs, prevExtents)+ e <- readEvent (e', nextRS, nextExts) <- case e of@@ -361,10 +370,13 @@ (next, eState) <- runStateT (runReaderT (runEventM (appHandleEvent app appState e')) eventRO) emptyES- return (next, nextRS { rsScrollRequests = esScrollRequests eState- , renderCache = applyInvalidations (cacheInvalidateRequests eState) $- renderCache nextRS- })+ return ( next+ , nextRS { rsScrollRequests = esScrollRequests eState+ , renderCache = applyInvalidations (cacheInvalidateRequests eState) $+ renderCache nextRS+ }+ , nextExts+ ) applyInvalidations :: (Ord n) => S.Set (CacheInvalidateRequest n) -> M.Map n v -> M.Map n v applyInvalidations ns cache =@@ -441,8 +453,11 @@ rs picWithCursor = case theCursor of Nothing -> pic { picCursor = NoCursor }- Just cloc -> pic { picCursor = AbsoluteCursor (cloc^.locationColumnL)- (cloc^.locationRowL)+ Just cloc -> pic { picCursor = (if cursorLocationVisible cloc+ then AbsoluteCursor+ else PositionOnly True)+ (cloc^.locationColumnL)+ (cloc^.locationRowL) } update vty picWithCursor@@ -529,6 +544,17 @@ -- state. continue :: s -> EventM n (Next s) continue = return . Continue++-- | Continue running the event loop with the specified application+-- state without redrawing the screen. This is faster than 'continue'+-- because it skips the redraw, but the drawback is that you need to+-- be really sure that you don't want a screen redraw. If your state+-- changed in a way that needs to be reflected on the screen, use+-- 'continue'. This function is for cases where you know that you did+-- something that won't have an impact on the screen state and you want+-- to save on redraw cost.+continueWithoutRedraw :: s -> EventM n (Next s)+continueWithoutRedraw = return . ContinueWithoutRedraw -- | Halt the event loop and return the specified application state as -- the final state value.
src/Brick/Types/Internal.hs view
@@ -19,6 +19,7 @@ , CursorLocation(..) , cursorLocationL , cursorLocationNameL+ , cursorLocationVisibleL , Context(..) , EventState(..) , EventRO(..)@@ -131,6 +132,7 @@ -- | The type of actions to take upon completion of an event handler. data Next a = Continue a+ | ContinueWithoutRedraw a | SuspendAndResume (IO a) | Halt a deriving Functor@@ -164,6 +166,8 @@ -- ^ The location , cursorLocationName :: !(Maybe n) -- ^ The name of the widget associated with the location+ , cursorLocationVisible :: !Bool+ -- ^ Whether the cursor should actually be visible } deriving (Read, Show, Generic, NFData)
src/Brick/Widgets/Core.hs view
@@ -59,6 +59,7 @@ -- * Cursor placement , showCursor+ , putCursor -- * Naming , Named(..)@@ -152,12 +153,14 @@ -- | When rendering the specified widget, use the specified border style -- for any border rendering. withBorderStyle :: BorderStyle -> Widget n -> Widget n-withBorderStyle bs p = Widget (hSize p) (vSize p) $ withReaderT (& ctxBorderStyleL .~ bs) (render p)+withBorderStyle bs p = Widget (hSize p) (vSize p) $+ withReaderT (ctxBorderStyleL .~ bs) (render p) -- | When rendering the specified widget, create borders that respond -- dynamically to their neighbors to form seamless connections. joinBorders :: Widget n -> Widget n-joinBorders p = Widget (hSize p) (vSize p) $ withReaderT (& ctxDynBordersL .~ True) (render p)+joinBorders p = Widget (hSize p) (vSize p) $+ withReaderT (ctxDynBordersL .~ True) (render p) -- | When rendering the specified widget, use static borders. This -- may be marginally faster, but will introduce a small gap between@@ -165,7 +168,8 @@ -- -- This is the default for backwards compatibility. separateBorders :: Widget n -> Widget n-separateBorders p = Widget (hSize p) (vSize p) $ withReaderT (&ctxDynBordersL .~ False) (render p)+separateBorders p = Widget (hSize p) (vSize p) $+ withReaderT (ctxDynBordersL .~ False) (render p) -- | After the specified widget has been rendered, freeze its borders. A -- frozen border will not be affected by neighbors, nor will it affect@@ -339,7 +343,7 @@ Widget (hSize p) (vSize p) $ do c <- getContext let attr = attrMapLookup (c^.ctxAttrNameL) (c^.ctxAttrMapL) `V.withURL` url- withReaderT (& ctxAttrMapL %~ setDefaultAttr attr) (render p)+ withReaderT (ctxAttrMapL %~ setDefaultAttr attr) (render p) -- | Pad the specified widget on the left. If max padding is used, this -- grows greedily horizontally; otherwise it defers to the padded@@ -690,7 +694,7 @@ -- | Given borders that should be placed next to each other (the first argument -- on the right or bottom, and the second argument on the left or top), compute -- new borders and the rewrites that should be done along the edges of the two--- images to keep the image in synch with the border information.+-- images to keep the image in sync with the border information. -- -- The input borders are assumed to be disjoint. This property is not checked. catBorders@@ -836,17 +840,16 @@ withAttr :: AttrName -> Widget n -> Widget n withAttr an p = Widget (hSize p) (vSize p) $- withReaderT (& ctxAttrNameL .~ an) (render p)+ withReaderT (ctxAttrNameL .~ an) (render p) -- | Update the attribute map while rendering the specified widget: set--- its new default attribute to the one that we get by looking up the--- specified attribute name in the map and then modifying it with the--- specified function.+-- its new default attribute to the one that we get by applying specified+-- function to the current default attribute. modifyDefAttr :: (V.Attr -> V.Attr) -> Widget n -> Widget n modifyDefAttr f p = Widget (hSize p) (vSize p) $ do c <- getContext- withReaderT (& ctxAttrMapL %~ (setDefaultAttr (f $ getDefaultAttr (c^.ctxAttrMapL)))) (render p)+ withReaderT (ctxAttrMapL %~ (setDefaultAttr (f $ getDefaultAttr (c^.ctxAttrMapL)))) (render p) -- | Update the attribute map while rendering the specified widget: set -- its new default attribute to the one that we get by looking up the@@ -855,14 +858,14 @@ withDefAttr an p = Widget (hSize p) (vSize p) $ do c <- getContext- withReaderT (& ctxAttrMapL %~ (setDefaultAttr (attrMapLookup an (c^.ctxAttrMapL)))) (render p)+ withReaderT (ctxAttrMapL %~ (setDefaultAttr (attrMapLookup an (c^.ctxAttrMapL)))) (render p) -- | When rendering the specified widget, update the attribute map with -- the specified transformation. updateAttrMap :: (AttrMap -> AttrMap) -> Widget n -> Widget n updateAttrMap f p = Widget (hSize p) (vSize p) $- withReaderT (& ctxAttrMapL %~ f) (render p)+ withReaderT (ctxAttrMapL %~ f) (render p) -- | When rendering the specified widget, force all attribute lookups -- in the attribute map to use the value currently assigned to the@@ -876,7 +879,7 @@ forceAttr an p = Widget (hSize p) (vSize p) $ do c <- getContext- withReaderT (& ctxAttrMapL .~ (forceAttrMap (attrMapLookup an (c^.ctxAttrMapL)))) (render p)+ withReaderT (ctxAttrMapL .~ (forceAttrMap (attrMapLookup an (c^.ctxAttrMapL)))) (render p) -- | Override the lookup of 'targetName' to return the attribute value -- associated with 'fromName' when rendering the specified widget.@@ -991,32 +994,37 @@ -- | When rendering the specified widget, also register a cursor -- positioning request using the specified name and location. showCursor :: n -> Location -> Widget n -> Widget n-showCursor n cloc p =- Widget (hSize p) (vSize p) $ do- result <- render p- return $ result & cursorsL %~ (CursorLocation cloc (Just n):)+showCursor n cloc p = Widget (hSize p) (vSize p) $+ (cursorsL %~ (CursorLocation cloc (Just n) True:)) <$> (render p) +-- | When rendering the specified widget, also register a cursor+-- positioning request using the specified name and location.+-- The cursor will only be positioned but not made visible.+putCursor :: n -> Location -> Widget n -> Widget n+putCursor n cloc p = Widget (hSize p) (vSize p) $+ (cursorsL %~ (CursorLocation cloc (Just n) False:)) <$> (render p)+ hRelease :: Widget n -> Maybe (Widget n) hRelease p = case hSize p of Fixed -> Just $ Widget Greedy (vSize p) $- withReaderT (& availWidthL .~ unrestricted) (render p)+ withReaderT (availWidthL .~ unrestricted) (render p) Greedy -> Nothing vRelease :: Widget n -> Maybe (Widget n) vRelease p = case vSize p of Fixed -> Just $ Widget (hSize p) Greedy $- withReaderT (& availHeightL .~ unrestricted) (render p)+ withReaderT (availHeightL .~ unrestricted) (render p) Greedy -> Nothing -- | If the specified resource name has an entry in the rendering cache, -- use the rendered version from the cache. If not, render the specified -- widget and update the cache with the result. ----- To ensure that mouse events are emitted correctly for cached widgets, --- in addition to the rendered widget, we also cache (the names of) --- any clickable extents that were rendered and restore that when utilizing+-- To ensure that mouse events are emitted correctly for cached widgets,+-- in addition to the rendered widget, we also cache (the names of) any+-- clickable extents that were rendered and restore that when utilizing -- the cache. -- -- See also 'invalidateCacheEntry'.@@ -1047,8 +1055,8 @@ cache <- lift $ gets (^.renderCacheL) return $ M.lookup n cache -cacheUpdate :: (Ord n) => n -> ([n], Result n) -> RenderM n ()-cacheUpdate n r = lift $ modify (& renderCacheL %~ M.insert n r)+cacheUpdate :: Ord n => n -> ([n], Result n) -> RenderM n ()+cacheUpdate n r = lift $ modify (renderCacheL %~ M.insert n r) -- | Render the specified widget in a named viewport with the -- specified type. This permits widgets to be scrolled without being@@ -1107,7 +1115,7 @@ doInsert (Just vp) = Just $ vp & vpSize .~ newSize doInsert Nothing = Just newVp - lift $ modify (& viewportMapL %~ (M.alter doInsert vpname))+ lift $ modify (viewportMapL %~ (M.alter doInsert vpname)) -- Then render the viewport content widget with the rendering -- layout constraint released (but raise an exception if we are@@ -1148,7 +1156,7 @@ Both -> scrollTo Horizontal rq (initialResult^.imageL) $ scrollTo Vertical rq (initialResult^.imageL) $ applyRequests rqs v- lift $ modify (& viewportMapL %~ (M.insert vpname updatedVp))+ lift $ modify (viewportMapL %~ (M.insert vpname updatedVp)) -- If the sub-rendering requested visibility, update the scroll -- state accordingly@@ -1162,7 +1170,7 @@ 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))+ 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@@ -1183,7 +1191,7 @@ Both -> fixLeft . fixTop Horizontal -> fixLeft Vertical -> fixTop- lift $ modify (& viewportMapL %~ (M.insert vpname (updateVp vp)))+ lift $ modify (viewportMapL %~ (M.insert vpname (updateVp vp))) -- Get the viewport state now that it has been updated. mVpFinal <- lift $ gets (M.lookup vpname . (^.viewportMapL))
src/Brick/Widgets/Edit.hs view
@@ -52,6 +52,7 @@ import qualified Data.Text.Encoding as T import qualified Data.Text.Zipper as Z hiding ( textZipper ) import qualified Data.Text.Zipper.Generic as Z+import qualified Data.Text.Zipper.Generic.Words as Z import Brick.Types import Brick.Widgets.Core@@ -59,12 +60,20 @@ -- | Editor state. Editors support the following events by default: ----- * Ctrl-a: go to beginning of line--- * Ctrl-e: go to end of line+-- * Meta-<: go to beginning of file+-- * Meta->: go to end of file+-- * Ctrl-a, Home: go to beginning of line+-- * Ctrl-e, End: go to end of line -- * Ctrl-d, Del: delete character at cursor position+-- * Meta-d: delete word at cursor position -- * Backspace: delete character prior to cursor position -- * Ctrl-k: delete all from cursor to end of line -- * Ctrl-u: delete all from cursor to beginning of line+-- * Ctrl-t: transpose character before cursor with the one at cursor position+-- * Meta-b: move one word to the left+-- * Ctrl-b: move one character to the left+-- * Meta-f: move one word to the right+-- * Ctrl-f: move one character to the right -- * Arrow keys: move cursor -- * Enter: break the current line at the cursor position -- * Paste: Bracketed Pastes from the terminal will be pasted, provided@@ -105,7 +114,8 @@ instance DecodeUtf8 String where decodeUtf8 bs = T.unpack <$> decodeUtf8 bs -handleEditorEvent :: (DecodeUtf8 t, Eq t, Monoid t) => Event -> Editor t n -> EventM n (Editor t n)+handleEditorEvent :: (DecodeUtf8 t, Eq t, Z.GenericTextZipper t)+ => Event -> Editor t n -> EventM n (Editor t n) handleEditorEvent e ed = let f = case e of EvPaste bs -> case decodeUtf8 bs of@@ -114,6 +124,7 @@ EvKey (KChar 'a') [MCtrl] -> Z.gotoBOL EvKey (KChar 'e') [MCtrl] -> Z.gotoEOL EvKey (KChar 'd') [MCtrl] -> Z.deleteChar+ EvKey (KChar 'd') [MMeta] -> Z.deleteWord EvKey (KChar 'k') [MCtrl] -> Z.killToEOL EvKey (KChar 'u') [MCtrl] -> Z.killToBOL EvKey KEnter [] -> Z.breakLine@@ -123,9 +134,16 @@ EvKey KDown [] -> Z.moveDown EvKey KLeft [] -> Z.moveLeft EvKey KRight [] -> Z.moveRight+ EvKey (KChar 'b') [MCtrl] -> Z.moveLeft+ EvKey (KChar 'f') [MCtrl] -> Z.moveRight+ EvKey (KChar 'b') [MMeta] -> Z.moveWordLeft+ EvKey (KChar 'f') [MMeta] -> Z.moveWordRight EvKey KBS [] -> Z.deletePrevChar+ EvKey (KChar 't') [MCtrl] -> Z.transposeChars EvKey KHome [] -> Z.gotoBOL EvKey KEnd [] -> Z.gotoEOL+ EvKey (KChar '<') [MMeta] -> Z.gotoBOF+ EvKey (KChar '>') [MMeta] -> Z.gotoEOF _ -> id in return $ applyEdit f ed
src/Brick/Widgets/FileBrowser.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-}--- | This module provids a file browser widget that allows users to+-- | This module provides a file browser widget that allows users to -- navigate directory trees, search for files and directories, and -- select entries of interest. For a complete working demonstration of -- this module, see @programs/FileBrowserDemo.hs@.@@ -798,7 +798,7 @@ addAttr = maybe id (withDefAttr . attrForFileType) (fileInfoFileType info) body = addAttr (hLimit (maxLen + 1) $ padRight Max $- (if foc && listSel then showCursor n (Location (0,0)) else id) $+ (if foc && listSel then putCursor n (Location (0,0)) else id) $ str $ fileInfoSanitizedFilename info <> suffix) suffix = (if fileInfoFileType info == Just Directory then "/" else "") <> (if sel then "*" else "")
src/Brick/Widgets/List.hs view
@@ -545,7 +545,7 @@ -- If @pos >= 0@, indexes from the start of the list (which gets -- evaluated up to the target index) ----- If @pos < 0@, indexes from the end of the list (which evalutes+-- If @pos < 0@, indexes from the end of the list (which evaluates -- 'length' of the list). -- -- Complexity: same as 'splitAt' for the container type.
src/Brick/Widgets/ProgressBar.hs view
@@ -10,7 +10,6 @@ where import Lens.Micro ((^.))-import Data.List (splitAt) import Data.Maybe (fromMaybe) #if !(MIN_VERSION_base(4,11,0)) import Data.Monoid
tests/List.hs view
@@ -353,7 +353,7 @@ -- Laziness tests. Here we create a custom container type -- that we use to ensure certain operations do not cause the--- whole container to be evaulated.+-- whole container to be evaluated. -- newtype L a = L [a] deriving (Functor, Foldable, Traversable)