summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--NEWS23
-rw-r--r--README83
-rw-r--r--src/Config.hs7
-rw-r--r--src/Plugins/DateZone.hs44
-rw-r--r--src/Plugins/Monitors.hs79
-rw-r--r--src/Plugins/Monitors/Batt.hs10
-rw-r--r--src/Plugins/Monitors/Bright.hs118
-rw-r--r--src/Plugins/Monitors/CoreCommon.hs151
-rw-r--r--src/Plugins/Monitors/CoreTemp.hs12
-rw-r--r--src/Plugins/Monitors/CpuFreq.hs18
-rw-r--r--src/Plugins/Monitors/MPD.hs13
-rw-r--r--src/Plugins/Monitors/ThermalZone.hs43
-rw-r--r--src/Plugins/Monitors/Top.hs1
-rw-r--r--xmobar.cabal19
14 files changed, 495 insertions, 126 deletions
diff --git a/NEWS b/NEWS
index 59accbd..1e15772 100644
--- a/NEWS
+++ b/NEWS
@@ -1,17 +1,37 @@
% xmobar - Release notes
% Jose A. Ortega Ruiz
-## Version 0.13
+## Version 0.14
+
+_New features_
+
+ - New monitor brightness monitor, courtesy of Martin Perner.
+
+_Bug fixes_
+
+ - [issue 50]: `MPD` monitor now works with libmpd 0.6.
+
+[issue 50]: http://code.google.com/p/xmobar/issues/detail?id=14
+
+## Version 0.13 (March 28, 2011)
_New features_
- New `Volume` monitor displaying ALSA soundcards information, by
Thomas Tuegel.
+ - New `ThermalZone` plugin substituting `Thermal` and using linux's
+ *sysfs* interface (you need this one if you're using a kernel
+ version equal to or above 2.6.37). See [issue 44].
- xmobar app new has WM_CLASS, WM_NAME and _NET_WM_PID xprops
([issue 38]).
_Incompatible changes_
+ - In the process of solving [issue 14], we've broken those
+ configurations that rely on including alignment separators in the
+ input fed to `StdinReader`.
+ - The MPD plugin does not accept host and port options anymore: use
+ the environment variables MPD_HOST and MPD_PORT instead.
- The `Mail` plugin now takes a second parameter (a string)
specifying its alias. As a side-effect, this solves [issue 30].
@@ -40,6 +60,7 @@ _Bug fixes_
[issue 38]: http://code.google.com/p/xmobar/issues/detail?id=38
[issue 40]: http://code.google.com/p/xmobar/issues/detail?id=40
[issue 42]: http://code.google.com/p/xmobar/issues/detail?id=42
+[issue 44]: http://code.google.com/p/xmobar/issues/detail?id=44
## Version 0.12 (Dec 24, 2010)
diff --git a/README b/README
index 920ba9c..626130d 100644
--- a/README
+++ b/README
@@ -46,7 +46,7 @@ bells and whistles, use:
If you don't have `cabal-install` installed, you can get xmobar's
source code in a variety of ways:
- - From [Hackage]. Just download [xmobar-0.12.tar.gz] from xmobar's
+ - From [Hackage]. Just download [xmobar-0.13.tar.gz] from xmobar's
hackage page.
- From [Github]. You can also obtain a tarball in [Github's
downloads page]. You'll find there links to each tagged release.
@@ -55,13 +55,13 @@ source code in a variety of ways:
git:
git clone git://github.com/jaor/xmobar
-[xmobar-0.12.tar.gz]: http://hackage.haskell.org/packages/archive/xmobar/0.12/xmobar-0.12.tar.gz
+[xmobar-0.13.tar.gz]: http://hackage.haskell.org/packages/archive/xmobar/0.13/xmobar-0.13.tar.gz
[Github's downloads page]: https://github.com/jaor/xmobar/downloads
To install simply run (if needed):
- tar xvfz xmobar-0.12
- cd xmobar-0.12
+ tar xvfz xmobar-0.13
+ cd xmobar-0.13
If you have cabal installed, you can now use it from within xmobar's
source tree. Otherwise, run the configure script:
@@ -124,6 +124,10 @@ Otherwise, you'll need to install them yourself.
: Support for ALSA sound cards. Enables the Volume plugin. Requires the
[alsa-mixer] package.
+`with_datezone`
+: Support for localized times. Enables the DateZone plugin. Requires
+ [timezone-olson] and [timezone-series] package.
+
`all_extensions`
: Enables all the extensions above.
@@ -317,9 +321,9 @@ standard input reader, an Unix named pipe reader, and a configurable
date plugin. These plugins install the following internal commands:
`Weather`, `Network`, `Wireless` (optional), `Memory`, `Swap`, `Cpu`,
`MultiCpu`, `Battery`, `TopProc`, `TopMem`, `DiskU`, `DiskIO`,
-`Thermal`, `CpuFreq`, `CoreTemp`, `Volume` (optional), `MPD`
-(optional), `Mail` (optional), `MBox` (optional), `Date`, `Uptime`,
-`StdinReader`, `CommandReader`, and `PipeReader`.
+`Thermal`, `ThermalZone`, `CpuFreq`, `CoreTemp`, `Volume` (optional),
+`MPD` (optional), `Mail` (optional), `MBox` (optional), `Date`,
+`Uptime`, `StdinReader`, `CommandReader`, and `PipeReader`.
To remove them see below Installing/Removing a Plugin
@@ -515,9 +519,28 @@ Monitors have default aliases.
Disks [("/", "<read> <write>"), ("sdb1", "<total>")] [] 10
+`ThermalZone Number Args RefreshRate`
+
+- Aliases to "thermaln": so `ThermalZone 0 []` can be used in template
+ as `%thermal0%`
+- Args: default monitor arguments (see below)
+- Variables that can be used with the `-t`/`--template` argument:
+ `temp`
+- Default template: `<temp>C`
+- This plugin works only on sytems with devices having thermal zone.
+ Check directories in `/sys/class/thermal` for possible values of the
+ zone number (e.g., 0 corresponds to `thermal_zone0` in that
+ directory).
+- Example:
+
+ Run ThermalZone 0 ["-t","<id>: <temp>C"] 30
+
`Thermal Zone Args RefreshRate`
-- Aliases to the Zone: so `Zone "THRM" []` can be used in template as `%THRM%`
+- **This plugin is deprecated. Use `ThermalZone` instead.**
+
+- Aliases to the Zone: so `Thermal "THRM" []` can be used in template
+ as `%THRM%`
- Args: default monitor arguments (see below)
- Variables that can be used with the `-t`/`--template` argument:
`temp`
@@ -526,7 +549,7 @@ Monitors have default aliases.
Check directories in /proc/acpi/thermal_zone for possible values.
- Example:
- Run Thermal "THRM" ["-t","iwl4965-temp: <temp>C"]
+ Run Thermal "THRM" ["-t","iwl4965-temp: <temp>C"] 50
`CpuFreq Args RefreshRate`
@@ -592,9 +615,9 @@ Monitors have default aliases.
- Aliases to `mpd`
- 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
- host is "localhost", port 6600 and empty password).
+ 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.
- Variables that can be used with the `-t`/`--template` argument:
`bar`, `state`, `statei`, `volume`, `length`
`lapsed`, `remaining`,
@@ -658,6 +681,24 @@ Monitors have default aliases.
distribution can be used to set the given property from the output
of any other program or script.
+`Brightness Args RefreshRate`
+
+- Aliases to `bright`
+- Args: default monitor arguments (see below), plus the following specif ones:
+ - `-D`: directory in `/sys/class/backlight/` with files in it
+ (default: "acpi_video0")
+ - `-C`: file with the current brightness (default:
+ actual_brightness)
+ - `-M`: file with the maximum brightness (default:
+ max_brigtness)
+- Variables that can be used with the `-t`/`--template` argument:
+ `hbar`, `percent`, `bar`
+- Default template: `<percent>`
+- Example:
+
+ Run Brightness ["-t", "<bar>"] 60
+
+
[samples/xmonadpropwrite.hs script]: https://github.com/jaor/xmobar/raw/master/samples/xmonadpropwrite.hs
## Monitor Plugins Commands Arguments
@@ -809,6 +850,16 @@ can be used in the output template as `%mydate%`
`strftime` function (or Haskell's `formatCalendarTime`).
- Sample usage: `Run Date "%a %b %_d %Y <fc=#ee9a00>%H:%M:%S</fc>" "date" 10`
+`Date Format Alias Zone RefreshRate`
+
+- Format is a time format string, as accepted by the standard ISO C
+ `strftime` function (or Haskell's `formatCalendarTime`).
+- Zone is the name of the TimeZone. Assumes that the tz database is stored in
+ /usr/share/zoneinfo/
+- Sample usage:
+ `Run DateZone "<fc=#ee9a00>%H:%M:%S</fc>" "viennaDate" "Europa/Vienna" 10`
+
+
`CommandReader "/path/to/program" Alias`
- Runs the given program, and displays its standard output.
@@ -965,10 +1016,10 @@ Credits
xmobar [incorporates patches] by Ben Boeckel, Roman Cheplyaka, John
Goerzen, Juraj Hercek, Tomas Janousek, Spencer Janssen, Lennart
-Kolmodin, Krzysztof Kosciuszkiewicz, Dmitry Kurochkin, Svein Ove, Jens
-Petersen, Petr Rockai, Andrew Sackville-West, Alexander Solovyov,
-Sergei Trofimovich, Thomas Tuegel, Jan Vornberger, Daniel Wagner and
-Norbert Zeh.
+Kolmodin, Krzysztof Kosciuszkiewicz, Dmitry Kurochkin, Svein Ove,
+Martin Perner, Jens Petersen, Petr Rockai, Andrew Sackville-West,
+Alexander Solovyov, Sergei Trofimovich, Thomas Tuegel, Jan Vornberger,
+Daniel Wagner and Norbert Zeh.
[incorporates patches]: http://www.ohloh.net/p/xmobar/contributors
diff --git a/src/Config.hs b/src/Config.hs
index 6eb55a0..3184023 100644
--- a/src/Config.hs
+++ b/src/Config.hs
@@ -38,6 +38,10 @@ import Plugins.Mail
import Plugins.MBox
#endif
+#ifdef DATEZONE
+import Plugins.DateZone
+#endif
+
-- $config
-- Configuration data type and default configuration
@@ -112,5 +116,8 @@ runnableTypes :: Command :*: Monitors :*: Date :*: PipeReader :*: CommandReader
#ifdef INOTIFY
Mail :*: MBox :*:
#endif
+#ifdef DATEZONE
+ DateZone :*:
+#endif
()
runnableTypes = undefined
diff --git a/src/Plugins/DateZone.hs b/src/Plugins/DateZone.hs
new file mode 100644
index 0000000..4d5ce6a
--- /dev/null
+++ b/src/Plugins/DateZone.hs
@@ -0,0 +1,44 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module : Plugins.DateZone
+-- Copyright : (c) Martin Perner
+-- License : BSD-style (see LICENSE)
+--
+-- Maintainer : Martin Perner <martin@perner.cc>
+-- Stability : unstable
+-- Portability : unportable
+--
+-- A date plugin with localization support for Xmobar
+--
+-- Based on Plugins.Date
+--
+-- Usage example: in template put
+--
+-- > Run DateZone "%H:%M:%S" "utcDate" "UTC" 10
+--
+-----------------------------------------------------------------------------
+
+module Plugins.DateZone (DateZone(..)) where
+
+import Plugins
+
+import System.Locale
+
+import Data.Time.LocalTime
+import Data.Time.Format
+import Data.Time.LocalTime.TimeZone.Olson
+import Data.Time.LocalTime.TimeZone.Series
+
+data DateZone = DateZone String String String Int
+ deriving (Read, Show)
+
+instance Exec DateZone where
+ alias (DateZone _ a _ _) = a
+ run (DateZone f _ z _) = date f z
+ rate (DateZone _ _ _ r) = r
+
+date :: String -> String -> IO String
+date format zone = do
+ timeZone <- getTimeZoneSeriesFromOlsonFile ("/usr/share/zoneinfo/" ++ zone)
+ zonedTime <- getZonedTime
+ return $ formatTime defaultTimeLocale format $ utcToLocalTime' timeZone $ zonedTimeToUTC zonedTime
diff --git a/src/Plugins/Monitors.hs b/src/Plugins/Monitors.hs
index 4f1795b..5e1cb62 100644
--- a/src/Plugins/Monitors.hs
+++ b/src/Plugins/Monitors.hs
@@ -3,7 +3,8 @@
-----------------------------------------------------------------------------
-- |
-- Module : Xmobar.Plugins.Monitors
--- Copyright : (c) Andrea Rossato
+-- Copyright : (c) 2010, 2011 Jose Antonio Ortega Ruiz
+-- (c) 2007-10 Andrea Rossato
-- License : BSD-style (see LICENSE)
--
-- Maintainer : Jose A. Ortega Ruiz <jao@gnu.org>
@@ -26,7 +27,9 @@ import Plugins.Monitors.Swap
import Plugins.Monitors.Cpu
import Plugins.Monitors.MultiCpu
import Plugins.Monitors.Batt
+import Plugins.Monitors.Bright
import Plugins.Monitors.Thermal
+import Plugins.Monitors.ThermalZone
import Plugins.Monitors.CpuFreq
import Plugins.Monitors.CoreTemp
import Plugins.Monitors.Disk
@@ -42,22 +45,24 @@ import Plugins.Monitors.MPD
import Plugins.Monitors.Volume
#endif
-data Monitors = Weather Station Args Rate
- | Network Interface Args Rate
- | Memory Args Rate
- | Swap Args Rate
- | Cpu Args Rate
- | MultiCpu Args Rate
- | Battery Args Rate
- | BatteryP [String] Args Rate
- | DiskU DiskSpec Args Rate
- | DiskIO DiskSpec Args Rate
- | Thermal Zone Args Rate
- | CpuFreq Args Rate
- | CoreTemp Args Rate
- | TopProc Args Rate
- | TopMem Args Rate
- | Uptime Args Rate
+data Monitors = Weather Station Args Rate
+ | Network Interface Args Rate
+ | BatteryP [String] Args Rate
+ | DiskU DiskSpec Args Rate
+ | DiskIO DiskSpec Args Rate
+ | Thermal Zone Args Rate
+ | ThermalZone ZoneNo Args Rate
+ | Memory Args Rate
+ | Swap Args Rate
+ | Cpu Args Rate
+ | MultiCpu Args Rate
+ | Battery Args Rate
+ | Brightness Args Rate
+ | CpuFreq Args Rate
+ | CoreTemp Args Rate
+ | TopProc Args Rate
+ | TopMem Args Rate
+ | Uptime Args Rate
#ifdef IWLIB
| Wireless Interface Args Rate
#endif
@@ -74,32 +79,35 @@ type Program = String
type Alias = String
type Station = String
type Zone = String
+type ZoneNo = Int
type Interface = String
type Rate = Int
type DiskSpec = [(String, String)]
instance Exec Monitors where
- alias (Weather s _ _) = s
- alias (Network i _ _) = i
- alias (Thermal z _ _) = z
- alias (Memory _ _) = "memory"
- alias (Swap _ _) = "swap"
- alias (Cpu _ _) = "cpu"
- alias (MultiCpu _ _) = "multicpu"
- alias (Battery _ _) = "battery"
- alias (BatteryP _ _ _)= "battery"
- alias (CpuFreq _ _) = "cpufreq"
- alias (TopProc _ _) = "top"
- alias (TopMem _ _) = "topmem"
- alias (CoreTemp _ _) = "coretemp"
- alias (DiskU _ _ _) = "disku"
- alias (DiskIO _ _ _) = "diskio"
- alias (Uptime _ _) = "uptime"
+ alias (Weather s _ _) = s
+ alias (Network i _ _) = i
+ alias (Thermal z _ _) = z
+ alias (ThermalZone z _ _) = "thermal" ++ show z
+ alias (Memory _ _) = "memory"
+ alias (Swap _ _) = "swap"
+ alias (Cpu _ _) = "cpu"
+ alias (MultiCpu _ _) = "multicpu"
+ alias (Battery _ _) = "battery"
+ alias (BatteryP _ _ _)= "battery"
+ alias (Brightness _ _) = "bright"
+ alias (CpuFreq _ _) = "cpufreq"
+ alias (TopProc _ _) = "top"
+ alias (TopMem _ _) = "topmem"
+ alias (CoreTemp _ _) = "coretemp"
+ alias (DiskU _ _ _) = "disku"
+ alias (DiskIO _ _ _) = "diskio"
+ alias (Uptime _ _) = "uptime"
#ifdef IWLIB
alias (Wireless i _ _) = i ++ "wi"
#endif
#ifdef LIBMPD
- alias (MPD _ _) = "mpd"
+ alias (MPD _ _) = "mpd"
#endif
#ifdef ALSA
alias (Volume m c _ _) = m ++ ":" ++ c
@@ -111,10 +119,13 @@ instance Exec Monitors where
start (TopMem a r) = runM a topMemConfig runTopMem r
start (Weather s a r) = runM (a ++ [s]) weatherConfig runWeather r
start (Thermal z a r) = runM (a ++ [z]) thermalConfig runThermal r
+ start (ThermalZone z a r) =
+ runM (a ++ [show z]) thermalZoneConfig runThermalZone r
start (Memory a r) = runM a memConfig runMem r
start (Swap a r) = runM a swapConfig runSwap r
start (Battery a r) = runM a battConfig runBatt r
start (BatteryP s a r) = runM a battConfig (runBatt' s) r
+ start (Brightness a r) = runM a brightConfig runBright r
start (CpuFreq a r) = runM a cpuFreqConfig runCpuFreq r
start (CoreTemp a r) = runM a coreTempConfig runCoreTemp r
start (DiskU s a r) = runM a diskUConfig (runDiskU s) r
diff --git a/src/Plugins/Monitors/Batt.hs b/src/Plugins/Monitors/Batt.hs
index 7d4242a..c276e6b 100644
--- a/src/Plugins/Monitors/Batt.hs
+++ b/src/Plugins/Monitors/Batt.hs
@@ -123,18 +123,20 @@ readBattery files =
return $ Battery (3600 * a / 1000000) -- wattseconds
(3600 * b / 1000000) -- wattseconds
(c / 1000000) -- volts
- (d / c) -- amperes
- where grab = fmap (read . B.unpack) . B.readFile
+ (if c > 0 then (d / c) else -1) -- amperes
+ where grab f = catch (fmap (read . B.unpack) $ B.readFile f) (\_ -> return 0)
readBatteries :: BattOpts -> [Files] -> IO Result
readBatteries opts bfs =
do bats <- mapM readBattery (take 3 bfs)
ac <- haveAc (onlineFile opts)
let sign = if ac then 1 else -1
- left = sum (map now bats) / sum (map full bats)
+ ft = sum (map full bats)
+ left = if ft > 0 then sum (map now bats) / ft else 0
watts = sign * sum (map voltage bats) * sum (map current bats)
time = if watts == 0 then 0 else sum $ map time' bats
- time' b = (if ac then full b - now b else now b) / (sign * watts)
+ mwatts = if watts == 0 then 1 else sign * watts
+ time' b = (if ac then full b - now b else now b) / mwatts
acstr = if ac then onString opts else offString opts
return $ if isNaN left then NA else Result left watts time acstr
diff --git a/src/Plugins/Monitors/Bright.hs b/src/Plugins/Monitors/Bright.hs
new file mode 100644
index 0000000..499e5bc
--- /dev/null
+++ b/src/Plugins/Monitors/Bright.hs
@@ -0,0 +1,118 @@
+-----------------------------------------------------------------------------
+---- |
+---- Module : Plugins.Monitors.Birght
+---- Copyright : (c) Martin Perner
+---- License : BSD-style (see LICENSE)
+----
+---- Maintainer : Martin Perner <martin@perner.cc>
+---- Stability : unstable
+---- Portability : unportable
+----
+---- A screen brightness monitor for Xmobar
+----
+-------------------------------------------------------------------------------
+
+module Plugins.Monitors.Bright (brightConfig, runBright) where
+
+import Plugins.Monitors.Common
+import qualified Data.ByteString.Lazy.Char8 as B
+import Data.Char
+import System.FilePath ((</>))
+import System.Posix.Files (fileExist)
+import System.Console.GetOpt
+
+data BrightOpts = BrightOpts
+ { subDir :: String
+ , currBright :: String
+ , maxBright :: String
+ }
+
+defaultOpts :: BrightOpts
+defaultOpts = BrightOpts
+ { subDir = "acpi_video0"
+ , currBright = "actual_brightness"
+ , maxBright = "max_brightness"
+ }
+
+options :: [OptDescr (BrightOpts -> BrightOpts)]
+options =
+ [ Option "D" ["device"] (ReqArg (\x o -> o { subDir = x }) "") ""
+ , Option "C" ["curr"] (ReqArg (\x o -> o { currBright = x }) "") ""
+ , Option "M" ["max"] (ReqArg (\x o -> o { maxBright = 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/"
+
+brightConfig :: IO MConfig
+brightConfig = mkMConfig
+ "<percent>" -- template
+ ["hbar", "percent", "bar"] -- replacements
+
+data Files = Files
+ { fCurr :: String
+ , fMax :: String
+ } | NoFiles
+
+brightFiles :: BrightOpts -> IO Files
+brightFiles opts =
+ do
+ is_curr <- fileExist $ (fCurr files)
+ is_max <- fileExist $ (fCurr files)
+ if is_curr && is_max
+ then return files
+ else return NoFiles
+ where
+ prefix = sysDir </> (subDir opts)
+ files = Files { fCurr = prefix </> (currBright opts)
+ , fMax = prefix </> (maxBright opts)
+ }
+
+
+runBright :: [String] -> Monitor String
+runBright args = do
+ opts <- io $ parseOpts args
+ f <- io $ brightFiles opts
+ c <- io $ readBright f
+ case f of
+ NoFiles -> return "hurz"
+ _ -> do x <- fmtPercent c
+ parseTemplate (x)
+ where
+ fmtPercent :: Float -> Monitor [String]
+ fmtPercent c = do
+ r <- showHorizontalBar (100 * c)
+ s <- showPercentWithColors c
+ t <- showPercentBar (100 * c) c
+ return [r,s,t]
+
+readBright :: Files -> IO Float
+readBright NoFiles = return 0
+readBright files =
+ do
+ currVal<- grab $ (fCurr files)
+ maxVal <- grab $ (fMax files)
+ return $ (currVal / maxVal)
+ where
+ grab f = catch (fmap (read . B.unpack) $ B.readFile f)(\_ -> return 0)
+
+
+showHorizontalBar :: Float -> Monitor String
+showHorizontalBar x = do
+ return $ [convert x]
+ where
+ convert :: Float -> Char
+ convert val
+ | t <= 9600 = ' '
+ | t > 9608 = chr 9608
+ | otherwise = chr t
+ where
+ -- we scale from 0 to 100, we have 8 slots (9 elements), 100/8 = 12
+ t = 9600 + ((round val) `div` 12)
diff --git a/src/Plugins/Monitors/CoreCommon.hs b/src/Plugins/Monitors/CoreCommon.hs
index 80e7700..e508f7d 100644
--- a/src/Plugins/Monitors/CoreCommon.hs
+++ b/src/Plugins/Monitors/CoreCommon.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE PatternGuards #-}
+
-----------------------------------------------------------------------------
-- |
-- Module : Plugins.Monitors.CoreCommon
@@ -14,46 +16,119 @@
module Plugins.Monitors.CoreCommon where
+import Control.Applicative
+import Control.Monad
+import Data.Char hiding (Space)
+import Data.Function
+import Data.List
+import Data.Maybe
import Plugins.Monitors.Common
-import System.Posix.Files (fileExist)
-import System.IO (withFile, IOMode(ReadMode), hGetLine)
import System.Directory
-import Data.Char (isDigit)
-import Data.List (isPrefixOf)
--- |
--- Function checks the existence of first file specified by pattern and if the
--- file doesn't exists failure message is shown, otherwise the data retrieval
--- is performed.
-checkedDataRetrieval :: (Num a, Ord a, Show a) =>
- String -> String -> String -> String -> (Double -> a)
- -> (a -> String) -> Monitor String
-checkedDataRetrieval failureMessage dir file pattern trans fmt = do
- exists <- io $ fileExist $ concat [dir, "/", pattern, "0/", file]
- case exists of
- False -> return failureMessage
- True -> retrieveData dir file pattern trans fmt
+checkedDataRetrieval :: (Ord a, Num a)
+ => String -> [String] -> Maybe (String, String -> Int)
+ -> (Double -> a) -> (a -> String) -> Monitor String
+checkedDataRetrieval msg path lbl trans fmt = liftM (maybe msg id) $
+ retrieveData path lbl trans fmt
--- |
--- Function retrieves data from files in directory dir specified by
--- pattern. String values are converted to double and 'trans' applied
--- to each one. Final array is processed by template parser function
--- and returned as monitor string.
-retrieveData :: (Num a, Ord a, Show a) =>
- String -> String -> String -> (Double -> a) -> (a -> String) ->
- Monitor String
-retrieveData dir file pattern trans fmt = do
- count <- io $ dirCount dir pattern
- contents <- io $ mapM getGuts $ files count
- values <- mapM (showWithColors fmt) $ map conversion contents
- parseTemplate values
- where
- getGuts f = withFile f ReadMode hGetLine
- dirCount path str = getDirectoryContents path
- >>= return . length
- . filter (\s -> str `isPrefixOf` s
- && isDigit (last s))
- files count = map (\i -> concat [dir, "/", pattern, show i, "/", file])
- [0 .. count - 1]
- conversion = trans . (read :: String -> Double)
+retrieveData :: (Ord a, Num a)
+ => [String] -> Maybe (String, String -> Int)
+ -> (Double -> a) -> (a -> String) -> Monitor (Maybe String)
+retrieveData path lbl trans fmt = do
+ pairs <- map snd . sortBy (compare `on` fst) <$> (mapM readFiles =<< findFiles path lbl)
+ if null pairs
+ then return Nothing
+ else Just <$> ( parseTemplate
+ =<< mapM (showWithColors fmt . trans . read) pairs
+ )
+
+-- | Represents the different types of path components
+data Comp = Fix String
+ | Var [String]
+ deriving Show
+
+-- | Used to represent parts of file names separated by slashes and spaces
+data CompOrSep = Slash
+ | Space
+ | Comp String
+ deriving (Eq, Show)
+
+-- | Function to turn a list of of strings into a list of path components
+pathComponents :: [String] -> [Comp]
+pathComponents = joinComps . drop 2 . concat . intersperse [Space] . map splitParts
+ where
+ splitParts p | (l, _:r) <- break (== '/') p = (Comp l):Slash:splitParts r
+ | otherwise = [Comp p]
+
+ joinComps = uncurry joinComps' . partition isComp
+
+ isComp (Comp _) = True
+ isComp _ = False
+
+ fromComp (Comp s) = s
+ fromComp _ = error "fromComp applied to value other than (Comp _)"
+
+ joinComps' cs [] = [Fix $ fromComp $ head cs] -- cs should have only one element here,
+ -- but this keeps the pattern matching
+ -- exhaustive
+ joinComps' cs (p:ps) = let (ss, ps') = span (== p) ps
+ ct = if null ps' || (p == Space) then length ss + 1
+ else length ss
+ (ls, rs) = splitAt (ct+1) cs
+ c = case p of
+ Space -> Var $ map fromComp ls
+ Slash -> Fix $ intercalate "/" $ map fromComp ls
+ _ -> error "Should not happen"
+ in if null ps' then [c]
+ else c:joinComps' rs (drop ct ps)
+
+-- | Function to find all files matching the given path and possible label file.
+-- The path must be absolute (start with a leading slash).
+findFiles :: [String] -> Maybe (String, String -> Int)
+ -> Monitor [(String, Either Int (String, String -> Int))]
+findFiles path lbl = catMaybes
+ <$> ( mapM addLabel . zip [0..] . sort
+ =<< recFindFiles (pathComponents path) "/"
+ )
+ where
+ addLabel (i, f) = maybe (return $ Just (f, Left i))
+ (\(s, t) -> justIfExists f s t)
+ lbl
+
+ justIfExists f s t = let f' = take (length f - length s) f ++ s
+ in ifthen (Just (f, Right (f', t))) Nothing <$> (io $ doesFileExist f')
+
+ recFindFiles [] d = ifthen [d] []
+ <$> (io $ if null d then return False else doesFileExist d)
+ recFindFiles ps d = ifthen (recFindFiles' ps d) (return [])
+ =<< (io $ if null d then return True else doesDirectoryExist d)
+
+ recFindFiles' [] _ = error "Should not happen"
+ recFindFiles' (Fix p:ps) d = recFindFiles ps (d ++ "/" ++ p)
+ recFindFiles' (Var p:ps) d = concat
+ <$> ( mapM (recFindFiles ps)
+ . map (\f -> d ++ "/" ++ f)
+ . filter (matchesVar p)
+ =<< (io $ getDirectoryContents d)
+ )
+
+ matchesVar [] _ = False
+ matchesVar [v] f = v == f
+ matchesVar (v:vs) f = let f' = drop (length v) f
+ f'' = dropWhile isDigit f'
+ in and [ v `isPrefixOf` f
+ , not (null f')
+ , isDigit (head f')
+ , matchesVar vs f''
+ ]
+
+-- | Function to read the contents of the given file(s)
+readFiles :: (String, Either Int (String, String -> Int))
+ -> Monitor (Int, String)
+readFiles (fval, flbl) = (,) <$> either return (\(f, ex) -> liftM ex
+ $ io $ readFile f) flbl
+ <*> (io $ readFile fval)
+-- | Function that captures if-then-else
+ifthen :: a -> a -> Bool -> a
+ifthen thn els cnd = if cnd then thn else els \ No newline at end of file
diff --git a/src/Plugins/Monitors/CoreTemp.hs b/src/Plugins/Monitors/CoreTemp.hs
index a24b284..f7b5c95 100644
--- a/src/Plugins/Monitors/CoreTemp.hs
+++ b/src/Plugins/Monitors/CoreTemp.hs
@@ -31,11 +31,9 @@ coreTempConfig = mkMConfig
-- Function retrieves monitor string holding the core temperature
-- (or temperatures)
runCoreTemp :: [String] -> Monitor String
-runCoreTemp _ = do
- let dir = "/sys/bus/platform/devices"
- file = "temp1_input"
- pattern = "coretemp."
- divisor = 1e3 :: Double
- failureMessage = "CoreTemp: N/A"
- checkedDataRetrieval failureMessage dir file pattern (/divisor) show
+runCoreTemp _ = let path = ["/sys/bus/platform/devices/coretemp.", "/temp", "_input"]
+ lbl = Just ("_label", read . drop 5)
+ divisor = 1e3 :: Double
+ failureMessage = "CoreTemp: N/A"
+ in checkedDataRetrieval failureMessage path lbl (/divisor) show
diff --git a/src/Plugins/Monitors/CpuFreq.hs b/src/Plugins/Monitors/CpuFreq.hs
index 4f01922..dcf75e5 100644
--- a/src/Plugins/Monitors/CpuFreq.hs
+++ b/src/Plugins/Monitors/CpuFreq.hs
@@ -28,16 +28,12 @@ cpuFreqConfig = mkMConfig
-- replacements
-- |
--- Function retrieves monitor string holding the cpu frequency (or
--- frequencies)
+-- Function retrieves monitor string holding the cpu frequency (or frequencies)
runCpuFreq :: [String] -> Monitor String
-runCpuFreq _ = do
- let dir = "/sys/devices/system/cpu"
- file = "cpufreq/scaling_cur_freq"
- pattern = "cpu"
- divisor = 1e6 :: Double
- failureMessage = "CpuFreq: N/A"
- fmt x | x < 1 = show (round (x * 1000) :: Integer) ++ "MHz"
- | otherwise = showDigits 1 x ++ "GHz"
- checkedDataRetrieval failureMessage dir file pattern (/divisor) fmt
+runCpuFreq _ = let path = ["/sys/devices/system/cpu/cpu", "/cpufreq/scaling_cur_freq"]
+ divisor = 1e6 :: Double
+ failureMessage = "CpuFreq: N/A"
+ fmt x | x < 1 = (show (round (x * 1000) :: Integer)) ++ "MHz"
+ | otherwise = (show x) ++ "GHz"
+ in checkedDataRetrieval failureMessage path Nothing (/divisor) fmt
diff --git a/src/Plugins/Monitors/MPD.hs b/src/Plugins/Monitors/MPD.hs
index daf0ed4..60c3e48 100644
--- a/src/Plugins/Monitors/MPD.hs
+++ b/src/Plugins/Monitors/MPD.hs
@@ -30,9 +30,6 @@ data MOpts = MOpts
{ mPlaying :: String
, mStopped :: String
, mPaused :: String
- , mHost :: String
- , mPort :: Integer
- , mPassword :: String
}
defaultOpts :: MOpts
@@ -40,9 +37,6 @@ defaultOpts = MOpts
{ mPlaying = ">>"
, mStopped = "><"
, mPaused = "||"
- , mHost = "127.0.0.1"
- , mPort = 6600
- , mPassword = ""
}
options :: [OptDescr (MOpts -> MOpts)]
@@ -50,15 +44,12 @@ options =
[ 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 "h" ["host"] (ReqArg (\x o -> o { mHost = x }) "") ""
- , Option "p" ["port"] (ReqArg (\x o -> o { mPort = read x }) "") ""
- , Option "x" ["password"] (ReqArg (\x o -> o { mPassword = x }) "") ""
]
runMPD :: [String] -> Monitor String
runMPD args = do
opts <- io $ mopts args
- let mpd = M.withMPDEx (mHost opts) (mPort opts) (mPassword opts)
+ let mpd = M.withMPD
status <- io $ mpd M.status
song <- io $ mpd M.currentSong
s <- parseMPD status song opts
@@ -100,7 +91,7 @@ parseSong (Right Nothing) = return $ repeat ""
parseSong (Right (Just s)) =
let join [] = ""
join (x:xs) = foldl (\a o -> a ++ ", " ++ o) x xs
- str sel = maybe "" join (M.sgGet sel s)
+ str sel = maybe "" join (M.sgGetTag sel s)
sels = [ M.Name, M.Artist, M.Composer, M.Performer
, M.Album, M.Title, M.Track, M.Genre ]
fields = M.sgFilePath s : map str sels
diff --git a/src/Plugins/Monitors/ThermalZone.hs b/src/Plugins/Monitors/ThermalZone.hs
new file mode 100644
index 0000000..55fb2ca
--- /dev/null
+++ b/src/Plugins/Monitors/ThermalZone.hs
@@ -0,0 +1,43 @@
+------------------------------------------------------------------------------
+-- |
+-- Module : Plugins.Monitors.ThermalZone
+-- Copyright : (c) 2011 Jose Antonio Ortega Ruiz
+-- License : BSD3-style (see LICENSE)
+--
+-- Maintainer : jao@gnu.org
+-- Stability : unstable
+-- Portability : portable
+-- Created : Fri Feb 25, 2011 03:18
+--
+--
+-- A thermal zone plugin based on the sysfs linux interface.
+-- See http://kernel.org/doc/Documentation/thermal/sysfs-api.txt
+--
+------------------------------------------------------------------------------
+
+module Plugins.Monitors.ThermalZone (thermalZoneConfig, runThermalZone) where
+
+import Plugins.Monitors.Common
+
+import System.Posix.Files (fileExist)
+import qualified Data.ByteString.Char8 as B
+
+-- | Default thermal configuration.
+thermalZoneConfig :: IO MConfig
+thermalZoneConfig = mkMConfig "<temp>C" ["temp"]
+
+-- | Retrieves thermal information. Argument is name of thermal
+-- directory in \/sys\/clas\/thermal. Returns the monitor string
+-- parsed according to template (either default or user specified).
+runThermalZone :: [String] -> Monitor String
+runThermalZone args = do
+ let zone = head args
+ file = "/sys/class/thermal/thermal_zone" ++ zone ++ "/temp"
+ parse = return . (read :: String -> Int) . B.unpack
+ exists <- io $ fileExist file
+ if exists
+ then do mdegrees <- io $ B.readFile file >>= parse
+ temp <- showWithColors show (mdegrees `quot` 1000)
+ parseTemplate [ temp ]
+ else return "N/A"
+
diff --git a/src/Plugins/Monitors/Top.hs b/src/Plugins/Monitors/Top.hs
index e45210c..6001164 100644
--- a/src/Plugins/Monitors/Top.hs
+++ b/src/Plugins/Monitors/Top.hs
@@ -13,6 +13,7 @@
-----------------------------------------------------------------------------
{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE BangPatterns #-}
module Plugins.Monitors.Top (startTop, topMemConfig, runTopMem) where
diff --git a/xmobar.cabal b/xmobar.cabal
index b87d740..ecafe1d 100644
--- a/xmobar.cabal
+++ b/xmobar.cabal
@@ -1,5 +1,5 @@
name: xmobar
-version: 0.12
+version: 0.13
homepage: http://projects.haskell.org/xmobar/
bug-reports: http://code.google.com/p/xmobar/issues
synopsis: A Minimalistic Text Based Status Bar
@@ -57,6 +57,10 @@ flag with_alsa
description: Use alsa-mixer to get the volume from soundcards.
default: False
+flag with_datezone
+ description: Enables localized date support
+ default: False
+
executable xmobar
hs-source-dirs: src
main-is: Main.hs
@@ -69,8 +73,10 @@ executable xmobar
Plugins.Monitors.CoreTemp, Plugins.Monitors.CpuFreq,
Plugins.Monitors.Cpu, Plugins.Monitors.Disk, Plugins.Monitors.Mem,
Plugins.Monitors.MultiCpu, Plugins.Monitors.Net,
- Plugins.Monitors.Swap, Plugins.Monitors.Thermal, Plugins.Monitors.Top,
- Plugins.Monitors.Uptime, Plugins.Monitors.Weather
+ Plugins.Monitors.Swap, Plugins.Monitors.Thermal,
+ Plugins.Monitors.ThermalZone, Plugins.Monitors.Top,
+ Plugins.Monitors.Uptime, Plugins.Monitors.Weather,
+ Plugins.Monitors.Bright
ghc-prof-options: -prof -auto-all
@@ -110,7 +116,7 @@ executable xmobar
cpp-options: -DIWLIB
if flag(with_mpd) || flag(all_extensions)
- build-depends: libmpd >= 0.5
+ build-depends: libmpd >= 0.6
other-modules: Plugins.Monitors.MPD
cpp-options: -DLIBMPD
@@ -118,3 +124,8 @@ executable xmobar
build-depends: alsa-mixer == 0.1.*
other-modules: Plugins.Monitors.Volume
cpp-options: -DALSA
+
+ if flag(with_datezone) || flag(all_extensions)
+ build-depends: timezone-olson, timezone-series
+ other-modules: Plugins.DateZone
+ cpp-options: -DDATEZONE