{-# LANGUAGE OverloadedStrings #-} module Much.State where import Blessings import Data.Aeson import Data.CaseInsensitive qualified as CI import Data.Default import Data.Functor.Identity import Data.Map qualified as M import Data.Text qualified as T import Data.Time import Data.Tree qualified as Tree import Data.Tree.Zipper qualified as Z import GHC.Generics import Much.API.Config qualified import Much.TreeView (TreeView(TVSearch)) import Notmuch.Message qualified as Notmuch import Scanner import System.Posix.Signals data State = State { cursor :: Z.TreePos Z.Full TreeView , xoffset :: Int , yoffset :: Int , flashMessage :: Blessings String , screenWidth :: Int , screenHeight :: Int , headBuffer :: [Blessings String] , treeBuffer :: [Blessings String] , now :: UTCTime , signalHandlers :: [(Signal, IO ())] , query :: String , keymap :: String -> State -> IO State , mousemap :: Scan -> State -> IO State , aliases :: M.Map T.Text T.Text , colorConfig :: ColorConfig Identity , apiConfig :: Much.API.Config.Config , attachmentOverwrite :: Bool , attachmentDirectory :: FilePath , attachmentFileName :: Notmuch.Message -> Notmuch.MessagePart -> FilePath } instance Show (State -> IO ()) where show = const "λ" data ColorConfig f = ColorConfig { alt :: f Pm , search :: f Pm , focus :: f Pm , quote :: f Pm , boring :: f Pm , prefix :: f Pm , date :: f Pm , tags :: f Pm , unreadSearch :: f Pm , unreadMessage :: f Pm , boringMessage :: f Pm , tagMap :: f (M.Map T.Text (f Pm)) , unprintableFocus :: f Pm , unprintableNormal :: f Pm } deriving (Generic) instance Applicative f => Default (ColorConfig f) where def = ColorConfig { tagMap = pure $ M.fromList [ ("killed", pure [38,5,088]) , ("star", pure [38,5,226]) , ("draft", pure [38,5,202]) ] , alt = pure [38,5,182] , search = pure [38,5,162] , focus = pure [38,5,160] , unprintableFocus = pure [38,5,204] , unprintableNormal = pure [35] , quote = pure [38,5,242] , boring = pure [38,5,240] , prefix = pure [38,5,235] , date = pure [38,5,071] , tags = pure [38,5,036] , boringMessage = pure [38,5,023] , unreadMessage = pure [38,5,117] , unreadSearch = pure [38,5,250] } instance FromJSON (ColorConfig Maybe) instance Default State where def = State { cursor = Z.fromTree (Tree.Node (TVSearch "") []) , xoffset = 0 , yoffset = 0 , flashMessage = "Welcome to much; quit with ^C" , screenWidth = 0 , screenHeight = 0 , headBuffer = [] , treeBuffer = [] , now = UTCTime (fromGregorian 1984 5 23) 49062 , signalHandlers = [] , query = "tag:inbox AND NOT tag:killed" , keymap = const return , mousemap = const return , colorConfig = def , aliases = M.empty , apiConfig = def , attachmentOverwrite = False , attachmentDirectory = "/tmp" , attachmentFileName = \message part -> case Notmuch.partContentFilename part of Just partFileName -> T.unpack partFileName Nothing -> "much_" <> formatTime defaultTimeLocale "%s" (Notmuch.messageTime message) <> "_" <> show (Notmuch.partID part) <> extension (Notmuch.partContentType part) } extension :: CI.CI T.Text -> String extension "text/html" = ".html" extension "text/plain" = ".txt" extension _ = ""