{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} module Brick.Widgets.CommentDialog ( CommentWidget , commentWidget , renderCommentWidget , commentDialogComment , CommentAction(..) , handleCommentEvent ) where import Brick import Brick.Widgets.Dialog import Brick.Widgets.Center import Data.Text.Zipper import Graphics.Vty.Input import qualified Data.Text as T import Data.Text (Text) import Lens.Micro import Lens.Micro.TH import Lens.Micro.Mtl import Brick.Widgets.Edit.EmacsBindings data CommentWidget n = CommentWidget { _origComment :: Text , _textArea :: Editor n , _dialogWidget :: Dialog () n , _promptPrefix :: Text } makeLenses ''CommentWidget commentWidget :: Eq n => n -> Text -> Text -> CommentWidget n commentWidget name prompt comment = let title = txt "ESC: cancel, RET: accept, Alt-RET: New line" maxWidth = 80 diag = dialog (Just title) Nothing maxWidth edit = editorText name (txt . T.unlines) Nothing comment in CommentWidget { _origComment = comment , _textArea = applyEdit gotoEnd edit , _dialogWidget = diag , _promptPrefix = prompt } data CommentAction = CommentContinue | CommentFinished Text handleCommentEvent :: Eq n => Event -> EventM n (CommentWidget n) CommentAction handleCommentEvent ev = case ev of EvKey KEsc [] -> CommentFinished <$> use origComment EvKey KEnter [] -> CommentFinished <$> gets commentDialogComment EvKey KEnter [MMeta] -> do zoom textArea $ applyEditM breakLine return CommentContinue _ -> do zoom textArea $ handleEditorEvent ev return CommentContinue renderCommentWidget :: (Ord n, Show n) => CommentWidget n -> Widget n renderCommentWidget widget = let height = min (length (getEditContents (widget^.textArea)) + 4) 24 textArea' = padTop (Pad 1) $ txt (widget^.promptPrefix <> ": ") <+> renderEditor True (widget^.textArea) in vCenterLayer $ vLimit height $ renderDialog (widget^.dialogWidget) textArea' commentDialogComment :: CommentWidget n -> Text commentDialogComment = T.intercalate "\n" . getEditContents . _textArea gotoEnd :: Monoid a => TextZipper a -> TextZipper a gotoEnd zipper = let lengths = lineLengths zipper (row, col) = (length lengths, last lengths) in moveCursor (row-1, col) zipper