packages feed

brick 1.3 → 1.4

raw patch · 6 files changed

+92/−59 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Brick.Widgets.Border: hBorderAttr :: AttrName
+ Brick.Widgets.Border: vBorderAttr :: AttrName
- Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1kuk a_a1kuY. Lens (Dialog a_a1kuk) (Dialog a_a1kuY) [(String, a_a1kuk)] [(String, a_a1kuY)]
+ Brick.Widgets.Dialog: dialogButtonsL :: forall a_a1kqd a_a1kqR. Lens (Dialog a_a1kqd) (Dialog a_a1kqR) [(String, a_a1kqd)] [(String, a_a1kqR)]
- Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1kuk. Lens' (Dialog a_a1kuk) (Maybe Int)
+ Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1kqd. Lens' (Dialog a_a1kqd) (Maybe Int)
- Brick.Widgets.Dialog: dialogTitleL :: forall a_a1kuk. Lens' (Dialog a_a1kuk) (Maybe String)
+ Brick.Widgets.Dialog: dialogTitleL :: forall a_a1kqd. Lens' (Dialog a_a1kqd) (Maybe String)
- Brick.Widgets.Dialog: dialogWidthL :: forall a_a1kuk. Lens' (Dialog a_a1kuk) Int
+ Brick.Widgets.Dialog: dialogWidthL :: forall a_a1kqd. Lens' (Dialog a_a1kqd) Int
- Brick.Widgets.Edit: editContentsL :: forall t_a1elU n_a1elV t_a1emz. Lens (Editor t_a1elU n_a1elV) (Editor t_a1emz n_a1elV) (TextZipper t_a1elU) (TextZipper t_a1emz)
+ Brick.Widgets.Edit: editContentsL :: forall t_a1ec9 n_a1eca t_a1ecO. Lens (Editor t_a1ec9 n_a1eca) (Editor t_a1ecO n_a1eca) (TextZipper t_a1ec9) (TextZipper t_a1ecO)
- Brick.Widgets.FileBrowser: fileBrowserEntriesG :: forall n_a1w2j. SimpleGetter (FileBrowser n_a1w2j) (List n_a1w2j FileInfo)
+ Brick.Widgets.FileBrowser: fileBrowserEntriesG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (List n_a1vYc FileInfo)
- Brick.Widgets.FileBrowser: fileBrowserEntryFilterG :: forall n_a1w2j. SimpleGetter (FileBrowser n_a1w2j) (Maybe (FileInfo -> Bool))
+ Brick.Widgets.FileBrowser: fileBrowserEntryFilterG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (Maybe (FileInfo -> Bool))
- Brick.Widgets.FileBrowser: fileBrowserExceptionG :: forall n_a1w2j. SimpleGetter (FileBrowser n_a1w2j) (Maybe IOException)
+ Brick.Widgets.FileBrowser: fileBrowserExceptionG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (Maybe IOException)
- Brick.Widgets.FileBrowser: fileBrowserLatestResultsG :: forall n_a1w2j. SimpleGetter (FileBrowser n_a1w2j) [FileInfo]
+ Brick.Widgets.FileBrowser: fileBrowserLatestResultsG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) [FileInfo]
- Brick.Widgets.FileBrowser: fileBrowserNameG :: forall n_a1w2j. SimpleGetter (FileBrowser n_a1w2j) n_a1w2j
+ Brick.Widgets.FileBrowser: fileBrowserNameG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) n_a1vYc
- Brick.Widgets.FileBrowser: fileBrowserSearchStringG :: forall n_a1w2j. SimpleGetter (FileBrowser n_a1w2j) (Maybe Text)
+ Brick.Widgets.FileBrowser: fileBrowserSearchStringG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (Maybe Text)
- Brick.Widgets.FileBrowser: fileBrowserSelectableG :: forall n_a1w2j. SimpleGetter (FileBrowser n_a1w2j) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (FileInfo -> Bool)
- Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1w2j. Lens' (FileBrowser n_a1w2j) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1vYc. Lens' (FileBrowser n_a1vYc) (FileInfo -> Bool)
- Brick.Widgets.FileBrowser: fileBrowserSelectedFilesG :: forall n_a1w2j. SimpleGetter (FileBrowser n_a1w2j) (Set String)
+ Brick.Widgets.FileBrowser: fileBrowserSelectedFilesG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) (Set String)
- Brick.Widgets.FileBrowser: fileBrowserWorkingDirectoryG :: forall n_a1w2j. SimpleGetter (FileBrowser n_a1w2j) FilePath
+ Brick.Widgets.FileBrowser: fileBrowserWorkingDirectoryG :: forall n_a1vYc. SimpleGetter (FileBrowser n_a1vYc) FilePath
- Brick.Widgets.List: listElementsL :: forall n_a1qvG t_a1qvH e_a1qvI t_a1qKS e_a1qKT. Lens (GenericList n_a1qvG t_a1qvH e_a1qvI) (GenericList n_a1qvG t_a1qKS e_a1qKT) (t_a1qvH e_a1qvI) (t_a1qKS e_a1qKT)
+ Brick.Widgets.List: listElementsL :: forall n_a1qrz t_a1qrA e_a1qrB t_a1qGL e_a1qGM. Lens (GenericList n_a1qrz t_a1qrA e_a1qrB) (GenericList n_a1qrz t_a1qGL e_a1qGM) (t_a1qrA e_a1qrB) (t_a1qGL e_a1qGM)
- Brick.Widgets.List: listItemHeightL :: forall n_a1qvG t_a1qvH e_a1qvI. Lens' (GenericList n_a1qvG t_a1qvH e_a1qvI) Int
+ Brick.Widgets.List: listItemHeightL :: forall n_a1qrz t_a1qrA e_a1qrB. Lens' (GenericList n_a1qrz t_a1qrA e_a1qrB) Int
- Brick.Widgets.List: listNameL :: forall n_a1qvG t_a1qvH e_a1qvI n_a1qKU. Lens (GenericList n_a1qvG t_a1qvH e_a1qvI) (GenericList n_a1qKU t_a1qvH e_a1qvI) n_a1qvG n_a1qKU
+ Brick.Widgets.List: listNameL :: forall n_a1qrz t_a1qrA e_a1qrB n_a1qGN. Lens (GenericList n_a1qrz t_a1qrA e_a1qrB) (GenericList n_a1qGN t_a1qrA e_a1qrB) n_a1qrz n_a1qGN
- Brick.Widgets.List: listSelectedL :: forall n_a1qvG t_a1qvH e_a1qvI. Lens' (GenericList n_a1qvG t_a1qvH e_a1qvI) (Maybe Int)
+ Brick.Widgets.List: listSelectedL :: forall n_a1qrz t_a1qrA e_a1qrB. Lens' (GenericList n_a1qrz t_a1qrA e_a1qrB) (Maybe Int)

Files

CHANGELOG.md view
@@ -2,6 +2,21 @@ Brick changelog --------------- +1.4+---++API changes:+* `Brick.Widgets.Border` got `hBorderAttr` and `vBorderAttr` for use by+  `hBorder` and `vBorder` respectively. The new attributes inherit from+  `borderAttr`, so applications that just specify `borderAttr` will not+  see any change in behavior for those specific border elements.++Performance improvements:+* `Brick.Widgets.Core.txt` had its performance improved. (thanks Fraser+  Tweedale)+* `Brick.Widgets.Core.hBox` and `vBox` had their performance improved.+  (thanks Fraser Tweedale)+ 1.3 --- @@ -47,7 +62,7 @@ you to update your programs. This section details the list of API changes in 1.0 that are likely to introduce breakage and how to deal with each one. You can also consult the demonstration-programs to see orking examples of the new API. For those+programs to see working examples of the new API. For those interested in a bit of discussion on the changes, see [this ticket](https://github.com/jtdaugherty/brick/issues/379). 
README.md view
@@ -86,12 +86,14 @@ | [`kpxhs`](https://github.com/akazukin5151/kpxhs) | An interactive [Keepass](https://github.com/keepassxreboot/keepassxc/) database viewer | | [`htyper`](https://github.com/Simon-Hostettler/htyper) | A typing speed test program | | [`ullekha`](https://github.com/ajithnn/ullekha) | An interactive terminal notes/todo app with file/redis persistence |+| [`mywork`](https://github.com/kquick/mywork) [[Hackage]](https://hackage.haskell.org/package/mywork) | A tool to keep track of the projects you are working on |  These third-party packages also extend `brick`:  | Project | Description | | ------- | ----------- | | [`brick-filetree`](https://github.com/ChrisPenner/brick-filetree) [[Hackage]](http://hackage.haskell.org/package/brick-filetree) | A widget for exploring a directory tree and selecting or flagging files and directories |+| [`brick-panes`](https://github.com/kquick/brick-panes) [[Hackage]](https://hackage.haskell.org/package/brick-panes) | A Brick overlay library providing composition and isolation of screen areas for TUI apps. |  Release Announcements / News ----------------------------
brick.cabal view
@@ -1,5 +1,5 @@ name:                brick-version:             1.3+version:             1.4 synopsis:            A declarative terminal user interface library description:   Write terminal user interfaces (TUIs) painlessly with 'brick'! You
programs/BorderDemo.hs view
@@ -73,6 +73,8 @@ borderMappings :: [(A.AttrName, V.Attr)] borderMappings =     [ (B.borderAttr,         V.yellow `on` V.black)+    , (B.vBorderAttr,        fg V.cyan)+    , (B.hBorderAttr,        fg V.magenta)     , (titleAttr,            fg V.cyan)     ] 
src/Brick/Widgets/Border.hs view
@@ -20,12 +20,17 @@    -- * Attribute names   , borderAttr+  , hBorderAttr+  , vBorderAttr    -- * Utility   , joinableBorder   ) where +#if !(MIN_VERSION_base(4,11,0))+import Data.Monoid ((<>))+#endif import Lens.Micro ((^.), (&), (.~), to) import Graphics.Vty (imageHeight, imageWidth) @@ -41,6 +46,14 @@ borderAttr :: AttrName borderAttr = attrName "border" +-- | The horizontal border attribute name. Inherits from 'borderAttr'.+hBorderAttr :: AttrName+hBorderAttr = borderAttr <> attrName "horizontal"++-- | The vertical border attribute name. Inherits from 'borderAttr'.+vBorderAttr :: AttrName+vBorderAttr = borderAttr <> attrName "vertical"+ -- | Draw the specified border element using the active border style -- using 'borderAttr'. --@@ -95,7 +108,8 @@              $ vLimit (middleResult^.imageL.to imageHeight + 2)              $ total --- | A horizontal border.  Fills all horizontal space.+-- | A horizontal border. Fills all horizontal space. Draws using+-- 'hBorderAttr'. hBorder :: Widget n hBorder =     withAttr borderAttr $ Widget Greedy Fixed $ do@@ -105,7 +119,8 @@       db <- dynBorderFromDirections (Edges False False True True)       let dynBorders = BM.insertH mempty (Run w db)                      $ BM.emptyCoordinates (Edges 0 0 0 (w-1))-      setDynBorders dynBorders $ render $ vLimit 1 $ fill (bsHorizontal bs)+      setDynBorders dynBorders $ render $ withAttr hBorderAttr+                               $ vLimit 1 $ fill (bsHorizontal bs)  -- | A horizontal border with a label placed in the center of the -- border. Fills all horizontal space.@@ -117,7 +132,8 @@       res <- render $ vLimit 1 label       render $ hBox [hBorder, Widget Fixed Fixed (return res), hBorder] --- | A vertical border.  Fills all vertical space.+-- | A vertical border. Fills all vertical space. Draws using+-- 'vBorderAttr'. vBorder :: Widget n vBorder =     withAttr borderAttr $ Widget Fixed Greedy $ do@@ -127,7 +143,8 @@       db <- dynBorderFromDirections (Edges True True False False)       let dynBorders = BM.insertV mempty (Run h db)                      $ BM.emptyCoordinates (Edges 0 (h-1) 0 0)-      setDynBorders dynBorders $ render $ hLimit 1 $ fill (bsVertical bs)+      setDynBorders dynBorders $ render $ withAttr vBorderAttr+                               $ hLimit 1 $ fill (bsVertical bs)  -- | Initialize a 'DynBorder'. It will be 'bsDraw'n and 'bsOffer'ing -- in the given directions to begin with, and accept join offers from
src/Brick/Widgets/Core.hs view
@@ -268,17 +268,6 @@ unrestricted :: Int unrestricted = 100000 --- | Take a substring capable of fitting into the number of specified--- columns. This function takes character column widths into--- consideration.-takeColumns :: Int -> String -> String-takeColumns _ "" = ""-takeColumns numCols (c:cs) =-    let w = V.safeWcwidth c-    in if w > numCols-       then []-       else c : takeColumns (numCols - w) cs- -- | Make a widget from a string, but wrap the words in the input's -- lines at the available width using the default wrapping settings. The -- input string should not contain escape sequences or carriage returns.@@ -296,9 +285,6 @@ strWrapWith :: WrapSettings -> String -> Widget n strWrapWith settings t = txtWrapWith settings $ T.pack t -safeTextWidth :: T.Text -> Int-safeTextWidth = V.safeWcswidth . T.unpack- -- | Make a widget from text, but wrap the words in the input's lines at -- the available width using the default wrapping settings. The input -- text should not contain escape sequences or carriage returns.@@ -322,15 +308,15 @@       case force theLines of           [] -> return emptyResult           multiple ->-              let maxLength = maximum $ safeTextWidth <$> multiple+              let maxLength = maximum $ textWidth <$> multiple                   padding = V.charFill (c^.attrL) ' ' (c^.availWidthL - maxLength) (length lineImgs)                   lineImgs = lineImg <$> multiple                   lineImg lStr = V.text' (c^.attrL)-                                   (lStr <> T.replicate (maxLength - safeTextWidth lStr) " ")+                                   (lStr <> T.replicate (maxLength - textWidth lStr) " ")               in return $ emptyResult & imageL .~ (V.horizCat [V.vertCat lineImgs, padding]) --- | Build a widget from a 'String'. Breaks newlines up and space-pads--- short lines out to the length of the longest line.+-- | Build a widget from a 'String'. Behaves the same as 'txt' when the+-- input contains multiple lines. -- -- The input string must not contain tab characters. If it does, -- interface corruption will result since the terminal will likely@@ -338,25 +324,10 @@ -- replace tabs with the appropriate number of spaces as desired. The -- input string should not contain escape sequences or carriage returns. str :: String -> Widget n-str s =-    Widget Fixed Fixed $ do-      c <- getContext-      let theLines = fixEmpty <$> (dropUnused . lines) s-          fixEmpty :: String -> String-          fixEmpty [] = " "-          fixEmpty l = l-          dropUnused l = takeColumns (availWidth c) <$> take (availHeight c) l-      case force theLines of-          [] -> return emptyResult-          [one] -> return $ emptyResult & imageL .~ (V.string (c^.attrL) one)-          multiple ->-              let maxLength = maximum $ V.safeWcswidth <$> multiple-                  lineImgs = lineImg <$> multiple-                  lineImg lStr = V.string (c^.attrL) (lStr ++ replicate (maxLength - V.safeWcswidth lStr) ' ')-              in return $ emptyResult & imageL .~ (V.vertCat lineImgs)+str = txt . T.pack --- | Build a widget from a 'T.Text' value. Behaves the same as 'str'--- when the input contains multiple lines.+-- | Build a widget from a 'T.Text' value. Breaks newlines up and+-- space-pads short lines out to the length of the longest line. -- -- The input string must not contain tab characters. If it does, -- interface corruption will result since the terminal will likely@@ -364,8 +335,45 @@ -- replace tabs with the appropriate number of spaces as desired. The -- input text should not contain escape sequences or carriage returns. txt :: T.Text -> Widget n-txt = str . T.unpack+txt s =+    -- Althoguh vty Image uses lazy Text internally, using lazy text at this+    -- level may not be an improvement.  Indeed it can be much worse, due+    -- the overhead of lazy Text being significant compared to the typically+    -- short string content used to compose UIs.+    Widget Fixed Fixed $ do+        c <- getContext+        let theLines = fixEmpty <$> (dropUnused . T.lines) s+            fixEmpty l = if T.null l then T.singleton ' ' else l+            dropUnused l = takeColumnsT (availWidth c) <$> take (availHeight c) l+        pure $ case theLines of+            [] -> emptyResult+            [one] -> emptyResult & imageL .~ (V.text' (c^.attrL) one)+            multiple ->+                let maxLength = maximum $ V.safeWctwidth <$> multiple+                    lineImgs = lineImg <$> multiple+                    lineImg lStr = V.text' (c^.attrL)+                        (lStr <> T.replicate (maxLength - V.safeWctwidth lStr) (T.singleton ' '))+                in emptyResult & imageL .~ (V.vertCat lineImgs) +-- | Take up to the given width, having regard to character width.+takeColumnsT :: Int -> T.Text -> T.Text+takeColumnsT w s = T.take (fst $ T.foldl' f (0,0) s) s+    where+    -- The accumulator value is (index in Text value, width of Text so far)+    f (i,z) c+        -- Width was previously exceeded; continue with same values.+        | z < 0                   = (i, z)+        -- Width exceeded.  Signal this with z = -1.  Index will no longer be+        -- incremented.+        --+        -- Why not short circuit (e.g. using foldlM construction)?+        -- Because in the typical case, the Either allocation costs exceed+        -- any benefits.  The pathological case, string length >> width, is+        -- probably rare.+        | z + V.safeWcwidth c > w = (i, -1)+        -- Width not yet exceeded.  Increment index and add character width.+        | otherwise               = (i + 1, z + V.safeWcwidth c)+ -- | Hyperlink the given widget to the specified URL. Not all terminal -- emulators support this. In those that don't, this should have no -- discernible effect.@@ -508,7 +516,6 @@                 , imagePrimary :: V.Image -> Int                 , imageSecondary :: V.Image -> Int                 , limitPrimary :: Int -> Widget n -> Widget n-                , limitSecondary :: Int -> Widget n -> Widget n                 , primaryWidgetSize :: Widget n -> Size                 , concatenatePrimary :: [V.Image] -> V.Image                 , concatenateSecondary :: [V.Image] -> V.Image@@ -534,7 +541,6 @@                 , imagePrimary = V.imageHeight                 , imageSecondary = V.imageWidth                 , limitPrimary = vLimit-                , limitSecondary = hLimit                 , primaryWidgetSize = vSize                 , concatenatePrimary = V.vertCat                 , concatenateSecondary = V.horizCat@@ -562,7 +568,6 @@                 , imagePrimary = V.imageWidth                 , imageSecondary = V.imageHeight                 , limitPrimary = hLimit-                , limitSecondary = vLimit                 , primaryWidgetSize = hSize                 , concatenatePrimary = V.horizCat                 , concatenateSecondary = V.vertCat@@ -639,18 +644,13 @@           (his, lows) = partition (\p -> (primaryWidgetSize br $ snd p) == Fixed)                         pairsIndexed -      let availPrimary = c^.(contextPrimary br)-          availSecondary = c^.(contextSecondary br)-           renderHi prim = do             remainingPrimary <- get-            result <- lift $ render $ limitPrimary br remainingPrimary-                                    $ limitSecondary br availSecondary-                                    $ cropToContext prim+            result <- lift $ render $ limitPrimary br remainingPrimary prim             result <$ (put $! remainingPrimary - (result^.imageL.(to $ imagePrimary br)))        (renderedHis, remainingPrimary) <--        runStateT (traverse (traverse renderHi) his) availPrimary+        runStateT (traverse (traverse renderHi) his) (c ^. contextPrimary br)        renderedLows <- case lows of           [] -> return []@@ -660,10 +660,7 @@                   primaries = replicate rest (primaryPerLow + 1) <>                               replicate (length ls - rest) primaryPerLow -              let renderLow ((i, prim), pri) =-                      (i,) <$> (render $ limitPrimary br pri-                                       $ limitSecondary br availSecondary-                                       $ cropToContext prim)+              let renderLow ((i, prim), pri) = (i,) <$> render (limitPrimary br pri prim)                if remainingPrimary > 0 then mapM renderLow (zip ls primaries) else return [] @@ -886,7 +883,7 @@ --                         , withAttr "highlight" (str b) --                         ] -----    render1 = renderA ("Brick", "fun")+--    render1 = renderA (\"Brick\", "fun") --    render2 = withAttr "warning" render1 -- @ --@@ -930,7 +927,7 @@ --                         , str " is " --                         , withAttr "highlight" (str b) ] -----    render1 = renderA ("Brick", "fun")+--    render1 = renderA (\"Brick\", "fun") --    render2 = withDefAttr "warning" render1 -- @ --