diff options
-rw-r--r-- | xmobar.hs | 90 |
1 files changed, 58 insertions, 32 deletions
@@ -30,7 +30,9 @@ module Main ( -- * Configuration -- $commands , getOptions , execCommands - , runCom + , execCommand + , runCommandLoop + , readVariables -- * Parsing -- $parser , parseString @@ -121,20 +123,21 @@ main = runXMobar :: Xbar () runXMobar = do config <- ask - dwgf <- io $ createWin config - eventLoop dwgf + dw <- createWin config + cl <- io $ parseTemplate config (template config) + var <- io $ execCommands config cl + eventLoop dw var -- | The event loop -eventLoop :: (Display, Window) -> Xbar () -eventLoop (d,w) = +eventLoop :: (Display, Window) -> [(ThreadId, MVar String)] -> Xbar () +eventLoop (d,w) var = do c <- ask - cl <- io $ parseTemplate c (template c) - i <- io $ execCommands c cl + i <- io $ readVariables var ps <- io $ parseString c i io $ drawInWin c (d,w) ps -- back again: we are never ending io $ threadDelay $ 100000 * refresh c - eventLoop (d,w) + eventLoop (d,w) var -- | The function to create the initial window createWin :: Config -> Xbar (Display, Window) @@ -210,30 +213,53 @@ getOptions c com = _ -> [] -- | Runs a list of programs -execCommands :: Config -> [(String,String,String)] -> IO String -execCommands _ [] = return "" -execCommands _ ((_,"",_):_) = return "Could not parse template" -execCommands c ((s,com,ss):xs) = - do i <- runCom c com +execCommands :: Config -> [(String,String,String)] -> IO [(ThreadId, MVar String)] +execCommands _ [] = return [] +execCommands c (x:xs) = + do i <- execCommand c x is <- execCommands c xs - return $ s ++ i ++ ss ++ is + return $ i : is + +execCommand :: Config -> (String,String,String) -> IO (ThreadId, MVar String) +execCommand c com = + do var <- newMVar "" + h <- forkIO $ runCommandLoop var c com + return (h,var) -- | Runs the external program -runCom :: Config -> String -> IO String -runCom c com = - do (i,o,e,p) <- runInteractiveCommand (com ++ concat (map (' ':) $ getOptions c com)) - -- the followinf leaks memory - --(i,o,e,p) <- runInteractiveProcess com (getOptions c com) Nothing Nothing - exit <- waitForProcess p - let closeHandles = do hClose o - hClose i - hClose e - case exit of - ExitSuccess -> do str <- hGetLine o - closeHandles - return str - _ -> do closeHandles - return $ "Could not execute command " ++ com +runCommandLoop :: MVar String -> Config -> (String,String,String) -> IO () +runCommandLoop var conf c@(s,com,ss) + | com == "" = + do modifyMVar_ var (\_ -> return $ "Could not parse the template") + threadDelay $ 100000 * refresh conf + runCommandLoop var conf c + | otherwise = + do (i,o,e,p) <- runInteractiveCommand (com ++ concat (map (' ':) $ getOptions conf com)) + -- the followinf leaks memory + --(i,o,e,p) <- runInteractiveProcess com (getOptions c com) Nothing Nothing + exit <- waitForProcess p + let closeHandles = do hClose o + hClose i + hClose e + case exit of + ExitSuccess -> do str <- hGetLine o + closeHandles + modifyMVar_ var (\_ -> return $ s ++ str ++ ss) + threadDelay $ 100000 * refresh conf + runCommandLoop var conf c + _ -> do closeHandles + modifyMVar_ var $ \_ -> return $ "Could not execute command " ++ com + threadDelay $ 100000 * refresh conf + runCommandLoop var conf c + + +-- | Reads MVars set by 'runCommandLoop' +readVariables :: [(ThreadId, MVar String)] -> IO String +readVariables [] = return "" +readVariables ((h,v):xs) = + do f <- readMVar v + fs <- readVariables xs + return $! f ++ fs {- $parser These are the neede parsers. Don't trust them too much. @@ -277,9 +303,9 @@ colorsAndText config = -- | Parses the output template string templateStringParser :: Config -> Parser (String,String,String) templateStringParser c = - do{ s <- many $ noneOf "%" + do{ s <- many $ noneOf (sepChar c) ; (_,com,_) <- templateCommandParser c - ; ss <- many $ noneOf "%" + ; ss <- many $ noneOf (sepChar c) ; return (s, com, ss) } @@ -294,7 +320,7 @@ templateCommandParser c = } -- | Combines the template parsers templateParser :: Config -> Parser [(String,String,String)] -templateParser c = many (templateStringParser c <|> templateCommandParser c) +templateParser c = many (templateStringParser c) -- | Actually runs the template parsers parseTemplate :: Config -> String -> IO [(String,String,String)] |