brick 1.7 → 1.8
raw patch · 9 files changed
+92/−39 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Brick.AttrMap: forceAttrMapAllowStyle :: Attr -> AttrMap -> AttrMap
+ Brick.Widgets.Core: forceAttrAllowStyle :: AttrName -> Widget n -> Widget n
- Brick.BorderMap: eBottomL :: forall a_aeEX. Lens' (Edges a_aeEX) a_aeEX
+ Brick.BorderMap: eBottomL :: forall a_aeXJ. Lens' (Edges a_aeXJ) a_aeXJ
- Brick.BorderMap: eLeftL :: forall a_aeEX. Lens' (Edges a_aeEX) a_aeEX
+ Brick.BorderMap: eLeftL :: forall a_aeXJ. Lens' (Edges a_aeXJ) a_aeXJ
- Brick.BorderMap: eRightL :: forall a_aeEX. Lens' (Edges a_aeEX) a_aeEX
+ Brick.BorderMap: eRightL :: forall a_aeXJ. Lens' (Edges a_aeXJ) a_aeXJ
- Brick.BorderMap: eTopL :: forall a_aeEX. Lens' (Edges a_aeEX) a_aeEX
+ Brick.BorderMap: eTopL :: forall a_aeXJ. Lens' (Edges a_aeXJ) a_aeXJ
- Brick.Types: availHeightL :: forall n_azap. Lens' (Context n_azap) Int
+ Brick.Types: availHeightL :: forall n_aztb. Lens' (Context n_aztb) Int
- Brick.Types: availWidthL :: forall n_azap. Lens' (Context n_azap) Int
+ Brick.Types: availWidthL :: forall n_aztb. Lens' (Context n_aztb) Int
- Brick.Types: bordersL :: forall n_azat. Lens' (Result n_azat) (BorderMap DynBorder)
+ Brick.Types: bordersL :: forall n_aztf. Lens' (Result n_aztf) (BorderMap DynBorder)
- Brick.Types: ctxAttrMapL :: forall n_azap. Lens' (Context n_azap) AttrMap
+ Brick.Types: ctxAttrMapL :: forall n_aztb. Lens' (Context n_aztb) AttrMap
- Brick.Types: ctxAttrNameL :: forall n_azap. Lens' (Context n_azap) AttrName
+ Brick.Types: ctxAttrNameL :: forall n_aztb. Lens' (Context n_aztb) AttrName
- Brick.Types: ctxBorderStyleL :: forall n_azap. Lens' (Context n_azap) BorderStyle
+ Brick.Types: ctxBorderStyleL :: forall n_aztb. Lens' (Context n_aztb) BorderStyle
- Brick.Types: ctxDynBordersL :: forall n_azap. Lens' (Context n_azap) Bool
+ Brick.Types: ctxDynBordersL :: forall n_aztb. Lens' (Context n_aztb) Bool
- Brick.Types: ctxHScrollBarOrientationL :: forall n_azap. Lens' (Context n_azap) (Maybe HScrollBarOrientation)
+ Brick.Types: ctxHScrollBarOrientationL :: forall n_aztb. Lens' (Context n_aztb) (Maybe HScrollBarOrientation)
- Brick.Types: ctxHScrollBarRendererL :: forall n_azap. Lens' (Context n_azap) (Maybe (ScrollbarRenderer n_azap))
+ Brick.Types: ctxHScrollBarRendererL :: forall n_aztb. Lens' (Context n_aztb) (Maybe (ScrollbarRenderer n_aztb))
- Brick.Types: ctxVScrollBarOrientationL :: forall n_azap. Lens' (Context n_azap) (Maybe VScrollBarOrientation)
+ Brick.Types: ctxVScrollBarOrientationL :: forall n_aztb. Lens' (Context n_aztb) (Maybe VScrollBarOrientation)
- Brick.Types: ctxVScrollBarRendererL :: forall n_azap. Lens' (Context n_azap) (Maybe (ScrollbarRenderer n_azap))
+ Brick.Types: ctxVScrollBarRendererL :: forall n_aztb. Lens' (Context n_aztb) (Maybe (ScrollbarRenderer n_aztb))
- Brick.Types: cursorLocationL :: forall n_azau. Lens' (CursorLocation n_azau) Location
+ Brick.Types: cursorLocationL :: forall n_aztg. Lens' (CursorLocation n_aztg) Location
- Brick.Types: cursorLocationNameL :: forall n_azau n_aBAl. Lens (CursorLocation n_azau) (CursorLocation n_aBAl) (Maybe n_azau) (Maybe n_aBAl)
+ Brick.Types: cursorLocationNameL :: forall n_aztg n_aBT7. Lens (CursorLocation n_aztg) (CursorLocation n_aBT7) (Maybe n_aztg) (Maybe n_aBT7)
- Brick.Types: cursorsL :: forall n_azat. Lens' (Result n_azat) [CursorLocation n_azat]
+ Brick.Types: cursorsL :: forall n_aztf. Lens' (Result n_aztf) [CursorLocation n_aztf]
- Brick.Types: eBottomL :: forall a_aeEX. Lens' (Edges a_aeEX) a_aeEX
+ Brick.Types: eBottomL :: forall a_aeXJ. Lens' (Edges a_aeXJ) a_aeXJ
- Brick.Types: eLeftL :: forall a_aeEX. Lens' (Edges a_aeEX) a_aeEX
+ Brick.Types: eLeftL :: forall a_aeXJ. Lens' (Edges a_aeXJ) a_aeXJ
- Brick.Types: eRightL :: forall a_aeEX. Lens' (Edges a_aeEX) a_aeEX
+ Brick.Types: eRightL :: forall a_aeXJ. Lens' (Edges a_aeXJ) a_aeXJ
- Brick.Types: eTopL :: forall a_aeEX. Lens' (Edges a_aeEX) a_aeEX
+ Brick.Types: eTopL :: forall a_aeXJ. Lens' (Edges a_aeXJ) a_aeXJ
- Brick.Types: extentsL :: forall n_azat. Lens' (Result n_azat) [Extent n_azat]
+ Brick.Types: extentsL :: forall n_aztf. Lens' (Result n_aztf) [Extent n_aztf]
- Brick.Types: imageL :: forall n_azat. Lens' (Result n_azat) Image
+ Brick.Types: imageL :: forall n_aztf. Lens' (Result n_aztf) Image
- Brick.Types: visibilityRequestsL :: forall n_azat. Lens' (Result n_azat) [VisibilityRequest]
+ Brick.Types: visibilityRequestsL :: forall n_aztf. Lens' (Result n_aztf) [VisibilityRequest]
- Brick.Types: windowHeightL :: forall n_azap. Lens' (Context n_azap) Int
+ Brick.Types: windowHeightL :: forall n_aztb. Lens' (Context n_aztb) Int
- Brick.Types: windowWidthL :: forall n_azap. Lens' (Context n_azap) Int
+ Brick.Types: windowWidthL :: forall n_aztb. Lens' (Context n_aztb) Int
- Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1kNp n_a1kNq a_a1kOd. Lens (Dialog a_a1kNp n_a1kNq) (Dialog a_a1kOd n_a1kNq) [(String, n_a1kNq, a_a1kNp)] [(String, n_a1kNq, a_a1kOd)]
+ Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1lea n_a1leb a_a1leY. Lens (Dialog a_a1lea n_a1leb) (Dialog a_a1leY n_a1leb) [(String, n_a1leb, a_a1lea)] [(String, n_a1leb, a_a1leY)]
- Brick.Widgets.Dialog: dialogTitleL :: forall a_a1kNp n_a1kNq. Lens' (Dialog a_a1kNp n_a1kNq) (Maybe (Widget n_a1kNq))
+ Brick.Widgets.Dialog: dialogTitleL :: forall a_a1lea n_a1leb. Lens' (Dialog a_a1lea n_a1leb) (Maybe (Widget n_a1leb))
- Brick.Widgets.Dialog: dialogWidthL :: forall a_a1kNp n_a1kNq. Lens' (Dialog a_a1kNp n_a1kNq) Int
+ Brick.Widgets.Dialog: dialogWidthL :: forall a_a1lea n_a1leb. Lens' (Dialog a_a1lea n_a1leb) Int
- Brick.Widgets.Edit: editContentsL :: forall t_a1eeR n_a1eeS t_a1efw. Lens (Editor t_a1eeR n_a1eeS) (Editor t_a1efw n_a1eeS) (TextZipper t_a1eeR) (TextZipper t_a1efw)
+ Brick.Widgets.Edit: editContentsL :: forall t_a1eFC n_a1eFD t_a1eGh. Lens (Editor t_a1eFC n_a1eFD) (Editor t_a1eGh n_a1eFD) (TextZipper t_a1eFC) (TextZipper t_a1eGh)
- Brick.Widgets.FileBrowser: fileBrowserEntriesG :: forall n_a1vX2. SimpleGetter (FileBrowser n_a1vX2) (List n_a1vX2 FileInfo)
+ Brick.Widgets.FileBrowser: fileBrowserEntriesG :: forall n_a1wnN. SimpleGetter (FileBrowser n_a1wnN) (List n_a1wnN FileInfo)
- Brick.Widgets.FileBrowser: fileBrowserEntryFilterG :: forall n_a1vX2. SimpleGetter (FileBrowser n_a1vX2) (Maybe (FileInfo -> Bool))
+ Brick.Widgets.FileBrowser: fileBrowserEntryFilterG :: forall n_a1wnN. SimpleGetter (FileBrowser n_a1wnN) (Maybe (FileInfo -> Bool))
- Brick.Widgets.FileBrowser: fileBrowserExceptionG :: forall n_a1vX2. SimpleGetter (FileBrowser n_a1vX2) (Maybe IOException)
+ Brick.Widgets.FileBrowser: fileBrowserExceptionG :: forall n_a1wnN. SimpleGetter (FileBrowser n_a1wnN) (Maybe IOException)
- Brick.Widgets.FileBrowser: fileBrowserLatestResultsG :: forall n_a1vX2. SimpleGetter (FileBrowser n_a1vX2) [FileInfo]
+ Brick.Widgets.FileBrowser: fileBrowserLatestResultsG :: forall n_a1wnN. SimpleGetter (FileBrowser n_a1wnN) [FileInfo]
- Brick.Widgets.FileBrowser: fileBrowserNameG :: forall n_a1vX2. SimpleGetter (FileBrowser n_a1vX2) n_a1vX2
+ Brick.Widgets.FileBrowser: fileBrowserNameG :: forall n_a1wnN. SimpleGetter (FileBrowser n_a1wnN) n_a1wnN
- Brick.Widgets.FileBrowser: fileBrowserSearchStringG :: forall n_a1vX2. SimpleGetter (FileBrowser n_a1vX2) (Maybe Text)
+ Brick.Widgets.FileBrowser: fileBrowserSearchStringG :: forall n_a1wnN. SimpleGetter (FileBrowser n_a1wnN) (Maybe Text)
- Brick.Widgets.FileBrowser: fileBrowserSelectableG :: forall n_a1vX2. SimpleGetter (FileBrowser n_a1vX2) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableG :: forall n_a1wnN. SimpleGetter (FileBrowser n_a1wnN) (FileInfo -> Bool)
- Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1vX2. Lens' (FileBrowser n_a1vX2) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1wnN. Lens' (FileBrowser n_a1wnN) (FileInfo -> Bool)
- Brick.Widgets.FileBrowser: fileBrowserSelectedFilesG :: forall n_a1vX2. SimpleGetter (FileBrowser n_a1vX2) (Set String)
+ Brick.Widgets.FileBrowser: fileBrowserSelectedFilesG :: forall n_a1wnN. SimpleGetter (FileBrowser n_a1wnN) (Set String)
- Brick.Widgets.FileBrowser: fileBrowserWorkingDirectoryG :: forall n_a1vX2. SimpleGetter (FileBrowser n_a1vX2) FilePath
+ Brick.Widgets.FileBrowser: fileBrowserWorkingDirectoryG :: forall n_a1wnN. SimpleGetter (FileBrowser n_a1wnN) FilePath
- Brick.Widgets.List: listElementsL :: forall n_a1qqp t_a1qqq e_a1qqr t_a1qFB e_a1qFC. Lens (GenericList n_a1qqp t_a1qqq e_a1qqr) (GenericList n_a1qqp t_a1qFB e_a1qFC) (t_a1qqq e_a1qqr) (t_a1qFB e_a1qFC)
+ Brick.Widgets.List: listElementsL :: forall n_a1qRa t_a1qRb e_a1qRc t_a1r6m e_a1r6n. Lens (GenericList n_a1qRa t_a1qRb e_a1qRc) (GenericList n_a1qRa t_a1r6m e_a1r6n) (t_a1qRb e_a1qRc) (t_a1r6m e_a1r6n)
- Brick.Widgets.List: listItemHeightL :: forall n_a1qqp t_a1qqq e_a1qqr. Lens' (GenericList n_a1qqp t_a1qqq e_a1qqr) Int
+ Brick.Widgets.List: listItemHeightL :: forall n_a1qRa t_a1qRb e_a1qRc. Lens' (GenericList n_a1qRa t_a1qRb e_a1qRc) Int
- Brick.Widgets.List: listNameL :: forall n_a1qqp t_a1qqq e_a1qqr n_a1qFD. Lens (GenericList n_a1qqp t_a1qqq e_a1qqr) (GenericList n_a1qFD t_a1qqq e_a1qqr) n_a1qqp n_a1qFD
+ Brick.Widgets.List: listNameL :: forall n_a1qRa t_a1qRb e_a1qRc n_a1r6o. Lens (GenericList n_a1qRa t_a1qRb e_a1qRc) (GenericList n_a1r6o t_a1qRb e_a1qRc) n_a1qRa n_a1r6o
- Brick.Widgets.List: listSelectedL :: forall n_a1qqp t_a1qqq e_a1qqr. Lens' (GenericList n_a1qqp t_a1qqq e_a1qqr) (Maybe Int)
+ Brick.Widgets.List: listSelectedL :: forall n_a1qRa t_a1qRb e_a1qRc. Lens' (GenericList n_a1qRa t_a1qRb e_a1qRc) (Maybe Int)
Files
- CHANGELOG.md +11/−0
- README.md +1/−0
- brick.cabal +1/−1
- docs/guide.rst +6/−6
- src/Brick/AttrMap.hs +18/−0
- src/Brick/Forms.hs +27/−2
- src/Brick/Themes.hs +0/−2
- src/Brick/Widgets/Core.hs +12/−0
- src/Brick/Widgets/FileBrowser.hs +16/−28
CHANGELOG.md view
@@ -2,6 +2,17 @@ Brick changelog --------------- +1.8+---++API changes:+* Added `Brick.Widgets.Core.forceAttrAllowStyle`, which is like+ `forceAttr` but allows styles to be preserved rather than overridden.++Other improvements:+* The `Brick.Forms` documentation was updated to clarify how attributes+ get used for form fields.+ 1.7 ---
README.md view
@@ -93,6 +93,7 @@ | [`codenames-haskell`](https://github.com/VigneshN1997/codenames-haskell) | An implementation of the Codenames game | | [`haradict`](https://github.com/srhoulam/haradict) | A TUI Arabic dictionary powered by [ElixirFM](https://github.com/otakar-smrz/elixir-fm) | | [`Giter`](https://gitlab.com/refaelsh/giter) | A UI wrapper around Git CLI inspired by [Magit](https://magit.vc/). |+| [`Brickudoku`](https://github.com/Thecentury/brickudoku) | A hybrid of Tetris and Sudoku | These third-party packages also extend `brick`:
brick.cabal view
@@ -1,5 +1,5 @@ name: brick-version: 1.7+version: 1.8 synopsis: A declarative terminal user interface library description: Write terminal user interfaces (TUIs) painlessly with 'brick'! You
docs/guide.rst view
@@ -1649,8 +1649,8 @@ ``Brick.Keybindings.KeyDispatcher``. The following table compares Brick application design decisions and-runtime behaviors in a typical application compared to one that uses the-customizable keybindings API:+runtime behaviors in a typical application to those of an application+that uses the customizable keybindings API: +---------------------+------------------------+-------------------------+ | **Approach** | **Before runtime** | **At runtime** |@@ -1745,12 +1745,12 @@ open and only handled ``QuitEvent`` when the window had been closed. This kind of "modal" approach to handling events means that we only consider a key to have a collision if it is bound to two or more- events that are handled in the same event handler.+ events that are handled in the same event handling context. -There's also another situation that would be problematic, which is when-an abstract event like ``QuitEvent`` has a key mapping that+There's also another situation that would be problematic, which is+when an abstract event like ``QuitEvent`` has a key mapping that collides with a key handler that is bound to a specific key using-``Brick.Keybindings.KeyDispatcher.onKey`` rather than an event:+``Brick.Keybindings.KeyDispatcher.onKey`` rather than an abstract event: .. code:: haskell
src/Brick/AttrMap.hs view
@@ -27,6 +27,7 @@ -- * Construction , attrMap , forceAttrMap+ , forceAttrMapAllowStyle , attrName -- * Inspection , attrNameComponents@@ -78,6 +79,7 @@ -- | An attribute map which maps 'AttrName' values to 'Attr' values. data AttrMap = AttrMap Attr (M.Map AttrName Attr) | ForceAttr Attr+ | ForceAttrAllowStyle Attr AttrMap deriving (Show, Generic, NFData) -- | Create an attribute name from a string.@@ -103,6 +105,11 @@ forceAttrMap :: Attr -> AttrMap forceAttrMap = ForceAttr +-- | Create an attribute map in which all lookups map to the same+-- attribute. This is functionally equivalent to @attrMap attr []@.+forceAttrMapAllowStyle :: Attr -> AttrMap -> AttrMap+forceAttrMapAllowStyle = ForceAttrAllowStyle+ -- | Given an attribute and a map, merge the attribute with the map's -- default attribute. If the map is forcing all lookups to a specific -- attribute, the forced attribute is returned without merging it with@@ -122,6 +129,7 @@ -- @ mergeWithDefault :: Attr -> AttrMap -> Attr mergeWithDefault _ (ForceAttr a) = a+mergeWithDefault _ (ForceAttrAllowStyle f _) = f mergeWithDefault a (AttrMap d _) = combineAttrs d a -- | Look up the specified attribute name in the map. Map lookups@@ -148,6 +156,12 @@ -- @ attrMapLookup :: AttrName -> AttrMap -> Attr attrMapLookup _ (ForceAttr a) = a+attrMapLookup a (ForceAttrAllowStyle forced m) =+ -- Look up the attribute in the contained map, then keep only its+ -- style.+ let result = attrMapLookup a m+ in forced { attrStyle = attrStyle forced `combineStyles` attrStyle result+ } attrMapLookup (AttrName []) (AttrMap theDefault _) = theDefault attrMapLookup (AttrName ns) (AttrMap theDefault m) = let results = mapMaybe (\n -> M.lookup (AttrName n) m) (inits ns)@@ -156,11 +170,14 @@ -- | Set the default attribute value in an attribute map. setDefaultAttr :: Attr -> AttrMap -> AttrMap setDefaultAttr _ (ForceAttr a) = ForceAttr a+setDefaultAttr newDefault (ForceAttrAllowStyle a m) =+ ForceAttrAllowStyle a (setDefaultAttr newDefault m) setDefaultAttr newDefault (AttrMap _ m) = AttrMap newDefault m -- | Get the default attribute value in an attribute map. getDefaultAttr :: AttrMap -> Attr getDefaultAttr (ForceAttr a) = a+getDefaultAttr (ForceAttrAllowStyle _ m) = getDefaultAttr m getDefaultAttr (AttrMap d _) = d combineAttrs :: Attr -> Attr -> Attr@@ -185,6 +202,7 @@ applyAttrMappings :: [(AttrName, Attr)] -> AttrMap -> AttrMap applyAttrMappings _ (ForceAttr a) = ForceAttr a applyAttrMappings ms (AttrMap d m) = AttrMap d ((M.fromList ms) `M.union` m)+applyAttrMappings ms (ForceAttrAllowStyle a m) = ForceAttrAllowStyle a (applyAttrMappings ms m) -- | Update an attribute map such that a lookup of 'ontoName' returns -- the attribute value specified by 'fromName'. This is useful for
src/Brick/Forms.hs view
@@ -359,6 +359,9 @@ -- | 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's attributes are governed by those exported from+-- 'Brick.Widgets.List'.+-- -- 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)@@ -492,6 +495,9 @@ -- a value. The other editing fields in this module are special cases of -- this function. --+-- This field's attributes are governed by those exported from+-- 'Brick.Widgets.Edit'.+-- -- This field responds to all events handled by 'editor', including -- mouse events. editField :: (Ord n, Show n)@@ -550,6 +556,9 @@ -- useful in cases where the user-facing representation of a value -- matches the 'Show' representation exactly, such as with 'Int'. --+-- This field's attributes are governed by those exported from+-- 'Brick.Widgets.Edit'.+-- -- This field responds to all events handled by 'editor', including -- mouse events. editShowableField :: (Ord n, Show n, Read a, Show a)@@ -570,6 +579,9 @@ -- user-facing representation of a value matches the 'Show' representation -- exactly, such as with 'Int', but you don't want to accept just /any/ 'Int'. --+-- This field's attributes are governed by those exported from+-- 'Brick.Widgets.Edit'.+-- -- This field responds to all events handled by 'editor', including -- mouse events. editShowableFieldWithValidate :: (Ord n, Show n, Read a, Show a)@@ -598,6 +610,9 @@ -- | A form field using an editor to edit a text value. Since the value -- is free-form text, it is always valid. --+-- This field's attributes are governed by those exported from+-- 'Brick.Widgets.Edit'.+-- -- This field responds to all events handled by 'editor', including -- mouse events. editTextField :: (Ord n, Show n)@@ -620,6 +635,9 @@ -- value represented as a password. The value is always considered valid -- and is always represented with one asterisk per password character. --+-- This field's attributes are governed by those exported from+-- 'Brick.Widgets.Edit'.+-- -- This field responds to all events handled by 'editor', including -- mouse events. editPasswordField :: (Ord n, Show n)@@ -644,11 +662,18 @@ formAttr :: AttrName formAttr = attrName "brickForm" --- | The attribute for form input fields with invalid values.+-- | The attribute for form input fields with invalid values. Note that+-- this attribute will affect any field considered invalid and will take+-- priority over any attributes that the field uses to render itself. invalidFormInputAttr :: AttrName invalidFormInputAttr = formAttr <> attrName "invalidInput" --- | The attribute for form input fields that have the focus.+-- | The attribute for form input fields that have the focus. Note that+-- this attribute only affects fields that do not already use their own+-- attributes when rendering, such as editor- and list-based fields.+-- Those need to be styled by setting the appropriate attributes; see+-- the documentation for field constructors to find out which attributes+-- need to be configured. focusedFormInputAttr :: AttrName focusedFormInputAttr = formAttr <> attrName "focusedInput"
src/Brick/Themes.hs view
@@ -6,8 +6,6 @@ -- | Support for representing attribute themes and loading and saving -- theme customizations in INI-style files. ----- The file format is as follows:--- -- Customization files are INI-style files with two sections, both -- optional: @"default"@ and @"other"@. --
src/Brick/Widgets/Core.hs view
@@ -50,6 +50,7 @@ , modifyDefAttr , withAttr , forceAttr+ , forceAttrAllowStyle , overrideAttr , updateAttrMap @@ -1028,6 +1029,17 @@ Widget (hSize p) (vSize p) $ do c <- getContext withReaderT (ctxAttrMapL .~ (forceAttrMap (attrMapLookup an (c^.ctxAttrMapL)))) (render p)++-- | Like 'forceAttr', except that the style of attribute lookups in the+-- attribute map is preserved and merged with the forced attribute. This+-- allows for situations where 'forceAttr' would otherwise ignore style+-- information that is important to preserve.+forceAttrAllowStyle :: AttrName -> Widget n -> Widget n+forceAttrAllowStyle an p =+ Widget (hSize p) (vSize p) $ do+ c <- getContext+ let m = c^.ctxAttrMapL+ withReaderT (ctxAttrMapL .~ (forceAttrMapAllowStyle (attrMapLookup an m) m)) (render p) -- | Override the lookup of the attribute name 'targetName' to return -- the attribute value associated with 'fromName' when rendering the
src/Brick/Widgets/FileBrowser.hs view
@@ -143,9 +143,10 @@ where import qualified Control.Exception as E-import Control.Monad (forM)+import Control.Monad (forM, when) import Control.Monad.IO.Class (liftIO) import Data.Char (toLower, isPrint)+import Data.Foldable (for_) import Data.Maybe (fromMaybe, isJust, fromJust) import qualified Data.Foldable as F import qualified Data.Text as T@@ -318,10 +319,7 @@ selectDirectories i = case fileInfoFileType i of Just Directory -> True- Just SymbolicLink ->- case fileInfoLinkTargetType i of- Just Directory -> True- _ -> False+ Just SymbolicLink -> fileInfoLinkTargetType i == Just Directory _ -> False -- | Set the filtering function used to determine which entries in@@ -362,7 +360,7 @@ Left (_::E.IOException) -> entries Right parent -> parent : entries - return $ (setEntries allEntries b)+ return $ setEntries allEntries b & fileBrowserWorkingDirectoryL .~ path & fileBrowserExceptionL .~ exc & fileBrowserSelectedFilesL .~ mempty@@ -492,7 +490,7 @@ applyFilterAndSearch b = let filterMatch = fromMaybe (const True) (b^.fileBrowserEntryFilterL) searchMatch = maybe (const True)- (\search i -> (T.toLower search `T.isInfixOf` (T.pack $ toLower <$> fileInfoSanitizedFilename i)))+ (\search i -> T.toLower search `T.isInfixOf` T.pack (toLower <$> fileInfoSanitizedFilename i)) (b^.fileBrowserSearchStringL) match i = filterMatch i && searchMatch i matching = filter match $ b^.fileBrowserLatestResultsL@@ -714,6 +712,9 @@ _ -> zoom fileBrowserEntriesL $ handleListEvent e +markSelected :: FileInfo -> EventM n (FileBrowser n) ()+markSelected e = fileBrowserSelectedFilesL %= Set.insert (fileInfoFilename e)+ -- | If the browser's current entry is selectable according to -- @fileBrowserSelectable@, add it to the selection set and return. -- If not, and if the entry is a directory or a symlink targeting a@@ -723,29 +724,16 @@ maybeSelectCurrentEntry :: EventM n (FileBrowser n) () maybeSelectCurrentEntry = do b <- get- case fileBrowserCursor b of- Nothing -> return ()- Just entry ->- if fileBrowserSelectable b entry- then fileBrowserSelectedFilesL %= Set.insert (fileInfoFilename entry)- else case fileInfoFileType entry of- Just Directory ->- put =<< (liftIO $ setWorkingDirectory (fileInfoFilePath entry) b)- Just SymbolicLink ->- case fileInfoLinkTargetType entry of- Just Directory ->- put =<< (liftIO $ setWorkingDirectory (fileInfoFilePath entry) b)- _ ->- return ()- _ ->- return ()+ for_ (fileBrowserCursor b) $ \entry ->+ if fileBrowserSelectable b entry+ then markSelected entry+ else when (selectDirectories entry) $+ put =<< liftIO (setWorkingDirectory (fileInfoFilePath entry) b) selectCurrentEntry :: EventM n (FileBrowser n) () selectCurrentEntry = do b <- get- case fileBrowserCursor b of- Nothing -> return ()- Just e -> fileBrowserSelectedFilesL %= Set.insert (fileInfoFilename e)+ for_ (fileBrowserCursor b) markSelected -- | Render a file browser. This renders a list of entries in the -- working directory, a cursor to select from among the entries, a@@ -765,7 +753,7 @@ -- ^ The browser to render. -> Widget n renderFileBrowser foc b =- let maxFilenameLength = maximum $ (length . fileInfoFilename) <$> (b^.fileBrowserEntriesL)+ let maxFilenameLength = maximum $ length . fileInfoFilename <$> (b^.fileBrowserEntriesL) cwdHeader = padRight Max $ str $ sanitizeFilename $ fileBrowserWorkingDirectory b selInfo = case listSelectedElement (b^.fileBrowserEntriesL) of@@ -789,7 +777,7 @@ then ", " <> prettyFileSize (fileStatusSize stat) else "" in fileTypeLabel (fileStatusFileType stat) <> maybeSize- in txt $ (T.pack $ fileInfoSanitizedFilename i) <> ": " <> label+ in txt $ T.pack (fileInfoSanitizedFilename i) <> ": " <> label maybeSearchInfo = case b^.fileBrowserSearchStringL of Nothing -> emptyWidget