brick-list-search 0.1.0.0 → 0.1.1.0
raw patch · 4 files changed
+101/−42 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Brick.Widgets.List.Search: listSearchBy :: (Searchable t, Foldable t, Splittable t) => (e -> Bool) -> Int -> GenericList n t e -> GenericList n t e
+ Brick.Widgets.List.Search: listSearchByPages :: (Searchable t, Foldable t, Splittable t, Ord n, RealFrac m) => (e -> Bool) -> m -> EventM n (GenericList n t e) ()
Files
- CHANGELOG.md +4/−0
- brick-list-search.cabal +1/−1
- demos/BrickListSearch.hs +10/−2
- src/Brick/Widgets/List/Search.hs +86/−39
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for brick-list-search +## 0.1.1.0 -- 2023-02-21++* Added `listSearchBy` and `listSearchByPages`.+ ## 0.1.0.0 -- 2023-02-20 * First version with proper documentation.
brick-list-search.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: brick-list-search-version: 0.1.0.0+version: 0.1.1.0 synopsis: Search forward or backward for certain kinds of items in brick list
demos/BrickListSearch.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE LambdaCase #-} module Main where +import Brick.Widgets.List.Search -- base import Control.Monad (void) -- Third party libraries@@ -15,7 +16,6 @@ import Brick.Widgets.Border import Brick.Widgets.List import Brick.Widgets.Center-import Brick.Widgets.List.Search import Graphics.Vty (defAttr, Event(..), Key(..), Modifier(..), black, white) data Name = TheList deriving (Eq, Ord, Show)@@ -37,6 +37,10 @@ VtyEvent (EvKey KEnd []) -> modify $ listSearchFromEnd isItem VtyEvent (EvKey KPageUp []) -> listSearchPageUp isItem VtyEvent (EvKey KPageDown []) -> listSearchPageDown isItem+ VtyEvent (EvKey (KChar 'u') [MCtrl]) -> listSearchByPages isItem (-0.5)+ VtyEvent (EvKey (KChar 'd') [MCtrl]) -> listSearchByPages isItem 0.5+ VtyEvent (EvKey (KChar 'k') []) -> modify $ listSearchBy isItem (-2)+ VtyEvent (EvKey (KChar 'j') []) -> modify $ listSearchBy isItem 2 _ -> return () renderListElement :: Bool -> ListElem -> Widget Name@@ -52,7 +56,11 @@ , "Press Home to move to the beginning" , "Press End to move to the end" , "Press PageUp to move up one page"- , "Press PageDown to move down one page" ]+ , "Press PageDown to move down one page"+ , "Press Ctrl+u to move up half page"+ , "Press Ctrl+d to move down half page"+ , "Press k to move up two items"+ , "Press j to move down two items"] in [vCenter $ vBox $ hCenter (border $ vLimit 20 $ hLimit 30 $ renderList renderListElement True l) : map (hCenter . str) msgs]
src/Brick/Widgets/List/Search.hs view
@@ -14,12 +14,14 @@ , searchListForward , searchListBackward -- * List manipulation-, listSearchDown+, listSearchBy , listSearchUp-, listSearchFromBeginning-, listSearchFromEnd+, listSearchDown+, listSearchByPages , listSearchPageUp , listSearchPageDown+, listSearchFromBeginning+, listSearchFromEnd -- * Classes , Searchable(..) ) where@@ -78,18 +80,34 @@ es = take start $ l ^. L.listElementsL in searchBackward (start-1) es --- | Search forward for the first element that passes the test.+-- | Move by an amount of list elements in the list. If the amount to move by is 0, no change is made. Otherwise, call+-- 'L.listMoveBy'. ----- The current element is not included in the search.+-- The element chosen by 'L.listMoveBy' is included in the search. ----- If forward search fails, no change is made.-listSearchDown :: Searchable t+-- After calling 'L.listMoveBy', if the amount to move by was positive, search forward for the first element that passes+-- the test. If forward search fails, search backward for the first such element. If backward search fails too, no+-- change is made.+--+-- After calling 'L.listMoveBy', if the amount to move by was negative, search backward for the first element that+-- passes the test. If backward search fails, search forward for the first such element. If forward search fails too, no+-- change is made.+listSearchBy :: (Searchable t, Foldable t, L.Splittable t) => (e -> Bool) -- ^ The test+ -> Int -- ^ The amount of list elements to move by -> L.GenericList n t e -> L.GenericList n t e-listSearchDown test l = case searchListForward False test l of- Nothing -> l- Just idx -> l & L.listSelectedL ?~ idx+listSearchBy test amt l = if amt == 0+ then l+ else let l' = L.listMoveBy amt l+ (searchList, searchListOpposite) = if amt < 0+ then (searchListBackward, searchListForward)+ else (searchListForward, searchListBackward)+ in case searchList True test l' of+ Nothing -> case searchListOpposite True test l' of+ Nothing -> l+ Just idx -> l & L.listSelectedL ?~ idx+ Just idx -> l & L.listSelectedL ?~ idx -- | Search backward for the first element that passes the test. --@@ -104,31 +122,48 @@ Nothing -> l Just idx -> l & L.listSelectedL ?~ idx --- | From the first element, search forward for the first element that passes the test.+-- | Search forward for the first element that passes the test. ----- The first element is included in the search.+-- The current element is not included in the search. -- -- If forward search fails, no change is made.-listSearchFromBeginning :: (Searchable t, Foldable t, L.Splittable t)+listSearchDown :: Searchable t => (e -> Bool) -- ^ The test -> L.GenericList n t e -> L.GenericList n t e-listSearchFromBeginning test l = case searchListForward True test (L.listMoveToBeginning l) of+listSearchDown test l = case searchListForward False test l of Nothing -> l Just idx -> l & L.listSelectedL ?~ idx --- | From the last element, search backward for the first element that passes the test.+-- | Move by a (fractional) number of pages in the list. If the number of pages to move by is 0, no change is made.+-- Otherwise, call 'L.listMoveByPages' with the number of pages to move by. ----- The last element is included in the search.+-- The element chosen by 'L.listMoveByPages' is included in the search. ----- If backward search fails, no change is made.-listSearchFromEnd :: (Searchable t, Foldable t, L.Splittable t)+-- After calling 'L.listMoveByPages', if the number of pages to move by was positive, search forward for the first+-- element that passes the test. If forward search fails, then search backward for the first such element. If backward+-- search fails too, cancel movements made by this function.+--+-- After calling 'L.listMoveByPages', if the number of pages to move by was negative, search backward for the first+-- element that passes the test. If backward search fails, then search forward for the first such element. If forward+-- search fails too, cancel movements made by this function.+listSearchByPages :: (Searchable t, Foldable t, L.Splittable t, Ord n, RealFrac m) => (e -> Bool) -- ^ The test- -> L.GenericList n t e- -> L.GenericList n t e-listSearchFromEnd test l = case searchListBackward True test (L.listMoveToEnd l) of- Nothing -> l- Just idx -> l & L.listSelectedL ?~ idx+ -> m -- ^ Pages to move by+ -> EventM n (L.GenericList n t e) ()+listSearchByPages test p = if p == 0+ then return ()+ else do+ origL <- get+ L.listMoveByPages p+ let (searchList, searchListOpposite) = if p < 0+ then (searchListBackward, searchListForward)+ else (searchListForward, searchListBackward)+ modify $ \l -> case searchList True test l of+ Nothing -> case searchListOpposite True test l of+ Nothing -> origL+ Just idx -> l & L.listSelectedL ?~ idx+ Just idx -> l & L.listSelectedL ?~ idx -- | Move up one page, and search backward for the first element that passes the test. --@@ -140,14 +175,7 @@ listSearchPageUp :: (Searchable t, Foldable t, L.Splittable t, Ord n) => (e -> Bool) -- ^ The test -> EventM n (L.GenericList n t e) ()-listSearchPageUp test = do- origL <- get- L.listMovePageUp- modify $ \l -> case searchListBackward True test l of- Nothing -> case searchListForward True test l of- Nothing -> origL- Just idx -> l & L.listSelectedL ?~ idx- Just idx -> l & L.listSelectedL ?~ idx+listSearchPageUp test = listSearchByPages test (-1 :: Double) -- | Move down one page, and search forward for the first element that passes the test. --@@ -159,14 +187,33 @@ listSearchPageDown :: (Searchable t, Foldable t, L.Splittable t, Ord n) => (e -> Bool) -- ^ The test -> EventM n (L.GenericList n t e) ()-listSearchPageDown test = do- origL <- get- L.listMovePageDown- modify $ \l -> case searchListForward True test l of- Nothing -> case searchListBackward True test l of- Nothing -> origL- Just idx -> l & L.listSelectedL ?~ idx- Just idx -> l & L.listSelectedL ?~ idx+listSearchPageDown test = listSearchByPages test (1 :: Double)++-- | From the first element, search forward for the first element that passes the test.+--+-- The first element is included in the search.+--+-- If forward search fails, no change is made.+listSearchFromBeginning :: (Searchable t, Foldable t, L.Splittable t)+ => (e -> Bool) -- ^ The test+ -> L.GenericList n t e+ -> L.GenericList n t e+listSearchFromBeginning test l = case searchListForward True test (L.listMoveToBeginning l) of+ Nothing -> l+ Just idx -> l & L.listSelectedL ?~ idx++-- | From the last element, search backward for the first element that passes the test.+--+-- The last element is included in the search.+--+-- If backward search fails, no change is made.+listSearchFromEnd :: (Searchable t, Foldable t, L.Splittable t)+ => (e -> Bool) -- ^ The test+ -> L.GenericList n t e+ -> L.GenericList n t e+listSearchFromEnd test l = case searchListBackward True test (L.listMoveToEnd l) of+ Nothing -> l+ Just idx -> l & L.listSelectedL ?~ idx -- | Functions for searching elements. class Searchable (t :: * -> *) where