{-# LANGUAGE RecordWildCards #-} -- | Main.hs -- Main program module. import Buffers import Config import Cmd import Help import Jabber import UI import Utils import Network import Network.XMPP.MUC import Control.Concurrent import Control.Concurrent.MVar import qualified Data.Map as M import Graphics.Vty import Graphics.Vty.Widgets.All import qualified Widgets.ListBox as L 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 DisplayRegion w h <- display_bounds $ terminal vty let ui = resizeUI (fromIntegral w) (fromIntegral h) $ defaultUI buffers rerender mev vty ui 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 -> let contents = msg:(chatContents chat) in insElem' k $ BufChat chat{chatContents=contents} BufRoom room -> let contents = msg:(roomContents room) in insElem' k $ BufRoom room{roomContents=contents} _ -> skip --- NewStatus k status' -> case getBuf k buffers of BufChat chat -> insElem' k $ BufChat chat{status=status'} _ -> skip --- NewRoomMsg k ev -> case getBuf k buffers of BufRoom room -> insElem' k (updRoom ev room) _ -> skip --- RoomPresence k presence -> case getBuf k buffers of BufRoom room -> do (cnt, occs) <- updateRoomOccupants presence (roomOccupants room) (roomNick room) let buf = BufRoom room{ roomContents=cnt++(roomContents room) , roomOccupants=occs } insElem' k buf _ -> skip --- RoomList k list -> case getBuf k buffers of BufRoom room -> do w <- getW' info <- withTime " == " (showRoomList list w) let cnts = (InfoMsg info):(roomContents room) insElem' k $ BufRoom room{roomContents=cnts} _ -> skip --- VtyEvent event' -> case event' of -- roster EvKey (KASCII 'p') [MCtrl] -> rerender' $ st { roster = L.moveUp roster } EvKey (KASCII 'n') [MCtrl] -> rerender' $ st { roster = L.moveDn roster } EvKey KEnter [] | E.contents edit == "" -> case getBuf cur buffers of BufAccount acc -> let buf = BufAccount acc{accCollapsed = not $ accCollapsed acc} in insElem' cur buf BufGroup grp -> let buf = BufGroup grp{grpCollapsed = not $ grpCollapsed grp} 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 -- editbox 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 'f') [MMeta] -> rerender' $ st { edit = E.moveWordRight edit } EvKey (KASCII 'b') [MMeta] -> rerender' $ st { edit = E.moveWordLeft 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 content | words content == ["/quit"] -> return () ('/':'/':msg) -> sendMsg ('/':msg) ('/':cmd) -> do w <- getW' buffers' <- doCmd mev config buffers acc cur cmd w let st' = st { edit = E.empty edit , roster = mkListBox roster buffers' } rerender mev vty st' config buffers' msg -> sendMsg msg -- other EvResize w h -> rerender' $ resizeUI w h st EvKey (KASCII 'q') [MCtrl] -> return () _ -> skip where skip = mainLoop mev vty st config buffers rerender' st = rerender mev vty st config buffers -- send msg to chat sendMsg msg = case getBuf cur buffers of -- fix copypaste? BufChat chat -> do buffer <- sendChatMessage acc chat msg let buffers' = insElem cur buffer buffers st' = st { edit = E.empty edit } rerender mev vty st' config buffers' BufRoom room -> do sendRoomMessage acc room msg let st' = st { edit = E.empty edit } rerender mev vty st' config buffers _ -> skip -- 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 = mkListBox roster buffers' } in rerender mev vty st' config buffers' -- current account acc = case getBuf cur buffers of BufAccount acc' -> acc' BufGroup grp -> getAcc' (grpName grp) BufChat chat -> getAcc' (chatName chat) BufRoom room -> getAcc' (roomName room) where getAcc' name = getAcc (takeWhile (/='|') name) buffers -- current buffer cur = L.cur roster -- get textbox width getW' = do w <- getW vty let roster_width = if null $ getCF "show_roster" config then 0 else read $ getCF "roster_width" config textbox_width = w - roster_width - 1 return textbox_width rerender mev vty st config buffers = mkImage vty (mkUI st config buffers) >>= update vty . pic_for_image >> mainLoop mev vty st config buffers