brick 0.47 → 0.47.1
raw patch · 8 files changed
+43/−27 lines, 8 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Brick.BorderMap: eBottomL :: forall a_aj62. Lens' (Edges a_aj62) a_aj62
+ Brick.BorderMap: eBottomL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
- Brick.BorderMap: eLeftL :: forall a_aj62. Lens' (Edges a_aj62) a_aj62
+ Brick.BorderMap: eLeftL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
- Brick.BorderMap: eRightL :: forall a_aj62. Lens' (Edges a_aj62) a_aj62
+ Brick.BorderMap: eRightL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
- Brick.BorderMap: eTopL :: forall a_aj62. Lens' (Edges a_aj62) a_aj62
+ Brick.BorderMap: eTopL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
- Brick.Types: bordersL :: forall n_aGdW. Lens' (Result n_aGdW) (BorderMap DynBorder)
+ Brick.Types: bordersL :: forall n_aGiC. Lens' (Result n_aGiC) (BorderMap DynBorder)
- Brick.Types: cursorLocationL :: forall n_aESx. Lens' (CursorLocation n_aESx) Location
+ Brick.Types: cursorLocationL :: forall n_aEXd. Lens' (CursorLocation n_aEXd) Location
- Brick.Types: cursorLocationNameL :: forall n_aESx n_aGR8. Lens (CursorLocation n_aESx) (CursorLocation n_aGR8) (Maybe n_aESx) (Maybe n_aGR8)
+ Brick.Types: cursorLocationNameL :: forall n_aEXd n_aGVO. Lens (CursorLocation n_aEXd) (CursorLocation n_aGVO) (Maybe n_aEXd) (Maybe n_aGVO)
- Brick.Types: cursorsL :: forall n_aGdW. Lens' (Result n_aGdW) [CursorLocation n_aGdW]
+ Brick.Types: cursorsL :: forall n_aGiC. Lens' (Result n_aGiC) [CursorLocation n_aGiC]
- Brick.Types: eBottomL :: forall a_aj62. Lens' (Edges a_aj62) a_aj62
+ Brick.Types: eBottomL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
- Brick.Types: eLeftL :: forall a_aj62. Lens' (Edges a_aj62) a_aj62
+ Brick.Types: eLeftL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
- Brick.Types: eRightL :: forall a_aj62. Lens' (Edges a_aj62) a_aj62
+ Brick.Types: eRightL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
- Brick.Types: eTopL :: forall a_aj62. Lens' (Edges a_aj62) a_aj62
+ Brick.Types: eTopL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
- Brick.Types: extentsL :: forall n_aGdW. Lens' (Result n_aGdW) [Extent n_aGdW]
+ Brick.Types: extentsL :: forall n_aGiC. Lens' (Result n_aGiC) [Extent n_aGiC]
- Brick.Types: imageL :: forall n_aGdW. Lens' (Result n_aGdW) Image
+ Brick.Types: imageL :: forall n_aGiC. Lens' (Result n_aGiC) Image
- Brick.Types: visibilityRequestsL :: forall n_aGdW. Lens' (Result n_aGdW) [VisibilityRequest]
+ Brick.Types: visibilityRequestsL :: forall n_aGiC. Lens' (Result n_aGiC) [VisibilityRequest]
- Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1gez a_a1gfg. Lens (Dialog a_a1gez) (Dialog a_a1gfg) [(String, a_a1gez)] [(String, a_a1gfg)]
+ Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1gjc a_a1gjT. Lens (Dialog a_a1gjc) (Dialog a_a1gjT) [(String, a_a1gjc)] [(String, a_a1gjT)]
- Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1gez. Lens' (Dialog a_a1gez) (Maybe Int)
+ Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1gjc. Lens' (Dialog a_a1gjc) (Maybe Int)
- Brick.Widgets.Dialog: dialogTitleL :: forall a_a1gez. Lens' (Dialog a_a1gez) (Maybe String)
+ Brick.Widgets.Dialog: dialogTitleL :: forall a_a1gjc. Lens' (Dialog a_a1gjc) (Maybe String)
- Brick.Widgets.Dialog: dialogWidthL :: forall a_a1gez. Lens' (Dialog a_a1gez) Int
+ Brick.Widgets.Dialog: dialogWidthL :: forall a_a1gjc. Lens' (Dialog a_a1gjc) Int
- Brick.Widgets.Edit: editContentsL :: forall t_a1bhI n_a1bhJ t_a1bis. Lens (Editor t_a1bhI n_a1bhJ) (Editor t_a1bis n_a1bhJ) (TextZipper t_a1bhI) (TextZipper t_a1bis)
+ Brick.Widgets.Edit: editContentsL :: forall t_a1bmn n_a1bmo t_a1bn7. Lens (Editor t_a1bmn n_a1bmo) (Editor t_a1bn7 n_a1bmo) (TextZipper t_a1bmn) (TextZipper t_a1bn7)
- Brick.Widgets.FileBrowser: fileBrowserEntryFilterL :: forall n_a1qKE. Lens' (FileBrowser n_a1qKE) (Maybe (FileInfo -> Bool))
+ Brick.Widgets.FileBrowser: fileBrowserEntryFilterL :: forall n_a1qMp. Lens' (FileBrowser n_a1qMp) (Maybe (FileInfo -> Bool))
- Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1qKE. Lens' (FileBrowser n_a1qKE) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1qMp. Lens' (FileBrowser n_a1qMp) (FileInfo -> Bool)
- Brick.Widgets.List: listElementsL :: forall n_a1ll8 t_a1ll9 e_a1lla t_a1lzI e_a1lzJ. Lens (GenericList n_a1ll8 t_a1ll9 e_a1lla) (GenericList n_a1ll8 t_a1lzI e_a1lzJ) (t_a1ll9 e_a1lla) (t_a1lzI e_a1lzJ)
+ Brick.Widgets.List: listElementsL :: forall n_a1lpL t_a1lpM e_a1lpN t_a1lEl e_a1lEm. Lens (GenericList n_a1lpL t_a1lpM e_a1lpN) (GenericList n_a1lpL t_a1lEl e_a1lEm) (t_a1lpM e_a1lpN) (t_a1lEl e_a1lEm)
- Brick.Widgets.List: listItemHeightL :: forall n_a1ll8 t_a1ll9 e_a1lla. Lens' (GenericList n_a1ll8 t_a1ll9 e_a1lla) Int
+ Brick.Widgets.List: listItemHeightL :: forall n_a1lpL t_a1lpM e_a1lpN. Lens' (GenericList n_a1lpL t_a1lpM e_a1lpN) Int
- Brick.Widgets.List: listNameL :: forall n_a1ll8 t_a1ll9 e_a1lla n_a1lzK. Lens (GenericList n_a1ll8 t_a1ll9 e_a1lla) (GenericList n_a1lzK t_a1ll9 e_a1lla) n_a1ll8 n_a1lzK
+ Brick.Widgets.List: listNameL :: forall n_a1lpL t_a1lpM e_a1lpN n_a1lEn. Lens (GenericList n_a1lpL t_a1lpM e_a1lpN) (GenericList n_a1lEn t_a1lpM e_a1lpN) n_a1lpL n_a1lEn
- Brick.Widgets.List: listSelectedL :: forall n_a1ll8 t_a1ll9 e_a1lla. Lens' (GenericList n_a1ll8 t_a1ll9 e_a1lla) (Maybe Int)
+ Brick.Widgets.List: listSelectedL :: forall n_a1lpL t_a1lpM e_a1lpN. Lens' (GenericList n_a1lpL t_a1lpM e_a1lpN) (Maybe Int)
Files
- CHANGELOG.md +10/−0
- README.md +2/−1
- brick.cabal +2/−2
- docs/guide.rst +1/−1
- docs/samtay-tutorial.md +2/−2
- src/Brick/Widgets/Core.hs +1/−1
- src/Brick/Widgets/List.hs +6/−8
- tests/List.hs +19/−12
CHANGELOG.md view
@@ -2,6 +2,16 @@ Brick changelog --------------- +0.47.1+------++Bug fixes:+ * userguide: update stale Result construction+ * Added test case for List initial selection (thanks Fraser Tweedale)+ * Fixed build on GHC 7.10 due to RULES pragma formatting issue (thanks+ Fraser Tweedale)+ * Various CI-related fixes (thanks Fraser Tweedale)+ 0.47 ----
README.md view
@@ -44,7 +44,7 @@ at these projects: * `tetris`, an implementation of the Tetris game: https://github.com/SamTay/tetris- * `gotta-go-fast`, a typing tutor: https://github.com/hot-leaf-juice/gotta-go-fast+ * `gotta-go-fast`, a typing tutor: https://github.com/callum-oakley/gotta-go-fast * `haskell-player`, an `afplay` frontend: https://github.com/potomak/haskell-player * `mushu`, an `MPD` client: https://github.com/elaye/mushu * `matterhorn`, a client for [Mattermost](https://about.mattermost.com/): https://github.com/matterhorn-chat/matterhorn@@ -60,6 +60,7 @@ * `VOIDSPACE`, a space-themed typing-tutor game: https://github.com/ChrisPenner/void-space * `solitaire`, the card game: https://github.com/ambuc/solitaire * `sudoku-tui`, a Sudoku implementation: https://github.com/evanrelf/sudoku-tui+ * `summoner-tui`, an interactive frontend to the Summoner tool: https://github.com/kowainik/summoner/tree/master/summoner-tui These third-party packages also extend `brick`:
brick.cabal view
@@ -1,5 +1,5 @@ name: brick-version: 0.47+version: 0.47.1 synopsis: A declarative terminal user interface library description: Write terminal applications painlessly with 'brick'! You write an@@ -37,7 +37,7 @@ cabal-version: 1.18 Homepage: https://github.com/jtdaugherty/brick/ Bug-reports: https://github.com/jtdaugherty/brick/issues-tested-with: GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.1+tested-with: GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.1, GHC == 8.6.5 extra-doc-files: README.md, docs/guide.rst,
docs/guide.rst view
@@ -1804,7 +1804,7 @@ ctx <- getContext let a = ctx^.attrL return $ Result (Graphics.Vty.charFill a ch (ctx^.availWidthL) (ctx^.availHeightL))- [] []+ [] [] [] Brick.BorderMap.empty Rendering Sub-Widgets ---------------------
docs/samtay-tutorial.md view
@@ -386,8 +386,8 @@ The score is straightforward, but it is the first border in this tutorial. Borders are well documented in the [border-demo](https://github.com/jtdaugherty/brick/blob/master/programs/BorderDe-mo.hs) and the Haddocks for that matter.+demo](https://github.com/jtdaugherty/brick/blob/master/programs/BorderDemo.hs)+and the Haddocks for that matter. We also only show the "game over" widget if the game is actually over. In that case, we are rendering the string widget with the `gameOverAttr`
src/Brick/Widgets/Core.hs view
@@ -1261,4 +1261,4 @@ "vBox2" forall as bs . vBox [vBox as, vBox bs] = vBox (as ++ bs) "vboxL" forall as b . vBox [vBox as, b] = vBox (as ++ [b]) "vboxR" forall a bs . vBox [a, vBox bs] = vBox (a : bs)-#-}+ #-}
src/Brick/Widgets/List.hs view
@@ -418,7 +418,7 @@ -- size) -> GenericList n t e -> GenericList n t e-listRemove pos l | null (l^.listElementsL) = l+listRemove pos l | null l = l | pos /= splitClamp l pos = l | otherwise = let newSel = case l^.listSelectedL of@@ -517,7 +517,7 @@ let target = case l ^. listSelectedL of Nothing | amt > 0 -> 0- | otherwise -> length (l ^. listElementsL) - 1+ | otherwise -> length l - 1 Just i -> max 0 (amt + i) -- don't be negative in listMoveTo target l @@ -541,12 +541,10 @@ -> GenericList n t e -> GenericList n t e listMoveTo pos l =- let len = length (l ^. listElementsL)+ let len = length l i = if pos < 0 then len - pos else pos newSel = splitClamp l i- in l & listSelectedL .~ if not (null (l ^. listElementsL))- then Just newSel- else Nothing+ in l & listSelectedL .~ if null l then Nothing else Just newSel -- | Split-based clamp that avoids evaluating 'length' of the structure -- (unless the structure is already fully evaluated).@@ -560,7 +558,7 @@ -- -- Otherwise if tail is not empty, then we already know that i -- 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+ clamp 0 (if null t then length l - 1 else i) i -- | 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@@ -627,7 +625,7 @@ -> GenericList n t e listReverse l = l & listElementsL %~ reverse- & listSelectedL %~ fmap (length (l ^. listElementsL) - 1 -)+ & listSelectedL %~ fmap (length l - 1 -) -- | Apply a function to the selected element. If no element is selected -- the list is not modified.
tests/List.hs view
@@ -98,6 +98,13 @@ => (op a -> List n a -> List n a) -> t (op a) -> List n a -> List n a applyListOps f = appEndo . foldMap (Endo . f) ++-- | Initial selection is always 0 (or Nothing for empty list)+prop_initialSelection :: [a] -> Bool+prop_initialSelection xs =+ list () (V.fromList xs) 1 ^. listSelectedL ==+ if null xs then Nothing else Just 0+ -- list operations keep the selected index in bounds prop_listOpsMaintainSelectedValid :: (Eq a) => [ListOp a] -> List n a -> Bool@@ -106,9 +113,9 @@ in case l' ^. listSelectedL of -- either there is no selection and list is empty- Nothing -> null (l' ^. listElementsL)+ Nothing -> null l' -- or the selected index is valid- Just i -> i >= 0 && i < length (l' ^. listElementsL)+ Just i -> i >= 0 && i < length l' -- reversing a list keeps the selected element the same prop_reverseMaintainsSelectedElement@@ -124,7 +131,7 @@ -- reversing maintains size of list prop_reverseMaintainsSizeOfList :: List n a -> Bool prop_reverseMaintainsSizeOfList l =- length (l ^. listElementsL) == length (listReverse l ^. listElementsL)+ length l == length (listReverse l) -- an inserted element may always be found at the given index -- (when target index is clamped to 0 <= n <= len)@@ -132,7 +139,7 @@ prop_insert i a l = let l' = listInsert i a l- i' = clamp 0 (length (l ^. listElementsL)) i+ i' = clamp 0 (length l) i in listSelectedElement (listMoveTo i' l') == Just (i', a) @@ -142,7 +149,7 @@ let l' = listInsert i a l in- length (l' ^. listElementsL) == length (l ^. listElementsL) + 1+ length l' == length l + 1 -- inserting an element and moving to it always succeeds and -- the selected element is the one we inserted.@@ -169,7 +176,7 @@ 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+ i' = clamp 0 (length l') i -- we can't have inserted past len in (find ((== Just i') . (^. listSelectedL)) seeks >>= listSelectedElement) == Just (i', a)@@ -188,7 +195,7 @@ prop_insertRemove :: (Eq a) => Int -> a -> List n a -> Bool prop_insertRemove i a l = let- i' = clamp 0 (length (l ^. listElementsL)) i+ i' = clamp 0 (length l) i l' = listInsert i' a l -- pre-clamped l'' = listRemove i' l' in@@ -199,13 +206,13 @@ prop_remove :: Int -> List n a -> Bool prop_remove i l = let- len = length (l ^. listElementsL)+ len = length l i' = clamp 0 (len - 1) i test | len > 0 && i == i' = (== len - 1) -- i is in bounds | otherwise = (== len) -- i is out of bounds in- test (length (listRemove i l ^. listElementsL))+ test (length (listRemove i l)) -- deleting an element and re-inserting it at same position -- gives the original list elements@@ -234,7 +241,7 @@ let l' = applyListOps op ops l l'' = converge ((==) `on` (^. listSelectedL)) listMoveUp l'- len = length (l'' ^. listElementsL)+ len = length l'' in maybe (len == 0) (== 0) (l'' ^. listSelectedL) @@ -244,7 +251,7 @@ let l' = applyListOps op ops l l'' = converge ((==) `on` (^. listSelectedL)) listMoveDown l'- len = length (l'' ^. listElementsL)+ len = length l'' in maybe (len == 0) (== len - 1) (l'' ^. listSelectedL) @@ -292,7 +299,7 @@ prop_moveByWhenNoSelection l amt = let l' = l & listSelectedL .~ Nothing- len = length (l ^. listElementsL)+ len = length l expected = if amt > 0 then 0 else len - 1 in len > 0 ==> listMoveBy amt l' ^. listSelectedL == Just expected