brick 0.44.1 → 0.45
raw patch · 7 files changed
+93/−19 lines, 7 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Brick.Widgets.List: listFindBy :: (Foldable t, Splittable t) => (e -> Bool) -> GenericList n t e -> GenericList n t e
+ Data.Text.Markup: empty :: Markup a -> Bool
- Brick.Widgets.FileBrowser: fileBrowserEntryFilterL :: forall n_a1qtL. Lens' (FileBrowser n_a1qtL) (Maybe (FileInfo -> Bool))
+ Brick.Widgets.FileBrowser: fileBrowserEntryFilterL :: forall n_a1qC2. Lens' (FileBrowser n_a1qC2) (Maybe (FileInfo -> Bool))
- Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1qtL. Lens' (FileBrowser n_a1qtL) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1qC2. Lens' (FileBrowser n_a1qC2) (FileInfo -> Bool)
- Brick.Widgets.List: listMoveToElement :: (Eq e, Traversable t) => e -> GenericList n t e -> GenericList n t e
+ Brick.Widgets.List: listMoveToElement :: (Eq e, Foldable t, Splittable t) => e -> GenericList n t e -> GenericList n t e
Files
- CHANGELOG.md +9/−0
- brick.cabal +1/−1
- src/Brick/Widgets/Border/Style.hs +1/−2
- src/Brick/Widgets/FileBrowser.hs +1/−1
- src/Brick/Widgets/List.hs +25/−11
- src/Data/Text/Markup.hs +5/−0
- tests/List.hs +51/−4
CHANGELOG.md view
@@ -2,6 +2,15 @@ Brick changelog --------------- +0.45+----++API changes:+ * List got a new `listFindBy` function (thanks Fraser Tweedale). This+ function uses a predicate to find a matching element in the list and+ move the cursor to that item.+ * Data.Text.Markup got a new `empty` function (#213)+ 0.44.1 ------
brick.cabal view
@@ -1,5 +1,5 @@ name: brick-version: 0.44.1+version: 0.45 synopsis: A declarative terminal user interface library description: Write terminal applications painlessly with 'brick'! You write an
src/Brick/Widgets/Border/Style.hs view
@@ -10,8 +10,7 @@ -- -- To use these in your widgets, see -- 'Brick.Widgets.Core.withBorderStyle'. By default, widgets rendered--- without a specified border style use 'unicode' via the 'Default'--- instance provided by 'BorderStyle'.+-- without a specified border style use 'unicode' style. module Brick.Widgets.Border.Style ( BorderStyle(..) , borderStyleFromChar
src/Brick/Widgets/FileBrowser.hs view
@@ -293,7 +293,7 @@ -- search string and/or entry filtering. -- -- If the directory scan raises an 'IOException', the exception is--- stored the browser and is accessible with 'fileBrowserException'. If+-- stored in the browser and is accessible with 'fileBrowserException'. If -- no exception is raised, the exception field is cleared. Regardless of -- whether an exception is raised, @..@ is always presented as a valid -- option in the browser.
src/Brick/Widgets/List.hs view
@@ -41,6 +41,7 @@ , listMoveBy , listMoveTo , listMoveToElement+ , listFindBy , listMoveUp , listMoveDown , listMoveByPages@@ -67,16 +68,15 @@ import Prelude hiding (reverse, splitAt) #if !MIN_VERSION_base(4,8,0)-import Control.Applicative ((<$>), (<*>), pure, (<|>))+import Control.Applicative ((<$>), (<*>), pure) import Data.Foldable (Foldable, find, toList) import Data.Traversable (Traversable) #else-import Control.Applicative ((<|>)) import Data.Foldable (find, toList) #endif import Control.Monad.Trans.State (evalState, get, put) -import Lens.Micro ((^.), (^?), (&), (.~), (%~), _2, _head)+import Lens.Micro ((^.), (^?), (&), (.~), (%~), _2, _head, set) import Data.Functor (($>)) import Data.List.NonEmpty (NonEmpty((:|))) import Data.Maybe (fromMaybe)@@ -545,18 +545,32 @@ -- is in the list, so we don't need to know the length clamp 0 (if null t then length (l ^. listElementsL) - 1 else i) i --- | 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.+-- | Set the selected index for a list to the index of the first+-- occurence of the specified element if it is in the list, or leave+-- the list unmodified otherwise. ----- Complexity: same as 'traverse' for the container type (typically--- /O(n)/).-listMoveToElement :: (Eq e, Traversable t)+-- /O(n)/. Only evaluates as much of the container as needed.+listMoveToElement :: (Eq e, Foldable t, Splittable t) => e -> GenericList n t e -> GenericList n t e-listMoveToElement e l =- let i = fmap fst $ find ((== e) . snd) $ imap (,) (l^.listElementsL)- in l & listSelectedL %~ (i <|>)+listMoveToElement e = listFindBy (== e) . set listSelectedL Nothing++-- | Set the selected index to the next element matching the+-- predicate. If there is no selected element, the search starts at+-- the beginning. If no matching element is found, leave the list+-- unmodified.+--+-- /O(n)/. Only evaluates as much of the container as needed.+listFindBy :: (Foldable t, Splittable t)+ => (e -> Bool)+ -> GenericList n t e+ -> GenericList n t e+listFindBy test l =+ let start = maybe 0 (+1) (l ^. listSelectedL)+ (_, t) = splitAt start (l ^. listElementsL)+ result = find (test . snd) . zip [0..] . toList $ t+ in maybe id (set listSelectedL . Just . (start +) . fst) result l -- | Return a list's selected element, if any. --
src/Data/Text/Markup.hs view
@@ -12,6 +12,7 @@ , fromList , fromText , toText+ , empty , (@@) ) where@@ -51,6 +52,10 @@ -- | Extract the text from markup, discarding the markup metadata. toText :: (Eq a) => Markup a -> T.Text toText = T.concat . (fst <$>) . concat . markupToList++-- | Test whether the markup is empty.+empty :: Markup a -> Bool+empty (Markup ls) = null ls -- | Set the metadata for a range of character positions in a piece of -- markup. This is useful for, e.g., syntax highlighting.
tests/List.hs view
@@ -12,6 +12,7 @@ import Prelude hiding (reverse, splitAt) +import Data.Foldable (find) import Data.Function (on) import qualified Data.List import Data.Maybe (isNothing)@@ -38,6 +39,7 @@ | MoveBy Int | MoveTo Int | MoveToElement a+ | FindElement a deriving (Show) instance Arbitrary a => Arbitrary (ListMoveOp a) where@@ -47,6 +49,7 @@ , MoveBy <$> arbitrary , MoveTo <$> arbitrary , MoveToElement <$> arbitrary+ , FindElement <$> arbitrary ] -- List operations. We don't have "page"-based movement operations@@ -67,7 +70,7 @@ , (1, Replace <$> arbitrary <*> arbitrary) , (1, pure Clear) , (1, pure Reverse)- , (5, arbitrary)+ , (6, arbitrary) ] -- Turn a ListOp into a List endomorphism@@ -88,6 +91,7 @@ moveOp (MoveBy n) = listMoveBy n moveOp (MoveTo n) = listMoveTo n moveOp (MoveToElement a) = listMoveToElement a+moveOp (FindElement a) = listFindBy (== a) applyListOps :: (Foldable t)@@ -155,6 +159,31 @@ in fmap snd sel == Just a +-- inserting an element and repeatedly seeking it always+-- reaches the element we inserted, at the index where we+-- inserted it.+--+prop_insertFindBy :: (Eq a) => [ListOp a] -> List n a -> Int -> a -> Bool+prop_insertFindBy ops l i a =+ let+ l' = applyListOps op ops l+ l'' = set listSelectedL Nothing . listInsert i a $ l'+ seeks = converging ((==) `on` (^. listSelectedL)) (listFindBy (== a)) l''+ i' = clamp 0 (length (l' ^. listElementsL)) i -- we can't have inserted past len+ in+ (find ((== Just i') . (^. listSelectedL)) seeks >>= listSelectedElement)+ == Just (i', a)++-- Find will never decrease the selected index. Note that we don't+-- need to handle the 'Nothing' case because ∀a. Nothing < Just a.+prop_findByNonDecreasing :: (Eq a) => [ListOp a] -> List n a -> a -> Bool+prop_findByNonDecreasing ops l a =+ let+ l' = applyListOps op ops l+ l'' = listFindBy (== a) l'+ in+ l' ^. listSelectedL <= l'' ^. listSelectedL+ -- inserting then deleting always yields a list with the original elems prop_insertRemove :: (Eq a) => Int -> a -> List n a -> Bool prop_insertRemove i a l =@@ -188,11 +217,17 @@ in l' ^. listElementsL == l ^. listElementsL +-- Apply @f@ until @test a (f a) == True@, then return @a@. converge :: (a -> a -> Bool) -> (a -> a) -> a -> a-converge test f a- | test (f a) a = a- | otherwise = converge test f (f a)+converge test f = last . converging test f +-- Apply @f@ until @test a (f a) == True@, returning the start,+-- intermediate and final values as a list.+converging :: (a -> a -> Bool) -> (a -> a) -> a -> [a]+converging test f a+ | test a (f a) = [a]+ | otherwise = a : converging test f (f a)+ -- listMoveUp always reaches 0 (or list is empty) prop_moveUp :: (Eq a) => [ListOp a] -> List n a -> Bool prop_moveUp ops l =@@ -338,6 +373,18 @@ l' = listMoveBy 1 l in l' ^. listSelectedL == Just 1++-- listFindBy is lazy+prop_findByLazy :: Bool+prop_findByLazy =+ let+ v = L (1:2:3:4:undefined) :: L Int+ l = list () v 1 & listSelectedL .~ Nothing+ l' = listFindBy even l+ l'' = listFindBy even l'+ in+ l' ^. listSelectedL == Just 1+ && l'' ^. listSelectedL == Just 3 return []