module Brick.Widgets.Edit
( Editor(editContents, editorName, editDrawContents)
, editor
, getEditContents
, handleEditorEvent
, applyEdit
, editContentsL
, editDrawContentsL
, renderEditor
, editAttr
, editFocusedAttr
)
where
import Data.Monoid
import Lens.Micro
import Graphics.Vty (Event(..), Key(..), Modifier(..))
import qualified Data.Text.Zipper as Z
import Brick.Types
import Brick.Widgets.Core
import Brick.AttrMap
data Editor n =
Editor { editContents :: Z.TextZipper String
, editDrawContents :: [String] -> Widget n
, editorName :: n
}
suffixLenses ''Editor
instance Named (Editor n) n where
getName = editorName
handleEditorEvent :: Event -> Editor n -> EventM n (Editor n)
handleEditorEvent e ed =
let f = case e of
EvKey (KChar 'a') [MCtrl] -> Z.gotoBOL
EvKey (KChar 'e') [MCtrl] -> Z.gotoEOL
EvKey (KChar 'd') [MCtrl] -> Z.deleteChar
EvKey (KChar 'k') [MCtrl] -> Z.killToEOL
EvKey KEnter [] -> Z.breakLine
EvKey KDel [] -> Z.deleteChar
EvKey (KChar c) [] | c /= '\t' -> Z.insertChar c
EvKey KUp [] -> Z.moveUp
EvKey KDown [] -> Z.moveDown
EvKey KLeft [] -> Z.moveLeft
EvKey KRight [] -> Z.moveRight
EvKey KBS [] -> Z.deletePrevChar
_ -> id
in return $ applyEdit f ed
editor :: n
-> ([String] -> Widget n)
-> Maybe Int
-> String
-> Editor n
editor name draw limit s = Editor (Z.stringZipper (lines s) limit) draw name
applyEdit :: (Z.TextZipper String -> Z.TextZipper String)
-> Editor n
-> Editor n
applyEdit f e = e & editContentsL %~ f
editAttr :: AttrName
editAttr = "edit"
editFocusedAttr :: AttrName
editFocusedAttr = editAttr <> "focused"
getEditContents :: Editor n -> [String]
getEditContents e = Z.getText $ e^.editContentsL
renderEditor :: (Ord n, Show n)
=> Bool
-> Editor n
-> Widget n
renderEditor foc e =
let cp = Z.cursorPosition $ e^.editContentsL
cursorLoc = Location (cp^._2, cp^._1)
limit = case e^.editContentsL.to Z.getLineLimit of
Nothing -> id
Just lim -> vLimit lim
in withAttr (if foc then editFocusedAttr else editAttr) $
limit $
viewport (e^.editorNameL) Both $
(if foc then showCursor (e^.editorNameL) cursorLoc else id) $
visibleRegion cursorLoc (1, 1) $
e^.editDrawContentsL $
getEditContents e