From f7cbb14d9ee40d07abcde45868507f858e072fdd Mon Sep 17 00:00:00 2001
From: Jose Antonio Ortega Ruiz <jao@gnu.org>
Date: Wed, 8 Dec 2010 23:02:56 +0100
Subject: Battery monitor: specific arguments instead of hardcoded hilite

---
 Plugins/Monitors/Batt.hs | 112 +++++++++++++++++++++++++++++++++++------------
 README                   |  76 ++++++++++++++++++++------------
 2 files changed, 132 insertions(+), 56 deletions(-)

diff --git a/Plugins/Monitors/Batt.hs b/Plugins/Monitors/Batt.hs
index bb2027c..b860210 100644
--- a/Plugins/Monitors/Batt.hs
+++ b/Plugins/Monitors/Batt.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Plugins.Monitors.Batt
--- Copyright   :  (c) Andrea Rossato
+-- Copyright   :  (c) Andrea Rossato, 2010 Petr Rockai, 2010 Jose A Ortega
 -- License     :  BSD-style (see LICENSE)
 --
 -- Maintainer  :  Andrea Rossato <andrea.rossato@unibz.it>
@@ -17,20 +17,72 @@ module Plugins.Monitors.Batt ( battConfig, runBatt, runBatt' ) where
 import qualified Data.ByteString.Lazy.Char8 as B
 import Plugins.Monitors.Common
 import System.Posix.Files (fileExist)
+import System.Console.GetOpt
 
-data Result = Result { percent :: Float, watts :: Float, time :: Float, ac :: String }
-            | NA
+data BattOpts = BattOpts
+  { onString :: String
+  , offString :: String
+  , posColor :: Maybe String
+  , lowWColor :: Maybe String
+  , mediumWColor :: Maybe String
+  , highWColor :: Maybe String
+  , lowThreshold :: Float
+  , highThreshold :: Float
+  }
 
+defaultOpts :: BattOpts
+defaultOpts = BattOpts
+  { onString = "On"
+  , offString = "Off"
+  , posColor = Nothing
+  , lowWColor = Nothing
+  , mediumWColor = Nothing
+  , highWColor = Nothing
+  , lowThreshold = -12
+  , highThreshold = -10
+  }
+
+options :: [OptDescr (BattOpts -> BattOpts)]
+options =
+  [ Option "O" ["on"] (ReqArg (\x o -> o { onString = x }) "") ""
+  , Option "o" ["off"] (ReqArg (\x o -> o { offString = x }) "") ""
+  , Option "p" ["positive"] (ReqArg (\x o -> o { posColor = Just x }) "") ""
+  , Option "l" ["low"] (ReqArg (\x o -> o { lowWColor = Just x }) "") ""
+  , Option "m" ["medium"] (ReqArg (\x o -> o { mediumWColor = Just x }) "") ""
+  , Option "h" ["high"] (ReqArg (\x o -> o { highWColor = Just x }) "") ""
+  , Option "L" ["lowt"] (ReqArg (\x o -> o { lowThreshold = read x }) "") ""
+  , Option "H" ["hight"] (ReqArg (\x o -> o { highThreshold = read 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 Result = Result Float Float Float String | NA
+
+base :: String
 base = "/sys/class/power_supply"
 
 battConfig :: IO MConfig
 battConfig = mkMConfig
-       "Batt: <watts>, <left> / <timeleft>" -- template
-       ["leftbar", "left", "status", "timeleft", "watts"] -- available replacements
+       "Batt: <watts>, <left>% / <timeleft>" -- template
+       ["leftbar", "left", "acstatus", "timeleft", "watts"] -- replacements
+
+data Files = Files
+  { f_full :: String
+  , f_now :: String
+  , f_voltage :: String
+  , f_current :: String
+  } | NoFiles
 
-data Files = Files { f_full :: String, f_now :: String
-                   , f_voltage :: String, f_current :: String } | NoFiles
-data Battery = Battery { full :: Float, now :: Float, voltage :: Float, current :: Float }
+data Battery = Battery
+  { full :: Float
+  , now :: Float
+  , voltage :: Float
+  , current :: Float
+  }
 
 batteryFiles :: String -> IO Files
 batteryFiles bat =
@@ -66,42 +118,48 @@ readBattery files =
                         (d / c) -- amperes
     where grab = fmap (read . B.unpack) . catRead
 
-readBatteries :: [Files] -> IO Result
-readBatteries bfs =
+readBatteries :: BattOpts -> [Files] -> IO Result
+readBatteries opts bfs =
     do bats <- mapM readBattery (take 3 bfs)
        ac' <- haveAc
-       let ac = if ac' == Just True then True else False
+       let ac = (ac' == Just True)
            sign = if ac then 1 else -1
-           left = (sum $ map now bats) / (sum $ map full bats)
-           watts = sign * (sum $ map voltage bats) * (sum $ map current bats)
+           left = sum (map now bats) / sum (map full bats)
+           watts = sign * sum (map voltage bats) * sum (map current bats)
            time = if watts == 0 then 0 else sum $ map time' bats -- negate sign
            time' b = (if ac then full b - now b else now b) / (sign * watts)
            acstr = case ac' of
              Nothing -> "?"
-             Just True -> "<fc=green>On</fc>"
-             Just False -> "<fc=red>Off</fc>"
+             Just True -> onString opts
+             Just False -> offString opts
        return $ if isNaN left then NA else Result left watts time acstr
 
 runBatt :: [String] -> Monitor String
 runBatt = runBatt' ["BAT0","BAT1","BAT2"]
 
 runBatt' :: [String] -> [String] -> Monitor String
-runBatt' bfs _ = do
-  c <- io $ readBatteries =<< mapM batteryFiles bfs
+runBatt' bfs args = do
+  opts <- io $ parseOpts args
+  c <- io $ readBatteries opts =<< mapM batteryFiles bfs
   case c of
-    Result x w t s -> do l <- fmtPercent x
-                         parseTemplate (l ++ [s] ++ [fmtTime $ floor t, fmtWatts w])
+    Result x w t s ->
+      do l <- fmtPercent x
+         parseTemplate (l ++ s:[fmtTime $ floor t, fmtWatts w opts])
     NA -> return "N/A"
  where fmtPercent :: Float -> Monitor [String]
        fmtPercent x = do
-         p <- showPercentsWithColors [x]
+         p <- showPercentWithColors x
          b <- showPercentBar (100 * x) x
-         return (b:p)
-       fmtWatts x = color x $ showDigits 1 x ++ "W"
-       fmtTime x = hours ++ ":" ++ if length minutes == 2 then minutes else "0" ++ minutes
+         return [b, p]
+       fmtWatts x o = color x o $ showDigits 1 x ++ "W"
+       fmtTime :: Integer -> String
+       fmtTime x = hours ++ ":" ++ if length minutes == 2
+                                   then minutes else '0' : minutes
          where hours = show (x `div` 3600)
                minutes = show ((x `mod` 3600) `div` 60)
-       color x str | x >= 0 = "<fc=orange>" ++ str ++ "</fc>"
-                   | x >= -10 = "<fc=green>" ++ str ++ "</fc>"
-                   | x >= -12 = str
-                   | otherwise = "<fc=red>" ++ str ++ "</fc>"
+       maybeColor Nothing _ = ""
+       maybeColor (Just c) str = "<fc=" ++ c ++ ">" ++ str ++ "</fc>"
+       color x o | x >= 0 = maybeColor (posColor o)
+                 | x >= highThreshold o = maybeColor (highWColor o)
+                 | x >= lowThreshold o = maybeColor (mediumWColor o)
+                 | otherwise = maybeColor (lowWColor o)
diff --git a/README b/README
index 146123c..10c6e9c 100644
--- a/README
+++ b/README
@@ -310,7 +310,7 @@ Monitors have default aliases.
 `Weather StationID Args RefreshRate`
 
 - aliases to the Station ID: so `Weather "LIPB" []` can be used in template as `%LIPB%`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
 	    `station`, `stationState`, `year`, `month`, `day`, `hour`,
 	    `wind`, `visibility`, `skyCondition`, `tempC`, `tempF`,
@@ -321,8 +321,9 @@ Monitors have default aliases.
 
 `Network Interface Args RefreshRate`
 
-- aliases to the interface name: so `Network "eth0" []` can be used as `%eth0%`
-- Args: the argument list (see below)
+- aliases to the interface name: so `Network "eth0" []` can be used as
+  `%eth0%`
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
 	    `dev`, `rx`, `tx`, `rxbar`, `txbar`
 - Default template: `<dev>: <rx>|<tx>`
@@ -331,7 +332,7 @@ Monitors have default aliases.
 
 - aliases to the interface name with the suffix "wi": thus, `Wirelss
   "wlan0" []` can be used as `%wlan0wi%`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
             `essid`, `quality`, `qualitybar`
 - Default template: `<essid> <quality>`
@@ -342,7 +343,7 @@ Monitors have default aliases.
 `Memory Args RefreshRate`
 
 - aliases to `memory`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
              `total`, `free`, `buffer`, `cache`, `rest`, `used`,
              `usedratio`, `usedbar`, `freebar`
@@ -351,7 +352,7 @@ Monitors have default aliases.
 `Swap Args RefreshRate`
 
 - aliases to `swap`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
 	    `total`, `used`, `free`, `usedratio`
 - Default template: `Swap: <usedratio>%`
@@ -359,7 +360,7 @@ Monitors have default aliases.
 `Cpu Args RefreshRate`
 
 - aliases to `cpu`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
 	    `total`, `bar`, `user`, `nice`, `system`, `idle`
 - Default template: `Cpu: <total>%`
@@ -367,7 +368,7 @@ Monitors have default aliases.
 `MultiCpu Args RefreshRate`
 
 - aliases to `multicpu`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
 	    `total`, `bar`, `user`, `nice`, `system`, `idle`,
 	    `total0`, `bar0`, `user0`, `nice0`, `system0`, `idle0`, ...
@@ -375,11 +376,7 @@ Monitors have default aliases.
 
 `Battery Args RefreshRate`
 
-- aliases to `battery`
-- Args: the argument list (see below)
-- Variables that can be used with the `-t`/`--template` argument:
-	    `left`, `leftbar`, `status`
-- Default template: `Batt: <left>`
+- Same as `BatteryP ["BAT0", "BAT1", "BAT2"] Args RefreshRate`.
 
 `BatteryP Dirs Args RefreshRate`
 
@@ -388,15 +385,36 @@ Monitors have default aliases.
   look for the `state` and `info` files. Example:
   `["BAT0","BAT1","BAT2"]`. Only the first 3 directories will be
   searched.
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below), plus the following specif ones:
+    - `-O`: string for AC "on" status (default: "On")
+    - `-o`: string for AC "off" status (default: "Off")
+    - `-L`: low power (`watts`) threshold (default: -12)
+    - `-H`: high power threshold (defualt: -10)
+    - `-l`: color to display power lower than the `-L` threshold
+    - `-m`: color to display power lower than the `-H` threshold
+    - `-h`: color to display power highter than the `-H` threshold
+    - `-p`: color to display positive power (battery charging)
 - Variables that can be used with the `-t`/`--template` argument:
-	    `left`, `leftbar`, `status`
-- Default template: `Batt: <left>%`
+	    `left`, `leftbar`, `timeleft`, `watts`, `acstatus`
+- Default template: `Batt: <watts>, <left>% / <timeleft>`
+- Example (note that you need "--" to separate regular monitor options from
+  Battery's specific ones):
+
+         Run BatteryP ["BAT0"]
+                      ["-t", "<acstatus><watts> (<left>%)",
+                       "-L", "10", "-H", "80", "-p", "3",
+                       "--", "-O", "<fc=green>On</fc> - ", "-o", "",
+                       "-L", "-15", "-H", "-5",
+                       "-l", "red", "-m", "blue", "-h", "green"]
+                      600
+  In the above example, the thresholds before the "--" separator
+  refer to the `<left>` field, while those after the separator affect
+  how `<watts>` is displayed.
 
 `TopProc Args RefreshRate`
 
 - aliases to `top`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
 	    `no`, `name1`, `cpu1`, `both1`, `mname1`, `mem1`, `mboth1`,
             `name2`, `cpu2`, `both2`, `mname2`, `mem2`, `mboth2`, ...
@@ -409,7 +427,7 @@ Monitors have default aliases.
 `TopMem Args RefreshRate`
 
 - aliases to `topmem`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
 	    `name1`, `mem1`, `both1`, `name2`, `mem2`, `both2`, ...
 - Default template: `<both1>`
@@ -424,7 +442,7 @@ Monitors have default aliases.
   where the template can contain <size>, <free>, <used>, <freep> or
   <usedp>, <freebar> or <usedbar> for total, free, used, free
   percentage and used percentage of the given file system capacity.
-- Args: the argument list (see above). `-t`/`--template` is ignored.
+- Args: default monitor arguments (see below). `-t`/`--template` is ignored.
 - Default template: none (you must specify a template for each file system).
 - Example:
 
@@ -438,7 +456,7 @@ Monitors have default aliases.
 - Disks: list of pairs of the form (device or mount point, template),
   where the template can contain <total>, <read>, <write> for total,
   read and write speed, respectively.
-- Args: the argument list (see above). `-t`/`--template` is ignored.
+- Args: default monitor arguments (see below). `-t`/`--template` is ignored.
 - Default template: none (you must specify a template for each file system).
 - Example:
 
@@ -447,7 +465,7 @@ Monitors have default aliases.
 `Thermal Zone Args RefreshRate`
 
 - aliases to the Zone: so `Zone "THRM" []` can be used in template as `%THRM%`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
 	    `temp`
 - Default template: `Thm: <temp>C`
@@ -460,7 +478,7 @@ Monitors have default aliases.
 `CpuFreq Args RefreshRate`
 
 - aliases to `cpufreq`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
 	    `cpu0`, `cpu1`, ..,  `cpuN`
 - Default template: `Freq: <cpu0>GHz`
@@ -473,7 +491,7 @@ Monitors have default aliases.
 `CoreTemp Args RefreshRate`
 
 - aliases to `coretemp`
-- Args: the argument list (see below)
+- Args: default monitor arguments (see below)
 - Variables that can be used with the `-t`/`--template` argument:
 	    `core0`, `core1`, ..,  `coreN`
 - Default template: `Temp: <core0>C`
@@ -489,7 +507,7 @@ Monitors have default aliases.
 - 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: the argument list (see below). In addition you can provide
+- Args: default monitor arguments (see below). 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,
   and `-h`, `-p` and `-x` for the host, port and password (default
@@ -739,11 +757,11 @@ code] or send mail to our [Mailing list].
 Credits
 =======
 
-xmobar [incorporates patches] from: Roman Cheplyaka, John Goerzen, Juraj
-Hercek, Tomas Janousek, Spencer Janssen, Krzysztof Kosciuszkiewicz,
-Lennart Kolmodin, Dmitry Kurochkin, Svein Ove, Jens Petersen, Andrew
-Sackville-West, Alexander Solovyov, Sergei Trofimovich, Jan
-Vornberger, Daniel Wagner and Norbert Zeh.
+xmobar [incorporates patches] from Roman Cheplyaka, John Goerzen,
+Juraj Hercek, Tomas Janousek, Spencer Janssen, Krzysztof
+Kosciuszkiewicz, Lennart Kolmodin, Dmitry Kurochkin, Svein Ove, Jens
+Petersen, Petr Rockai, Andrew Sackville-West, Alexander Solovyov,
+Sergei Trofimovich, Jan Vornberger, Daniel Wagner and Norbert Zeh.
 
 [incorporates patches]: http://www.ohloh.net/p/xmobar/contributors
 
-- 
cgit v1.2.3