brick 0.47.1 → 0.48
raw patch · 6 files changed
+80/−28 lines, 6 filesdep +bytestringdep ~basePVP ok
version bump matches the API change (PVP)
Dependencies added: bytestring
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Brick.Widgets.Edit: class DecodeUtf8 t
+ Brick.Widgets.Edit: decodeUtf8 :: DecodeUtf8 t => ByteString -> Either String t
+ Brick.Widgets.Edit: instance Brick.Widgets.Edit.DecodeUtf8 Data.Text.Internal.Text
+ Brick.Widgets.Edit: instance Brick.Widgets.Edit.DecodeUtf8 GHC.Base.String
- Brick.BorderMap: eBottomL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
+ Brick.BorderMap: eBottomL :: forall a_aj4I. Lens' (Edges a_aj4I) a_aj4I
- Brick.BorderMap: eLeftL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
+ Brick.BorderMap: eLeftL :: forall a_aj4I. Lens' (Edges a_aj4I) a_aj4I
- Brick.BorderMap: eRightL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
+ Brick.BorderMap: eRightL :: forall a_aj4I. Lens' (Edges a_aj4I) a_aj4I
- Brick.BorderMap: eTopL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
+ Brick.BorderMap: eTopL :: forall a_aj4I. Lens' (Edges a_aj4I) a_aj4I
- Brick.Types: bordersL :: forall n_aGiC. Lens' (Result n_aGiC) (BorderMap DynBorder)
+ Brick.Types: bordersL :: forall n_aGiM. Lens' (Result n_aGiM) (BorderMap DynBorder)
- Brick.Types: cursorLocationL :: forall n_aEXd. Lens' (CursorLocation n_aEXd) Location
+ Brick.Types: cursorLocationL :: forall n_aEXn. Lens' (CursorLocation n_aEXn) Location
- Brick.Types: cursorLocationNameL :: forall n_aEXd n_aGVO. Lens (CursorLocation n_aEXd) (CursorLocation n_aGVO) (Maybe n_aEXd) (Maybe n_aGVO)
+ Brick.Types: cursorLocationNameL :: forall n_aEXn n_aGVY. Lens (CursorLocation n_aEXn) (CursorLocation n_aGVY) (Maybe n_aEXn) (Maybe n_aGVY)
- Brick.Types: cursorsL :: forall n_aGiC. Lens' (Result n_aGiC) [CursorLocation n_aGiC]
+ Brick.Types: cursorsL :: forall n_aGiM. Lens' (Result n_aGiM) [CursorLocation n_aGiM]
- Brick.Types: eBottomL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
+ Brick.Types: eBottomL :: forall a_aj4I. Lens' (Edges a_aj4I) a_aj4I
- Brick.Types: eLeftL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
+ Brick.Types: eLeftL :: forall a_aj4I. Lens' (Edges a_aj4I) a_aj4I
- Brick.Types: eRightL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
+ Brick.Types: eRightL :: forall a_aj4I. Lens' (Edges a_aj4I) a_aj4I
- Brick.Types: eTopL :: forall a_aj4y. Lens' (Edges a_aj4y) a_aj4y
+ Brick.Types: eTopL :: forall a_aj4I. Lens' (Edges a_aj4I) a_aj4I
- Brick.Types: extentsL :: forall n_aGiC. Lens' (Result n_aGiC) [Extent n_aGiC]
+ Brick.Types: extentsL :: forall n_aGiM. Lens' (Result n_aGiM) [Extent n_aGiM]
- Brick.Types: imageL :: forall n_aGiC. Lens' (Result n_aGiC) Image
+ Brick.Types: imageL :: forall n_aGiM. Lens' (Result n_aGiM) Image
- Brick.Types: visibilityRequestsL :: forall n_aGiC. Lens' (Result n_aGiC) [VisibilityRequest]
+ Brick.Types: visibilityRequestsL :: forall n_aGiM. Lens' (Result n_aGiM) [VisibilityRequest]
- 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: dialogButtonsL :: forall a_a1gDk a_a1gE1. Lens (Dialog a_a1gDk) (Dialog a_a1gE1) [(String, a_a1gDk)] [(String, a_a1gE1)]
- Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1gjc. Lens' (Dialog a_a1gjc) (Maybe Int)
+ Brick.Widgets.Dialog: dialogSelectedIndexL :: forall a_a1gDk. Lens' (Dialog a_a1gDk) (Maybe Int)
- Brick.Widgets.Dialog: dialogTitleL :: forall a_a1gjc. Lens' (Dialog a_a1gjc) (Maybe String)
+ Brick.Widgets.Dialog: dialogTitleL :: forall a_a1gDk. Lens' (Dialog a_a1gDk) (Maybe String)
- Brick.Widgets.Dialog: dialogWidthL :: forall a_a1gjc. Lens' (Dialog a_a1gjc) Int
+ Brick.Widgets.Dialog: dialogWidthL :: forall a_a1gDk. Lens' (Dialog a_a1gDk) Int
- 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.Edit: editContentsL :: forall t_a1bxN n_a1bxO t_a1byx. Lens (Editor t_a1bxN n_a1bxO) (Editor t_a1byx n_a1bxO) (TextZipper t_a1bxN) (TextZipper t_a1byx)
- Brick.Widgets.Edit: handleEditorEvent :: (Eq t, Monoid t) => Event -> Editor t n -> EventM n (Editor t n)
+ Brick.Widgets.Edit: handleEditorEvent :: (DecodeUtf8 t, Eq t, Monoid t) => Event -> Editor t n -> EventM n (Editor t n)
- Brick.Widgets.FileBrowser: fileBrowserEntryFilterL :: forall n_a1qMp. Lens' (FileBrowser n_a1qMp) (Maybe (FileInfo -> Bool))
+ Brick.Widgets.FileBrowser: fileBrowserEntryFilterL :: forall n_a1r6u. Lens' (FileBrowser n_a1r6u) (Maybe (FileInfo -> Bool))
- Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1qMp. Lens' (FileBrowser n_a1qMp) (FileInfo -> Bool)
+ Brick.Widgets.FileBrowser: fileBrowserSelectableL :: forall n_a1r6u. Lens' (FileBrowser n_a1r6u) (FileInfo -> Bool)
- 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: listElementsL :: forall n_a1lJR t_a1lJS e_a1lJT t_a1lYr e_a1lYs. Lens (GenericList n_a1lJR t_a1lJS e_a1lJT) (GenericList n_a1lJR t_a1lYr e_a1lYs) (t_a1lJS e_a1lJT) (t_a1lYr e_a1lYs)
- Brick.Widgets.List: listItemHeightL :: forall n_a1lpL t_a1lpM e_a1lpN. Lens' (GenericList n_a1lpL t_a1lpM e_a1lpN) Int
+ Brick.Widgets.List: listItemHeightL :: forall n_a1lJR t_a1lJS e_a1lJT. Lens' (GenericList n_a1lJR t_a1lJS e_a1lJT) Int
- 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: listNameL :: forall n_a1lJR t_a1lJS e_a1lJT n_a1lYt. Lens (GenericList n_a1lJR t_a1lJS e_a1lJT) (GenericList n_a1lYt t_a1lJS e_a1lJT) n_a1lJR n_a1lYt
- Brick.Widgets.List: listSelectedL :: forall n_a1lpL t_a1lpM e_a1lpN. Lens' (GenericList n_a1lpL t_a1lpM e_a1lpN) (Maybe Int)
+ Brick.Widgets.List: listSelectedL :: forall n_a1lJR t_a1lJS e_a1lJT. Lens' (GenericList n_a1lJR t_a1lJS e_a1lJT) (Maybe Int)
Files
- CHANGELOG.md +14/−0
- README.md +18/−18
- brick.cabal +2/−1
- src/Brick/Types.hs +10/−7
- src/Brick/Widgets/Core.hs +10/−1
- src/Brick/Widgets/Edit.hs +26/−1
CHANGELOG.md view
@@ -2,6 +2,20 @@ Brick changelog --------------- +0.48+----++New features:+ * The `Edit` widget now supports `EvPaste` Vty events by default,+ assuming UTF-8 encoding of pasted bytes. If pasted bytes are not+ UTF-8-decodable, the pastes will be ignored. In any case, users can+ still intercept `EvPaste` events as before and handle them as desired+ if the default behavior is not desirable.++Other changes:+ * `txtWrapWith` now always pads its output to the available width to+ obey its `Greedy` requirement.+ 0.47.1 ------
README.md view
@@ -43,24 +43,24 @@ To get an idea of what some people have done with `brick`, take a look at these projects: - * `tetris`, an implementation of the Tetris game: https://github.com/SamTay/tetris- * `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- * `viewprof`, a GHC profile viewer: https://github.com/maoe/viewprof- * `tart`, a mouse-driven ASCII art drawing program: https://github.com/jtdaugherty/tart- * `silly-joy`, an interpreter for Joy: https://github.com/rootmos/silly-joy- * `herms`, a command-line tool for managing kitchen recipes: https://github.com/jackkiefer/herms- * `purebred`, a mail user agent: https://github.com/purebred-mua/purebred- * `2048Haskell`, an implementation of the 2048 game: https://github.com/8Gitbrix/2048Haskell- * `bhoogle`, a [Hoogle](https://www.haskell.org/hoogle/) client: https://github.com/andrevdm/bhoogle- * `clifm`, a file manager: https://github.com/pasqu4le/clifm- * `towerHanoi`, animated solutions to The Tower of Hanoi: https://github.com/shajenM/projects/tree/master/towerHanoi- * `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+ * [`tetris`](https://github.com/SamTay/tetris), an implementation of the Tetris game+ * [`gotta-go-fast`](https://github.com/callum-oakley/gotta-go-fast), a typing tutor+ * [`haskell-player`](https://github.com/potomak/haskell-player), an `afplay` frontend+ * [`mushu`](https://github.com/elaye/mushu), an `MPD` client+ * [`matterhorn`](https://github.com/matterhorn-chat/matterhorn), a client for [Mattermost](https://about.mattermost.com/)+ * [`viewprof`](https://github.com/maoe/viewprof), a GHC profile viewer+ * [`tart`](https://github.com/jtdaugherty/tart), a mouse-driven ASCII art drawing program+ * [`silly-joy`](https://github.com/rootmos/silly-joy), an interpreter for Joy+ * [`herms`](https://github.com/jackkiefer/herms), a command-line tool for managing kitchen recipes+ * [`purebred`](https://github.com/purebred-mua/purebred), a mail user agent+ * [`2048Haskell`](https://github.com/8Gitbrix/2048Haskell), an implementation of the 2048 game+ * [`bhoogle`](https://github.com/andrevdm/bhoogle), a [Hoogle](https://www.haskell.org/hoogle/) client+ * [`clifm`](https://github.com/pasqu4le/clifm), a file manager+ * [`towerHanoi`](https://github.com/shajenM/projects/tree/master/towerHanoi), animated solutions to The Tower of Hanoi+ * [`VOIDSPACE`](https://github.com/ChrisPenner/void-space), a space-themed typing-tutor game+ * [`solitaire`](https://github.com/ambuc/solitaire), the card game+ * [`sudoku-tui`](https://github.com/evanrelf/sudoku-tui), a Sudoku implementation+ * [`summoner-tui`](https://github.com/kowainik/summoner/tree/master/summoner-tui), an interactive frontend to the Summoner tool These third-party packages also extend `brick`:
brick.cabal view
@@ -1,5 +1,5 @@ name: brick-version: 0.47.1+version: 0.48 synopsis: A declarative terminal user interface library description: Write terminal applications painlessly with 'brick'! You write an@@ -107,6 +107,7 @@ template-haskell, deepseq >= 1.3 && < 1.5, unix,+ bytestring, word-wrap >= 0.2 if impl(ghc < 8.0) build-depends: semigroups
src/Brick/Types.hs view
@@ -130,15 +130,18 @@ } deriving (Functor, Applicative, Monad, MonadIO) --- | Widget growth policies. These policies communicate to layout--- algorithms how a widget uses space when being rendered. These--- policies influence rendering order and space allocation in the box--- layout algorithm.+-- | Widget size policies. These policies communicate how a widget uses+-- space when being rendered. These policies influence rendering order+-- and space allocation in the box layout algorithm for 'hBox' and+-- 'vBox'. data Size = Fixed- -- ^ Fixed widgets take up the same amount of space no matter- -- how much they are given (non-greedy).+ -- ^ Widgets advertising this size policy should take up the+ -- same amount of space no matter how much they are given,+ -- i.e. their size depends on their contents alone rather than+ -- on the size of the rendering area. | Greedy- -- ^ Greedy widgets take up all the space they are given.+ -- ^ Widgets advertising this size policy must take up all the+ -- space they are given. deriving (Show, Eq, Ord) -- | The type of widgets.
src/Brick/Widgets/Core.hs view
@@ -243,12 +243,16 @@ -- | 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 escapes.+--+-- Unlike 'str', this is greedy horizontally. strWrap :: String -> Widget n strWrap = strWrapWith defaultWrapSettings -- | Make a widget from a string, but wrap the words in the input's -- lines at the available width using the specified wrapping settings. -- The input string should not contain escapes.+--+-- Unlike 'str', this is greedy horizontally. strWrapWith :: WrapSettings -> String -> Widget n strWrapWith settings t = txtWrapWith settings $ T.pack t @@ -258,12 +262,16 @@ -- | 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 escapes.+--+-- Unlike 'txt', this is greedy horizontally. txtWrap :: T.Text -> Widget n txtWrap = txtWrapWith defaultWrapSettings -- | Make a widget from text, but wrap the words in the input's lines at -- the available width using the specified wrapping settings. The input -- text should not contain escapes.+--+-- Unlike 'txt', this is greedy horizontally. txtWrapWith :: WrapSettings -> T.Text -> Widget n txtWrapWith settings s = Widget Greedy Fixed $ do@@ -276,10 +284,11 @@ [one] -> return $ emptyResult & imageL .~ (V.text' (c^.attrL) one) multiple -> let maxLength = maximum $ safeTextWidth <$> 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) " ")- in return $ emptyResult & imageL .~ (V.vertCat lineImgs)+ 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.
src/Brick/Widgets/Edit.hs view
@@ -36,6 +36,8 @@ -- * Attributes , editAttr , editFocusedAttr+ -- * UTF-8 decoding of editor pastes+ , DecodeUtf8(..) ) where @@ -45,7 +47,9 @@ import Lens.Micro import Graphics.Vty (Event(..), Key(..), Modifier(..)) +import qualified Data.ByteString as BS import qualified Data.Text as T+import qualified Data.Text.Encoding as T import qualified Data.Text.Zipper as Z hiding ( textZipper ) import qualified Data.Text.Zipper.Generic as Z @@ -63,6 +67,8 @@ -- * Ctrl-u: delete all from cursor to beginning of line -- * Arrow keys: move cursor -- * Enter: break the current line at the cursor position+-- * Paste: Bracketed Pastes from the terminal will be pasted, provided+-- the incoming data is UTF-8-encoded. data Editor t n = Editor { editContents :: Z.TextZipper t -- ^ The contents of the editor@@ -83,9 +89,28 @@ instance Named (Editor t n) n where getName = editorName -handleEditorEvent :: (Eq t, Monoid t) => Event -> Editor t n -> EventM n (Editor t n)+-- | Values that can be constructed by decoding bytestrings in UTF-8+-- encoding.+class DecodeUtf8 t where+ -- | Decode a bytestring assumed to be text in UTF-8 encoding. If+ -- the decoding fails, return 'Left'. This must not raise+ -- exceptions.+ decodeUtf8 :: BS.ByteString -> Either String t++instance DecodeUtf8 T.Text where+ decodeUtf8 bs = case T.decodeUtf8' bs of+ Left e -> Left $ show e+ Right t -> Right t++instance DecodeUtf8 String where+ decodeUtf8 bs = T.unpack <$> decodeUtf8 bs++handleEditorEvent :: (DecodeUtf8 t, Eq t, Monoid t) => Event -> Editor t n -> EventM n (Editor t n) handleEditorEvent e ed = let f = case e of+ EvPaste bs -> case decodeUtf8 bs of+ Left _ -> id+ Right t -> Z.insertMany t EvKey (KChar 'a') [MCtrl] -> Z.gotoBOL EvKey (KChar 'e') [MCtrl] -> Z.gotoEOL EvKey (KChar 'd') [MCtrl] -> Z.deleteChar