1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
module Main where
import qualified Brick.AttrMap as A
import qualified Brick.Main as M
import Brick.Types (Widget)
import qualified Brick.Types as T
import Brick.Util (fg)
import Brick.Widgets.Core
( str,
vBox,
vLimit,
withAttr,
(<+>),
)
import qualified Brick.Widgets.List as L
import Control.Monad (void)
import Control.Monad.State (gets, modify)
import Data.Maybe (fromMaybe)
import qualified Data.Vector as Vec
import qualified Graphics.Vty as V
drawUI :: (Show a) => L.List () a -> [Widget ()]
drawUI l = [ui]
where
ui =
vBox
[ box,
vLimit 1 label
]
label = str "Item " <+> cur <+> str " of " <+> total
cur = case L.listSelected l of
Nothing -> str "-"
Just i -> str (show (i + 1))
total = str $ show $ Vec.length $ L.listElements l
box =
L.renderList listDrawElement True l
appEvent :: T.BrickEvent () e -> T.EventM () (L.List () Char) ()
appEvent (T.VtyEvent e) =
case e of
V.EvKey (V.KChar '+') [] -> do
els <- gets L.listElements
let el = nextElement els
pos = Vec.length els
modify $ L.listInsert pos el
V.EvKey (V.KChar '-') [] -> do
sel <- gets L.listSelected
case sel of
Nothing -> pure ()
Just i -> modify $ L.listRemove i
V.EvKey V.KEsc [] -> M.halt
ev -> L.handleListEvent ev
where
nextElement :: Vec.Vector Char -> Char
nextElement v = fromMaybe '?' $ Vec.find (`Vec.notElem` v) (Vec.fromList ['a' .. 'z'])
appEvent _ = pure ()
listDrawElement :: (Show a) => Bool -> a -> Widget ()
listDrawElement sel a =
let selStr s =
if sel
then withAttr customAttr (str $ "<" <> s <> ">")
else str s
in str "Item " <+> selStr (show a)
initialState :: L.List () Char
initialState = L.list () (Vec.fromList ['a', 'b', 'c']) 1
customAttr :: A.AttrName
customAttr = L.listSelectedAttr <> A.attrName "custom"
theMap :: A.AttrMap
theMap =
A.attrMap
V.defAttr
[ (L.listAttr, fg V.blue),
(L.listSelectedAttr, fg V.white),
(customAttr, fg V.cyan)
]
theApp :: M.App (L.List () Char) e ()
theApp =
M.App
{ M.appDraw = drawUI,
M.appChooseCursor = M.showFirstCursor,
M.appHandleEvent = appEvent,
M.appStartEvent = pure (),
M.appAttrMap = const theMap
}
main :: IO ()
main = void $ M.defaultMain theApp initialState
|