Alex Scriba
Alex Scriba

Reputation: 105

Brick not exporting Next or continue

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

Answers (3)

coderSiddhant
coderSiddhant

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

Alex Scriba
Alex Scriba

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

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

Related Questions