### Joining Borders Example Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Demonstrates how to join borders within a widget using freezeBorders and border. ```haskell joinBorders . freezeBorders . border . hBox $ [str "left", vBorder, str "right"] ``` -------------------------------- ### Build and Find Demo Programs Source: https://github.com/jtdaugherty/brick/blob/master/README.md Commands to build all demo programs for the Brick library and then find their executable files. Ensure you have Cabal installed and configured. ```bash $ cabal new-build -f demos ``` ```bash $ find dist-newstyle -type f -name \*-demo ``` -------------------------------- ### AppStartEvent Handler Action Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Define an EventM action to be run once at application startup for initial setup. ```haskell appStartEvent :: EventM n s () ``` -------------------------------- ### Vertical Box Layout Example Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Demonstrates vertical layout using the `<=>` operator, which stacks widgets vertically. The example shows how unoccupied space is handled. ```haskell let w = (str "Hello," <=> str "World!") ``` -------------------------------- ### External Border Connections Example Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Shows how to create a box that allows external connections but not internal ones. ```haskell joinBorders . border . freezeBorders . hBox $ [str "left", vBorder, str "right"] ``` -------------------------------- ### Run Brick Application with Default Event Loop Source: https://context7.com/jtdaugherty/brick/llms.txt Launches a Brick application using the standard event loop and Vty configuration. It returns the final application state after the application halts. This is the most common way to start a Brick app. ```haskell import Brick import qualified Graphics.Vty as V ui :: Widget () ui = str "Press any key to quit." main :: IO () main = do _ <- defaultMain (simpleApp ui) () return () -- Renders the widget; exits on any keypress ``` -------------------------------- ### Define Brick UI Layout Source: https://github.com/jtdaugherty/brick/blob/master/README.md Use declarative layout combinators to describe the user interface. This example shows how to create a bordered window with a label and two centered text elements separated by a vertical border. ```haskell joinBorders $ withBorderStyle unicode $ borderWithLabel (str "Hello!") $ (center (str "Left") <+> vBorder <+> center (str "Right")) ``` -------------------------------- ### Show Cursor with Custom Name Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Example of a widget requesting a cursor placement with a specific resource name. ```haskell data MyName = CustomName let w = showCursor CustomName (Brick.Types.Location (1, 0)) (Brick.Widgets.Core.str "foobar") ``` -------------------------------- ### Define Application State with Editor Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Example of defining a Brick application state that includes a text editor component and using Template Haskell for lens generation to access the editor state. ```haskell data MyState n = MyState { _editor :: Editor Text n } makeLenses ''MyState ``` -------------------------------- ### Defining a Default Theme in Haskell Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Example of defining a default theme for a Brick application using the `newTheme` function. It imports necessary modules for theme creation and color definitions. ```haskell import Brick.Themes (Theme, newTheme) import Brick (attrName) import Brick.Util (fg, on) import Graphics.Vty (defAttr, white, blue, yellow, magenta) defaultTheme :: Theme ``` -------------------------------- ### Define Form Fields with Brick.Forms Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Example of defining form fields for UserInfo, including radio buttons, text fields, and checkboxes. Requires lenses for state management. ```haskell radioField handed [ (LeftHanded, LeftHandField, "Left") , (RightHanded, RightHandField, "Right") , (Ambidextrous, AmbiField, "Both") ] , checkboxField ridesBike BikeField "Do you ride a bicycle?" ] ``` -------------------------------- ### Custom Event Loop with BChan for Custom Events Source: https://context7.com/jtdaugherty/brick/llms.txt Starts a Brick application with a custom event loop, allowing injection of custom events via `BChan`. It returns the final state and the Vty handle. Useful for integrating with other threads or asynchronous operations. ```haskell import Brick import Brick.BChan (newBChan, writeBChan) import Brick.Main (customMainWithDefaultVty, halt) import Control.Concurrent (forkIO, threadDelay) import Control.Monad (forever) import qualified Graphics.Vty as V data Tick = Tick type St = Int drawUI :: St -> [Widget ()] drawUI n = [str $ "Ticks: " <> show n] handleEvent :: BrickEvent () Tick -> EventM () St () handleEvent (AppEvent Tick) = modify (+1) handleEvent (VtyEvent (V.EvKey V.KEsc [])) = halt handleEvent _ = return () theApp :: App St Tick () theApp = App drawUI neverShowCursor handleEvent (return ()) (const $ attrMap V.defAttr []) main :: IO () main = do chan <- newBChan 10 void $ forkIO $ forever $ writeBChan chan Tick >> threadDelay 1000000 (finalSt, vty) <- customMainWithDefaultVty (Just chan) theApp 0 V.shutdown vty print finalSt -- Increments counter once per second; Esc exits ``` -------------------------------- ### Handle Low-Level Vty Mouse Down Event Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Example of handling a low-level Vty mouse down event, extracting click coordinates, button, and modifiers. ```haskell handleEvent (VtyEvent (EvMouseDown col row button mods) = ... ``` -------------------------------- ### Limit Viewport Size Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Embeds a widget in a viewport and limits its size using hLimit and vLimit combinators. This example creates a viewport that is 5 columns wide and 1 row high. ```haskell let w = hLimit 5 $ vLimit 1 $ viewport Viewport1 Horizontal $ str "Hello, world!" ``` -------------------------------- ### Custom Attribute Map with Default Background Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Example of creating a custom attribute map where a default background color is set for all entries unless overridden. This avoids repetition. ```haskell let myMap = attrMap (bg blue) [ ... ] ``` -------------------------------- ### Define a Custom Widget in Brick Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Implement a custom widget by using the Widget constructor, providing horizontal and vertical growth policies. Access the rendering context to determine available space and render content using functions like 'str'. This example shows a widget that displays a string followed by the available width. ```haskell customWidget :: String -> Widget n customWidget s = Widget Fixed Fixed $ do ctx <- getContext render $ str (s <> " " <> show (ctx^.availWidthL)) ``` -------------------------------- ### Create a Fill Widget in Brick Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst A widget that fills the available space with a specified character using the current attribute. It retrieves the rendering context to get available dimensions and the current attribute, then uses Graphics.Vty.charFill to create the image. ```haskell myFill :: Char -> Widget n myFill ch = Widget Greedy Greedy $ do ctx <- getContext let a = ctx^.attrL return $ Result (Graphics.Vty.charFill a ch (ctx^.availWidthL) (ctx^.availHeightL)) [] [] [] Brick.BorderMap.empty ``` -------------------------------- ### Control Scrollable Viewports with viewportScroll Source: https://context7.com/jtdaugherty/brick/llms.txt Use `viewportScroll` to get a handle for controlling scrollable regions. Call functions like `vScrollBy`, `vScrollToBeginning`, and `vScrollToEnd` from event handlers to manipulate the scroll position. ```haskell import Brick import qualified Brick.Main as M import qualified Brick.Widgets.Border as B import qualified Graphics.Vty as V import Brick.Types (ViewportType(..)) data Name = VP1 | VP2 deriving (Eq, Ord, Show) vp1Scroll :: M.ViewportScroll Name vp1Scroll = M.viewportScroll VP1 drawUI :: () -> [Widget Name] drawUI _ = [ B.border $ hLimit 50 $ vLimit 15 $ hBox [ viewport VP1 Vertical $ vBox (str <$> ["Line " <> show i | i <- [1..50::Int]]) , B.vBorder , viewport VP2 Horizontal $ str "Scroll me left/right with arrow keys →→→→→→→→→" ] ] handleEvent :: BrickEvent Name () -> EventM Name () () handleEvent (VtyEvent (V.EvKey V.KDown [])) = M.vScrollBy vp1Scroll 1 handleEvent (VtyEvent (V.EvKey V.KUp [])) = M.vScrollBy vp1Scroll (-1) handleEvent (VtyEvent (V.EvKey V.KEnd [])) = M.vScrollToEnd vp1Scroll handleEvent (VtyEvent (V.EvKey V.KHome [])) = M.vScrollToBeginning vp1Scroll handleEvent (VtyEvent (V.EvKey V.KEsc [])) = M.halt handleEvent _ = return () main :: IO () main = do _ <- defaultMain (App drawUI M.neverShowCursor handleEvent (return ()) (const $ attrMap V.defAttr [])) () return () ``` -------------------------------- ### Scrollable Viewports (`viewport`, `viewportScroll`) Source: https://context7.com/jtdaugherty/brick/llms.txt Embed widgets in named scrollable regions. Use `viewportScroll` to get a scroll handle and control scroll position with functions like `vScrollBy`, `hScrollBy`, `vScrollToBeginning`, and `vScrollToEnd`. ```APIDOC ## `viewport` / `viewportScroll` — Scrollable Viewports Embed a widget in a named scrollable region. Use `viewportScroll` to obtain a scroll handle, then call `vScrollBy`, `hScrollBy`, `vScrollToBeginning`, `vScrollToEnd`, etc. from event handlers to control the scroll position. ```haskell import Brick import qualified Brick.Main as M import qualified Brick.Widgets.Border as B import qualified Graphics.Vty as V import Brick.Types (ViewportType(..)) data Name = VP1 | VP2 deriving (Eq, Ord, Show) vp1Scroll :: M.ViewportScroll Name vp1Scroll = M.viewportScroll VP1 drawUI :: () -> [Widget Name] drawUI _ = [ B.border $ hLimit 50 $ vLimit 15 $ hBox [ viewport VP1 Vertical $ vBox (str <$> ["Line " <> show i | i <- [1..50::Int]]) , B.vBorder , viewport VP2 Horizontal $ str "Scroll me left/right with arrow keys →→→→→→→→→" ] ] handleEvent :: BrickEvent Name () -> EventM Name () () handleEvent (VtyEvent (V.EvKey V.KDown [])) = M.vScrollBy vp1Scroll 1 handleEvent (VtyEvent (V.EvKey V.KUp [])) = M.vScrollBy vp1Scroll (-1) handleEvent (VtyEvent (V.EvKey V.KEnd [])) = M.vScrollToEnd vp1Scroll handleEvent (VtyEvent (V.EvKey V.KHome [])) = M.vScrollToBeginning vp1Scroll handleEvent (VtyEvent (V.EvKey V.KEsc [])) = M.halt handleEvent _ = return () main :: IO () main = do _ <- defaultMain (App drawUI M.neverShowCursor handleEvent (return ()) (const $ attrMap V.defAttr [])) () return () ``` ``` -------------------------------- ### defaultMain — Standard Event Loop Entry Point Source: https://context7.com/jtdaugherty/brick/llms.txt Runs the application with the given initial state using the default Vty configuration. Returns the final application state once `halt` is called. ```APIDOC ## `defaultMain` — Standard Event Loop Entry Point Runs the application with the given initial state using the default Vty configuration. Returns the final application state once `halt` is called. This is the most common way to launch a Brick application. ```haskell import Brick import qualified Graphics.Vty as V ui :: Widget () ui = str "Press any key to quit." main :: IO () main = do _ <- defaultMain (simpleApp ui) () return () -- Renders the widget; exits on any keypress ``` ``` -------------------------------- ### Define Brick Application with State and Event Handling Source: https://context7.com/jtdaugherty/brick/llms.txt Defines a complete Brick application including state, UI drawing, event handling, and the main entry point. Use this as a template for standard Brick applications. ```haskell {-# LANGUAGE TemplateHaskell #-} module Main where import Lens.Micro.TH (makeLenses) import Lens.Micro.Mtl ((.=), use) import qualified Graphics.Vty as V import Brick data Name = MyViewport deriving (Eq, Ord, Show) data AppState = AppState { _counter :: Int } makeLenses ''AppState drawUI :: AppState -> [Widget Name] drawUI st = [ border $ str $ "Counter: " <> show (st ^. counter) ] handleEvent :: BrickEvent Name () -> EventM Name AppState () handleEvent (VtyEvent (V.EvKey (V.KChar 'q') [])) = halt handleEvent (VtyEvent (V.EvKey V.KUp [])) = counter %= (+1) handleEvent (VtyEvent (V.EvKey V.KDown [])) = counter %= subtract 1 handleEvent _ = return () theApp :: App AppState () Name theApp = App { appDraw = drawUI , appChooseCursor = neverShowCursor , appHandleEvent = handleEvent , appStartEvent = return () , appAttrMap = const $ attrMap V.defAttr [] } main :: IO () main = do finalState <- defaultMain theApp (AppState 0) putStrLn $ "Final counter: " <> show (finalState ^. counter) -- Output: renders a bordered counter widget; prints final value on exit ``` -------------------------------- ### Scroll Viewport Horizontally by One Column Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst An example event handler that scrolls the specified viewport one column to the right using the hScrollBy function. ```haskell myHandler :: e -> EventM n s () myHandler e = do let vp = viewportScroll Viewport1 hScrollBy vp 1 ``` -------------------------------- ### Create Text Widgets with str and txt Source: https://context7.com/jtdaugherty/brick/llms.txt Build fixed-size widgets from `String` using `str` or `Data.Text` using `txt`. Both handle multi-line strings by padding shorter lines. Use `strWrap` / `txtWrap` for word-wrapping. ```haskell import Brick import qualified Data.Text as T ui :: Widget () ui = vBox [ str "Plain string widget" , txt (T.pack "Text widget") , strWrap "This long string will be wrapped at the available terminal width automatically." ] main :: IO () main = simpleMain ui ``` -------------------------------- ### Initialize Brick with Custom Event Channel Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Use customMain to initialize Brick with a BChan for custom events and a custom Vty builder. ```haskell main :: IO () main = do eventChan <- Brick.BChan.newBChan 10 let buildVty = Graphics.Vty.CrossPlatform.mkVty Graphics.Vty.Config.defaultConfig initialVty <- buildVty finalState <- customMain initialVty buildVty (Just eventChan) app initialState -- Use finalState and exit ``` -------------------------------- ### Run Brick Application with defaultMain Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Use defaultMain to run a Brick application with a given App configuration and initial state. The final state is returned upon application exit. ```haskell main :: IO () main = do let app = App { ... } initialState = ... finalState <- defaultMain app initialState -- Use finalState and exit ``` -------------------------------- ### Layout Widgets with hBox, vBox, (<+>), and (<=>) Source: https://context7.com/jtdaugherty/brick/llms.txt Arrange widgets horizontally with `hBox` or `(<+>)`, and vertically with `vBox` or `(<=>)`. Fixed-size children are allocated space first; remaining space is divided among greedy children. ```haskell import Brick import qualified Brick.Widgets.Border as B ui :: Widget () ui = vBox [ str "Top row" , B.hBorder , hBox [ str "Left column" , B.vBorder , str "Middle column" , B.vBorder , str "Right column" ] , B.hBorder , str "Bottom row" ] main :: IO () main = simpleMain ui ``` -------------------------------- ### Implement Clickable Widget with Brick Mouse Events Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Defines a clickable widget using `clickable` and demonstrates handling `MouseDown` and `MouseUp` events for a specific named widget. Click coordinates are local to the widget. ```haskell data Name = MyButton ui :: Widget Name ui = center $ clickable MyButton $ border $ str "Click me" handleEvent (MouseDown MyButton button modifiers coords) = ... handleEvent (MouseUp MyButton button coords) = ... ``` -------------------------------- ### Display a Single Widget with SimpleMain Source: https://context7.com/jtdaugherty/brick/llms.txt Renders a static widget and exits upon any key press. Ideal for simple displays or quick prototypes where complex event handling is not required. ```haskell import Brick main :: IO () main = simpleMain $ str "Hello, world!" -- Output: displays "Hello, world!" in the terminal until a key is pressed ``` -------------------------------- ### Compose Event Handler with Nested Editor State using nestEventM Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst An alternative method to `zoom` for dispatching events to a nested component. This example uses `nestEventM` to run an `EventM` computation with a specific nested state, then updates the main state with the result. Requires importing `use` and `(.=)` from `Lens.Micro.Mtl`. ```haskell import Lens.Micro (_1) import Lens.Micro.Mtl (use, (.=)) handleEvent :: BrickEvent n e -> EventM n MyState () handleEvent e = do editorState <- use editor (newEditorState, ()) <- nestEventM editorState $ do handleEditorEvent e editor .= newEditorState ``` -------------------------------- ### Load Custom Theme Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Loads custom theme customizations from a file, merging them with a default theme. Requires `Brick.Themes`. ```haskell import Brick.Themes (loadCustomizations) main :: IO () main = do customizedTheme <- loadCustomizations "custom.ini" defaultTheme ``` -------------------------------- ### simpleMain — One-Shot Widget Display Source: https://context7.com/jtdaugherty/brick/llms.txt Renders a single widget and exits when any key is pressed. Useful for static displays or quick prototypes where no event handling beyond resize/quit is needed. ```APIDOC ## `simpleMain` — One-Shot Widget Display Renders a single widget and exits when any key is pressed. Useful for static displays or quick prototypes where no event handling beyond resize/quit is needed. ```haskell import Brick main :: IO () main = simpleMain $ str "Hello, world!" -- Output: displays "Hello, world!" in the terminal until a key is pressed ``` ``` -------------------------------- ### Scrollable List Widget with `Brick.Widgets.List` Source: https://context7.com/jtdaugherty/brick/llms.txt Implements a scrollable and selectable list using `Brick.Widgets.List`. Handles keyboard events for navigation and selection, and defines custom attributes for list items. Requires Brick, Vty, and Vector imports. ```haskell import Brick import Brick.Main (halt) import qualified Brick.Widgets.List as L import qualified Brick.Widgets.Border as B import qualified Brick.Widgets.Center as C import qualified Data.Vector as Vec import qualified Graphics.Vty as V import Brick.Util (on, fg) data Name = MyList deriving (Eq, Ord, Show) type St = L.List Name String drawUI :: St -> [Widget Name] drawUI lst = [ C.center $ B.borderWithLabel (str " Items ") $ L.renderList renderItem True lst ] where renderItem focused item = let w = str item in if focused then withAttr selectedAttr w else w selectedAttr :: AttrName selectedAttr = L.listSelectedAttr <> attrName "custom" handleEvent :: BrickEvent Name () -> EventM Name St () handleEvent (VtyEvent (V.EvKey V.KEsc [])) = halt handleEvent (VtyEvent ev) = L.handleListEvent ev handleEvent _ = return () theApp :: App St () Name theApp = App { appDraw = drawUI , appChooseCursor = showFirstCursor , appHandleEvent = handleEvent , appStartEvent = return () , appAttrMap = const $ attrMap V.defAttr [ (L.listAttr, V.white `on` V.blue) , (L.listSelectedAttr, V.blue `on` V.white) , (selectedAttr, fg V.cyan) ] } main :: IO () main = do let items = Vec.fromList ["Apple", "Banana", "Cherry", "Date", "Elderberry"] _ <- defaultMain theApp (L.list MyList items 1) return () ``` -------------------------------- ### Add Padding with padLeft, padRight, padTop, padBottom, padAll Source: https://context7.com/jtdaugherty/brick/llms.txt Add space around a widget. `Pad n` pads by `n` cells; `Max` pads to fill all remaining space, making the widget greedy in that dimension. ```haskell import Brick import qualified Brick.Widgets.Border as B ui :: Widget () ui = B.border $ vBox [ padAll 2 $ str "2-cell padding on all sides" , B.hBorder , padLeft Max $ str "right-aligned via Max left padding" , padLeftRight 4 $ str "4-cell left/right padding" ] main :: IO () main = simpleMain ui ``` -------------------------------- ### Create AttrMap from Theme Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Converts a Brick theme into an AttrMap, which is used for rendering attributes. Requires `Brick.Themes`. ```haskell import Brick.Themes (themeToAttrMap) main :: IO () main = do customizedTheme <- loadCustomizations "custom.ini" defaultTheme let mapping = themeToAttrMap customizedTheme ``` -------------------------------- ### Create Seamless Borders with joinBorders Source: https://context7.com/jtdaugherty/brick/llms.txt Wraps a widget so that adjacent borders automatically join their corners and intersections, producing a seamless grid appearance instead of disconnected border segments. ```haskell import Brick import qualified Brick.Widgets.Border as B import qualified Brick.Widgets.Center as C ui :: Widget () ui = joinBorders $ B.border $ vBox [ C.hCenter (str "top section") , B.hBorder , hBox [ C.center (str "left") , B.vBorder , C.center (str "right") ] ] main :: IO () main = simpleMain ui ``` -------------------------------- ### Manage Focus Ring with Brick.Focus Source: https://context7.com/jtdaugherty/brick/llms.txt Utilize `focusRing`, `focusNext`, `focusPrev`, `focusGetCurrent`, and `focusRingCursor` for circular widget focus management. Use `withFocusRing` to pass focus state to rendering functions. Handles tab for next focus and Shift+Tab for previous focus. ```haskell {-# LANGUAGE TemplateHaskell #-} import Brick import Brick.Main (halt) import Brick.Focus (FocusRing, focusRing, focusNext, focusPrev, focusGetCurrent, focusRingCursor) import qualified Brick.Widgets.Edit as E import Lens.Micro.TH (makeLenses) import Lens.Micro.Mtl (use, zoom, (%=)) import qualified Graphics.Vty as V data Name = Field1 | Field2 deriving (Eq, Ord, Show) data St = { _edit1 :: E.Editor String Name , _edit2 :: E.Editor String Name , _focus :: FocusRing Name } makeLenses ''St drawUI :: St -> [Widget Name] drawUI st = [ vBox [ str "Tab to switch focus, Esc to quit" , withFocusRing (st ^. focus) (E.renderEditor (str . unlines)) (st ^. edit1) , withFocusRing (st ^. focus) (E.renderEditor (str . unlines)) (st ^. edit2) ] ] handleEvent :: BrickEvent Name () -> EventM Name St () handleEvent (VtyEvent (V.EvKey (V.KChar '\t') [])) = focus %= focusNext handleEvent (VtyEvent (V.EvKey V.KBackTab [])) = focus %= focusPrev handleEvent (VtyEvent (V.EvKey V.KEsc [])) = halt handleEvent ev = do f <- use focus case focusGetCurrent f of Just Field1 -> zoom edit1 (E.handleEditorEvent ev) Just Field2 -> zoom edit2 (E.handleEditorEvent ev) Nothing -> return () main :: IO () main = do let initSt = St { _edit1 = E.editor Field1 (Just 3) "" , _edit2 = E.editor Field2 (Just 3) "" , _focus = focusRing [Field1, Field2] } _ <- defaultMain (App drawUI (focusRingCursor (^. focus)) handleEvent (return ()) (const $ attrMap V.defAttr [(E.editFocusedAttr, V.black `on` V.yellow)])) initSt return () ``` -------------------------------- ### Attribute Styling with `attrMap`, `withAttr`, `forceAttr`, `withDefAttr` Source: https://context7.com/jtdaugherty/brick/llms.txt Defines a hierarchical attribute map and demonstrates applying, overriding, and setting default attributes for widgets. Requires Brick and Graphics.Vty imports. ```haskell import Brick import qualified Graphics.Vty as V import Brick.AttrMap (attrName) highlight, warning, good :: AttrName highlight = attrName "highlight" warning = attrName "warning" good = attrName "good" theMap :: AttrMap theMap = attrMap (V.white `on` V.black) [ (highlight, V.yellow `on` V.black) , (warning, V.white `on` V.red) , (good, V.black `on` V.green) , (highlight <> good, V.black `on` V.cyan) -- hierarchical override ] ui :: Widget () u i = vBox [ str "Default attribute (white on black)" , withAttr highlight $ str "Highlighted (yellow on black)" , withAttr warning $ str "Warning (white on red)" , withAttr good $ str "Good (black on green)" , forceAttr warning $ withAttr highlight $ str "Forced warning everywhere" ] main :: IO () main = do _ <- defaultMain (App (const [ui]) neverShowCursor resizeOrQuit (return ()) (const theMap)) () return () ``` -------------------------------- ### Define Brick Application Structure Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst The App type defines the core components of a Brick application: drawing function, cursor selection, event handling, startup event, and attribute map. It is parameterized by the application state type 's', event type 'e', and name type 'n'. ```haskell data App s e n = App { appDraw :: s -> [Widget n] , appChooseCursor :: s -> [CursorLocation n] -> Maybe (CursorLocation n) , appHandleEvent :: BrickEvent n e -> EventM n s () , appStartEvent :: EventM n s () , appAttrMap :: s -> AttrMap } ``` -------------------------------- ### Define Key Events and Bindings in Haskell Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Defines custom key events like QuitEvent and CloseWindowEvent, and associates them with default keybindings using Brick's key event utilities. ```haskell data KeyEvent = QuitEvent | CloseWindowEvent allKeyEvents :: KeyEvents KeyEvent allKeyEvents = K.keyEvents [ ("quit", QuitEvent) , ("close-window", CloseWindowEvent) ] defaultBindings :: [(KeyEvent, [Binding])] defaultBindings = [ (QuitEvent, [ctrl 'q']) , (CloseWindowEvent, [bind KEsc]) ] ``` -------------------------------- ### Define Viewports with Unique Names Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Shows the correct way to define multiple viewports by assigning a unique name to each to avoid ambiguity. ```haskell data Name = Viewport1 | Viewport2 ui :: Widget Name ui = (viewport Viewport1 Vertical $ str "Foo") <+> (viewport Viewport2 Vertical $ str "Bar") <+> ``` -------------------------------- ### App - Application Definition Record Source: https://context7.com/jtdaugherty/brick/llms.txt The central abstraction for a Brick application, defining its drawing, event handling, styling, and cursor behavior. ```APIDOC ## App - Application Definition Record The central abstraction: a record of five functions that fully describe the behavior of a Brick application. `appDraw` converts state to layers of widgets, `appHandleEvent` processes events, `appAttrMap` provides styling, `appChooseCursor` selects the active cursor, and `appStartEvent` runs once before the first render. ```haskell {-# LANGUAGE TemplateHaskell #-} module Main where import Lens.Micro.TH (makeLenses) import Lens.Micro.Mtl ((.=), use) import qualified Graphics.Vty as V import Brick data Name = MyViewport deriving (Eq, Ord, Show) data AppState = AppState { _counter :: Int } makeLenses ''AppState drawUI :: AppState -> [Widget Name] drawUI st = [ border $ str $ "Counter: " <> show (st ^. counter) ] handleEvent :: BrickEvent Name () -> EventM Name AppState () handleEvent (VtyEvent (V.EvKey (V.KChar 'q') [])) = halt handleEvent (VtyEvent (V.EvKey V.KUp [])) = counter <>= (+1) handleEvent (VtyEvent (V.EvKey V.KDown [])) = counter <>= subtract 1 handleEvent _ = return () theApp :: App AppState () Name theApp = App { appDraw = drawUI , appChooseCursor = neverShowCursor , appHandleEvent = handleEvent , appStartEvent = return () , appAttrMap = const $ attrMap V.defAttr [] } main :: IO () main = do finalState <- defaultMain theApp (AppState 0) putStrLn $ "Final counter: " <> show (finalState ^. counter) -- Output: renders a bordered counter widget; prints final value on exit ``` ``` -------------------------------- ### Define UI with Extent Reporting Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Defines a UI element and requests that its extent (position and size) be reported by the renderer using a specific resource name. Requires `Brick.Types.Extent` and `Brick.Main`. ```haskell data Name = FooBox ui = center $ reportExtent FooBox $ border $ str "Foo" ``` -------------------------------- ### Define App Attribute Map Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Use `Brick.AttrMap.attrMap` to create an attribute map for the application. This function maps abstract attribute names to concrete attributes. ```haskell App { ... , appAttrMap = const $ attrMap Graphics.Vty.defAttr [(someAttrName, fg blue)] } ``` -------------------------------- ### Text Editor Widget with `Brick.Widgets.Edit` Source: https://context7.com/jtdaugherty/brick/llms.txt Provides a single- or multi-line text editor with Emacs-style keybindings. Embeds an `Editor` in the application state, routes events through `handleEditorEvent`, and retrieves content using `getEditContents`. Requires Brick, Vty, Text, and Lens imports. ```haskell {-# LANGUAGE TemplateHaskell #-} import Brick import Brick.Main (halt) import qualified Brick.Widgets.Edit as E import qualified Brick.Widgets.Border as B import qualified Data.Text as T import Lens.Micro.TH (makeLenses) import Lens.Micro.Mtl (zoom) import qualified Graphics.Vty as V data Name = Ed deriving (Eq, Ord, Show) data St = St { _editor :: E.Editor T.Text Name } makeLenses ''St drawUI :: St -> [Widget Name] drawUI st = [ B.borderWithLabel (str " Editor ") $ vLimit 5 $ E.renderEditor (vBox . map txt) True (st ^. editor) ] handleEvent :: BrickEvent Name () -> EventM Name St () handleEvent (VtyEvent (V.EvKey V.KEsc [])) = do st <- get let contents = T.unlines (E.getEditContents (st ^. editor)) halt handleEvent ev = zoom editor (E.handleEditorEvent ev) main :: IO () main = do let initSt = St { _editor = E.editor Ed (Just 5) "" } finalSt <- defaultMain (App drawUI showFirstCursor handleEvent (return ()) (const $ attrMap V.defAttr [(E.editFocusedAttr, V.black `on` V.yellow)])) initSt mapM_ (putStrLn . T.unpack) (E.getEditContents (finalSt ^. editor)) -- Ctrl-a/e: line start/end; Ctrl-k: kill to EOL; arrow keys: navigation ``` -------------------------------- ### Create a Brick Form for User Input Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Constructs a Brick form for editing a `UserInfo` value. It utilizes various `edit*Field` functions to define input widgets for different data types, including text, integers, and passwords. ```haskell mkForm :: UserInfo -> Form UserInfo e Name mkForm = newForm [ editTextField name NameField (Just 1) , editTextField address AddressField (Just 3) , editShowableField age AgeField , editPasswordField password PasswordField ] ``` -------------------------------- ### Enable Mouse Click Support on Widgets Source: https://context7.com/jtdaugherty/brick/llms.txt Register widgets as clickable using `clickable`. The event loop translates raw mouse coordinates into `MouseDown` events with widget-local coordinates. `reportExtent` can be used for non-clickable extent queries. ```haskell import Brick import Brick.Main (halt) import qualified Graphics.Vty as V data Name = BtnOk | BtnCancel deriving (Eq, Ord, Show) data St = St { _msg :: String } drawUI :: St -> [Widget Name] drawUI st = [ vBox [ str $ "Message: " <> _msg st , hBox [ clickable BtnOk $ withAttr (attrName "btn") $ str " [ OK ] " , clickable BtnCancel $ withAttr (attrName "btn") $ str " [Cancel] " ] ] ] handleEvent :: BrickEvent Name () -> EventM Name St () handleEvent (MouseDown BtnOk _ _ _) = modify (\s -> s { _msg = "OK clicked!" }) handleEvent (MouseDown BtnCancel _ _ _) = halt handleEvent (VtyEvent (V.EvKey V.KEsc [])) = halt handleEvent _ = return () main :: IO () main = do _ <- defaultMain (App drawUI neverShowCursor handleEvent (return ()) (const $ attrMap V.defAttr [(attrName "btn", V.white `on` V.blue)])) (St "none") return () -- Mouse clicks on the buttons generate MouseDown events with the Name ``` -------------------------------- ### suspendAndResume Source: https://context7.com/jtdaugherty/brick/llms.txt Temporarily suspend the Brick event loop, run an arbitrary IO action (e.g., launch an external editor, show a pager), and resume with an updated state. ```APIDOC ## suspendAndResume ### Description Temporarily suspend the Brick event loop, run an arbitrary `IO` action (e.g., launch an external editor, show a pager), and resume with an updated state. ### Method `suspendAndResume` is a function that takes an `IO` action and returns an updated state. ### Parameters - `IO St`: An IO action that produces the new state of the application. ### Request Example ```haskell suspendAndResume $ do callCommand "vim /tmp/brick-demo.txt" content <- readFile "/tmp/brick-demo.txt" return $ St content ``` ### Response - `St`: The updated application state after the IO action completes. ``` -------------------------------- ### Define appChooseCursor Function Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Implement `appChooseCursor` to select the desired cursor location from a list of possibilities based on application state. ```haskell appChooseCursor :: s -> [CursorLocation n] -> Maybe (CursorLocation n) ``` -------------------------------- ### Suspend TUI and Run External IO Action Source: https://context7.com/jtdaugherty/brick/llms.txt Use `suspendAndResume` to temporarily pause the Brick event loop, execute an IO action (like launching an editor), and then resume with updated state. This is useful for integrating external tools or processes. ```haskell import Brick import Brick.Main (halt, suspendAndResume) import qualified Graphics.Vty as V import System.Process (callCommand) data St = St { _lastOutput :: String } drawUI :: St -> [Widget ()] drawUI st = [str $ "Last output: " <> _lastOutput st] handleEvent :: BrickEvent () () -> EventM () St () handleEvent (VtyEvent (V.EvKey (V.KChar 'e') [])) = suspendAndResume $ do callCommand "vim /tmp/brick-demo.txt" content <- readFile "/tmp/brick-demo.txt" return $ St content handleEvent (VtyEvent (V.EvKey V.KEsc [])) = halt handleEvent _ = return () main :: IO () main = do _ <- defaultMain (App drawUI neverShowCursor handleEvent (return ()) (const $ attrMap V.defAttr [])) (St "none") return () -- Press 'e' to open vim; Brick resumes automatically when vim exits ``` -------------------------------- ### Connect Adjacent Borders Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Demonstrates how adjacent borders connect when `joinBorders` is applied to both. This creates a continuous border line, unlike the default behavior which leaves gaps. ```text ├─ ``` -------------------------------- ### Create ViewportScroll Handle Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Creates a handle for a specific viewport to make scrolling requests. This handle is used to call scrolling functions. ```haskell -- Assuming that App uses 'Name' for its resource names: data Name = Viewport1 let vp = viewportScroll Viewport1 ``` -------------------------------- ### INI-style Attribute Theme Customization Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Demonstrates the INI-style format for customizing Brick attribute themes. This includes setting default attributes, specific attributes, styles, and hierarchical attributes. ```ini [default] default.fg = blue default.bg = black [other] someAttribute.fg = red someAttribute.style = underline otherAttribute.style = [underline, bold] otherAttribute.inner.fg = white ``` -------------------------------- ### Scroll Bar Overlays (`withVScrollBars`, `withHScrollBars`) Source: https://context7.com/jtdaugherty/brick/llms.txt Automatically render a scroll bar alongside any `viewport` widgets in the subtree. Accepts an orientation (`OnLeft`/`OnRight` for vertical; `OnTop`/`OnBottom` for horizontal). ```APIDOC ## `withVScrollBars` / `withHScrollBars` — Scroll Bar Overlays Automatically render a scroll bar alongside any `viewport` widgets in the subtree. Accepts an orientation (`OnLeft`/`OnRight` for vertical; `OnTop`/`OnBottom` for horizontal). ```haskell import Brick import Brick.Types (ViewportType(..)) import Brick.Widgets.Core (withVScrollBars, withHScrollBars) import Brick.Types (VScrollBarOrientation(..), HScrollBarOrientation(..)) data Name = VP deriving (Eq, Ord, Show) drawUI :: () -> [Widget Name] drawUI _ = [ withVScrollBars OnRight $ withHScrollBars OnBottom $ viewport VP Both $ vBox (str <$> ["Line " <> show i | i <- [1..100::Int]]) ] main :: IO () main = simpleMain (head $ drawUI ()) ``` ``` -------------------------------- ### customMainWithDefaultVty — Custom Event Loop with BChan Source: https://context7.com/jtdaugherty/brick/llms.txt Like `defaultMain` but accepts an optional `BChan e` for injecting custom application events from other threads. Returns both the final state and the Vty handle for further use. ```APIDOC ## `customMainWithDefaultVty` — Custom Event Loop with BChan Like `defaultMain` but accepts an optional `BChan e` for injecting custom application events from other threads. Returns both the final state and the Vty handle for further use. ```haskell import Brick import Brick.BChan (newBChan, writeBChan) import Brick.Main (customMainWithDefaultVty, halt) import Control.Concurrent (forkIO, threadDelay) import Control.Monad (forever) import qualified Graphics.Vty as V data Tick = Tick type St = Int drawUI :: St -> [Widget ()] drawUI n = [str $ "Ticks: " <> show n] handleEvent :: BrickEvent () Tick -> EventM () St () handleEvent (AppEvent Tick) = modify (+1) handleEvent (VtyEvent (V.EvKey V.KEsc [])) = halt handleEvent _ = return () theApp :: App St Tick () theApp = App drawUI neverShowCursor handleEvent (return ()) (const $ attrMap V.defAttr []) main :: IO () main = do chan <- newBChan 10 void $ forkIO $ forever $ writeBChan chan Tick >> threadDelay 1000000 (finalSt, vty) <- customMainWithDefaultVty (Just chan) theApp 0 V.shutdown vty print finalSt -- Increments counter once per second; Esc exits ``` ``` -------------------------------- ### Build Validated Input Forms with Brick.Forms Source: https://context7.com/jtdaugherty/brick/llms.txt Use `editTextField`, `editShowableField`, `radioField`, and `checkboxField` to construct forms from data types. `handleFormEvent` dispatches input, `formState` retrieves current state, and `allFieldsValid` checks validity. Requires `TemplateHaskell` and `OverloadedStrings` extensions. ```haskell {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-} import Brick import Brick.Main (halt) import Brick.Forms import qualified Brick.Widgets.Border as B import qualified Brick.Widgets.Center as C import Lens.Micro.TH (makeLenses) import qualified Data.Text as T import qualified Graphics.Vty as V data Name = NameF | EmailF | AgeF | AgreeF deriving (Eq, Ord, Show) data FormData = { _fdName :: T.Text , _fdEmail :: T.Text , _fdAge :: Int , _fdAgree :: Bool } deriving (Show) makeLenses ''FormData mkForm :: FormData -> Form FormData e Name mkForm = newForm [ label "Name" @@= editTextField fdName NameF (Just 1) , label "Email" @@= editTextField fdEmail EmailF (Just 1) , label "Age" @@= editShowableField fdAge AgeF , label "" @@= checkboxField fdAgree AgreeF "I agree to the terms" ] where label t w = (vLimit 1 (hLimit 10 (str t <+> fill ' ')) <+> w) theMap :: AttrMap theMap = attrMap V.defAttr [ (focusedFormInputAttr, V.black `on` V.yellow) , (invalidFormInputAttr, V.white `on` V.red) ] handleEvent :: BrickEvent Name () -> EventM Name (Form FormData () Name) () handleEvent (VtyEvent (V.EvKey V.KEsc [])) = halt handleEvent ev = handleFormEvent ev main :: IO () main = do let initData = FormData "Alice" "alice@example.com" 30 False finalForm <- defaultMain (App (const . pure . C.center . B.border . renderForm) showFirstCursor handleEvent (return ()) (const theMap)) (mkForm initData) if allFieldsValid finalForm then print (formState finalForm) else putStrLn "Form has invalid fields" ``` -------------------------------- ### Configure appChooseCursor with showCursorNamed Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Set the `appChooseCursor` function in your application to use `showCursorNamed` for selecting a cursor by its resource name. ```haskell myApp = App { ... , appChooseCursor = \_ -> showCursorNamed CustomName } ``` -------------------------------- ### Enable Vty Mouse Mode Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Enables mouse mode in Vty if the terminal supports it. Requires access to the Vty handle within EventM. ```haskell do vty <- Brick.Main.getVtyHandle let output = outputIface vty when (supportsMode output Mouse) $ liftIO $ setMode output Mouse True ``` -------------------------------- ### Constrain Widget Size with hLimit, vLimit, hLimitPercent, vLimitPercent Source: https://context7.com/jtdaugherty/brick/llms.txt Constrain a widget's width or height to a fixed number of columns/rows or a percentage of available space. This is essential for preventing greedy widgets from consuming all space. ```haskell import Brick import qualified Brick.Widgets.Border as B import qualified Brick.Widgets.Center as C ui :: Widget () ui = C.center $ hLimit 40 $ vLimit 10 $ B.border $ C.center $ str "I am constrained to 40x10" main :: IO () main = simpleMain ui ``` -------------------------------- ### Request Visibility with visible and visibleRegion Source: https://context7.com/jtdaugherty/brick/llms.txt Mark widgets to ensure they are brought into view by a parent viewport. The viewport automatically scrolls to make the marked widget visible during the next render cycle. ```haskell import Brick import Brick.Types (ViewportType(..)) data Name = VP deriving (Eq, Ord, Show) -- Wrapping an item with `visible` causes the viewport to scroll to show it. renderItem :: Bool -> String -> Widget Name renderItem isFocused label = let w = str label in if isFocused then visible w else w drawUI :: Int -> [Widget Name] drawUI focusedIdx = [ viewport VP Vertical $ vBox [ renderItem (i == focusedIdx) ("Item " <> show i) | i <- [0..99::Int] ] ] ``` -------------------------------- ### Handle Custom Events in Brick Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Handle custom events within the Brick event handler by pattern matching on AppEvent. ```haskell myEvent :: BrickEvent n CounterEvent -> EventM n s () myEvent (AppEvent (Counter i)) = ... ``` -------------------------------- ### Correct Text Width Calculation Source: https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst Calculates the screen width of a string, correctly handling wide characters using the `TextWidth` type class. Requires `Brick.Widgets.Core`. ```haskell let width = Brick.Widgets.Core.textWidth t ```