xmobar 0.32 → 0.33
raw patch · 31 files changed
+829/−302 lines, 31 filesdep +bsd-sysctldep +cerealdep +netlink
Dependencies added: bsd-sysctl, cereal, netlink
Files
- changelog.md +26/−1
- readme.md +56/−34
- src/Xmobar/App/EventLoop.hs +37/−9
- src/Xmobar/App/Main.hs +12/−9
- src/Xmobar/App/Timer.hs +221/−0
- src/Xmobar/Plugins/DateZone.hs +1/−1
- src/Xmobar/Plugins/MBox.hs +2/−7
- src/Xmobar/Plugins/Mail.hs +2/−8
- src/Xmobar/Plugins/Monitors.hs +9/−9
- src/Xmobar/Plugins/Monitors/Alsa.hs +4/−9
- src/Xmobar/Plugins/Monitors/Batt.hs +59/−25
- src/Xmobar/Plugins/Monitors/Bright.hs +1/−8
- src/Xmobar/Plugins/Monitors/Common/Parsers.hs +13/−0
- src/Xmobar/Plugins/Monitors/Common/Run.hs +24/−3
- src/Xmobar/Plugins/Monitors/Common/Types.hs +3/−2
- src/Xmobar/Plugins/Monitors/CoreTemp.hs +1/−2
- src/Xmobar/Plugins/Monitors/Cpu.hs +1/−7
- src/Xmobar/Plugins/Monitors/Disk.hs +35/−39
- src/Xmobar/Plugins/Monitors/MPD.hs +2/−8
- src/Xmobar/Plugins/Monitors/Mem.hs +1/−7
- src/Xmobar/Plugins/Monitors/MultiCoreTemp.hs +1/−7
- src/Xmobar/Plugins/Monitors/MultiCpu.hs +1/−7
- src/Xmobar/Plugins/Monitors/Net.hs +2/−8
- src/Xmobar/Plugins/Monitors/UVMeter.hs +68/−16
- src/Xmobar/Plugins/Monitors/Volume.hs +26/−12
- src/Xmobar/Plugins/Monitors/Weather.hs +122/−35
- src/Xmobar/Plugins/Monitors/Wireless.hs +70/−11
- src/Xmobar/Run/Command.hs +1/−1
- src/Xmobar/Run/Exec.hs +3/−12
- src/Xmobar/X11/Draw.hs +2/−0
- xmobar.cabal +23/−5
changelog.md view
@@ -1,4 +1,29 @@-## Version 0.32+## Version 0.33 (February, 2020)++_New features_++ - New template parameter `<weather>` for the `Weather` plugin, potentially+ displaying specific weather conditions that are occurring near the+ station (thanks to *slotThe*).+ - New option `--weathers`, for `Weather` to display a default string in+ case the `weather` field is not reported (thanks to *slotThe*).+ - New template parameter `<volumestatus>` for the `Volume` plugin, combining+ the effects of `<volume>` and `<status>`. This will show the volume+ (possibly prefixed by `onString` or a percentage-based string) if and only+ if the volume is not muted. Otherwise it will show the+ `offString` (thanks to *slotThe*).+ - `Battery` and `BatteryN` now support FreeBSD (thanks to Dhananjay+ Balan).+ - New option `--useManager` for `Weather` and `UVMeter` to decide whether to+ use one single manager per monitor for managing network connections or+ create a new one every time a connection is made.+ - New more efficient time coalescing strategy for monitor updates,+ available with the threaded runtime: use the `with_threaded` flag+ to enable it (see #410; thanks to Tomáš Janoušek).+ - `Wireless` supports current nl80211 API on Linux now, old Wext ioctls still+ available as compile-time option (thanks to Paul Fertser).++## Version 0.32 (December, 2019) _New features_
readme.md view
@@ -117,12 +117,16 @@ option is needed for the MBox and Mail plugins to work. Requires the [hinotify] package. -- `with_iwlib` Support for wireless cards. Enables the Wireless- plugin. No Haskell library is required, but you will need the- [iwlib] C library and headers in your system (e.g., install- `libiw-dev` in Debian-based systems or `wireless_tools` on Arch- Linux).+- `with_nl80211` Support for wireless cards on Linux via nl80211 (all+ upstream drivers). Enables the Wireless plugin. Requires [netlink]+ and [cereal] packages. +- `with_iwlib` Support for wireless cards via Wext ioctls+ (deprecated). Enables the Wireless plugin. No Haskell library is+ required, but you will need the [iwlib] C library and headers in your+ system (e.g., install `libiw-dev` in Debian-based systems or+ `wireless_tools` on Arch Linux). Conflicts with `with_nl80211`.+ - `with_alsa` Support for ALSA sound cards. Enables the Volume plugin. Requires the [alsa-mixer] package. To install the latter, you'll need the [libasound] C library and headers in your system@@ -735,11 +739,20 @@ - Aliases to the Station ID: so `Weather "LIPB" []` can be used in template as `%LIPB%` - Thresholds refer to temperature in the selected units-- Args: default monitor arguments+- Args: default monitor arguments, plus:+ - `--weathers` _string_ : display a default string when the `weather`+ variable is not reported.+ - short option: `-w`+ - Default: ""+ - `--useManager` _bool_ : Whether to use one single manager per monitor for+ managing network connections or create a new one every time a connection is+ made.+ - Short option: `-m`+ - Default: True - Variables that can be used with the `-t`/`--template` argument: `station`, `stationState`, `year`, `month`, `day`, `hour`, `windCardinal`, `windAzimuth`, `windMph`, `windKnots`, `windMs`, `windKmh`- `visibility`, `skyCondition`, `tempC`, `tempF`,+ `visibility`, `skyCondition`, `weather`, `tempC`, `tempF`, `dewPointC`, `dewPointF`, `rh`, `pressure` - Default template: `<station>: <tempC>C, rh <rh>% (<hour>)` - Retrieves weather information from http://tgftp.nws.noaa.gov.@@ -811,18 +824,21 @@ ### `Wireless Interface Args RefreshRate` -- If set to "", the interface is looked up in /proc/net/wireless.+- If set to "", first suitable wireless interface is used. - Aliases to the interface name with the suffix "wi": thus, `Wireless "wlan0" []` can be used as `%wlan0wi%`, and `Wireless "" []` as `%wi%`. - Args: default monitor arguments, plus: - `--quality-icon-pattern`: dynamic string for connection quality in `qualityipat`. - Variables that can be used with the `-t`/`--template` argument:- `essid`, `quality`, `qualitybar`, `qualityvbar`, `qualityipat`-- Thresholds refer to link quality in a `[0, 100]` scale-- Default template: `<essid> <quality>`-- Requires the C library [iwlib] (part of the wireless tools suite)- installed in your system. In addition, to activate this plugin you- must pass `--flags="with_iwlib"` during compilation+ `ssid`, `signal`, `quality`, `qualitybar`, `qualityvbar`, `qualityipat`+- Thresholds refer to link quality on a `[0, 100]` scale. Note that+ `quality` is calculated from `signal` (in dBm) by a possibly lossy+ conversion. It is also not taking into account many factors such as+ noise level, air busy time, transcievers' capabilities and the+ others which can have drastic impact on the link performance.+- Default template: `<ssid> <quality>`+- To activate this plugin you must pass `--flags="with_nl80211"` or+ `--flags="with_iwlib"` during compilation ### `Memory Args RefreshRate` @@ -924,7 +940,7 @@ threshold (default: "") - `--mediums`: string for AC "off" status and power lower than the `-H` threshold (default: "")- - `--high`: string for AC "off" status and power higher than the `-H`+ - `--highs`: string for AC "off" status and power higher than the `-H` threshold (default: "") @@ -1178,7 +1194,8 @@ Defaults to "". - Long option: `--lows` - Variables that can be used with the `-t`/`--template` argument:- `volume`, `volumebar`, `volumevbar`, `volumeipat`, `dB`, `status`+ `volume`, `volumebar`, `volumevbar`, `volumeipat`, `dB`, `status`,+ `volumestatus` - Note that `dB` might only return 0 on your system. This is known to happen on systems with a pulseaudio backend. - Default template: `Vol: <volume>% <status>`@@ -1409,9 +1426,14 @@ ### `UVMeter` -- Aliases to "uv " + station id. For example: `%uv brisbane%` or `%uv- alice springs%`-- Args: default monitor arguments.+- Aliases to "uv " + station id. For example: `%uv Brisbane%` or `%uv+ Alice Springs%`+- Args: default monitor arguments, plus:+ - `--useManager` _bool_ : Whether to use one single manager per monitor for+ managing network connections or create a new one every time a connection is+ made.+ - Short option: `-m`+ - Default: True - *Reminder:* Keep the refresh rate high, to avoid making unnecessary requests every time the plug-in is run.@@ -1419,7 +1441,7 @@ http://www.arpansa.gov.au/uvindex/realtime/xml/uvvalues.xml - Example: - Run UVMeter "brisbane" ["-H", "3", "-L", "3", "--low", "green", "--high", "red"] 900+ Run UVMeter "Brisbane" ["-H", "3", "-L", "3", "--low", "green", "--high", "red"] 900 ## Executing External Commands @@ -1667,20 +1689,20 @@ with the help of the greater xmobar and Haskell communities. In particular, xmobar [incorporates patches] by Mohammed Alshiekh,-Alex Ameen, Axel Angel, Claudio Bley, Dragos Boca, Ben Boeckel, Duncan-Burke, Roman Cheplyaka, Patrick Chilton, Antoine Eiche, Nathaniel-Wesley Filardo, John Goerzen, Reto Hablützel, Juraj Hercek, Tomáš-Janoušek, Ada Joule, Spencer Janssen, Roman Joost, Jochen Keil,-Lennart Kolmodin, Krzysztof Kosciuszkiewicz, Dmitry Kurochkin, Todd-Lunter, Vanessa McHale, Robert J. Macomber, Dmitry Malikov, David-McLean, Marcin Mikołajczyk, Dino Morelli, Tony Morris, Eric Mrak,-Thiago Negri, Edward O'Callaghan, Svein Ove, Martin Perner, Jens-Petersen, Alexander Polakov, Pavan Rikhi, Petr Rockai, Andrew Emmanuel-Rosa, Sackville-West, Markus Scherer, Daniel Schüssler, Olivier-Schneider, Alexander Shabalin, Valentin Shirokov, Peter Simons,-Alexander Solovyov, Will Song, John Soros, Felix Springer, Travis-Staton, Artem Tarasov, Samuli Thomasson, Edward Tjörnhammar, Sergei-Trofimovich, Thomas Tuegel, John Tyree, Jan Vornberger, Anton+Alex Ameen, Axel Angel, Dhananjay Balan, Claudio Bley, Dragos Boca,+Ben Boeckel, Duncan Burke, Roman Cheplyaka, Patrick Chilton, Antoine+Eiche, Nathaniel Wesley Filardo, John Goerzen, Reto Hablützel, Juraj+Hercek, Tomáš Janoušek, Ada Joule, Spencer Janssen, Roman Joost,+Jochen Keil, Lennart Kolmodin, Krzysztof Kosciuszkiewicz, Dmitry+Kurochkin, Todd Lunter, Vanessa McHale, Robert J. Macomber, Dmitry+Malikov, David McLean, Marcin Mikołajczyk, Dino Morelli, Tony Morris,+Eric Mrak, Thiago Negri, Edward O'Callaghan, Svein Ove, Martin Perner,+Jens Petersen, Alexander Polakov, Pavan Rikhi, Petr Rockai, Andrew+Emmanuel Rosa, Sackville-West, Markus Scherer, Daniel Schüssler,+Olivier Schneider, Alexander Shabalin, Valentin Shirokov, Peter+Simons, Alexander Solovyov, Will Song, John Soros, Felix Springer,+Travis Staton, Artem Tarasov, Samuli Thomasson, Edward Tjörnhammar,+Sergei Trofimovich, Thomas Tuegel, John Tyree, Jan Vornberger, Anton Vorontsov, Daniel Wagner, Zev Weiss, Phil Xiaojun Hu, Edward Z. Yang and Norbert Zeh.
src/Xmobar/App/EventLoop.hs view
@@ -17,7 +17,12 @@ ------------------------------------------------------------------------------ -module Xmobar.App.EventLoop (startLoop, startCommand) where+module Xmobar.App.EventLoop+ ( startLoop+ , startCommand+ , newRefreshLock+ , refreshLock+ ) where import Prelude hiding (lookup) import Graphics.X11.Xlib hiding (textExtents, textWidth)@@ -31,7 +36,7 @@ import Control.Concurrent import Control.Concurrent.Async (Async, async) import Control.Concurrent.STM-import Control.Exception (handle, SomeException(..))+import Control.Exception (bracket_, handle, SomeException(..)) import Data.Bits import Data.Map hiding (foldr, map, filter) import Data.Maybe (fromJust, isJust)@@ -47,7 +52,10 @@ import Xmobar.X11.Draw import Xmobar.X11.Bitmap as Bitmap import Xmobar.X11.Types++#ifndef THREADED_RUNTIME import Xmobar.X11.Events(nextEvent')+#endif #ifdef XFT import Graphics.X11.Xft@@ -60,15 +68,34 @@ runX :: XConf -> X () -> IO () runX xc f = runReaderT f xc +newRefreshLock :: IO (TMVar ())+newRefreshLock = atomically $ newTMVar ()++refreshLock :: TMVar () -> IO a -> IO a+refreshLock var = bracket_ lock unlock+ where+ lock = atomically $ takeTMVar var+ unlock = atomically $ putTMVar var ()++refreshLockT :: TMVar () -> STM a -> STM a+refreshLockT var action = do+ takeTMVar var+ r <- action+ putTMVar var ()+ return r+ -- | Starts the main event loop and threads-startLoop :: XConf -> TMVar SignalType -> [[([Async ()], TVar String)]]- -> IO ()-startLoop xcfg@(XConf _ _ w _ _ _ _) sig vs = do+startLoop :: XConf+ -> TMVar SignalType+ -> TMVar ()+ -> [[([Async ()], TVar String)]]+ -> IO ()+startLoop xcfg@(XConf _ _ w _ _ _ _) sig pauser vs = do #ifdef XFT xftInitFtLibrary #endif tv <- atomically $ newTVar []- _ <- forkIO (handle (handler "checker") (checker tv [] vs sig))+ _ <- forkIO (handle (handler "checker") (checker tv [] vs sig pauser)) #ifdef THREADED_RUNTIME _ <- forkOS (handle (handler "eventer") (eventer sig)) #else@@ -108,15 +135,16 @@ -> [String] -> [[([Async ()], TVar String)]] -> TMVar SignalType+ -> TMVar () -> IO ()-checker tvar ov vs signal = do- nval <- atomically $ do+checker tvar ov vs signal pauser = do+ nval <- atomically $ refreshLockT pauser $ do nv <- mapM concatV vs guard (nv /= ov) writeTVar tvar nv return nv atomically $ putTMVar signal Wakeup- checker tvar nval vs signal+ checker tvar nval vs signal pauser where concatV = fmap concat . mapM (readTVar . snd)
src/Xmobar/App/Main.hs view
@@ -40,9 +40,10 @@ import Xmobar.X11.Text import Xmobar.X11.Window import Xmobar.App.Opts (recompileFlag, verboseFlag, getOpts, doOpts)-import Xmobar.App.EventLoop (startLoop, startCommand)+import Xmobar.App.EventLoop (startLoop, startCommand, newRefreshLock, refreshLock) import Xmobar.App.Compile (recompile, trace) import Xmobar.App.Config+import Xmobar.App.Timer (withTimer) xmobar :: Config -> IO () xmobar conf = withDeferSignals $ do@@ -53,14 +54,16 @@ cls <- mapM (parseTemplate (commands conf) (sepChar conf)) (splitTemplate (alignSep conf) (template conf)) sig <- setupSignalHandler- bracket (mapM (mapM $ startCommand sig) cls)- cleanupThreads- $ \vars -> do- (r,w) <- createWin d fs conf- let ic = Map.empty- to = textOffset conf- ts = textOffsets conf ++ replicate (length fl) (-1)- startLoop (XConf d r w (fs:fl) (to:ts) ic conf) sig vars+ refLock <- newRefreshLock+ withTimer (refreshLock refLock) $+ bracket (mapM (mapM $ startCommand sig) cls)+ cleanupThreads+ $ \vars -> do+ (r,w) <- createWin d fs conf+ let ic = Map.empty+ to = textOffset conf+ ts = textOffsets conf ++ replicate (length fl) (-1)+ startLoop (XConf d r w (fs:fl) (to:ts) ic conf) sig refLock vars configFromArgs :: Config -> IO Config configFromArgs cfg = getArgs >>= getOpts >>= doOpts cfg . fst
+ src/Xmobar/App/Timer.hs view
@@ -0,0 +1,221 @@+{-# LANGUAGE LambdaCase #-}+------------------------------------------------------------------------------+-- |+-- Module: Xmobar.App.Timer+-- Copyright: (c) 2019 Tomáš Janoušek+-- License: BSD3-style (see LICENSE)+--+-- Maintainer: Tomáš Janoušek <tomi@nomi.cz>+-- Stability: unstable+--+-- Timer coalescing for recurring actions.+--+------------------------------------------------------------------------------++module Xmobar.App.Timer+ ( doEveryTenthSeconds+ , tenthSeconds+ , withTimer+ ) where++import Control.Concurrent (threadDelay)+import Control.Concurrent.Async (withAsync)+import Control.Concurrent.STM+import Control.Exception+import Control.Monad (forever, forM, guard)+import Data.Foldable (foldrM, for_)+import Data.Int (Int64)+import Data.Map (Map)+import qualified Data.Map as M+import Data.Maybe (isJust, fromJust)+import Data.Time.Clock.POSIX (getPOSIXTime)+import Data.Unique+import System.IO.Unsafe (unsafePerformIO)++type Periods = Map Unique Period++data Tick = Tick (TMVar ()) | UnCoalesce++data Period = Period { rate :: Int64, next :: Int64, tick :: TMVar Tick }++data UnCoalesceException = UnCoalesceException deriving Show+instance Exception UnCoalesceException++{-# NOINLINE periodsVar #-}+periodsVar :: TVar (Maybe Periods)+periodsVar = unsafePerformIO $ newTVarIO Nothing++now :: IO Int64+now = do+ posix <- getPOSIXTime+ return $ floor (10 * posix)++newPeriod :: Int64 -> IO (Unique, Period)+newPeriod r = do+ u <- newUnique+ t <- now+ v <- atomically newEmptyTMVar+ let t' = t - t `mod` r+ return (u, Period { rate = r, next = t', tick = v })++-- | Perform a given action every N tenths of a second.+--+-- The timer is aligned (coalesced) with other timers to minimize the number+-- of wakeups and unnecessary redraws. If the action takes too long (one+-- second or when the next timer is due), coalescing is disabled for it and it+-- falls back to periodic sleep.+doEveryTenthSeconds :: Int -> IO () -> IO ()+doEveryTenthSeconds r action =+ doEveryTenthSecondsCoalesced r action `catch` \UnCoalesceException ->+ doEveryTenthSecondsSleeping r action++-- | Perform a given action every N tenths of a second,+-- coalesce with other timers using a given Timer instance.+doEveryTenthSecondsCoalesced :: Int -> IO () -> IO ()+doEveryTenthSecondsCoalesced r action = do+ (u, p) <- newPeriod (fromIntegral r)+ bracket_ (push u p) (pop u) $ forever $ bracket (wait p) done $ const action+ where+ push u p = atomically $ modifyTVar' periodsVar $ \case+ Just periods -> Just $ M.insert u p periods+ Nothing -> throw UnCoalesceException+ pop u = atomically $ modifyTVar' periodsVar $ \case+ Just periods -> Just $ M.delete u periods+ Nothing -> Nothing++ wait p = atomically (takeTMVar $ tick p) >>= \case+ Tick doneVar -> return doneVar+ UnCoalesce -> throwIO UnCoalesceException+ done doneVar = atomically $ putTMVar doneVar ()++-- | Perform a given action every N tenths of a second,+-- making no attempt to synchronize with other timers.+doEveryTenthSecondsSleeping :: Int -> IO () -> IO ()+doEveryTenthSecondsSleeping r action = go+ where go = action >> tenthSeconds r >> go++-- | Sleep for a given amount of tenths of a second.+--+-- (Work around 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 (x * 100000)+ tenthSeconds (s - x)+ | otherwise = threadDelay (s * 100000)+ where x = (maxBound :: Int) `div` 100000++-- | Start the timer coordination thread and perform a given IO action (this+-- is meant to surround the entire xmobar execution), terminating the timer+-- thread afterwards.+--+-- Additionally, if the timer thread fails, individual+-- 'doEveryTenthSecondsCoalesced' invocations that are waiting to be+-- coordinated by it are notified to fall back to periodic sleeping.+--+-- The timer thread _will_ fail immediately when running in a non-threaded+-- RTS.+withTimer :: (IO () -> IO ()) -> IO a -> IO a+withTimer pauseRefresh action =+ withAsync (timerThread `finally` cleanup) $ const action+ where+ timerThread = do+ atomically $ writeTVar periodsVar $ Just M.empty+ timerLoop pauseRefresh++ cleanup = atomically $ readTVar periodsVar >>= \case+ Just periods -> do+ for_ periods unCoalesceTimer'+ writeTVar periodsVar Nothing+ Nothing -> return ()++timerLoop :: (IO () -> IO ()) -> IO ()+timerLoop pauseRefresh = forever $ do+ tNow <- now+ (toFire, tMaybeNext) <- atomically $ do+ periods <- fromJust <$> readTVar periodsVar+ let toFire = timersToFire tNow periods+ let periods' = advanceTimers tNow periods+ let tMaybeNext = nextFireTime periods'+ writeTVar periodsVar $ Just periods'+ return (toFire, tMaybeNext)+ pauseRefresh $ do+ -- To avoid multiple refreshes, pause refreshing for up to 1 second,+ -- fire timers and wait for them to finish (update their text).+ -- Those that need more time (e.g. weather monitors) will be dropped+ -- from timer coalescing and will fall back to periodic sleep.+ timeoutVar <- registerDelay $ case tMaybeNext of+ Just tNext -> fromIntegral ((tNext - tNow) `max` 10) * 100000+ Nothing -> 1000000+ fired <- fireTimers toFire+ timeouted <- waitForTimers timeoutVar fired+ unCoalesceTimers timeouted+ delayUntilNextFire++advanceTimers :: Int64 -> Periods -> Periods+advanceTimers t = M.map advance+ where+ advance p | next p <= t = p { next = t - t `mod` rate p + rate p }+ | otherwise = p++timersToFire :: Int64 -> Periods -> [(Unique, Period)]+timersToFire t periods = [ (u, p) | (u, p) <- M.toList periods, next p <= t ]++nextFireTime :: Periods -> Maybe Int64+nextFireTime periods+ | M.null periods = Nothing+ | otherwise = Just $ minimum [ next p | p <- M.elems periods ]++fireTimers :: [(Unique, Period)] -> IO [(Unique, TMVar ())]+fireTimers toFire = atomically $ forM toFire $ \(u, p) -> do+ doneVar <- newEmptyTMVar+ putTMVar (tick p) (Tick doneVar)+ return (u, doneVar)++waitForTimers :: TVar Bool -> [(Unique, TMVar ())] -> IO [Unique]+waitForTimers timeoutVar fired = atomically $ do+ timeoutOver <- readTVar timeoutVar+ dones <- forM fired $ \(u, doneVar) -> do+ done <- isJust <$> tryReadTMVar doneVar+ return (u, done)+ guard $ timeoutOver || all snd dones+ return [u | (u, False) <- dones]++-- | Handle slow timers (drop and signal them to stop coalescing).+unCoalesceTimers :: [Unique] -> IO ()+unCoalesceTimers timers = atomically $ do+ periods <- fromJust <$> readTVar periodsVar+ periods' <- foldrM unCoalesceTimer periods timers+ writeTVar periodsVar $ Just periods'++unCoalesceTimer :: Unique -> Periods -> STM Periods+unCoalesceTimer u periods = do+ unCoalesceTimer' (periods M.! u)+ return $ u `M.delete` periods++unCoalesceTimer' :: Period -> STM ()+unCoalesceTimer' p = do+ _ <- tryTakeTMVar (tick p)+ putTMVar (tick p) UnCoalesce++delayUntilNextFire :: IO ()+delayUntilNextFire = do+ Just periods <- readTVarIO periodsVar+ let tMaybeNext = nextFireTime periods+ tNow <- now+ delayVar <- case tMaybeNext of+ Just tNext -> do+ -- Work around the Int max bound: threadDelay takes an Int, we can+ -- only sleep for so long, which is okay, we'll just check timers+ -- sooner and sleep again.+ let maxDelay = (maxBound :: Int) `div` 100000+ delay = (tNext - tNow) `min` fromIntegral maxDelay+ delayUsec = fromIntegral delay * 100000+ registerDelay delayUsec+ Nothing -> atomically $ newTVar False+ atomically $ do+ delayOver <- readTVar delayVar+ periods' <- fromJust <$> readTVar periodsVar+ let tMaybeNext' = nextFireTime periods'+ -- Return also if a new period is added (it may fire sooner).+ guard $ delayOver || tMaybeNext /= tMaybeNext'
src/Xmobar/Plugins/DateZone.hs view
@@ -72,7 +72,7 @@ else go (date f locale) - where go func = func >>= cb >> tenthSeconds r >> go func+ where go func = doEveryTenthSeconds r $ func >>= cb {-# NOINLINE localeLock #-} -- ensures that only one plugin instance sets the locale
src/Xmobar/Plugins/MBox.hs view
@@ -19,6 +19,7 @@ import Xmobar.Run.Exec #ifdef INOTIFY +import Xmobar.Plugins.Monitors.Common (parseOptsWith) import Xmobar.System.Utils (changeLoop, expandHome) import Control.Monad (when)@@ -63,12 +64,6 @@ , Option "s" ["suffix"] (ReqArg (\x o -> o { oSuffix = x }) "") "" ] -parseOptions :: [String] -> IO Options-parseOptions args =- case getOpt Permute options args of- (o, _, []) -> return $ foldr id defaults o- (_, _, errs) -> ioError . userError $ concat errs- #else import System.IO #endif@@ -86,7 +81,7 @@ " but the MBox plugin requires it" #else start (MBox boxes args _) cb = do- opts <- parseOptions args+ opts <- parseOptsWith options defaults args let showAll = oAll opts prefix = oPrefix opts suffix = oSuffix opts
src/Xmobar/Plugins/Mail.hs view
@@ -18,6 +18,7 @@ import Xmobar.Run.Exec #ifdef INOTIFY +import Xmobar.Plugins.Monitors.Common (parseOptsWith) import Xmobar.System.Utils (expandHome, changeLoop) import Control.Monad@@ -64,13 +65,6 @@ , Option "s" ["suffix"] (ReqArg (\x o -> o { oSuffix = x }) "") "" ] -parseOptions :: [String] -> IO MOptions-parseOptions args =- case getOpt Permute options args of- (o, _, []) -> return $ foldr id defaults o- (_, _, errs) -> ioError . userError $ concat errs-- -- | A list of mail box names and paths to maildirs. data Mail = Mail [(String, FilePath)] String deriving (Read, Show)@@ -92,7 +86,7 @@ #else start (MailX ms args _) cb = do vs <- mapM (const $ newTVarIO S.empty) ms- opts <- parseOptions args+ opts <- parseOptsWith options defaults args let prefix = oPrefix opts suffix = oSuffix opts dir = oDir opts
src/Xmobar/Plugins/Monitors.hs view
@@ -19,7 +19,7 @@ import Xmobar.Run.Exec -import Xmobar.Plugins.Monitors.Common (runM, runMD)+import Xmobar.Plugins.Monitors.Common (runM) #ifdef WEATHER import Xmobar.Plugins.Monitors.Weather #endif@@ -42,12 +42,12 @@ #ifdef UVMETER import Xmobar.Plugins.Monitors.UVMeter #endif-#ifdef IWLIB+#if defined IWLIB || defined USE_NL80211 import Xmobar.Plugins.Monitors.Wireless #endif #ifdef LIBMPD import Xmobar.Plugins.Monitors.MPD-import Xmobar.Plugins.Monitors.Common (runMBD)+import Xmobar.Plugins.Monitors.Common (runMBD, runMD) #endif #ifdef ALSA import Xmobar.Plugins.Monitors.Volume@@ -85,7 +85,7 @@ #ifdef UVMETER | UVMeter Station Args Rate #endif-#ifdef IWLIB+#if defined IWLIB || defined USE_NL80211 | Wireless Interface Args Rate #endif #ifdef LIBMPD@@ -142,7 +142,7 @@ #ifdef UVMETER alias (UVMeter s _ _) = "uv " ++ s #endif-#ifdef IWLIB+#if defined IWLIB || defined USE_NL80211 alias (Wireless i _ _) = i ++ "wi" #endif #ifdef LIBMPD@@ -164,8 +164,8 @@ start (TopProc a r) = startTop a r start (TopMem a r) = runM a topMemConfig runTopMem r #ifdef WEATHER- start (Weather s a r) = runMD (a ++ [s]) weatherConfig runWeather r weatherReady- start (WeatherX s c a r) = runMD (a ++ [s]) weatherConfig (runWeather' c) r weatherReady+ start (Weather s a r) = startWeather s a r+ start (WeatherX s c a r) = startWeather' c s a r #endif start (Thermal z a r) = runM (a ++ [z]) thermalConfig runThermal r start (ThermalZone z a r) =@@ -184,9 +184,9 @@ start (Uptime a r) = runM a uptimeConfig runUptime r start (CatInt _ s a r) = runM a catIntConfig (runCatInt s) r #ifdef UVMETER- start (UVMeter s a r) = runM (a ++ [s]) uvConfig runUVMeter r+ start (UVMeter s a r) = startUVMeter s a r #endif-#ifdef IWLIB+#if defined IWLIB || defined USE_NL80211 start (Wireless i a r) = runM a wirelessConfig (runWireless i) r #endif #ifdef LIBMPD
src/Xmobar/Plugins/Monitors/Alsa.hs view
@@ -57,17 +57,12 @@ where modifyVolumeOpts f o = o { aoVolumeOpts = f (aoVolumeOpts o) } -parseOpts :: [String] -> IO AlsaOpts-parseOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs-+-- | Drop generic Monitor args first, then apply 'parseOptsWith' in order to+-- parse everything. parseOptsIncludingMonitorArgs :: [String] -> IO AlsaOpts parseOptsIncludingMonitorArgs args =- -- Drop generic Monitor args first case getOpt Permute [] args of- (_, args', _) -> parseOpts args'+ (_, args', _) -> parseOptsWith options defaultOpts args' startAlsaPlugin :: String -> String -> [String] -> (String -> IO ()) -> IO () startAlsaPlugin mixerName controlName args cb = do@@ -80,7 +75,7 @@ -- it would have to inline 'runMBD', 'doArgs' and 'parseOpts' to see -- it, which probably isn't going to happen with the default -- optimization settings).- opts2 <- io $ parseOpts args2+ opts2 <- io $ parseOptsWith options defaultOpts args2 Volume.runVolumeWith (aoVolumeOpts opts2) mixerName controlName withMonitorWaiter mixerName (aoAlsaCtlPath opts) cb $ \wait_ ->
src/Xmobar/Plugins/Monitors/Batt.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE CPP #-}+ ----------------------------------------------------------------------------- -- | -- Module : Plugins.Monitors.Batt@@ -17,11 +19,14 @@ import System.Process (system) import Control.Monad (void, unless)-import Control.Exception (SomeException, handle) import Xmobar.Plugins.Monitors.Common+import Control.Exception (SomeException, handle) import System.FilePath ((</>)) import System.IO (IOMode(ReadMode), hGetLine, withFile) import System.Posix.Files (fileExist)+#ifdef FREEBSD+import System.BSD.Sysctl (sysctlReadInt)+#endif import System.Console.GetOpt import Data.List (sort, sortBy, group) import Data.Maybe (fromMaybe)@@ -103,14 +108,8 @@ , Option "" ["highs"] (ReqArg (\x o -> o { highString = x }) "") "" ] -parseOpts :: [String] -> IO BattOpts-parseOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs- data Status = Charging | Discharging | Full | Idle | Unknown deriving (Read, Eq)-+-- Result perc watts time-seconds Status data Result = Result Float Float Float Status | NA sysDir :: FilePath@@ -154,6 +153,39 @@ where c = 100 * min 1 charge +maybeAlert :: BattOpts -> Float -> IO ()+maybeAlert opts left =+ case onLowAction opts of+ Nothing -> return ()+ Just x -> unless (isNaN left || actionThreshold opts < 100 * left)+ $ void $ system x++-- | FreeBSD battery query+#ifdef FREEBSD+battStatusFbsd :: Int -> Status+battStatusFbsd x+ | x == 1 = Discharging+ | x == 2 = Charging+ | otherwise = Unknown++readBatteriesFbsd :: BattOpts -> IO Result+readBatteriesFbsd opts = do+ lf <- sysctlReadInt "hw.acpi.battery.life"+ rt <- sysctlReadInt "hw.acpi.battery.rate"+ tm <- sysctlReadInt "hw.acpi.battery.time"+ st <- sysctlReadInt "hw.acpi.battery.state"+ acline <- sysctlReadInt "hw.acpi.acline"+ let p = fromIntegral lf / 100+ w = fromIntegral rt+ t = fromIntegral tm * 60+ ac = acline == 1+ -- battery full when rate is 0 and on ac.+ sts = if (w == 0 && ac) then Full else (battStatusFbsd $ fromIntegral st)+ unless ac (maybeAlert opts p)+ return (Result p w t sts)++#else+-- | query linux battery safeFileExist :: String -> String -> IO Bool safeFileExist d f = handle noErrors $ fileExist (d </> f) where noErrors = const (return False) :: SomeException -> IO Bool@@ -195,7 +227,7 @@ a' = max a b -- sometimes the reported max charge is lower than return $ Battery (3600 * a' / sc') -- wattseconds (3600 * b / sc') -- wattseconds- (d / sc') -- watts+ (abs d / sc') -- watts s -- string: Discharging/Charging/Full where grab f = handle onError $ withFile f ReadMode (fmap read . hGetLine) onError = const (return (-1)) :: SomeException -> IO Float@@ -210,15 +242,8 @@ mostCommonDef :: Eq a => a -> [a] -> a mostCommonDef x xs = head $ last $ [x] : sortOn length (group xs) -maybeAlert :: BattOpts -> Float -> IO ()-maybeAlert opts left =- case onLowAction opts of- Nothing -> return ()- Just x -> unless (isNaN left || actionThreshold opts < 100 * left)- $ void $ system x--readBatteries :: BattOpts -> [Files] -> IO Result-readBatteries opts bfs =+readBatteriesLinux :: BattOpts -> [Files] -> IO Result+readBatteriesLinux opts bfs = do let bfs' = filter (/= NoFiles) bfs bats <- mapM (readBattery (scale opts)) (take 3 bfs') ac <- haveAc (onlineFile opts)@@ -239,25 +264,34 @@ | otherwise = Discharging unless ac (maybeAlert opts left) return $ if isNaN left then NA else Result left watts time racst+#endif runBatt :: [String] -> Monitor String runBatt = runBatt' ["BAT", "BAT0", "BAT1", "BAT2"] runBatt' :: [String] -> [String] -> Monitor String runBatt' bfs args = do- opts <- io $ parseOpts args- let sp = incPerc opts- c <- io $ readBatteries opts =<< mapM batteryFiles bfs+ opts <- io $ parseOptsWith options defaultOpts args+#ifdef FREEBSD+ c <- io $ readBatteriesFbsd opts+#else+ c <- io $ readBatteriesLinux opts =<< mapM batteryFiles bfs+#endif+ formatResult c opts++formatResult :: Result -> BattOpts -> Monitor String+formatResult res bopt = do+ let sp = incPerc bopt suffix <- getConfigValue useSuffix d <- getConfigValue decDigits nas <- getConfigValue naString- case c of+ case res of Result x w t s -> do l <- fmtPercent x sp- ws <- fmtWatts w opts suffix d- si <- getIconPattern opts s x+ ws <- fmtWatts w bopt suffix d+ si <- getIconPattern bopt s x st <- showWithColors'- (fmtStatus opts s nas (getBattStatus x opts))+ (fmtStatus bopt s nas (getBattStatus x bopt)) (100 * x) parseTemplate (l ++ [st, fmtTime $ floor t, ws, si]) NA -> getConfigValue naString
src/Xmobar/Plugins/Monitors/Bright.hs view
@@ -44,13 +44,6 @@ o { curBrightIconPattern = Just $ parseIconPattern x }) "") "" ] --- from Batt.hs-parseOpts :: [String] -> IO BrightOpts-parseOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs- sysDir :: FilePath sysDir = "/sys/class/backlight/" @@ -75,7 +68,7 @@ runBright :: [String] -> Monitor String runBright args = do- opts <- io $ parseOpts args+ opts <- io $ parseOptsWith options defaultOpts args f <- io $ brightFiles opts c <- io $ readBright f case f of
src/Xmobar/Plugins/Monitors/Common/Parsers.hs view
@@ -24,12 +24,14 @@ , skipTillString , parseTemplate , parseTemplate'+ , parseOptsWith ) where import Xmobar.Plugins.Monitors.Common.Types import Control.Applicative ((<$>)) import qualified Data.Map as Map+import System.Console.GetOpt (ArgOrder(Permute), OptDescr, getOpt) import Text.ParserCombinators.Parsec runP :: Parser [a] -> String -> IO [a]@@ -150,3 +152,14 @@ Nothing -> return $ "<" ++ ts ++ ">" Just r -> let f "" = r; f n = n; in f <$> parseTemplate' r m return $ s ++ str ++ ss ++ next++-- | Try to parse arguments from the config file and apply them to Options.+parseOptsWith+ :: [OptDescr (opts -> opts)] -- ^ Options that are specifiable+ -> opts -- ^ Default options to use as a fallback+ -> [String] -- ^ Actual arguments given+ -> IO opts+parseOptsWith options defaultOpts argv =+ case getOpt Permute options argv of+ (o, _, [] ) -> pure $ foldr id defaultOpts o+ (_, _, errs) -> ioError . userError $ concat errs
src/Xmobar/Plugins/Monitors/Common/Run.hs view
@@ -19,6 +19,9 @@ , runMD , runMB , runMBD+ , runML+ , runMLD+ , getArgvs ) where import Control.Exception (SomeException,handle)@@ -27,7 +30,7 @@ import System.Console.GetOpt import Xmobar.Plugins.Monitors.Common.Types-import Xmobar.Run.Exec (tenthSeconds)+import Xmobar.Run.Exec (doEveryTenthSeconds) options :: [OptDescr Opts] options =@@ -55,6 +58,13 @@ , Option "E" ["maxtwidthellipsis"] (ReqArg MaxTotalWidthEllipsis "Maximum total width ellipsis") "Ellipsis to be added to the total text when it has reached its max width." ] +-- | Get all argument values out of a list of arguments.+getArgvs :: [String] -> [String]+getArgvs args =+ case getOpt Permute options args of+ (_, n, [] ) -> n+ (_, _, errs) -> errs+ doArgs :: [String] -> ([String] -> Monitor String) -> ([String] -> Monitor Bool)@@ -100,11 +110,11 @@ runM :: [String] -> IO MConfig -> ([String] -> Monitor String) -> Int -> (String -> IO ()) -> IO ()-runM args conf action r = runMB args conf action (tenthSeconds r)+runM args conf action r = runML args conf action (doEveryTenthSeconds r) runMD :: [String] -> IO MConfig -> ([String] -> Monitor String) -> Int -> ([String] -> Monitor Bool) -> (String -> IO ()) -> IO ()-runMD args conf action r = runMBD args conf action (tenthSeconds r)+runMD args conf action r = runMLD args conf action (doEveryTenthSeconds r) runMB :: [String] -> IO MConfig -> ([String] -> Monitor String) -> IO () -> (String -> IO ()) -> IO ()@@ -115,6 +125,17 @@ runMBD args conf action wait detect cb = handle (cb . showException) loop where ac = doArgs args action detect loop = conf >>= runReaderT ac >>= cb >> wait >> loop++runML :: [String] -> IO MConfig -> ([String] -> Monitor String)+ -> (IO () -> IO ()) -> (String -> IO ()) -> IO ()+runML args conf action looper = runMLD args conf action looper (\_ -> return True)++runMLD :: [String] -> IO MConfig -> ([String] -> Monitor String)+ -> (IO () -> IO ()) -> ([String] -> Monitor Bool) -> (String -> IO ())+ -> IO ()+runMLD args conf action looper detect cb = handle (cb . showException) loop+ where ac = doArgs args action detect+ loop = looper $ conf >>= runReaderT ac >>= cb showException :: SomeException -> String showException = ("error: "++) . show . flip asTypeOf undefined
src/Xmobar/Plugins/Monitors/Common/Types.hs view
@@ -25,8 +25,9 @@ , io ) where -import Data.IORef-import Control.Monad.Reader+import Control.Monad.Reader (ReaderT, ask, liftIO)+import Data.IORef (IORef, modifyIORef, newIORef, readIORef)+ type Monitor a = ReaderT MConfig IO a
src/Xmobar/Plugins/Monitors/CoreTemp.hs view
@@ -25,8 +25,7 @@ coreTempConfig :: IO MConfig coreTempConfig = mkMConfig "Temp: <core0>C" -- template- (map ((++) "core" . show) [0 :: Int ..]) -- available- -- replacements+ (map ((++) "core" . show) [0 :: Int ..]) -- available replacements -- | -- Function retrieves monitor string holding the core temperature
src/Xmobar/Plugins/Monitors/Cpu.hs view
@@ -35,12 +35,6 @@ o { loadIconPattern = Just $ parseIconPattern x }) "") "" ] -parseOpts :: [String] -> IO CpuOpts-parseOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs- cpuConfig :: IO MConfig cpuConfig = mkMConfig "Cpu: <total>%"@@ -77,7 +71,7 @@ runCpu :: CpuDataRef -> [String] -> Monitor String runCpu cref argv = do c <- io (parseCpu cref)- opts <- io $ parseOpts argv+ opts <- io $ parseOptsWith options defaultOpts argv l <- formatCpu opts c parseTemplate l
src/Xmobar/Plugins/Monitors/Disk.hs view
@@ -34,27 +34,25 @@ , contiguous :: Bool } -parseDiskIOOpts :: [String] -> IO DiskIOOpts-parseDiskIOOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs- where defaultOpts = DiskIOOpts- { totalIconPattern = Nothing- , writeIconPattern = Nothing- , readIconPattern = Nothing- , contiguous = False- }- options =- [ Option "" ["total-icon-pattern"] (ReqArg (\x o ->- o { totalIconPattern = Just $ parseIconPattern x}) "") ""- , Option "" ["write-icon-pattern"] (ReqArg (\x o ->- o { writeIconPattern = Just $ parseIconPattern x}) "") ""- , Option "" ["read-icon-pattern"] (ReqArg (\x o ->- o { readIconPattern = Just $ parseIconPattern x}) "") ""- , Option "c" ["contiguous"] (NoArg (\o -> o {contiguous = True})) ""- ]+dioDefaultOpts :: DiskIOOpts+dioDefaultOpts = DiskIOOpts+ { totalIconPattern = Nothing+ , writeIconPattern = Nothing+ , readIconPattern = Nothing+ , contiguous = False+ } +dioOptions :: [OptDescr (DiskIOOpts -> DiskIOOpts)]+dioOptions =+ [ Option "" ["total-icon-pattern"] (ReqArg (\x o ->+ o { totalIconPattern = Just $ parseIconPattern x}) "") ""+ , Option "" ["write-icon-pattern"] (ReqArg (\x o ->+ o { writeIconPattern = Just $ parseIconPattern x}) "") ""+ , Option "" ["read-icon-pattern"] (ReqArg (\x o ->+ o { readIconPattern = Just $ parseIconPattern x}) "") ""+ , Option "c" ["contiguous"] (NoArg (\o -> o {contiguous = True})) ""+ ]+ diskIOConfig :: IO MConfig diskIOConfig = mkMConfig "" ["total", "read", "write" ,"totalb", "readb", "writeb"@@ -72,24 +70,22 @@ , contiguousU :: Bool } -parseDiskUOpts :: [String] -> IO DiskUOpts-parseDiskUOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs- where defaultOpts = DiskUOpts- { freeIconPattern = Nothing- , usedIconPattern = Nothing- , contiguousU = False- }- options =- [ Option "" ["free-icon-pattern"] (ReqArg (\x o ->- o { freeIconPattern = Just $ parseIconPattern x}) "") ""- , Option "" ["used-icon-pattern"] (ReqArg (\x o ->- o { usedIconPattern = Just $ parseIconPattern x}) "") ""- , Option "c" ["contiguous"] (NoArg (\o -> o {contiguousU = True})) ""- ]+duDefaultOpts :: DiskUOpts+duDefaultOpts = DiskUOpts+ { freeIconPattern = Nothing+ , usedIconPattern = Nothing+ , contiguousU = False+ } +duOptions :: [OptDescr (DiskUOpts -> DiskUOpts)]+duOptions =+ [ Option "" ["free-icon-pattern"] (ReqArg (\x o ->+ o { freeIconPattern = Just $ parseIconPattern x}) "") ""+ , Option "" ["used-icon-pattern"] (ReqArg (\x o ->+ o { usedIconPattern = Just $ parseIconPattern x}) "") ""+ , Option "c" ["contiguous"] (NoArg (\o -> o {contiguousU = True})) ""+ ]+ diskUConfig :: IO MConfig diskUConfig = mkMConfig "" [ "size", "free", "used", "freep", "usedp"@@ -208,7 +204,7 @@ runDiskIO :: DevDataRef -> [(String, String)] -> [String] -> Monitor String runDiskIO dref disks argv = do- opts <- io $ parseDiskIOOpts argv+ opts <- io $ parseOptsWith dioOptions dioDefaultOpts argv dev <- io $ mountedOrDiskDevices (map fst disks) dat <- io $ mountedData dref (map fst dev) strs <- mapM (runDiskIO' opts) $ devTemplates disks dev dat@@ -254,6 +250,6 @@ runDiskU :: [(String, String)] -> [String] -> Monitor String runDiskU disks argv = do devs <- io $ mountedDevices (map fst disks)- opts <- io $ parseDiskUOpts argv+ opts <- io $ parseOptsWith duOptions duDefaultOpts argv strs <- mapM (\(d, p) -> runDiskU' opts (findTempl d p disks) p) devs return $ (if contiguousU opts then concat else unwords) strs
src/Xmobar/Plugins/Monitors/MPD.hs view
@@ -64,7 +64,7 @@ runMPD :: [String] -> Monitor String runMPD args = do- opts <- io $ mopts args+ opts <- io $ parseOptsWith options defaultOpts args status <- io $ withMPD opts M.status song <- io $ withMPD opts M.currentSong s <- parseMPD status song opts@@ -79,7 +79,7 @@ mpdReady :: [String] -> Monitor Bool mpdReady args = do- opts <- io $ mopts args+ opts <- io $ parseOptsWith options defaultOpts args response <- io $ withMPD opts M.ping case response of Right _ -> return True@@ -88,12 +88,6 @@ Left M.NoMPD -> return False Left (M.ConnectionError _) -> return False Left _ -> return True--mopts :: [String] -> IO MOpts-mopts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs parseMPD :: M.Response M.Status -> M.Response (Maybe M.Song) -> MOpts -> Monitor [String]
src/Xmobar/Plugins/Monitors/Mem.hs view
@@ -41,12 +41,6 @@ o { availableIconPattern = Just $ parseIconPattern x }) "") "" ] -parseOpts :: [String] -> IO MemOpts-parseOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs- memConfig :: IO MConfig memConfig = mkMConfig "Mem: <usedratio>% (<cache>M)" -- template@@ -91,6 +85,6 @@ runMem :: [String] -> Monitor String runMem argv = do m <- io parseMEM- opts <- io $ parseOpts argv+ opts <- io $ parseOptsWith options defaultOpts argv l <- formatMem opts m parseTemplate l
src/Xmobar/Plugins/Monitors/MultiCoreTemp.hs view
@@ -60,12 +60,6 @@ "" ] --- | Parse Arguments and apply them to Options.-parseOpts :: [String] -> IO CTOpts-parseOpts argv = case getOpt Permute options argv of- (opts , _ , [] ) -> return $ foldr id defaultOpts opts- (_ , _ , errs) -> ioError . userError $ concat errs- -- | Generate Config with a default template and options. cTConfig :: IO MConfig cTConfig = mkMConfig cTTemplate cTOptions@@ -157,7 +151,7 @@ runCT :: [String] -> Monitor String runCT argv = do cTs <- io parseCT- opts <- io $ parseOpts argv+ opts <- io $ parseOptsWith options defaultOpts argv l <- formatCT opts cTs parseTemplate l
src/Xmobar/Plugins/Monitors/MultiCpu.hs view
@@ -47,12 +47,6 @@ , Option "" ["contiguous-icons"] (NoArg (\o -> o {contiguous = True})) "" ] -parseOpts :: [String] -> IO MultiCpuOpts-parseOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs- variables :: [String] variables = ["bar", "vbar","ipat","total","user","nice","system","idle"] vNum :: Int@@ -122,7 +116,7 @@ runMultiCpu :: CpuDataRef -> [String] -> Monitor String runMultiCpu cref argv = do c <- io $ parseCpuData cref- opts <- io $ parseOpts argv+ opts <- io $ parseOptsWith options defaultOpts argv l <- formatMultiCpus opts c a <- formatAutoCpus opts l parseTemplate $ a ++ l
src/Xmobar/Plugins/Monitors/Net.hs view
@@ -68,12 +68,6 @@ o { onlyDevList = Just $ parseDevList x }) "") "" ] -parseOpts :: [String] -> IO NetOpts-parseOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs- data UnitPerSec = Bs | KBs | MBs | GBs deriving (Eq,Enum,Ord) data NetValue = NetValue Float UnitPerSec deriving (Eq,Show) @@ -188,7 +182,7 @@ runNet :: NetDevRef -> String -> [String] -> Monitor String runNet nref i argv = do dev <- io $ parseNet nref i- opts <- io $ parseOpts argv+ opts <- io $ parseOptsWith options defaultOpts argv printNet opts dev parseNets :: [(NetDevRef, String)] -> IO [NetDevRate]@@ -196,7 +190,7 @@ runNets :: [(NetDevRef, String)] -> [String] -> Monitor String runNets refs argv = do- opts <- io $ parseOpts argv+ opts <- io $ parseOptsWith options defaultOpts argv dev <- io $ parseActive $ filterRefs opts refs printNet opts dev where parseActive refs' = fmap selectActive (parseNets refs')
src/Xmobar/Plugins/Monitors/UVMeter.hs view
@@ -19,15 +19,40 @@ import qualified Control.Exception as CE import Network.HTTP.Conduit- (parseRequest, newManager, tlsManagerSettings, httpLbs,- responseBody)+ ( Manager+ , httpLbs+ , managerConnCount+ , newManager+ , parseRequest+ , responseBody+ , tlsManagerSettings+ ) import Data.ByteString.Lazy.Char8 as B+import Data.Maybe (fromMaybe)+import System.Console.GetOpt (ArgDescr(ReqArg), OptDescr(Option)) import Text.Read (readMaybe) import Text.Parsec import Text.Parsec.String import Control.Monad (void) +-- | Options the user may specify.+newtype UVMeterOpts = UVMeterOpts+ { useManager :: Bool+ }++-- | Default values for options.+defaultOpts :: UVMeterOpts+defaultOpts = UVMeterOpts+ { useManager = True+ }++-- | Apply options.+options :: [OptDescr (UVMeterOpts -> UVMeterOpts)]+options =+ [ Option "m" ["useManager"] (ReqArg (\m o -> o { useManager = read m }) "") ""+ ]+ uvConfig :: IO MConfig uvConfig = mkMConfig "<station>" -- template@@ -40,16 +65,19 @@ uvURL :: String uvURL = "https://uvdata.arpansa.gov.au/xml/uvvalues.xml" -getData :: IO String-getData =- CE.catch (do request <- parseRequest uvURL- manager <- newManager tlsManagerSettings- res <- httpLbs request manager- return $ B.unpack $ responseBody res)- errHandler- where errHandler- :: CE.SomeException -> IO String- errHandler _ = return "<Could not retrieve data>"+-- | Get the UV data from the given url.+getData :: Maybe Manager -> IO String+getData uvMan = CE.catch+ (do man <- flip fromMaybe uvMan <$> mkManager+ -- Create a new manager if none was present or the user does not want to+ -- use one, otherwise use the provided manager.+ request <- parseRequest uvURL+ res <- httpLbs request man+ return $ B.unpack $ responseBody res)+ errHandler+ where+ errHandler :: CE.SomeException -> IO String+ errHandler _ = return "<Could not retrieve data>" textToXMLDocument :: String -> Either ParseError [XML] textToXMLDocument = parse document ""@@ -69,11 +97,23 @@ getUVRating locID (_:xs) = getUVRating locID xs getUVRating _ [] = Nothing +-- | Start the uvmeter monitor, create a new 'Maybe Manager', should the user have+-- chosen to use one.+startUVMeter+ :: String -- ^ Station+ -> [String] -- ^ User supplied arguments+ -> Int -- ^ Update rate+ -> (String -> IO ())+ -> IO ()+startUVMeter station args rate cb = do+ opts <- parseOptsWith options defaultOpts (getArgvs args)+ uvMan <- tryMakeManager opts+ runM (station : args) uvConfig (runUVMeter uvMan) rate cb -runUVMeter :: [String] -> Monitor String-runUVMeter [] = return "N.A."-runUVMeter (s:_) = do- resp <- io getData+runUVMeter :: Maybe Manager -> [String] -> Monitor String+runUVMeter _ [] = return "N.A."+runUVMeter uvMan (s:_) = do+ resp <- io $ getData uvMan case textToXMLDocument resp of Right doc -> formatUVRating (getUVRating s doc) Left _ -> getConfigValue naString@@ -155,3 +195,15 @@ char '"' spaces return (Attribute (name, value))++-- | Possibly create a new 'Manager', based upon the users preference. If one+-- is created, this 'Manager' will be used throughout the monitor.+tryMakeManager :: UVMeterOpts -> IO (Maybe Manager)+tryMakeManager opts =+ if useManager opts+ then Just <$> mkManager+ else pure Nothing++-- | Create a new 'Manager' for managing network connections.+mkManager :: IO Manager+mkManager = newManager $ tlsManagerSettings {managerConnCount = 1}
src/Xmobar/Plugins/Monitors/Volume.hs view
@@ -23,16 +23,26 @@ import Control.Applicative ( (<$>), liftA3 ) import Control.Monad ( liftM2, liftM3, mplus )+import Data.Maybe (fromMaybe) import Data.Traversable (sequenceA) import Xmobar.Plugins.Monitors.Common import Sound.ALSA.Mixer import qualified Sound.ALSA.Exception as AE import System.Console.GetOpt -volumeConfig :: IO MConfig-volumeConfig = mkMConfig "Vol: <volume>% <status>"- ["volume", "volumebar", "volumevbar", "dB","status", "volumeipat"] +volumeConfig :: IO MConfig+volumeConfig =+ mkMConfig+ "Vol: <volume>% <status>"+ [ "volume"+ , "volumebar"+ , "volumevbar"+ , "dB"+ , "status"+ , "volumeipat"+ , "volumestatus"+ ] data VolumeOpts = VolumeOpts { onString :: String@@ -101,12 +111,6 @@ , Option "h" ["highs"] (ReqArg (\x o -> o { highString = x }) "") "" ] -parseOpts :: [String] -> IO VolumeOpts-parseOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs- percent :: Integer -> Integer -> Integer -> Float percent v' lo' hi' = (v - lo) / (hi - lo) where v = fromIntegral v'@@ -141,7 +145,7 @@ ++ maybe "" (const "</fc>") (cHelp opts) formatSwitch :: VolumeOpts -> Bool -> VolumeStatus -> Monitor String-formatSwitch opts True vs = switchHelper opts onColor onString vs+formatSwitch opts True vs = switchHelper opts onColor onString vs formatSwitch opts False _ = switchHelper opts offColor offString VolOff -- | Convert the current volume status into user defined strings@@ -173,7 +177,7 @@ runVolume :: String -> String -> [String] -> Monitor String runVolume mixerName controlName argv = do- opts <- io $ parseOpts argv+ opts <- io $ parseOptsWith options defaultOpts argv runVolumeWith opts mixerName controlName runVolumeWith :: VolumeOpts -> String -> String -> Monitor String@@ -189,8 +193,14 @@ (liftA3 percent val lo hi) -- current volume in % s <- getFormatSwitch opts sw volStat ipat <- liftMonitor $ liftM3 (formatVolDStr $ volumeIconPattern opts) lo hi val- parseTemplate [p, b, v, d, s, ipat] + -- Volume and status in one.+ let vs = if isVolOff sw+ then offString opts -- User defined off string+ else s ++ p -- Status string, current volume in %++ parseTemplate [p, b, v, d, s, ipat, vs]+ where readMixer =@@ -244,5 +254,9 @@ getFormatSwitch _ Nothing _ = unavailable getFormatSwitch _ _ Nothing = unavailable getFormatSwitch opts' (Just sw) (Just vs) = formatSwitch opts' sw vs++ -- | Determine whether the volume is off based on the value of 'sw' from+ -- 'runVolumeWith'.+ isVolOff = not . fromMaybe False unavailable = getConfigValue naString
src/Xmobar/Plugins/Monitors/Weather.hs view
@@ -19,14 +19,37 @@ import qualified Control.Exception as CE +import qualified Data.ByteString.Lazy.Char8 as B+import Data.Char (toLower)+import Data.Maybe (fromMaybe) import Network.HTTP.Conduit import Network.HTTP.Types.Status import Network.HTTP.Types.Method-import qualified Data.ByteString.Lazy.Char8 as B-import Data.Char (toLower) import Text.ParserCombinators.Parsec+import System.Console.GetOpt (ArgDescr(ReqArg), OptDescr(Option)) ++-- | Options the user may specify.+data WeatherOpts = WeatherOpts+ { weatherString :: String+ , useManager :: Bool+ }++-- | Default values for options.+defaultOpts :: WeatherOpts+defaultOpts = WeatherOpts+ { weatherString = ""+ , useManager = True+ }++-- | Apply options.+options :: [OptDescr (WeatherOpts -> WeatherOpts)]+options =+ [ Option "w" ["weathers" ] (ReqArg (\s o -> o { weatherString = s }) "") ""+ , Option "m" ["useManager"] (ReqArg (\b o -> o { useManager = read b }) "") ""+ ]+ weatherConfig :: IO MConfig weatherConfig = mkMConfig "<station>: <tempC>C, rh <rh>% (<hour>)" -- template@@ -45,6 +68,7 @@ , "visibility" , "skyCondition" , "skyConditionS"+ , "weather" , "tempC" , "tempF" , "dewPointC"@@ -73,6 +97,7 @@ , windInfo :: WindInfo , visibility :: String , skyCondition :: String+ , weather :: String , tempC :: Int , tempF :: Int , dewPointC :: Int@@ -169,6 +194,7 @@ w <- pWind v <- getAfterString "Visibility: " sk <- getAfterString "Sky conditions: "+ we <- getAfterString "Weather: " skipTillString "Temperature: " (tC,tF) <- pTemp skipTillString "Dew Point: "@@ -178,7 +204,7 @@ skipTillString "Pressure (altimeter): " p <- pPressure manyTill skipRestOfLine eof- return [WI st ss y m d h w v sk tC tF dC dF rh p]+ return [WI st ss y m d h w v sk we tC tF dC dF rh p] defUrl :: String defUrl = "https://tgftp.nws.noaa.gov/data/observations/metar/decoded/"@@ -186,50 +212,111 @@ stationUrl :: String -> String stationUrl station = defUrl ++ station ++ ".TXT" -getData :: String -> IO String-getData station = CE.catch (do- manager <- newManager tlsManagerSettings- request <- parseUrlThrow $ stationUrl station- res <- httpLbs request manager- return $ B.unpack $ responseBody res- ) errHandler- where errHandler :: CE.SomeException -> IO String- errHandler _ = return "<Could not retrieve data>"+-- | Get the decoded weather data from the given station.+getData :: Maybe Manager -> String -> IO String+getData weMan station = CE.catch+ (do man <- flip fromMaybe weMan <$> mkManager+ -- Create a new manager if none was present or the user does not want to+ -- use one.+ request <- parseUrlThrow $ stationUrl station+ res <- httpLbs request man+ return $ B.unpack $ responseBody res)+ errHandler+ where+ errHandler :: CE.SomeException -> IO String+ errHandler _ = return "<Could not retrieve data>" formatSk :: Eq p => [(p, p)] -> p -> p formatSk ((a,b):sks) sk = if a == sk then b else formatSk sks sk formatSk [] sk = sk -formatWeather :: [(String,String)] -> [WeatherInfo] -> Monitor String-formatWeather sks [WI st ss y m d h (WindInfo wc wa wm wk wkh wms) v sk tC tF dC dF r p] =+formatWeather+ :: WeatherOpts -- ^ Formatting options from the cfg file+ -> [(String,String)] -- ^ 'SkyConditionS' for 'WeatherX'+ -> [WeatherInfo] -- ^ The actual weather info+ -> Monitor String+formatWeather opts sks [WI st ss y m d h (WindInfo wc wa wm wk wkh wms) v sk we tC tF dC dF r p] = do cel <- showWithColors show tC far <- showWithColors show tF let sk' = formatSk sks (map toLower sk)+ we' = showWeather (weatherString opts) we parseTemplate [st, ss, y, m, d, h, wc, wa, wm, wk, wkh- , wms, v, sk, sk', cel, far+ , wms, v, sk, sk', we', cel, far , show dC, show dF, show r , show p ]-formatWeather _ _ = getConfigValue naString+formatWeather _ _ _ = getConfigValue naString -runWeather :: [String] -> Monitor String-runWeather = runWeather' []+-- | Show the 'weather' field with a default string in case it was empty.+showWeather :: String -> String -> String+showWeather "" d = d+showWeather s _ = s -runWeather' :: [(String, String)] -> [String] -> Monitor String-runWeather' sks args =- do d <- io $ getData $ head args- i <- io $ runP parseData d- formatWeather sks i+-- | Start a weather monitor, create a new 'Maybe Manager', should the user have+-- chosen to use one.+startWeather'+ :: [(String, String)] -- ^ 'SkyConditionS' replacement strings+ -> String -- ^ Weather station+ -> [String] -- ^ User supplied arguments+ -> Int -- ^ Update rate+ -> (String -> IO ())+ -> IO ()+startWeather' sks station args rate cb = do+ opts <- parseOptsWith options defaultOpts (getArgvs args)+ weRef <- tryMakeManager opts+ runMD+ (station : args)+ weatherConfig+ (runWeather sks weRef opts)+ rate+ weatherReady+ cb +-- | Same as 'startWeather'', only for 'Weather' instead of 'WeatherX', meaning+-- no 'SkyConditionS'.+startWeather :: String -> [String] -> Int -> (String -> IO ()) -> IO ()+startWeather = startWeather' []++-- | Run a weather monitor.+runWeather+ :: [(String, String)] -- ^ 'SkyConditionS' replacement strings+ -> Maybe Manager -- ^ Whether to use a 'Manager'+ -> WeatherOpts -- ^ Weather specific options+ -> [String] -- ^ User supplied arguments+ -> Monitor String+runWeather sks weMan opts args = do+ d <- io $ getData weMan (head args)+ i <- io $ runP parseData d+ formatWeather opts sks i+ weatherReady :: [String] -> Monitor Bool-weatherReady str = do+weatherReady str = io $ do initRequest <- parseUrlThrow $ stationUrl $ head str- let request = initRequest{method = methodHead}- io $ CE.catch ( do- manager <- newManager tlsManagerSettings- res <- httpLbs request manager- return $ checkResult $responseStatus res ) errHandler- where errHandler :: CE.SomeException -> IO Bool- errHandler _ = return False- checkResult status- | statusIsServerError status = False- | statusIsClientError status = False- | otherwise = True+ let request = initRequest { method = methodHead }++ CE.catch+ (do man <- mkManager+ res <- httpLbs request man+ return $ checkResult $ responseStatus res)+ errHandler+ where+ -- | If any exception occurs, indicate that the monitor is not ready.+ errHandler :: CE.SomeException -> IO Bool+ errHandler _ = return False++ -- | Check for and indicate any errors in the http response.+ checkResult :: Status -> Bool+ checkResult status+ | statusIsServerError status = False+ | statusIsClientError status = False+ | otherwise = True++-- | Possibly create a new 'Manager', based upon the users preference. If one+-- is created, this 'Manager' will be used throughout the monitor.+tryMakeManager :: WeatherOpts -> IO (Maybe Manager)+tryMakeManager opts =+ if useManager opts+ then Just <$> mkManager+ else pure Nothing++-- | Create a new 'Manager' for managing network connections.+mkManager :: IO Manager+mkManager = newManager $ tlsManagerSettings { managerConnCount = 1 }
src/Xmobar/Plugins/Monitors/Wireless.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TypeApplications, CPP #-} ----------------------------------------------------------------------------- -- | -- Module : Plugins.Monitors.Wireless@@ -8,17 +9,69 @@ -- Stability : unstable -- Portability : unportable ----- A monitor reporting ESSID and link quality for wireless interfaces+-- A monitor reporting SSID and signal level for wireless interfaces -- ----------------------------------------------------------------------------- module Xmobar.Plugins.Monitors.Wireless (wirelessConfig, runWireless) where import System.Console.GetOpt+import Data.Maybe (fromMaybe) import Xmobar.Plugins.Monitors.Common++#ifdef IWLIB import Network.IWlib+#elif defined USE_NL80211+import Control.Exception (bracket)+import qualified Data.Map as M+import GHC.Int (Int8)+import Data.Maybe (listToMaybe)+import Control.Monad.IO.Class (liftIO)+import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)+import Data.ByteString.Char8 (unpack)+import Data.Serialize.Put (runPut, putWord32host, putByteString)+import Data.Serialize.Get (runGet) +import System.Linux.Netlink hiding (query)+import System.Linux.Netlink.GeNetlink.NL80211+import System.Linux.Netlink.GeNetlink.NL80211.StaInfo+import System.Linux.Netlink.GeNetlink.NL80211.Constants+import System.Posix.IO (closeFd)++data IwData = IwData { wiEssid :: String, wiSignal :: Maybe Int, wiQuality :: Int }++getWirelessInfo :: String -> IO IwData+getWirelessInfo ifname = do+ bracket makeNL80211Socket (closeFd . getFd) (\s -> do+ iflist <- getInterfaceList s+ iwdata <- runMaybeT $ do+ ifidx <- MaybeT . return $ foldr (\(n, i) z ->+ if (ifname == "" || ifname == n) then Just i else z)+ Nothing+ iflist+ scanp <- liftIO (getConnectedWifi s ifidx) >>=+ MaybeT . return . listToMaybe+ bssid <- MaybeT . return $ M.lookup eNL80211_ATTR_BSS (packetAttributes scanp) >>=+ rightToMaybe . runGet getAttributes >>=+ M.lookup eNL80211_BSS_BSSID+ stap <- liftIO (query s eNL80211_CMD_GET_STATION True $ M.fromList+ [(eNL80211_ATTR_IFINDEX, runPut $ putWord32host ifidx),+ (eNL80211_ATTR_MAC, runPut $ putByteString bssid)]) >>=+ MaybeT . return . listToMaybe+ let ssid = fromMaybe "" $ getWifiAttributes scanp >>= M.lookup eWLAN_EID_SSID >>=+ return . unpack+ signal = staInfoFromPacket stap >>= staSignalMBM >>=+ return . fromIntegral @Int8 . fromIntegral+ qlty = fromMaybe (-1) (round @Float . (/ 0.7) . (+ 110) .+ clamp (-110) (-40) . fromIntegral <$> signal)+ MaybeT . return $ Just $ IwData ssid signal qlty+ return $ fromMaybe (IwData "" Nothing (-1)) iwdata)+ where+ rightToMaybe = either (const Nothing) Just+ clamp lb up v = if v < lb then lb else if v > up then up else v+#endif+ newtype WirelessOpts = WirelessOpts { qualityIconPattern :: Maybe IconPattern }@@ -34,37 +87,43 @@ opts { qualityIconPattern = Just $ parseIconPattern d }) "") "" ] -parseOpts :: [String] -> IO WirelessOpts-parseOpts argv =- case getOpt Permute options argv of- (o, _, []) -> return $ foldr id defaultOpts o- (_, _, errs) -> ioError . userError $ concat errs- wirelessConfig :: IO MConfig wirelessConfig =- mkMConfig "<essid> <quality>"- ["essid", "quality", "qualitybar", "qualityvbar", "qualityipat"]+ mkMConfig "<ssid> <quality>"+ ["ssid", "essid", "signal", "quality", "qualitybar", "qualityvbar", "qualityipat"] runWireless :: String -> [String] -> Monitor String runWireless iface args = do- opts <- io $ parseOpts args+ opts <- io $ parseOptsWith options defaultOpts args+#ifdef IWLIB iface' <- if "" == iface then io findInterface else return iface+#else+ let iface' = iface+#endif wi <- io $ getWirelessInfo iface' na <- getConfigValue naString let essid = wiEssid wi qlty = fromIntegral $ wiQuality wi e = if essid == "" then na else essid ep <- showWithPadding e+#ifdef USE_NL80211+ let s = wiSignal wi+#else+ let s = if qlty >= 0 then Just (qlty * 0.7 - 110) else Nothing+#endif+ sp <- showWithPadding $ maybe "" show s q <- if qlty >= 0 then showPercentWithColors (qlty / 100) else showWithPadding "" qb <- showPercentBar qlty (qlty / 100) qvb <- showVerticalBar qlty (qlty / 100) qipat <- showIconPattern (qualityIconPattern opts) (qlty / 100)- parseTemplate [ep, q, qb, qvb, qipat]+ parseTemplate [ep, ep, sp, q, qb, qvb, qipat] +#ifdef IWLIB findInterface :: IO String findInterface = do c <- readFile "/proc/net/wireless" let nds = lines c return $ if length nds > 2 then takeWhile (/= 'c') (nds!!2) else []+#endif
src/Xmobar/Run/Command.hs view
@@ -41,7 +41,7 @@ start (Com p as al r) cb = start (ComX p as ("Could not execute command " ++ p) al r) cb start (ComX prog args msg _ r) cb = if r > 0 then go else exec- where go = exec >> tenthSeconds r >> go+ where go = doEveryTenthSeconds r exec exec = do (i,o,e,p) <- runInteractiveProcess prog args Nothing Nothing exit <- waitForProcess p
src/Xmobar/Run/Exec.hs view
@@ -17,23 +17,14 @@ -- ----------------------------------------------------------------------------- -module Xmobar.Run.Exec (Exec (..), tenthSeconds) where+module Xmobar.Run.Exec (Exec (..), tenthSeconds, doEveryTenthSeconds) where import Prelude import Data.Char-import Control.Concurrent +import Xmobar.App.Timer (doEveryTenthSeconds, tenthSeconds) import Xmobar.System.Signal --- | Work around 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 (x * 100000)- tenthSeconds (s - x)- | otherwise = threadDelay (s * 100000)- where x = (maxBound :: Int) `div` 100000- class Show e => Exec e where alias :: e -> String alias e = takeWhile (not . isSpace) $ show e@@ -43,6 +34,6 @@ run _ = return "" start :: e -> (String -> IO ()) -> IO () start e cb = go- where go = run e >>= cb >> tenthSeconds (rate e) >> go+ where go = doEveryTenthSeconds (rate e) $ run e >>= cb trigger :: e -> (Maybe SignalType -> IO ()) -> IO () trigger _ sh = sh Nothing
src/Xmobar/X11/Draw.hs view
@@ -62,6 +62,8 @@ (defaultDepthOfScreen (defaultScreenOfDisplay d)) #if XFT when (alpha c /= 255) (liftIO $ drawBackground d p (bgColor c) (alpha c) wr)+#else+ _ <- return wr #endif withColors d [bgColor c, borderColor c] $ \[bgcolor, bdcolor] -> do gc <- liftIO $ createGC d w
xmobar.cabal view
@@ -1,5 +1,5 @@ name: xmobar-version: 0.32+version: 0.33 homepage: http://xmobar.org synopsis: A Minimalistic Text Based Status Bar description: Xmobar is a minimalistic text based status bar.@@ -40,9 +40,13 @@ default: False flag with_iwlib- description: Wireless info support. Required for the Wireless plugin, needs iwlib installed.+ description: Wireless info support via Wext ioctls (deprecated). Required for the Wireless plugin, needs iwlib installed. default: False +flag with_nl80211+ description: Wireless info support via nl80211. Required for the Wireless plugin on systems running Linux, the kernel.+ default: False+ flag with_mpd description: MPD support. Needs libmpd installed. default: False@@ -72,7 +76,7 @@ default: False flag with_threaded- description: Use threaded runtime.+ description: Use threaded runtime. Required for timer coalescing (less power usage). default: False flag with_rtsopts@@ -105,6 +109,7 @@ Xmobar.App.Main, Xmobar.App.Opts, Xmobar.App.Compile,+ Xmobar.App.Timer, Xmobar.System.Utils, Xmobar.System.StatFS, Xmobar.System.Environment,@@ -208,12 +213,19 @@ exposed-modules: Xmobar.Plugins.Mail, Xmobar.Plugins.MBox cpp-options: -DINOTIFY - if flag(with_iwlib) || flag(all_extensions)+ if flag(with_iwlib) || flag(with_nl80211) || flag(all_extensions)+ exposed-modules: Xmobar.Plugins.Monitors.Wireless++ if flag(with_iwlib) extra-libraries: iw build-depends: iwlib >= 0.1.0 && < 0.2- exposed-modules: Xmobar.Plugins.Monitors.Wireless cpp-options: -DIWLIB + if !flag(with_iwlib) && (flag(with_nl80211) || flag(all_extensions))+ build-depends: netlink >= 1.1.1.0,+ cereal >= 0.5.8.1+ cpp-options: -DUSE_NL80211+ if flag(with_mpd) || flag(all_extensions) build-depends: libmpd >= 0.9.0.10 exposed-modules: Xmobar.Plugins.Monitors.MPD@@ -257,6 +269,11 @@ build-depends: http-conduit, http-types cpp-options: -DUVMETER + if os(freebsd)+ -- enables freebsd specific code+ build-depends: bsd-sysctl+ cpp-options: -DFREEBSD+ executable xmobar hs-source-dirs: app main-is: Main.hs@@ -315,6 +332,7 @@ Xmobar.Plugins.Monitors.Common.Output Xmobar.Plugins.Monitors.Common.Files Xmobar.Run.Exec+ Xmobar.App.Timer Xmobar.System.Signal if flag(with_alsa) || flag(all_extensions)