diff options
| -rw-r--r-- | Xmobar.hs | 95 | 
1 files changed, 36 insertions, 59 deletions
| @@ -26,9 +26,7 @@ module Xmobar (-- * Main Stuff                , printStrings                -- * Program Execution                -- $commands -              , execCommands                , execCommand -              , runCommandLoop                , readVariables                -- * Unmamaged Windows                -- $unmanwin @@ -66,13 +64,13 @@ newtype Xbar a = X (ReaderT Config (StateT XState IO) a)  -- | The State component of StateT  data XState =       XState { display :: Display -           , window :: Window -           , vars :: [(ThreadId, MVar String)] +           , window  :: Window +           , vars    :: [(Maybe ThreadId, MVar String)]             }  -- | We use get to get the state and ask to get the configuration: whis way   -- functions requires less arguments. -runXbar :: Config -> [(ThreadId, MVar String)] -> Display -> Window -> Xbar () -> IO () +runXbar :: Config -> [(Maybe ThreadId, MVar String)] -> Display -> Window -> Xbar () -> IO ()  runXbar c v d w (X f) =       do runStateT (runReaderT f c) (XState d w v)         return () @@ -90,7 +88,7 @@ nextEvent' d p = do      fd = connectionNumber d  -- | The event loop -eventLoop :: Config -> [(ThreadId, MVar String)] -> Display -> Window -> IO () +eventLoop :: Config -> [(Maybe ThreadId, MVar String)] -> Display -> Window -> IO ()  eventLoop c v d w = do      t <- forkIO (block go)      timer t @@ -111,21 +109,21 @@ createWin :: Config -> IO (Display, Window)  createWin config =    do dpy   <- openDisplay ""       let dflt = defaultScreen dpy -     rootw  <- rootWindow dpy dflt -     win <- mkUnmanagedWindow dpy (defaultScreenOfDisplay dpy) rootw  +     rootw <- rootWindow dpy dflt +     win   <- mkUnmanagedWindow dpy (defaultScreenOfDisplay dpy) rootw               (fi $ xPos config)               (fi $ yPos config)               (fi $ width config)               (fi $ height config)       selectInput dpy win exposureMask -     mapWindow dpy win +     mapWindow   dpy win       return (dpy,win)  updateWin :: Xbar ()  updateWin = -    do c <- ask -       s <- get -       i <- io $ readVariables (vars s) +    do c  <- ask +       s  <- get +       i  <- io $ readVariables (vars s)         ps <- io $ parseString c i         drawInWin ps @@ -134,14 +132,14 @@ updateWin =  -- | Draws in and updates the window  drawInWin :: [(String, String)] -> Xbar ()  drawInWin str =  -    do config <- ask -       st <- get +    do config  <- ask +       st      <- get         let (dpy,win) = (display st, window st) -       bgcolor  <-  io $ initColor dpy $ bgColor config -       gc <- io $ createGC dpy win +       bgcolor <-  io $ initColor dpy $ bgColor config +       gc      <- io $ createGC dpy win         --let's get the fonts         let lf c = loadQueryFont dpy (font c) -       fontst <-  io $ catch (lf config) (const $ lf defaultConfig) +       fontst  <-  io $ catch (lf config) (const $ lf defaultConfig)         io $ setFont dpy gc (fontFromFontStruct fontst)         -- create a pixmap to write to and fill it with a rectangle         p <- io $ createPixmap dpy win  @@ -177,14 +175,14 @@ printStrings d gc fontst offs sl@((s,c,l):xs) =      do config <- ask         st <- get         let (_,asc,_,_) = textExtents fontst s -           totSLen = foldr (\(_,_,len) -> (+) len) 0 sl -           valign = (fi (height config) + fi asc) `div` 2 -           remWidth = fi (width config) - fi totSLen -           offset = case (align config) of -                      "center" -> (remWidth + offs) `div` 2 -                      "right" -> remWidth - 1 -                      "left" -> offs -                      _ -> offs +           totSLen     = foldr (\(_,_,len) -> (+) len) 0 sl +           valign      = (fi (height config) + fi asc) `div` 2 +           remWidth    = fi (width config) - fi totSLen +           offset      = case (align config) of +                           "center" -> (remWidth + offs) `div` 2 +                           "right"  -> remWidth - 1 +                           "left"   -> offs +                           _        -> offs         fgcolor <- io $ initColor (display st) c         bgcolor <- io $ initColor (display st) (bgColor config)         io $ setForeground (display st) gc fgcolor @@ -194,34 +192,23 @@ printStrings d gc fontst offs sl@((s,c,l):xs) =  -- $commands --- | Runs a list of programs as independent threads and returns their thread id --- and the MVar they will be writing to. -execCommands :: Config -> [(Runnable,String,String)] -> IO [(ThreadId, MVar String)] -execCommands c xs = mapM (execCommand c) xs - -execCommand :: Config -> (Runnable,String,String) -> IO (ThreadId, MVar String) -execCommand c com =  -    do var <- newMVar "Updating..." -       h <- forkIO $ runCommandLoop var c com -       return (h,var) - -runCommandLoop :: MVar String -> Config -> (Runnable,String,String) -> IO () -runCommandLoop var conf c@(com,s,ss) -    | alias com == "" =  -        do modifyMVar_ var (\_ -> return $ "Could not parse the template") -           tenthSeconds (refresh conf) -           runCommandLoop var conf c -    | otherwise = -        do str <- run com -           modifyMVar_ var (\_ -> return $ s ++ str ++ ss) -           tenthSeconds (rate com)  -           runCommandLoop var conf c +-- | Runs a command as an independent thread and returns its thread id +-- and the MVar the command will be writing to. +execCommand :: (Runnable,String,String) -> IO (Maybe ThreadId, MVar String) +execCommand (com,s,ss) +    | alias com == ""  = do var <- newMVar "Updating..." +                            modifyMVar_ var (const $ return $ "Could not parse the template") +                            return (Nothing,var) +    | otherwise        = do var <- newMVar "Updating..." +                            let cb str = modifyMVar_ var (\_ -> return $ s ++ str ++ ss) +                            h <- forkIO $ start com cb +                            return (Just h,var)  -- | Reads MVars set by 'runCommandLoop' -readVariables :: [(ThreadId, MVar String)] -> IO String +readVariables :: [(Maybe ThreadId, MVar String)] -> IO String  readVariables [] = return ""  readVariables ((_,v):xs) = -    do f <- readMVar v +    do f  <- readMVar v         fs <- readVariables xs         return $! f ++ fs @@ -270,16 +257,6 @@ initColor' dpy c = (color_pixel . fst) `liftM` allocNamedColor dpy colormap c  io :: IO a -> Xbar a  io = liftIO --- | Work arount to the Int max bound: since threadDelay takes an Int, it --- is not possible to set a thread delay grater than about 45 minutes. --- With a little recursion we solve the problem. -tenthSeconds :: Int -> IO () -tenthSeconds s | s >= x = do threadDelay y -                             tenthSeconds (x - s) -               | otherwise = threadDelay (s * 100000) -               where y = (maxBound :: Int) -                     x = y `div` 100000 -  -- | Short-hand for 'fromIntegral'  fi :: (Integral a, Num b) => a -> b  fi = fromIntegral | 
