matsuri-0.0.1: Main.hs
{-# LANGUAGE RecordWildCards #-}
-- | Main.hs
-- Main program module.
import Buffers
import Config
import Help
import Jabber
import UI
import Network
import Control.Concurrent
import Control.Concurrent.MVar
import qualified Data.Map as M
import Graphics.Vty
import Graphics.Vty.Widgets.All
import qualified Widgets.Tree as T
import qualified Widgets.EditBox as E
-- | Read configs and start main loop.
main = withSocketsDo $ do
-- read config
(config, buffers) <- readConfig ".matsurirc"
vty <- mkVty
mev <- newEmptyMVar
-- main loop
forkIO $ loopGetEvent mev vty
rerender mev vty (defaultUI buffers) config buffers
-- disconnect all accounts
mapM_ disconnect $ [acc | BufAccount acc <- (M.elems buffers)]
-- shutdown && exiting
shutdown vty
where
loopGetEvent mev vty = do
event <- next_event vty
putMVar mev (VtyEvent event)
loopGetEvent mev vty
-- | Get event and process it.
mainLoop mev vty st@(UIState {..}) config buffers = do
event <- takeMVar mev
case event of
InsBuffer k buffer -> insElem' k buffer
---
NewMsg k msg ->
case getBuf k buffers of
BufChat chat -> do
let contents = msg:(chatContents chat)
insElem' k $ BufChat chat{chatContents=contents}
_ -> skip
---
NewStatus k status' ->
case getBuf k buffers of
BufChat chat -> insElem' k $ BufChat chat{status=status'}
_ -> skip
---
VtyEvent event' -> case event' of
-- tree
EvKey (KASCII 'p') [MCtrl] -> rerender' $ st { roster = T.moveUp roster }
EvKey (KASCII 'n') [MCtrl] -> rerender' $ st { roster = T.moveDn roster }
EvKey KEnter [] | E.contents edit == "" ->
case getAccount cur buffers of
Just acc ->
let buf = BufAccount acc{accCollapsed = not $ accCollapsed acc}
in insElem' cur buf
_ -> skip
-- show/hide
EvKey (KASCII 'v') [MCtrl] ->
let isShow = getCF "show_roster" config
isShow' = if null isShow then "1"
else ""
config' = setCF "show_roster" isShow' config
in rerender mev vty st config' buffers
-- edit box
EvKey (KASCII c ) [] -> rerender' $ st { edit = E.insert c edit }
EvKey (KASCII 'a') [MCtrl] -> rerender' $ st { edit = E.moveToHome edit }
EvKey (KASCII 'f') [MCtrl] -> rerender' $ st { edit = E.moveRight edit }
EvKey (KASCII 'b') [MCtrl] -> rerender' $ st { edit = E.moveLeft edit }
EvKey (KASCII 'e') [MCtrl] -> rerender' $ st { edit = E.moveToEnd edit }
EvKey KBS [] -> rerender' $ st { edit = E.backSpace edit }
EvKey KDel [] -> rerender' $ st { edit = E.delete edit }
-- parse command || send message
EvKey KEnter [] -> case E.contents edit of
"/q" -> return ()
('/':cmd) -> do
buffers' <- parseCmd cmd
let st' = st { edit = E.empty
, roster = mkTree roster buffers'
}
rerender mev vty st' config buffers'
msg -> case getBuf cur buffers of
BufChat chat -> do
buffer <- sendChatMessage chat (E.contents edit)
let buffers' = insElem cur buffer buffers
st' = st { edit = E.empty }
rerender mev vty st' config buffers'
_ -> skip
-- other
EvResize w h -> rerender' st
EvKey (KASCII 'q') [MCtrl] -> return ()
_ -> skip
where
skip = mainLoop mev vty st config buffers
rerender' st = rerender mev vty st config buffers
-- insert new element in buffer (or simply replace old element)
-- and re-create roster tree
insElem' k buffer =
let buffers' = insElem k buffer buffers
st' = st { roster = mkTree roster buffers' }
in rerender mev vty st' config buffers'
-- connect
parseCmd "c" = case getAccount cur buffers of
Just acc -> do
buffer <- connect mev config acc
return $ insElem (accName acc) buffer buffers
_ -> ins2help (InfoMsg "can't connect: not an account")
-- disconnect
parseCmd "d" = case getAccount cur buffers of
Just acc -> do
buffer <- disconnect acc
let buffers' = insElem cur buffer buffers
buffers'' = killBuffers (accName acc++"|") buffers'
return buffers''
_ -> ins2help (InfoMsg "can't disconnect: not an account")
where cur = T.cur roster
-- help
parseCmd "help" = ins2help (InfoMsg help_all)
parseCmd unknown_cmd = ins2help (InfoMsg $ "unknown `"++unknown_cmd++
"' command, try `/help'")
---
cur = T.cur roster
ins2help cnt = return $ case getBuf "help" buffers of
BufHelp cnts -> insElem "help" (BufHelp $ cnt:cnts) buffers
_ -> buffers
rerender mev vty st config buffers
= mkImage vty (mkUI st config buffers) >>=
update vty . pic_for_image >>
mainLoop mev vty st config buffers