reflex-vty 0.2.0.1 → 0.3.0.0
raw patch · 3 files changed
+52/−8 lines, 3 filesdep ~vty
Dependency ranges changed: vty
Files
- ChangeLog.md +8/−0
- reflex-vty.cabal +2/−2
- src/Reflex/Vty/Widget/Input/Text.hs +42/−6
ChangeLog.md view
@@ -1,5 +1,13 @@ # Revision history for reflex-vty +## 0.3.0.0++* Re-design `textInput`, `TextInput` and `TextInputConfig`.+ * Allows users to implement more complex behavior.+ * `_textInputConfig_modify` is now applied to the text-value of `textInput`+ after user input events such as mouse clicks and keyboard input.+ This may change the observable behavior.+ ## 0.2.0.1 * Loosen version bounds on ref-tf and vty
reflex-vty.cabal view
@@ -1,5 +1,5 @@ name: reflex-vty-version: 0.2.0.1+version: 0.3.0.0 synopsis: Reflex FRP host and widgets for VTY applications description: Build terminal applications using functional reactive programming (FRP) with Reflex FRP (<https://reflex-frp.org>).@@ -56,7 +56,7 @@ ref-tf >= 0.4.0 && < 0.6, reflex >= 0.8 && < 0.9, time >= 1.8.0 && < 1.10,- vty >= 5.28 && < 5.37+ vty >= 5.28 && < 5.34 hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall
src/Reflex/Vty/Widget/Input/Text.hs view
@@ -10,6 +10,7 @@ import Control.Monad (join) import Control.Monad.Fix (MonadFix) import Data.Default (Default(..))+import Data.Function ((&)) import Data.Text (Text) import Data.Text.Zipper import qualified Graphics.Vty as V@@ -23,7 +24,29 @@ -- 'TextZipper', see 'Data.Text.Zipper'. data TextInputConfig t = TextInputConfig { _textInputConfig_initialValue :: TextZipper+ -- ^ Initial value. This is a 'TextZipper' because it is more flexible+ -- than plain 'Text'. For example, this allows to set the Cursor position,+ -- by choosing appropriate values for '_textZipper_before' and '_textZipper_after'. , _textInputConfig_modify :: Event t (TextZipper -> TextZipper)+ -- ^ Event to update the value of the 'textInput'.+ --+ -- Event is applied after other Input sources have been applied to the 'TextZipper',+ -- thus you may modify the final value that is displayed to the user.+ --+ -- You may set the value of the displayed text in 'textInput' by ignoring the input parameter.+ --+ -- Additionally, you can modify the updated value before displaying it to the user.+ -- For example, the following 'TextInputConfig' inserts an additional 'a'+ -- when the letter 'b' is entered into 'textInput':+ --+ -- @+ -- i <- input+ -- textInput def+ -- { _textInputConfig_modify = fforMaybe i $ \case+ -- V.EvKey (V.KChar 'b') _ -> Just (insert "a")+ -- _ -> Nothing+ -- }+ -- @ , _textInputConfig_tabWidth :: Int , _textInputConfig_display :: Dynamic t (Char -> Char) -- ^ Transform the characters in a text input before displaying them. This is useful, e.g., for@@ -38,6 +61,11 @@ -- display lines may not be visible due to scrolling. data TextInput t = TextInput { _textInput_value :: Dynamic t Text+ -- ^ The current value of the textInput as Text.+ , _textInput_userInput :: Event t TextZipper+ -- ^ UI Event updates with the current 'TextZipper'.+ -- This does not include Events added by '_textInputConfig_setValue', but+ -- it does include '_textInputConfig_modify' Events. , _textInput_lines :: Dynamic t Int } @@ -53,12 +81,19 @@ dw <- displayWidth bt <- theme attr0 <- sample bt- rec v <- foldDyn ($) (_textInputConfig_initialValue cfg) $ mergeWith (.)- [ uncurry (updateTextZipper (_textInputConfig_tabWidth cfg)) <$> attach (current dh) i- , _textInputConfig_modify cfg- , let displayInfo = (,) <$> current rows <*> scrollTop- in ffor (attach displayInfo click) $ \((dl, st), MouseDown _ (mx, my) _) ->- goToDisplayLinePosition mx (st + my) dl+ rec+ -- we split up the events from vty and the one users provide to avoid cyclical+ -- update dependencies. This way, users may subscribe only to UI updates.+ let valueChangedByCaller = _textInputConfig_modify cfg+ let valueChangedByUI = mergeWith (.)+ [ uncurry (updateTextZipper (_textInputConfig_tabWidth cfg)) <$> attach (current dh) i+ , let displayInfo = (,) <$> current rows <*> scrollTop+ in ffor (attach displayInfo click) $ \((dl, st), MouseDown _ (mx, my) _) ->+ goToDisplayLinePosition mx (st + my) dl+ ]+ v <- foldDyn ($) (_textInputConfig_initialValue cfg) $ mergeWith (.)+ [ valueChangedByCaller+ , valueChangedByUI ] click <- mouseDown V.BLeft @@ -85,6 +120,7 @@ tellImages $ (\imgs st -> (:[]) . V.vertCat $ drop st imgs) <$> current img <*> scrollTop return $ TextInput { _textInput_value = value <$> v+ , _textInput_userInput = attachWith (&) (current v) valueChangedByUI , _textInput_lines = length . _displayLines_spans <$> rows }