summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathanDaugherty <>2020-02-14 01:57:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2020-02-14 01:57:00 (GMT)
commitdfc30c1b8018cb76d43450ba1a165c76561a4a8f (patch)
treefa81419a910a132e3f18676fc46a89c6beb46fd2
parent5e684d92cdfcea57b5d80b750e7857812697e547 (diff)
version 0.52HEAD0.52master
-rw-r--r--CHANGELOG.md17
-rw-r--r--brick.cabal3
-rw-r--r--programs/BorderDemo.hs4
-rw-r--r--programs/CacheDemo.hs3
-rw-r--r--programs/FormDemo.hs3
-rw-r--r--programs/MarkupDemo.hs3
-rw-r--r--programs/MouseDemo.hs44
-rw-r--r--programs/TextWrapDemo.hs3
-rw-r--r--programs/ViewportScrollDemo.hs3
-rw-r--r--src/Brick/Forms.hs78
-rw-r--r--src/Brick/Themes.hs2
-rw-r--r--src/Brick/Types.hs8
-rw-r--r--src/Brick/Util.hs2
-rw-r--r--src/Brick/Widgets/Core.hs6
-rw-r--r--src/Brick/Widgets/FileBrowser.hs26
-rw-r--r--src/Brick/Widgets/Internal.hs2
-rw-r--r--src/Brick/Widgets/List.hs6
17 files changed, 148 insertions, 65 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea4849c..924624a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,23 @@
Brick changelog
---------------
+0.52
+----
+
+API changes:
+ * EventM now provides a MonadFail instance
+ * EventM now provides MonadMask, MonadCatch, and MonadThrow instances
+ (thanks Fraser Tweedale)
+
+Other changes:
+ * The FileBrowser now has support for vi-style bindings in addition to
+ its previous bindings. New bindings include:
+ * `j`/`k`: next/previous element
+ * `C-n`/`C-p`: page down/up
+ * `C-d`/`C-u`: half page down/up
+ * `g`: select first entry
+ * `G`: select last entry
+
0.51
----
diff --git a/brick.cabal b/brick.cabal
index 6f77794..dc52701 100644
--- a/brick.cabal
+++ b/brick.cabal
@@ -1,5 +1,5 @@
name: brick
-version: 0.51
+version: 0.52
synopsis: A declarative terminal user interface library
description:
Write terminal applications painlessly with 'brick'! You write an
@@ -118,6 +118,7 @@ library
data-clist >= 0.1,
directory >= 1.2.5.0,
dlist,
+ exceptions >= 0.10.0,
filepath,
containers >= 0.5.7,
microlens >= 0.3.0.0,
diff --git a/programs/BorderDemo.hs b/programs/BorderDemo.hs
index 983f1d0..c2ba5b2 100644
--- a/programs/BorderDemo.hs
+++ b/programs/BorderDemo.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
@@ -5,7 +6,10 @@ module Main where
import Control.Applicative ((<$>))
#endif
+#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
+#endif
+
import qualified Data.Text as T
import qualified Graphics.Vty as V
diff --git a/programs/CacheDemo.hs b/programs/CacheDemo.hs
index 2581716..19f7ffc 100644
--- a/programs/CacheDemo.hs
+++ b/programs/CacheDemo.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
@@ -6,7 +7,9 @@ import Control.Applicative
#endif
import Control.Monad (void)
+#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
+#endif
import qualified Graphics.Vty as V
import qualified Brick.Types as T
diff --git a/programs/FormDemo.hs b/programs/FormDemo.hs
index 3a1209b..5f5bac4 100644
--- a/programs/FormDemo.hs
+++ b/programs/FormDemo.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
@@ -5,7 +6,9 @@ module Main where
import qualified Data.Text as T
import Lens.Micro ((^.))
import Lens.Micro.TH
+#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
+#endif
import qualified Graphics.Vty as V
import Brick
diff --git a/programs/MarkupDemo.hs b/programs/MarkupDemo.hs
index 0500579..1790e68 100644
--- a/programs/MarkupDemo.hs
+++ b/programs/MarkupDemo.hs
@@ -1,7 +1,10 @@
+{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
+#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
+#endif
import qualified Graphics.Vty as V
import Brick.Main (App(..), defaultMain, resizeOrQuit, neverShowCursor)
diff --git a/programs/MouseDemo.hs b/programs/MouseDemo.hs
index e06476d..cfeb144 100644
--- a/programs/MouseDemo.hs
+++ b/programs/MouseDemo.hs
@@ -1,12 +1,17 @@
+{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Main where
+#if !MIN_VERSION_base(4,8,0)
import Control.Applicative ((<$>))
+#endif
import Lens.Micro ((^.), (&), (.~), (%~))
import Lens.Micro.TH (makeLenses)
import Control.Monad (void)
+#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
+#endif
import qualified Graphics.Vty as V
import qualified Brick.Types as T
@@ -125,23 +130,24 @@ main = do
initialVty <- buildVty
void $ M.customMain initialVty buildVty Nothing app $ St [] Nothing
- "Try clicking on various UI elements.\n\
- \Observe that the click coordinates identify the\n\
- \underlying widget coordinates.\n\
- \\n\
- \Lorem ipsum dolor sit amet,\n\
- \consectetur adipiscing elit,\n\
- \sed do eiusmod tempor incididunt ut labore\n\
- \et dolore magna aliqua.\n\
- \ \n\
- \Ut enim ad minim veniam\n\
- \quis nostrud exercitation ullamco laboris\n\
- \nisi ut aliquip ex ea commodo consequat.\n\
- \\n\
- \Duis aute irure dolor in reprehenderit\n\
- \in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n\
- \\n\
- \Excepteur sint occaecat cupidatat not proident,\n\
- \sunt in culpa qui officia deserunt mollit\n\
- \anim id est laborum.\n"
+ (unlines [ "Try clicking on various UI elements."
+ , "Observe that the click coordinates identify the"
+ , "underlying widget coordinates."
+ , ""
+ , "Lorem ipsum dolor sit amet,"
+ , "consectetur adipiscing elit,"
+ , "sed do eiusmod tempor incididunt ut labore"
+ , "et dolore magna aliqua."
+ , ""
+ , "Ut enim ad minim veniam"
+ , "quis nostrud exercitation ullamco laboris"
+ , "isi ut aliquip ex ea commodo consequat."
+ , ""
+ , "Duis aute irure dolor in reprehenderit"
+ , "in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
+ , ""
+ , "Excepteur sint occaecat cupidatat not proident,"
+ , "sunt in culpa qui officia deserunt mollit"
+ , "anim id est laborum."
+ ])
(E.editor TextBox Nothing "")
diff --git a/programs/TextWrapDemo.hs b/programs/TextWrapDemo.hs
index 5853215..f69a81d 100644
--- a/programs/TextWrapDemo.hs
+++ b/programs/TextWrapDemo.hs
@@ -1,6 +1,9 @@
+{-# LANGUAGE CPP #-}
module Main where
+#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
+#endif
import Brick
import Text.Wrap (defaultWrapSettings, preserveIndentation)
diff --git a/programs/ViewportScrollDemo.hs b/programs/ViewportScrollDemo.hs
index 1cd992f..3d9c4e0 100644
--- a/programs/ViewportScrollDemo.hs
+++ b/programs/ViewportScrollDemo.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
@@ -6,7 +7,9 @@ import Control.Applicative
#endif
import Control.Monad (void)
+#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
+#endif
import qualified Graphics.Vty as V
import qualified Brick.Types as T
diff --git a/src/Brick/Forms.hs b/src/Brick/Forms.hs
index 9555fa4..887f268 100644
--- a/src/Brick/Forms.hs
+++ b/src/Brick/Forms.hs
@@ -5,7 +5,11 @@
{-# LANGUAGE ScopedTypeVariables #-}
-- | NOTE: This API is experimental and will probably change. Please try
-- it out! Feedback is very much appreciated, and your patience in the
--- face of breaking API changes is also appreciated!
+-- face of breaking API changes is also appreciated! It's also worth
+-- bearing in mind that this API is designed to support a narrow range
+-- of use cases. If you find that you need more customization than this
+-- offers, then you will need to consider building your own layout and
+-- event handling for input fields.
--
-- For a fuller introduction to this API, see the "Input Forms" section
-- of the Brick User Guide. Also see the demonstration programs for
@@ -19,10 +23,6 @@
-- user when a form field's value is invalid, and stores valid inputs in
-- your data type when possible.
--
--- This module provides the API to create forms, populate them with some
--- basic input field types, render forms, handle form events, and create
--- custom input field types.
---
-- A form has both a visual representation and a corresponding data
-- structure representing the latest valid values for that form
-- (referred to as the "state" of the form). A 'FormField' is a single
@@ -91,7 +91,6 @@ import Data.Vector (Vector)
import Brick
import Brick.Focus
-import Brick.Widgets.Core (showCursor)
import Brick.Widgets.Edit
import Brick.Widgets.List
import qualified Data.Text.Zipper as Z
@@ -113,9 +112,9 @@ import Lens.Micro
-- * @e@ - your application's event type
-- * @n@ - your application's resource name type
data FormField a b e n =
- FormField { formFieldName :: n
+ FormField { formFieldName :: n
-- ^ The name identifying this form field.
- , formFieldValidate :: b -> Maybe a
+ , formFieldValidate :: b -> Maybe a
-- ^ A validation function converting this field's state
-- into a value of your choosing. @Nothing@ indicates a
-- validation failure. For example, this might validate
@@ -131,7 +130,7 @@ data FormField a b e n =
-- can be set with 'setFieldValid'. The value of this
-- field also affects the behavior of 'allFieldsValid' and
-- 'getInvalidFields'.
- , formFieldRender :: Bool -> b -> Widget n
+ , formFieldRender :: Bool -> b -> Widget n
-- ^ A function to render this form field. Parameters are
-- whether the field is currently focused, followed by the
-- field state.
@@ -166,11 +165,11 @@ data FormFieldState s e n where
-- the field collection. Note that this type is
-- existential. All form fields in the collection
-- must validate to this type.
- , formFieldLens :: Lens' s a
+ , formFieldLens :: Lens' s a
-- ^ A lens to extract and store a
-- successfully-validated form input back into
-- your form state.
- , formFields :: [FormField a b e n]
+ , formFields :: [FormField a b e n]
-- ^ The form fields, in order, that the user will
-- interact with to manipulate this state value.
, formFieldRenderHelper :: Widget n -> Widget n
@@ -195,10 +194,10 @@ data FormFieldState s e n where
-- * @n@ - your application's resource name type
data Form s e n =
Form { formFieldStates :: [FormFieldState s e n]
- , formFocus :: FocusRing n
+ , formFocus :: FocusRing n
-- ^ The focus ring for the form, indicating which form field
-- has input focus.
- , formState :: s
+ , formState :: s
-- ^ The current state of the form. Forms guarantee that only
-- valid inputs ever get stored in the state, and that after
-- each input event on a form field, if that field contains a
@@ -306,14 +305,14 @@ checkboxCustomField lb check rb stLens name label initialState =
handleEvent (VtyEvent (EvKey (KChar ' ') [])) s = return $ not s
handleEvent _ s = return s
- in FormFieldState { formFieldState = initVal
- , formFields = [ FormField name Just True
- (renderCheckbox lb check rb label name)
- handleEvent
- ]
- , formFieldLens = stLens
+ in FormFieldState { formFieldState = initVal
+ , formFields = [ FormField name Just True
+ (renderCheckbox lb check rb label name)
+ handleEvent
+ ]
+ , formFieldLens = stLens
, formFieldRenderHelper = id
- , formFieldConcat = vBox
+ , formFieldConcat = vBox
}
renderCheckbox :: Char -> Char -> Char -> T.Text -> n -> Bool -> Bool -> Widget n
@@ -360,14 +359,14 @@ listField options stLens renderItem itemHeight name initialState =
handleEvent (VtyEvent e) s = handleListEvent e s
handleEvent _ s = return s
- in FormFieldState { formFieldState = initVal
- , formFields = [ FormField name Just True
- (renderList renderItem)
- handleEvent
- ]
- , formFieldLens = customStLens
+ in FormFieldState { formFieldState = initVal
+ , formFields = [ FormField name Just True
+ (renderList renderItem)
+ handleEvent
+ ]
+ , formFieldLens = customStLens
, formFieldRenderHelper = id
- , formFieldConcat = vBox
+ , formFieldConcat = vBox
}
-- | A form field for selecting a single choice from a set of possible
-- choices. Each choice has an associated value and text label.
@@ -393,8 +392,11 @@ radioField = radioCustomField '[' '*' ']'
-- option and to mouse clicks.
radioCustomField :: (Ord n, Show n, Eq a)
=> Char
+ -- ^ Left bracket character.
-> Char
+ -- ^ Checkmark character.
-> Char
+ -- ^ Right bracket character.
-> Lens' s a
-- ^ The state lens for this value.
-> [(a, n, T.Text)]
@@ -427,11 +429,11 @@ radioCustomField lb check rb stLens options initialState =
(renderRadio lb check rb val name label)
(handleEvent val)
- in FormFieldState { formFieldState = initVal
- , formFields = optionFields
- , formFieldLens = stLens
+ in FormFieldState { formFieldState = initVal
+ , formFields = optionFields
+ , formFieldLens = stLens
, formFieldRenderHelper = id
- , formFieldConcat = vBox
+ , formFieldConcat = vBox
}
renderRadio :: (Eq a) => Char -> Char -> Char -> a -> n -> T.Text -> Bool -> a -> Widget n
@@ -490,13 +492,13 @@ editField stLens n limit ini val renderText wrapEditor initialState =
handleEvent _ ed = return ed
in FormFieldState { formFieldState = initVal
- , formFields = [ FormField n
- (val . getEditContents)
- True
- (\b e -> wrapEditor $ renderEditor renderText b e)
- handleEvent
- ]
- , formFieldLens = stLens
+ , formFields = [ FormField n
+ (val . getEditContents)
+ True
+ (\b e -> wrapEditor $ renderEditor renderText b e)
+ handleEvent
+ ]
+ , formFieldLens = stLens
, formFieldRenderHelper = id
, formFieldConcat = vBox
}
diff --git a/src/Brick/Themes.hs b/src/Brick/Themes.hs
index adba54a..c954c74 100644
--- a/src/Brick/Themes.hs
+++ b/src/Brick/Themes.hs
@@ -89,7 +89,9 @@ import Data.Tuple (swap)
import Data.List (intercalate)
import Data.Bits ((.|.), (.&.))
import Data.Maybe (fromMaybe, isNothing, catMaybes, mapMaybe)
+#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
+#endif
import qualified Data.Foldable as F
import Data.Ini.Config
diff --git a/src/Brick/Types.hs b/src/Brick/Types.hs
index 6220623..547a3e1 100644
--- a/src/Brick/Types.hs
+++ b/src/Brick/Types.hs
@@ -88,6 +88,10 @@ import Data.Monoid (Monoid(..))
import Lens.Micro (_1, _2, to, (^.), (&), (.~), Lens')
import Lens.Micro.Type (Getting)
+import Control.Monad.Catch (MonadThrow, MonadCatch, MonadMask)
+#if !MIN_VERSION_base(4,13,0)
+import Control.Monad.Fail (MonadFail)
+#endif
import Control.Monad.Trans.State.Lazy
import Control.Monad.Trans.Reader
import Graphics.Vty (Attr)
@@ -128,7 +132,9 @@ handleEventLensed v target handleEvent ev = do
newtype EventM n a =
EventM { runEventM :: ReaderT (EventRO n) (StateT (EventState n) IO) a
}
- deriving (Functor, Applicative, Monad, MonadIO)
+ deriving ( Functor, Applicative, Monad, MonadIO
+ , MonadThrow, MonadCatch, MonadMask, MonadFail
+ )
-- | Widget size policies. These policies communicate how a widget uses
-- space when being rendered. These policies influence rendering order
diff --git a/src/Brick/Util.hs b/src/Brick/Util.hs
index a129c7c..76571db 100644
--- a/src/Brick/Util.hs
+++ b/src/Brick/Util.hs
@@ -9,7 +9,9 @@ module Brick.Util
where
import Lens.Micro ((&), (%~))
+#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
+#endif
import Graphics.Vty
import Brick.Types.Internal (Location(..), CursorLocation(..), cursorLocationL)
diff --git a/src/Brick/Widgets/Core.hs b/src/Brick/Widgets/Core.hs
index 5dea18b..b4dbabd 100644
--- a/src/Brick/Widgets/Core.hs
+++ b/src/Brick/Widgets/Core.hs
@@ -91,9 +91,11 @@ module Brick.Widgets.Core
)
where
-#if MIN_VERSION_base(4,8,0)
+#if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>))
-#else
+#endif
+
+#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
import Data.Monoid ((<>), mempty)
#endif
diff --git a/src/Brick/Widgets/FileBrowser.hs b/src/Brick/Widgets/FileBrowser.hs
index 27169ca..594ed01 100644
--- a/src/Brick/Widgets/FileBrowser.hs
+++ b/src/Brick/Widgets/FileBrowser.hs
@@ -53,6 +53,7 @@ module Brick.Widgets.FileBrowser
, FileInfo(..)
, FileStatus(..)
, FileType(..)
+
-- * Making a new file browser
, newFileBrowser
, selectNonDirectories
@@ -598,6 +599,31 @@ handleFileBrowserEventNormal e b =
handleFileBrowserEventCommon :: (Ord n) => Vty.Event -> FileBrowser n -> EventM n (FileBrowser n)
handleFileBrowserEventCommon e b =
case e of
+ Vty.EvKey (Vty.KChar 'b') [Vty.MCtrl] -> do
+ let old = b ^. fileBrowserEntriesL
+ new <- listMovePageUp old
+ return $ b & fileBrowserEntriesL .~ new
+ Vty.EvKey (Vty.KChar 'f') [Vty.MCtrl] -> do
+ let old = b ^. fileBrowserEntriesL
+ new <- listMovePageDown old
+ return $ b & fileBrowserEntriesL .~ new
+ Vty.EvKey (Vty.KChar 'd') [Vty.MCtrl] -> do
+ let old = b ^. fileBrowserEntriesL
+ new <- listMoveByPages (0.5::Double) old
+ return $ b & fileBrowserEntriesL .~ new
+ Vty.EvKey (Vty.KChar 'u') [Vty.MCtrl] -> do
+ let old = b ^. fileBrowserEntriesL
+ new <- listMoveByPages (-0.5::Double) old
+ return $ b & fileBrowserEntriesL .~ new
+ Vty.EvKey (Vty.KChar 'g') [] ->
+ return $ b & fileBrowserEntriesL %~ listMoveTo 0
+ Vty.EvKey (Vty.KChar 'G') [] -> do
+ let sz = length (listElements $ b^.fileBrowserEntriesL)
+ return $ b & fileBrowserEntriesL %~ listMoveTo (sz - 1)
+ Vty.EvKey (Vty.KChar 'j') [] ->
+ return $ b & fileBrowserEntriesL %~ listMoveBy 1
+ Vty.EvKey (Vty.KChar 'k') [] ->
+ return $ b & fileBrowserEntriesL %~ listMoveBy (-1)
Vty.EvKey (Vty.KChar 'n') [Vty.MCtrl] ->
return $ b & fileBrowserEntriesL %~ listMoveBy 1
Vty.EvKey (Vty.KChar 'p') [Vty.MCtrl] ->
diff --git a/src/Brick/Widgets/Internal.hs b/src/Brick/Widgets/Internal.hs
index e755a56..335e777 100644
--- a/src/Brick/Widgets/Internal.hs
+++ b/src/Brick/Widgets/Internal.hs
@@ -21,7 +21,7 @@ import Brick.Types
import Brick.Types.Internal
import Brick.AttrMap
import Brick.Widgets.Border.Style
-import Brick.BorderMap (BorderMap, Edges(..))
+import Brick.BorderMap (BorderMap)
import qualified Brick.BorderMap as BM
renderFinal :: AttrMap
diff --git a/src/Brick/Widgets/List.hs b/src/Brick/Widgets/List.hs
index 13726af..4bdd384 100644
--- a/src/Brick/Widgets/List.hs
+++ b/src/Brick/Widgets/List.hs
@@ -461,9 +461,9 @@ listMoveUp :: (Foldable t, Splittable t)
listMoveUp = listMoveBy (-1)
-- | Move the list selected index up by one page.
-listMovePageUp
- :: (Foldable t, Splittable t, Ord n)
- => GenericList n t e -> EventM n (GenericList n t e)
+listMovePageUp :: (Foldable t, Splittable t, Ord n)
+ => GenericList n t e
+ -> EventM n (GenericList n t e)
listMovePageUp = listMoveByPages (-1::Double)
-- | Move the list selected index down by one. (Moves the cursor down,