packages feed

xmobar 0.31 → 0.32

raw patch · 14 files changed

+392/−140 lines, 14 filesdep ~base

Dependency ranges changed: base

Files

changelog.md view
@@ -1,4 +1,30 @@-## Version 0.31+## Version 0.32++_New features_++  - New options `--host` and `--port` for `MPD` monitor.+  - New plugin `MailX` extending `Mail` with colors and prefix/suffix.+  - New options `--lows`, `--mediums`, and `--highs` for `Battery`+    to display an additional string depending on battery level (thanks+    to *slotThe*).+  - New options `-L` and `-H` for `Volume` to set low and high volume+    levels, as well as `-l`, `-m`, and `-h` to display an additional+    string depending on current volume level (thanks to *slotThe*).+  - New option `-P` in `Battery` to add a `%` symbol to `<left>`.+  - New option `--devices` in `DynNetwork` to select what interfaces+    to monitor (thanks to *vindex10*).+  - DateZone plugin now also checks TZDIR (thanks to Emmanuel Rosa).++_Bug fixes_++   - `Kbd` plugin: ignore "terminate" layout token (thanks to Greg+     Steuck).+   - Fixed compilation with GHC 8.8.x (thanks to Vanessa McHale).+   - Avoid creating `~/.xmobar` ([issue #405]).++[issue #405]: https://github.com/jaor/xmobar/issues/405++## Version 0.31 (October, 2019)  _New features_ 
readme.md view
@@ -198,11 +198,11 @@   managers to feed xmobar strings with `<action>` tags mixed with un-trusted   content (e.g. window titles).  For example, if xmobar is invoked as -    ```xmobar -c "[Run UnsafeStdinReader]" -t "%UnsafeStdinReader%"```+        xmobar -c "[Run UnsafeStdinReader]" -t "%UnsafeStdinReader%"    and receives on standard input the line -    ```<action=`echo test` button=1><raw=41:<action=`echo mooo` button=1>foo</action>/></action>```+        <action=`echo test` button=1><raw=41:<action=`echo mooo` button=1>foo</action>/></action>`    then it will display the text ```<action=`echo mooo` button=1>foo</action>```,   which, when clicked, will cause `test` to be echoed.@@ -799,13 +799,15 @@ - Thresholds are expressed in Kb/s - Args: default monitor arguments, plus:   - `--rx-icon-pattern`: dynamic string for reception rate in `rxipat`.-  - `--tx-icon-pattern`: dynamic string for transmission rate in `txipat`.+  - `--tx-icon-pattern`: dynamic string for transmission rate in `txipat`+  - `--devices`: comma-separated list of devices to show. - Variables that can be used with the `-t`/`--template` argument:   `dev`, `rx`, `tx`, `rxbar`, `rxvbar`, `rxipat`, `txbar`, `txvbar`,   `txipat`. Reception and transmission rates (`rx` and `tx`) are displayed   in Kbytes per second, and you can set the `-S` to "True" to make them   displayed with units (the string "Kb/s"). - Default template: `<dev>: <rx>KB|<tx>KB`+- Example of usage of `--devices` option: `["--", "--devices", "wlp2s0,enp0s20f41"]`  ### `Wireless Interface Args RefreshRate` @@ -911,13 +913,21 @@     percentage left in the battery is less or equal than the threshold     given by the `-A` option.  If not present, no action is     undertaken.+  - `-P`: to include a percentage symbol in `left`.   - `--on-icon-pattern`: dynamic string for current battery charge     when AC is "on" in `leftipat`.   - `--off-icon-pattern`: dynamic string for current battery charge     when AC is "off" in `leftipat`.   - `--idle-icon-pattern`: dynamic string for current battery charge     when AC is "idle" in `leftipat`.+  - `--lows`: string for AC "off" status and power lower than the `-L`+    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`+    threshold (default: "") + - Variables that can be used with the `-t`/`--template` argument: 	    `left`, `leftbar`, `leftvbar`, `leftipat`, `timeleft`, `watts`, `acstatus` - Default template: `Batt: <watts>, <left>% / <timeleft>`@@ -1148,6 +1158,25 @@     - `--highd` _number_ High threshold for dB. Defaults to -5.0.     - `--lowd` _number_ Low threshold for dB. Defaults to -30.0.     - `--volume-icon-pattern` _string_ dynamic string for current volume in `volumeipat`.+    - `-H` _number_ High threshold for volume (in %). Defaults to 60.0.+        - Long option: `--highv`+    - `-L` _number_ Low threshold for volume (in %). Defaults to 20.0.+        - Long option: `--lowv`+    - `-h`: _string_ High string+        - The string added in front of `<status>` when the mixer element+          is on and the volume percentage is higher than the `-H` threshold.+          Defaults to "".+        - Long option: `--highs`+    - `-m`: _string_ Medium string+        - The string added in front of `<status>` when the mixer element+          is on and the volume percentage is lower than the `-H` threshold.+          Defaults to "".+        - Long option: `--mediums`+    - `-l`: _string_ Low string+        - The string added in front of `<status>` when the mixer element+          is on and the volume percentage is lower than the `-L` threshold.+          Defaults to "".+        - Long option: `--lows` - Variables that can be used with the `-t`/`--template` argument:             `volume`, `volumebar`, `volumevbar`, `volumeipat`, `dB`, `status` - Note that `dB` might only return 0 on your system. This is known@@ -1159,29 +1188,35 @@  ### `Alsa Mixer Element Args` -Like [Volume](#volume-mixer-element-args-refreshrate), but with the following differences:-- Uses event-based refreshing via `alsactl monitor` instead of polling, so it will refresh-  instantly when there's a volume change, and won't use CPU until a change happens.-- Aliases to `alsa:` followed by the mixer name and element name separated by a colon. Thus,-  `Alsa "default" "Master" []` can be used as `%alsa:default:Master%`.+Like [Volume](#volume-mixer-element-args-refreshrate), but with the+following differences:+- Uses event-based refreshing via `alsactl monitor` instead of+  polling, so it will refresh instantly when there's a volume change,+  and won't use CPU until a change happens.+- Aliases to `alsa:` followed by the mixer name and element name+  separated by a colon. Thus, `Alsa "default" "Master" []` can be used+  as `%alsa:default:Master%`. - Additional options (after the `--`):     - `--alsactl=/path/to/alsactl`-        - If this option is not specified, `alsactl` will be sought in your `PATH`-          first, and failing that, at `/usr/sbin/alsactl` (this is its location on-          Debian systems. `alsactl monitor` works as a non-root user despite living-          in `/usr/sbin`.).-- `stdbuf` (from coreutils) must be (and most probably already is) in your `PATH`.+        - If this option is not specified, `alsactl` will be sought in+          your `PATH` first, and failing that, at `/usr/sbin/alsactl`+          (this is its location on Debian systems. `alsactl monitor`+          works as a non-root user despite living in `/usr/sbin`.).+- `stdbuf` (from coreutils) must be (and most probably already is) in+  your `PATH`.  ### `MPD Args RefreshRate`  - This monitor will only be compiled if you ask for it using the   `with_mpd` flag. It needs [libmpd] 5.0 or later (available on Hackage). - Aliases to `mpd`-- Args: default monitor arguments. In addition you can provide-  `-P`, `-S` and `-Z`, with an string argument, to represent the-  playing, stopped and paused states in the `statei` template field.-  The environment variables `MPD_HOST` and `MPD_PORT` are used to configure the-  mpd server to communicate with. Also available:+- Args: default monitor arguments. In addition you can provide `-P`,+  `-S` and `-Z`, with an string argument, to represent the playing,+  stopped and paused states in the `statei` template field.  The+  environment variables `MPD_HOST` and `MPD_PORT` are used to+  configure the mpd server to communicate with, unless given in the+  additional arguments `-p` (`--port`) and `-h` (`--host`). Also+  available:   - `lapsed-icon-pattern`: dynamic string for current track position in `ipat`. - Variables that can be used with the `-t`/`--template` argument:              `bar`, `vbar`, `ipat`, `state`, `statei`, `volume`, `length`,@@ -1245,6 +1280,30 @@                    ("lists", "~/var/mail/lists")]                   "mail" +### `MailX Args Opts Alias`++- Args: list of maildirs in form+  `[("name1","path1","color1"),...]`. Paths may start with a '~'+  to expand to the user's home directory.  When mails are present,+  counts are displayed with the given name and color.+- Opts is a possibly empty list of options, as flags. Possible values:+   -d dir  --dir dir a string giving the base directory where maildir files with+                     a relative path live.+   -p prefix --prefix prefix  a string giving a prefix for the list+                      of displayed mail counts+   -s suffix --suffix suffix  a string giving a suffix for the list+                      of displayed mail counts+- This plugin requires inotify support in your Linux kernel and the+  [hinotify] package. To activate, pass `--flags="with_inotify"`+  during compilation.+- Example:++         Run MailX [("I", "inbox", "green"),+                    ("L", "lists", "orange")]+                   ["-d", "~/var/mail", "-p", " ", "-s", " "]+                   "mail"++ ### `MBox Mboxes Opts Alias`  - Mboxes a list of mbox files of the form `[("name", "path", "color")]`,@@ -1405,7 +1464,7 @@  ## Other Plugins -<font size="+1">**`StdinReader`**</font>+### `StdinReader`  - Aliases to StdinReader - Displays any text received by xmobar on its standard input.@@ -1413,7 +1472,7 @@   actions via stdin.  This is safer than `UnsafeStdinReader` because there is   no need to escape the content before passing it to xmobar's standard input. -<font size="+1">**`UnsafeStdinReader`**</font>+### `UnsafeStdinReader`  - Aliases to UnsafeStdinReader - Displays any text received by xmobar on its standard input.@@ -1427,13 +1486,13 @@   clicking on xmobar:   ```<action=`xdotool key alt+1`>ws1</action> <action=`xdotool key alt+1`>ws2</action>``` -<font size="+1">**`Date Format Alias RefreshRate`**</font>+### `Date Format Alias RefreshRate`  - Format is a time format string, as accepted by the standard ISO C   `strftime` function (or Haskell's `formatCalendarTime`). - Sample usage: `Run Date "%a %b %_d %Y <fc=#ee9a00>%H:%M:%S</fc>" "date" 10` -<font size="+1">**`DateZone Format Locale Zone Alias RefreshRate`**</font>+### `DateZone Format Locale Zone Alias RefreshRate`  - Format is a time format string, as accepted by the standard ISO C   `strftime` function (or Haskell's `formatCalendarTime`).@@ -1446,17 +1505,17 @@ - Sample usage:   `Run DateZone "%a %H:%M:%S" "de_DE.UTF-8" "Europe/Vienna" "viennaTime" 10` -<font size="+1">**`CommandReader "/path/to/program" Alias`**</font>+### `CommandReader "/path/to/program" Alias`  - Runs the given program, and displays its standard output. -<font size="+1">**`PipeReader "default text:/path/to/pipe" Alias`**</font>+### `PipeReader "default text:/path/to/pipe" Alias`  - Reads its displayed output from the given pipe. - Prefix an optional default text separated by a colon - Expands environment variables in the first argument of syntax '${VAR}' or '$VAR' -<font size="+1">**`MarqueePipeReader "default text:/path/to/pipe" (length, rate, sep) Alias`**</font>+### `MarqueePipeReader "default text:/path/to/pipe" (length, rate, sep) Alias`  - Generally equivalent to PipeReader - Text is displayed as marquee with the specified length, rate in 10th@@ -1466,9 +1525,7 @@  - Expands environment variables in the first argument -<font size="+1">-**`BufferedPipeReader Alias [(Timeout, Bool, "/path/to/pipe1"), ..]`**-</font>+### `BufferedPipeReader Alias [(Timeout, Bool, "/path/to/pipe1"), ..]`  - Display data from multiple pipes. - Timeout (in tenth of seconds) is the value after which the previous@@ -1500,7 +1557,7 @@ [examples/status.sh]: http://github.com/jaor/xmobar/raw/master/examples/status.sh  -<font size="+1">**`XMonadLog`**</font>+### `XMonadLog`  - Aliases to XMonadLog - Displays information from xmonad's `_XMONAD_LOG`. You can set this@@ -1518,7 +1575,7 @@  [here]: http://xmonad.org/xmonad-docs/xmonad-contrib/XMonad-Hooks-DynamicLog.html -<font size="+1">**`UnsafeXMonadLog`**</font>+### `UnsafeXMonadLog`  - Aliases to UnsafeXMonadLog - Similar to StdinReader versus UnsafeStdinReader, this does not strip `<action@@ -1618,13 +1675,14 @@ 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-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.+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.  [jao]: http://jao.io [incorporates patches]: http://www.ohloh.net/p/xmobar/contributors
src/Xmobar/App/Config.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.Config.Defaults--- Copyright: (c) 2018 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2018, 2019 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org@@ -21,6 +21,8 @@                           xmobarDataDir,                           xmobarConfigFile) where +import Control.Monad (when)+ import System.Environment import System.Directory import System.FilePath ((</>))@@ -79,10 +81,10 @@ -- -- The first directory that exists will be used.  If none of the -- directories exist then (1) will be used if it is set, otherwise (2)--- will be used.  Either way, a directory will be created if necessary.+-- will be used. xmobarConfigDir :: IO String xmobarConfigDir =-    findFirstDirWithEnv "XMOBAR_CONFIG_DIR"+    findFirstDirWithEnv False "XMOBAR_CONFIG_DIR"       [ getAppUserDataDirectory "xmobar"       , getXdgDirectory XdgConfig "xmobar"       ]@@ -94,8 +96,8 @@ -- Several directories are considered.  In order of preference: -- --   1. The directory specified in the @XMOBAR_DATA_DIR@ environment variable.---   2. The @~\/.xmobar@ directory.---   3. The @XDG_DATA_HOME/xmobar@ directory.+--   2. The @XDG_DATA_HOME/xmobar@ directory.+--   3. The @~\/.xmobar@ directory. -- -- The first directory that exists will be used.  If none of the -- directories exist then (1) will be used if it is set, otherwise (2)@@ -103,24 +105,25 @@ -- necessary. xmobarDataDir :: IO String xmobarDataDir =-    findFirstDirWithEnv "XMOBAR_DATA_DIR"-      [ getAppUserDataDirectory "xmobar"-      , getXdgDirectory XdgData "xmobar"+    findFirstDirWithEnv True "XMOBAR_DATA_DIR"+      [ getXdgDirectory XdgData "xmobar"+      , getAppUserDataDirectory "xmobar"       ]  -- | Helper function that will find the first existing directory and--- return its path.  If none of the directories can be found, create--- and return the first from the list.  If the list is empty this--- function returns the historical @~\/.xmobar@ directory.-findFirstDirOf :: [IO FilePath] -> IO FilePath-findFirstDirOf [] = findFirstDirOf [getAppUserDataDirectory "xmobar"]-findFirstDirOf possibles = do+-- return its path.  If none of the directories can be found,+-- optionally create and return the first from the list.  If the list+-- is empty this function returns the historical @~\/.xmobar@+-- directory.+findFirstDirOf :: Bool -> [IO FilePath] -> IO FilePath+findFirstDirOf create [] = findFirstDirOf create [getAppUserDataDirectory "xmobar"]+findFirstDirOf create possibles = do     found <- go possibles     case found of       Just path -> return path       Nothing ->  do         primary <- head possibles-        createDirectoryIfMissing True primary+        when create (createDirectoryIfMissing True primary)         return primary   where     go [] = return Nothing@@ -130,12 +133,12 @@  -- | Simple wrapper around @findFirstDirOf@ that allows the primary -- path to be specified by an environment variable.-findFirstDirWithEnv :: String -> [IO FilePath] -> IO FilePath-findFirstDirWithEnv envName paths = do+findFirstDirWithEnv :: Bool -> String -> [IO FilePath] -> IO FilePath+findFirstDirWithEnv create envName paths = do     envPath' <- lookupEnv envName     case envPath' of-      Nothing -> findFirstDirOf paths-      Just envPath -> findFirstDirOf (return envPath:paths)+      Nothing -> findFirstDirOf create paths+      Just envPath -> findFirstDirOf create (return envPath:paths)  xmobarConfigFile :: IO (Maybe FilePath) xmobarConfigFile =
src/Xmobar/App/Main.hs view
@@ -70,13 +70,13 @@   for_ (concat vars) $ \(asyncs, _) ->     for_ asyncs cancel -buildLaunch :: Bool -> Bool -> FilePath -> String -> ParseError -> IO ()-buildLaunch verb force p datadir e = do+buildLaunch :: Bool -> Bool -> String -> ParseError -> IO ()+buildLaunch verb force p e = do   let exec = takeBaseName p       confDir = takeDirectory p       ext = takeExtension p   if ext `elem` [".hs", ".hsc", ".lhs"]-    then recompile confDir datadir exec force verb >>+    then xmobarDataDir >>= \dd -> recompile confDir dd exec force verb >>          executeFile (confDir </> exec) False [] Nothing     else trace True ("Invalid configuration file: " ++ show e) >>          trace True "\n(No compilation attempted: \@@ -101,8 +101,7 @@                 (c:_) -> error $ c ++ ": file not found"                 _ -> doOpts defaultConfig flags >>= xmobar     Just p -> do r <- readConfig defaultConfig p-                 dataDir <- xmobarDataDir                  case r of                    Left e ->-                     buildLaunch (verboseFlag flags) (recompileFlag flags) p dataDir e+                     buildLaunch (verboseFlag flags) (recompileFlag flags) p e                    Right (c, defs) -> doOpts c flags >>= xmobar' defs
src/Xmobar/Plugins/DateZone.hs view
@@ -28,7 +28,10 @@ import Control.Concurrent.STM  import System.IO.Unsafe+import System.Environment (lookupEnv) +import Data.Maybe (fromMaybe)+ import Data.Time.Format import Data.Time.LocalTime import Data.Time.LocalTime.TimeZone.Olson@@ -63,7 +66,8 @@       locale <- getTimeLocale       atomically $ putTMVar localeLock lock       if z /= "" then do-        timeZone <- getTimeZoneSeriesFromOlsonFile ("/usr/share/zoneinfo/" ++ z)+        tzdir <- lookupEnv "TZDIR"+        timeZone <- getTimeZoneSeriesFromOlsonFile ((fromMaybe "/usr/share/zoneinfo" tzdir) ++ "/" ++ z)         go (dateZone f locale timeZone)        else         go (date f locale)
src/Xmobar/Plugins/Kbd.hs view
@@ -27,7 +27,7 @@  -- 'Bad' prefixes of layouts noLaySymbols :: [String]-noLaySymbols = ["group", "inet", "ctr", "pc", "ctrl"]+noLaySymbols = ["group", "inet", "ctr", "pc", "ctrl", "terminate"]   -- splits the layout string into the actual layouts
src/Xmobar/Plugins/Mail.hs view
@@ -13,7 +13,7 @@ -- ----------------------------------------------------------------------------- -module Xmobar.Plugins.Mail(Mail(..)) where+module Xmobar.Plugins.Mail(Mail(..),MailX(..)) where  import Xmobar.Run.Exec #ifdef INOTIFY@@ -26,6 +26,7 @@ import System.Directory import System.FilePath import System.INotify+import System.Console.GetOpt  import Data.List (isPrefixOf) import Data.Set (Set)@@ -47,23 +48,56 @@ import System.IO #endif +data MOptions = MOptions+               { oDir :: FilePath+               , oPrefix :: String+               , oSuffix :: String+               } +defaults :: MOptions+defaults = MOptions {oDir = "", oPrefix = "", oSuffix = ""}++options :: [OptDescr (MOptions -> MOptions)]+options =+  [ Option "d" ["dir"] (ReqArg (\x o -> o { oDir = x }) "") ""+  , Option "p" ["prefix"] (ReqArg (\x o -> o { oPrefix = x }) "") ""+  , 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) +-- | A list of mail box names, paths to maildirs and display colors.+data MailX = MailX [(String, FilePath, String)] [String] String+    deriving (Read, Show)+ instance Exec Mail where-    alias (Mail _ a) = a+  alias (Mail _ a) = a+  start (Mail ms a) = start (MailX (map (\(n,p) -> (n,p,"")) ms) [] a)++instance Exec MailX where+    alias (MailX _ _ a) = a #ifndef INOTIFY     start _ _ =         hPutStrLn stderr $ "Warning: xmobar is not compiled with -fwith_inotify,"                         ++ " but the Mail plugin requires it." #else-    start (Mail ms _) cb = do+    start (MailX ms args _) cb = do         vs <- mapM (const $ newTVarIO S.empty) ms--        let ts = map fst ms-            rs = map ((</> "new") . snd) ms+        opts <- parseOptions args+        let prefix = oPrefix opts+            suffix = oSuffix opts+            dir = oDir opts+            ps = map (\(_,p,_) -> if null dir then p else dir </> p) ms+            rs = map (</> "new") ps             ev = [Move, MoveIn, MoveOut, Create, Delete]          ds <- mapM expandHome rs@@ -76,9 +110,11 @@             atomically $ modifyTVar v (S.union s)          changeLoop (mapM (fmap S.size . readTVar) vs) $ \ns ->-            cb . unwords $ [m ++ show n-                            | (m, n) <- zip ts ns-                            , n /= 0 ]+            let showmbx m n c = if c == ""+                                then m ++ show n+                                else "<fc=" ++ c ++ ">" ++ m ++ show n ++ "</fc>"+                cnts = [showmbx m n c | ((m,_,c), n) <- zip ms ns , n /= 0 ]+            in cb $ if null cnts then "" else prefix ++ unwords cnts ++ suffix  handle :: TVar (Set String) -> Event -> IO () handle v e = atomically $ modifyTVar v $ case e of
src/Xmobar/Plugins/Monitors/Batt.hs view
@@ -45,6 +45,10 @@   , onIconPattern :: Maybe IconPattern   , offIconPattern :: Maybe IconPattern   , idleIconPattern :: Maybe IconPattern+  , lowString :: String+  , mediumString :: String+  , highString :: String+  , incPerc :: Bool   }  defaultOpts :: BattOpts@@ -65,6 +69,10 @@   , onIconPattern = Nothing   , offIconPattern = Nothing   , idleIconPattern = Nothing+  , lowString = ""+  , mediumString = ""+  , highString = ""+  , incPerc = False   }  options :: [OptDescr (BattOpts -> BattOpts)]@@ -81,6 +89,7 @@   , Option "f" ["online"] (ReqArg (\x o -> o { onlineFile = x }) "") ""   , Option "s" ["scale"] (ReqArg (\x o -> o {scale = read x}) "") ""   , Option "a" ["action"] (ReqArg (\x o -> o { onLowAction = Just x }) "") ""+  , Option "P" ["percent"] (NoArg (\o -> o {incPerc = True})) ""   , Option "A" ["action-threshold"]                (ReqArg (\x o -> o { actionThreshold = read x }) "") ""   , Option "" ["on-icon-pattern"] (ReqArg (\x o ->@@ -89,6 +98,9 @@      o { offIconPattern = Just $ parseIconPattern x }) "") ""   , Option "" ["idle-icon-pattern"] (ReqArg (\x o ->      o { idleIconPattern = Just $ parseIconPattern x }) "") ""+  , Option "" ["lows"] (ReqArg (\x o -> o { lowString = x }) "") ""+  , Option "" ["mediums"] (ReqArg (\x o -> o { mediumString = x }) "") ""+  , Option "" ["highs"] (ReqArg (\x o -> o { highString = x }) "") ""   ]  parseOpts :: [String] -> IO BattOpts@@ -125,6 +137,23 @@   , status :: !String   } +data BatteryStatus+  = BattHigh+  | BattMedium+  | BattLow++-- | Convert the current battery charge into a 'BatteryStatus'+getBattStatus+  :: Float    -- ^ Current battery charge, assumed to be in [0,1]+  -> BattOpts -- ^ Battery options, including high/low thresholds+  -> BatteryStatus+getBattStatus charge opts+  | c >= highThreshold opts = BattHigh+  | c >= lowThreshold  opts = BattMedium+  | otherwise = BattLow+ where+   c = 100 * min 1 charge+ safeFileExist :: String -> String -> IO Bool safeFileExist d f = handle noErrors $ fileExist (d </> f)   where noErrors = const (return False) :: SomeException -> IO Bool@@ -217,25 +246,29 @@ runBatt' :: [String] -> [String] -> Monitor String runBatt' bfs args = do   opts <- io $ parseOpts args+  let sp = incPerc opts   c <- io $ readBatteries opts =<< mapM batteryFiles bfs   suffix <- getConfigValue useSuffix   d <- getConfigValue decDigits   nas <- getConfigValue naString   case c of     Result x w t s ->-      do l <- fmtPercent x+      do l <- fmtPercent x sp          ws <- fmtWatts w opts suffix d          si <- getIconPattern opts s x-         st <- showWithColors' (fmtStatus opts s nas) (100 * x)+         st <- showWithColors'+                 (fmtStatus opts s nas (getBattStatus x opts))+                 (100 * x)          parseTemplate (l ++ [st, fmtTime $ floor t, ws, si])     NA -> getConfigValue naString-  where fmtPercent :: Float -> Monitor [String]-        fmtPercent x = do+  where fmtPercent :: Float -> Bool -> Monitor [String]+        fmtPercent x sp = do           let x' = minimum [1, x]+          pc <- if sp then colorizeString (100 * x') "%" else return ""           p <- showPercentWithColors x'           b <- showPercentBar (100 * x') x'           vb <- showVerticalBar (100 * x') x'-          return [b, vb, p]+          return [b, vb, p ++ pc]         fmtWatts x o s d = do           ws <- showWithPadding $ showDigits d x ++ (if s then "W" else "")           return $ color x o ws@@ -244,11 +277,21 @@                                     then minutes else '0' : minutes           where hours = show (x `div` 3600)                 minutes = show ((x `mod` 3600) `div` 60)-        fmtStatus opts Idle _ = idleString opts-        fmtStatus _ Unknown na = na-        fmtStatus opts Full _ = idleString opts-        fmtStatus opts Charging _ = onString opts-        fmtStatus opts Discharging _ = offString opts+        fmtStatus+          :: BattOpts+          -> Status+          -> String -- ^ What to in case battery status is unknown+          -> BatteryStatus+          -> String+        fmtStatus opts Idle _ _ = idleString opts+        fmtStatus _ Unknown na _ = na+        fmtStatus opts Full _ _ = idleString opts+        fmtStatus opts Charging _ _ = onString opts+        fmtStatus opts Discharging _ battStatus =+          (case battStatus of+            BattHigh -> highString+            BattMedium -> mediumString+            BattLow -> lowString) opts ++ offString opts         maybeColor Nothing str = str         maybeColor (Just c) str = "<fc=" ++ c ++ ">" ++ str ++ "</fc>"         color x o | x >= 0 = maybeColor (posColor o)
src/Xmobar/Plugins/Monitors/Common/Output.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.Plugins.Monitors.Strings--- Copyright: (c) 2018 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2018, 2019 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org@@ -18,6 +18,7 @@ module Xmobar.Plugins.Monitors.Common.Output ( IconPattern                                              , parseIconPattern                                              , padString+                                             , colorizeString                                              , showWithPadding                                              , showWithColors                                              , showWithColors'
src/Xmobar/Plugins/Monitors/Disk.hs view
@@ -31,6 +31,7 @@   { totalIconPattern :: Maybe IconPattern   , writeIconPattern :: Maybe IconPattern   , readIconPattern :: Maybe IconPattern+  , contiguous :: Bool   }  parseDiskIOOpts :: [String] -> IO DiskIOOpts@@ -42,6 +43,7 @@           { totalIconPattern = Nothing           , writeIconPattern = Nothing           , readIconPattern = Nothing+          , contiguous = False           }        options =           [ Option "" ["total-icon-pattern"] (ReqArg (\x o ->@@ -50,6 +52,7 @@              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@@ -66,6 +69,7 @@ data DiskUOpts = DiskUOpts   { freeIconPattern :: Maybe IconPattern   , usedIconPattern :: Maybe IconPattern+  , contiguousU :: Bool   }  parseDiskUOpts :: [String] -> IO DiskUOpts@@ -76,12 +80,14 @@  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})) ""           ]  diskUConfig :: IO MConfig@@ -147,25 +153,26 @@   return $ map (parseDev (zipWith diff dt' dt)) devs   where diff (dev, xs) (_, ys) = (dev, zipWith (-) xs ys) + parseDev :: [(DevName, [Float])] -> DevName -> (DevName, [Float]) parseDev dat dev =   case find ((==dev) . fst) dat of     Nothing -> (dev, [0, 0, 0])     Just (_, xs) ->-      let r = xs !! 2-          w = xs !! 6+      let r = 4096 * xs !! 2+          w = 4096 * xs !! 6           t = r + w           rSp = speed r (xs !! 3)           wSp = speed w (xs !! 7)           sp =  speed t (xs !! 3 + xs !! 7)-          speed x d = if d == 0 then 0 else 500 * x / d+          speed x d = if d == 0 then 0 else x / d           dat' = if length xs > 6                  then [sp, rSp, wSp, t, r, w]                  else [0, 0, 0, 0, 0, 0]       in (dev, dat')  speedToStr :: Float -> String-speedToStr = showWithUnits 2 1+speedToStr = showWithUnits 2 1 . (/ 1024)  sizeToStr :: Integer -> String sizeToStr = showWithUnits 3 0 . fromIntegral@@ -205,7 +212,7 @@   dev <- io $ mountedOrDiskDevices (map fst disks)   dat <- io $ mountedData dref (map fst dev)   strs <- mapM (runDiskIO' opts) $ devTemplates disks dev dat-  return $ unwords strs+  return $ (if contiguous opts then concat else unwords) strs  startDiskIO :: [(String, String)] ->                [String] -> Int -> (String -> IO ()) -> IO ()@@ -249,4 +256,4 @@   devs <- io $ mountedDevices (map fst disks)   opts <- io $ parseDiskUOpts argv   strs <- mapM (\(d, p) -> runDiskU' opts (findTempl d p disks) p) devs-  return $ unwords strs+  return $ (if contiguousU opts then concat else unwords) strs
src/Xmobar/Plugins/Monitors/MPD.hs view
@@ -34,6 +34,8 @@   , mStopped :: String   , mPaused :: String   , mLapsedIconPattern :: Maybe IconPattern+  , mPort :: Maybe String+  , mHost :: Maybe String   }  defaultOpts :: MOpts@@ -42,6 +44,8 @@   , mStopped = "><"   , mPaused = "||"   , mLapsedIconPattern = Nothing+  , mPort = Nothing+  , mHost = Nothing   }  options :: [OptDescr (MOpts -> MOpts)]@@ -49,15 +53,20 @@   [ Option "P" ["playing"] (ReqArg (\x o -> o { mPlaying = x }) "") ""   , Option "S" ["stopped"] (ReqArg (\x o -> o { mStopped = x }) "") ""   , Option "Z" ["paused"] (ReqArg (\x o -> o { mPaused = x }) "") ""+  , Option "p" ["port"] (ReqArg (\x o -> o { mPort = Just x }) "") ""+  , Option "h" ["host"] (ReqArg (\x o -> o { mHost = Just x }) "") ""   , Option "" ["lapsed-icon-pattern"] (ReqArg (\x o ->      o { mLapsedIconPattern = Just $ parseIconPattern x }) "") ""   ] +withMPD :: MOpts -> M.MPD a -> IO (M.Response a)+withMPD opts = M.withMPD_ (mHost opts) (mPort opts)+ runMPD :: [String] -> Monitor String runMPD args = do   opts <- io $ mopts args-  status <- io $ M.withMPD M.status-  song <- io $ M.withMPD M.currentSong+  status <- io $ withMPD opts M.status+  song <- io $ withMPD opts M.currentSong   s <- parseMPD status song opts   parseTemplate s @@ -69,8 +78,9 @@     _ -> return ()  mpdReady :: [String] -> Monitor Bool-mpdReady _ = do-  response <- io $ M.withMPD M.ping+mpdReady args = do+  opts <- io $ mopts args+  response <- io $ withMPD opts M.ping   case response of     Right _         -> return True     -- Only cases where MPD isn't responding is an issue; bogus information at
src/Xmobar/Plugins/Monitors/Net.hs view
@@ -13,6 +13,8 @@ -- ----------------------------------------------------------------------------- +{-# LANGUAGE OverloadedStrings #-}+ module Xmobar.Plugins.Monitors.Net (                         startNet                       , startDynNet@@ -20,26 +22,40 @@  import Xmobar.Plugins.Monitors.Common -import Data.Word (Word64) import Data.IORef (IORef, newIORef, readIORef, writeIORef)+import Data.Monoid ((<>)) import Data.Time.Clock (UTCTime, getCurrentTime, diffUTCTime)+import Data.Word (Word64) import Control.Monad (forM, filterM) import System.Directory (getDirectoryContents, doesFileExist) import System.FilePath ((</>)) import System.Console.GetOpt import System.IO.Error (catchIOError)+import System.IO.Unsafe (unsafeInterleaveIO) -import qualified Data.ByteString.Lazy.Char8 as B+import qualified Data.ByteString.Char8 as B +type DevList = [String]++parseDevList :: String -> DevList+parseDevList = splitOnComma+  where splitOnComma [] = [[]]+        splitOnComma (',':xs) = [] : splitOnComma xs+        splitOnComma (x:xs) =+           let rest = splitOnComma xs+           in (x : head rest) : tail rest+ data NetOpts = NetOpts   { rxIconPattern :: Maybe IconPattern   , txIconPattern :: Maybe IconPattern+  , onlyDevList :: Maybe DevList   }  defaultOpts :: NetOpts defaultOpts = NetOpts   { rxIconPattern = Nothing   , txIconPattern = Nothing+  , onlyDevList = Nothing   }  options :: [OptDescr (NetOpts -> NetOpts)]@@ -48,6 +64,8 @@      o { rxIconPattern = Just $ parseIconPattern x }) "") ""   , Option "" ["tx-icon-pattern"] (ReqArg (\x o ->      o { txIconPattern = Just $ parseIconPattern x }) "") ""+  , Option "" ["devices"] (ReqArg (\x o ->+     o { onlyDevList = Just $ parseDevList x }) "") ""   ]  parseOpts :: [String] -> IO NetOpts@@ -65,10 +83,8 @@     show MBs = "MB/s"     show GBs = "GB/s" -data NetDev num-    = NA-    | NI String-    | ND String num num deriving (Eq,Show,Read)+data NetDev num = N String (NetDevInfo num) | NA deriving (Eq,Show,Read)+data NetDevInfo num = NI | ND num num deriving (Eq,Show,Read)  type NetDevRawTotal = NetDev Word64 type NetDevRate = NetDev Float@@ -79,18 +95,17 @@ -- Note that names don't matter. Therefore, if only the names differ, -- a compare evaluates to EQ while (==) evaluates to False. instance Ord num => Ord (NetDev num) where-    compare NA NA              = EQ-    compare NA _               = LT-    compare _  NA              = GT-    compare (NI _) (NI _)      = EQ-    compare (NI _) ND {}       = LT-    compare ND {} (NI _)     = GT-    compare (ND _ x1 y1) (ND _ x2 y2) =-        if downcmp /= EQ-           then downcmp-           else y1 `compare` y2-      where downcmp = x1 `compare` x2+    compare NA NA             = EQ+    compare NA _              = LT+    compare _  NA             = GT+    compare (N _ i1) (N _ i2) = i1 `compare` i2 +instance Ord num => Ord (NetDevInfo num) where+    compare NI NI                 = EQ+    compare NI ND {}              = LT+    compare ND {} NI              = GT+    compare (ND x1 y1) (ND x2 y2) = x1 `compare` x2 <> y1 `compare` y2+ netConfig :: IO MConfig netConfig = mkMConfig     "<dev>: <rx>KB|<tx>KB"      -- template@@ -108,25 +123,20 @@ isUp :: String -> IO Bool isUp d = flip catchIOError (const $ return False) $ do   operstate <- B.readFile (operstateDir d)-  return $! (B.unpack . head . B.lines) operstate `elem`  ["up", "unknown"]+  return $! (head . B.lines) operstate `elem` ["up", "unknown"]  readNetDev :: [String] -> IO NetDevRawTotal-readNetDev (d:x:y:_) = do-  up <- isUp d-  return (if up then ND d (r x) (r y) else NI d)+readNetDev ~[d, x, y] = do+  up <- unsafeInterleaveIO $ isUp d+  return $ N d (if up then ND (r x) (r y) else NI)     where r s | s == "" = 0               | otherwise = read s -readNetDev _ = return NA- netParser :: B.ByteString -> IO [NetDevRawTotal] netParser = mapM (readNetDev . splitDevLine) . readDevLines   where readDevLines = drop 2 . B.lines-        splitDevLine = selectCols . wordsBy (`elem` " :") . B.unpack+        splitDevLine = map B.unpack . selectCols . filter (not . B.null) . B.splitWith (`elem` [' ',':'])         selectCols cols = map (cols!!) [0,1,9]-        wordsBy f s = case dropWhile f s of-          [] -> []-          s' -> w : wordsBy f s'' where (w, s'') = break f s'  findNetDev :: String -> IO NetDevRawTotal findNetDev dev = do@@ -134,8 +144,7 @@   case filter isDev nds of     x:_ -> return x     _ -> return NA-  where isDev (ND d _ _) = d == dev-        isDev (NI d) = d == dev+  where isDev (N d _) = d == dev         isDev NA = False  formatNet :: Maybe IconPattern -> Float -> Monitor (String, String, String, String)@@ -154,11 +163,11 @@ printNet :: NetOpts -> NetDevRate -> Monitor String printNet opts nd =   case nd of-    ND d r t -> do+    N d (ND r t) -> do         (rx, rb, rvb, ripat) <- formatNet (rxIconPattern opts) r         (tx, tb, tvb, tipat) <- formatNet (txIconPattern opts) t         parseTemplate [d,rx,tx,rb,rvb,ripat,tb,tvb,tipat]-    NI _ -> return ""+    N _ NI -> return ""     NA -> getConfigValue naString  parseNet :: NetDevRef -> String -> IO NetDevRate@@ -170,9 +179,9 @@   let scx = realToFrac (diffUTCTime t1 t0)       scx' = if scx > 0 then scx else 1       rate da db = takeDigits 2 $ fromIntegral (db - da) / scx'-      diffRate (ND d ra ta) (ND _ rb tb) = ND d (rate ra rb) (rate ta tb)-      diffRate (NI d) _ = NI d-      diffRate _ (NI d) = NI d+      diffRate (N d (ND ra ta)) (N _ (ND rb tb)) = N d (ND (rate ra rb) (rate ta tb))+      diffRate (N d NI) _ = N d NI+      diffRate _ (N d NI) = N d NI       diffRate _ _ = NA   return $ diffRate n0 n1 @@ -187,10 +196,16 @@  runNets :: [(NetDevRef, String)] -> [String] -> Monitor String runNets refs argv = do-  dev <- io $ parseActive refs   opts <- io $ parseOpts argv+  dev <- io $ parseActive $ filterRefs opts refs   printNet opts dev     where parseActive refs' = fmap selectActive (parseNets refs')+          refInDevList opts' (_, refname') = case onlyDevList opts' of+            Just theList -> refname' `elem` theList+            Nothing -> True+          filterRefs opts' refs' = case filter (refInDevList opts') refs' of+            [] -> refs'+            xs -> xs           selectActive = maximum  startNet :: String -> [String] -> Int -> (String -> IO ()) -> IO ()
src/Xmobar/Plugins/Monitors/Volume.hs view
@@ -21,7 +21,7 @@   , VolumeOpts   ) where -import Control.Applicative ((<$>))+import Control.Applicative ( (<$>), liftA3 ) import Control.Monad ( liftM2, liftM3, mplus ) import Data.Traversable (sequenceA) import Xmobar.Plugins.Monitors.Common@@ -42,6 +42,11 @@     , highDbThresh :: Float     , lowDbThresh :: Float     , volumeIconPattern :: Maybe IconPattern+    , lowVolThresh :: Maybe Float+    , highVolThresh :: Maybe Float+    , lowString :: String+    , mediumString :: String+    , highString :: String     }  defaultOpts :: VolumeOpts@@ -53,8 +58,32 @@     , highDbThresh = -5.0     , lowDbThresh = -30.0     , volumeIconPattern = Nothing+    , lowVolThresh = Just 20.0+    , highVolThresh = Just 60.0+    , lowString = ""+    , mediumString = ""+    , highString = ""     } +data VolumeStatus+    = VolLow+    | VolMedium+    | VolHigh+    | VolOff++-- | Set the volume status according to user set thresholds and the current+-- volume+getVolStatus :: Float -- ^ Low volume threshold, in [0,100]+             -> Float -- ^ High volume threshold, in  [0,100]+             -> Float -- ^ Current volume, in [0,1]+             -> VolumeStatus+getVolStatus lo hi val'+    | val >= hi = VolHigh+    | val >= lo = VolMedium+    | otherwise = VolLow+  where+    val = val' * 100+ options :: [OptDescr (VolumeOpts -> VolumeOpts)] options =     [ Option "O" ["on"] (ReqArg (\x o -> o { onString = x }) "") ""@@ -65,6 +94,11 @@     , Option "c" ["offc"] (ReqArg (\x o -> o { offColor = Just x }) "") ""     , Option "" ["volume-icon-pattern"] (ReqArg (\x o ->        o { volumeIconPattern = Just $ parseIconPattern x }) "") ""+    , Option "L" ["lowv"] (ReqArg (\x o -> o { lowVolThresh = Just $ read x }) "") ""+    , Option "H" ["highv"] (ReqArg (\x o -> o { highVolThresh = Just $ read x }) "") ""+    , Option "l" ["lows"] (ReqArg (\x o -> o { lowString = x }) "") ""+    , Option "m" ["mediums"] (ReqArg (\x o -> o { mediumString = x }) "") ""+    , Option "h" ["highs"] (ReqArg (\x o -> o { highString = x }) "") ""     ]  parseOpts :: [String] -> IO VolumeOpts@@ -98,16 +132,27 @@ switchHelper :: VolumeOpts              -> (VolumeOpts -> Maybe String)              -> (VolumeOpts -> String)+             -> VolumeStatus              -> Monitor String-switchHelper opts cHelp strHelp = return $+switchHelper opts cHelp strHelp vs = return $     colorHelper (cHelp opts)+    ++ volHelper vs opts     ++ strHelp opts     ++ maybe "" (const "</fc>") (cHelp opts) -formatSwitch :: VolumeOpts -> Bool -> Monitor String-formatSwitch opts True = switchHelper opts onColor onString-formatSwitch opts False = switchHelper opts offColor offString+formatSwitch :: VolumeOpts -> Bool -> VolumeStatus -> Monitor String+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+volHelper :: VolumeStatus -> VolumeOpts -> String+volHelper volStatus opts =+    case volStatus of+        VolHigh -> highString opts+        VolMedium -> mediumString opts+        VolLow -> lowString opts+        VolOff -> ""+ colorHelper :: Maybe String -> String colorHelper = maybe "" (\c -> "<fc=" ++ c ++ ">") @@ -138,7 +183,11 @@     b <- liftMonitor $ liftM3 formatVolBar lo hi val     v <- liftMonitor $ liftM3 formatVolVBar lo hi val     d <- getFormatDB opts db-    s <- getFormatSwitch opts sw+    let volStat = liftA3 getVolStatus+                         (lowVolThresh opts)+                         (highVolThresh opts)+                         (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] @@ -191,8 +240,9 @@     getFormatDB _ Nothing = unavailable     getFormatDB opts' (Just d) = formatDb opts' d -    getFormatSwitch :: VolumeOpts -> Maybe Bool -> Monitor String-    getFormatSwitch _ Nothing = unavailable-    getFormatSwitch opts' (Just sw) = formatSwitch opts' sw+    getFormatSwitch :: VolumeOpts -> Maybe Bool -> Maybe VolumeStatus -> Monitor String+    getFormatSwitch _ Nothing _ = unavailable+    getFormatSwitch _ _ Nothing = unavailable+    getFormatSwitch opts' (Just sw) (Just vs) = formatSwitch opts' sw vs      unavailable = getConfigValue naString
xmobar.cabal view
@@ -1,5 +1,5 @@ name:               xmobar-version:            0.31+version:            0.32 homepage:           http://xmobar.org synopsis:           A Minimalistic Text Based Status Bar description: 	    Xmobar is a minimalistic text based status bar.@@ -159,7 +159,7 @@     ghc-options: -funbox-strict-fields -Wall -fno-warn-unused-do-bind      build-depends:-      base >= 4.9.1.0 && < 4.13,+      base >= 4.9.1.0 && < 4.14,       containers,       regex-compat,       process,