diff options
| -rw-r--r-- | NEWS | 23 | ||||
| -rw-r--r-- | README | 83 | ||||
| -rw-r--r-- | src/Config.hs | 7 | ||||
| -rw-r--r-- | src/Plugins/DateZone.hs | 44 | ||||
| -rw-r--r-- | src/Plugins/Monitors.hs | 79 | ||||
| -rw-r--r-- | src/Plugins/Monitors/Batt.hs | 10 | ||||
| -rw-r--r-- | src/Plugins/Monitors/Bright.hs | 118 | ||||
| -rw-r--r-- | src/Plugins/Monitors/CoreCommon.hs | 151 | ||||
| -rw-r--r-- | src/Plugins/Monitors/CoreTemp.hs | 12 | ||||
| -rw-r--r-- | src/Plugins/Monitors/CpuFreq.hs | 18 | ||||
| -rw-r--r-- | src/Plugins/Monitors/MPD.hs | 13 | ||||
| -rw-r--r-- | src/Plugins/Monitors/ThermalZone.hs | 43 | ||||
| -rw-r--r-- | src/Plugins/Monitors/Top.hs | 1 | ||||
| -rw-r--r-- | xmobar.cabal | 19 | 
14 files changed, 495 insertions, 126 deletions
| @@ -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) @@ -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 | 
