| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 | {-# LANGUAGE OverloadedStrings #-}module Bunyan.App (runApp) whereimport qualified Brickimport qualified Data.Map as Mimport           Data.Monoid ((<>))import qualified Data.Sequence as Simport qualified Data.Text as Timport qualified Graphics.Vty as Vtyimport qualified Graphics.Vty.Input.Events as Vtyimport qualified Bunyan.Log as Logdata Modal  = AddSectionModal ()  | ConfirmQuitModal  deriving (Eq, Show)data Annot  = Annot T.Text Log.Entry  | Skip Log.Entry  deriving (Eq, Show)data State = State  { stateSections :: M.Map T.Text (S.Seq (S.Seq T.Text))  , stateCommits  :: S.Seq Log.Entry  , stateFinished :: S.Seq Annot  , stateKeys     :: M.Map Char T.Text  , stateModal    :: Maybe Modal  , stateStatus   :: T.Text  } deriving (Eq, Show)defaultSections :: [(Char, T.Text)]defaultSections =  [ ('f', "New features")  , ('b', "Bug fixes")  , ('p', "Package changes")  , ('d', "Documentation changes")  , ('i', "Performance improvements")  ]newState :: S.Seq Log.Entry -> StatenewState commits = State  { stateSections = M.fromList    [ (name, mempty) | (_, name) <- defaultSections ]  , stateKeys = M.fromList defaultSections  , stateCommits = commits  , stateFinished = S.empty  , stateModal = Nothing  , stateStatus = ""  }runApp :: S.Seq Log.Entry -> IO (M.Map T.Text (S.Seq (S.Seq T.Text)))runApp entries = do  let state = newState entries      vty = Vty.mkVty Vty.defaultConfig  final <- Brick.customMain vty Nothing app state  return (stateSections final)app :: Brick.App State () ()app = Brick.App  { Brick.appDraw         = draw  , Brick.appChooseCursor = Brick.showFirstCursor  , Brick.appHandleEvent  = event  , Brick.appStartEvent   = return  , Brick.appAttrMap      = \ _ -> Brick.forceAttrMap mempty  }draw :: State -> [Brick.Widget ()]draw st  | Just ConfirmQuitModal <- stateModal st =      [ Brick.txt "Are you sure you want to quit? (y/n)" ]  | otherwise =      [ Brick.vBox        [ Brick.str (show (stateModal st))        , Brick.txt (stateStatus st)        ]      ]type EventHandler =  State -> Vty.Key -> [Vty.Modifier] -> Brick.EventM () (Brick.Next State)event :: State -> Brick.BrickEvent () () -> Brick.EventM () (Brick.Next State)event st (Brick.VtyEvent (Vty.EvKey key mod)) =  case stateModal st of    Nothing -> mainEvent st key mod    Just ConfirmQuitModal -> confirmQuitEvent st key mod    Just (AddSectionModal ()) -> addSectionEvent st key modevent st _ = Brick.continue stmainEvent :: EventHandlermainEvent st (Vty.KChar ' ') [] = do  let car S.:< cdr = S.viewl (stateCommits st)  Brick.continue st    { stateFinished = Skip car S.<| stateFinished st    , stateCommits = cdr    , stateStatus = "skipped"    }mainEvent st (Vty.KChar 'q') [] =  Brick.continue st { stateModal = Just ConfirmQuitModal }mainEvent st (Vty.KChar 'a') [] =  Brick.continue st { stateModal = Just (AddSectionModal ()) }mainEvent st (Vty.KChar c) []  | Just annot <- M.lookup c (stateKeys st) = do      let car S.:< cdr = S.viewl (stateCommits st)      Brick.continue st        { stateFinished = Annot annot car S.<| stateFinished st        , stateCommits  = cdr        , stateSections =          M.adjust ((Log.logMessage car) S.<|) annot (stateSections st)        , stateStatus =          "Added " <> Log.logCommit car <> " to section " <> annot        }  | otherwise =    Brick.continue st { stateStatus = "Unknown keybindings: " <> T.pack (show c) }mainEvent st _ _ = Brick.continue stconfirmQuitEvent :: EventHandlerconfirmQuitEvent st (Vty.KChar 'y') _ = Brick.halt stconfirmQuitEvent st _ _  = Brick.continue st { stateModal = Nothing }addSectionEvent :: EventHandleraddSectionEvent st _ _ = Brick.continue st { stateModal = Nothing }
 |