Reputation: 105
I am attempting to build a CLI interface for a basic app using Haskell and the Brick package. In all examples I have seen (including the documentation), the handleEvent
function has the following type signature, in order to tell Brick to continue or stop execution after the state is updated:
AppState -> BrickEvent n e -> EventM n (Next AppState)
However, for me, my compiler is saying that Next
is not found (nor can I manually export it from the package it is meant to be in, Brick.Main
). The same is true for the continue
function used below.
Minimum reproducible problem:
Main.hs:
module Main where
import Brick.Main
import Brick.Types
import Graphics.Vty.Input.Events
data AppState = AppState deriving (Show, Eq)
handleEvent :: AppState -> BrickEvent n e -> EventM n (Next AppState)
handleEvent s e =
case e of
VtyEvent vtye ->
case vtye of
EvKey (KChar 'q') [] -> halt s
_ -> continue s
_ -> continue s
brick-test.cabal:
cabal-version: 2.4
name: brick-test
version: 0.1.0.0
author: AlexScriba
maintainer: [email protected]
extra-source-files: CHANGELOG.md
executable brick-test
main-is: Main.hs
build-depends:
base ^>=4.14.3.0,
brick >= 1.7,
vty
hs-source-dirs: app
default-language: Haskell2010
I have tried again in different projects and it seems not to work in any of them. Have also tried with different versions of brick.
Upvotes: 3
Views: 519
Reputation: 1
For brick-1.4, one of the easiest ways to use event handlers is to modify the current state into a new state. This can be achieved by using get
(just like what you'd do in previous versions). For example, if you have a string field and you want to edit the string, you can achieve it using the code below. Basically here, you can create a text box using this technique -
handleEvent :: BrickEvent n e -> EventM n AppState ()
handleEvent e = do
state <- get -- The current state
let currentExample = _example state
case e of
VtyEvent (EvKey (KChar 'q') [MCtrl]) -> halt
VtyEvent (EvKey (KChar c) []) ->
modify (\s -> AppState (currentExample ++ c)) -- append characters that are pressed
_other -> return ()
Upvotes: 0
Reputation: 105
Based on answers useful answers, the problem was that the approach above is based on outdated documentation. The latest versions use MonadState
to handle the state, recommending changing the state using lens
package.
The changed code (using microlens):
import Brick.Main
...
import Lens.Micro.Mtl (use, (.=))
import Lens.Micro.TH (makeLenses)
data AppState = AppState { _example :: String }
makeLenses ''AppState -- Make lens to 'example'
handleEvent :: BrickEvent n e -> EventM n AppState ()
handleEvent e = do
eg <- use example -- Use lens to get _example from state
example .= "New String" -- Set example field in state
case e of
VtyEvent vtye ->
case stye of
EvKey (KChar 'q') [] -> halt
_other -> return ()
_other -> return ()
Upvotes: 2
Reputation: 48572
You're looking at outdated documentation and examples. Look at the ones from the version of brick
you're using instead. Next
and continue
were removed from brick
in version 1.0. You now need a type like this for handleEvent
instead: BrickEvent n e -> EventM n AppState ()
. And instead of continue s
, you do return ()
now.
Upvotes: 6