packages feed

xmobar 0.42 → 0.43

raw patch · 22 files changed

+479/−139 lines, 22 filesdep ~base

Dependency ranges changed: base

Files

changelog.md view
@@ -1,3 +1,20 @@+## Version 0.43 (May, 2023)++_New features_++  - New monitor `Load` providing load averages (stolen from Finn+    Lawler, with FreeBSD support thanks to Michał Zielonka).+  - New argument `scale` for `Memory` monitor to scale size units.+  - New dbus signal: `SetAlpha` (see issue #499).+  - `CpuFreq`: new template parameters `max`, `min` and `avg`.++_Bug fixes_++  - MultiCoreTemp: allow temperature directory names with more than+    one digit.+  - Batt (linux): correct computation of power consumption based on+    actual voltage (Patrick Günther).+ ## Version 0.42 (March, 2022)  _New features_@@ -16,7 +33,7 @@  _New features_ -  - Disk monitors for FreeBSD (Michal Zielonka).+  - Disk monitors for FreeBSD (Michał Zielonka).   - Improvements to signal handling when using xmobar as a library (John Soo).  ## Version 0.40 (November, 2021)@@ -25,7 +42,7 @@    - New plugin: `QueueReader` (Guy Gastineau).   - Greatly improved FreeBSD support: Mem, Network and Swap monitors-    fixes, and CI build for FreeBSD (Michal Zielonka).+    fixes, and CI build for FreeBSD (Michał Zielonka).   - New template markup: `<hspace>`(tulthix)  ## Version 0.39 (August, 2021)
doc/plugins.org view
@@ -382,7 +382,9 @@       - Thresholds refer to frequency in GHz        - Variables that can be used with the =-t/--template= argument:-        =cpu0=, =cpu1=, .., =cpuN=+        =cpu0=, =cpu1=, .., =cpuN=, give the current frequency of the+        respective CPU core, and =max=, =min= and =avg= the maximum, minimum+        and average frequency over all available cores.        - Default template: =Freq: <cpu0>GHz= @@ -393,6 +395,9 @@         #+begin_src haskell           Run CpuFreq ["-t", "Freq:<cpu0>|<cpu1>GHz", "-L", "0", "-H", "2",                        "-l", "lightblue", "-n","white", "-h", "red"] 50++          Run CpuFreq ["-t", "Freq:<avg> GHz", "-L", "0", "-H", "2",+                       "-l", "lightblue", "-n","white", "-h", "red"] 50         #+end_src  ***** =CoreTemp Args RefreshRate=@@ -510,6 +515,10 @@           =freeipat=.         - =--available-icon-pattern=: dynamic string for available memory           ratio in =availableipat=.+        - =--scale=: sizes (total, free, etc.) are reported in units of+          ~Mb/scale~, with scale defaulting to 1.0.  So, for+          instance, to get sizes reported in Gb, set this parameter+          to 1024.        - Thresholds refer to percentage of used memory       - Variables that can be used with the =-t/--template= argument:@@ -517,8 +526,18 @@         =usedbar=, =usedvbar=, =usedipat=, =freeratio=, =freebar=, =freevbar=,         =freeipat=, =availableratio=, =availablebar=, =availablevbar=,         =availableipat=+       - Default template: =Mem: <usedratio>% (<cache>M)= +      - Examples:++        #+begin_src haskell+          -- A monitor reporting memory used in Gb+          Memory [ "-t", "<used> Gb", "--", "--scale", "1024"] 20+          -- As above, but using one decimal digit to print numbers+          Memory [ "-t", "<used> Gb", "-d", "1", "--", "--scale", "1024"] 20+        #+end_src+ ***** =Swap Args RefreshRate=        - Aliases to =swap=@@ -662,7 +681,33 @@           Run Locks         #+end_src -*** Process Monitors+*** Load and Process Monitors+***** =Load Args RefreshRate=++      - Aliases to =load=++      - Args: default monitor arguments. The low and high thresholds+        (=-L= and =-H=) refer to load average values.++      - Variables that can be used with the =-t/--template= argument:+        =load1=, =load5=, =load15=.++      - Default template: =Load: <load1>=.++      - Displays load averages for the last 1, 5 or 15 minutes as+        reported by, e.g., ~uptime(1)~.  The displayed values are float,+        so that the ~"-d"~ option will control how many decimal digits+        are shown (zero by default).++      - Example: to have 2 decimal digits displayed, with a low+        threshold at 1.0 and a high one at 3, you'd write something+        like:++        #+begin_src haskell+            Run Load ["-t" , "<load1> <load5> <load15>"+                     , "-L", "1", "-H", "3", "-d", "2"]) 300+        #+end_src+ ***** =TopProc Args RefreshRate=        - Aliases to =top=
doc/quick-start.org view
@@ -428,13 +428,14 @@    When compiled with the optional =with_dbus= flag, xmobar can be   controlled over dbus. All signals defined in [[https://github.com/jaor/xmobar/blob/master/src/Xmobar/System/Signal.hs][src/Signal.hs]] as =data-  SignalType= can now be sent over dbus to xmobar. Due to current-  limitations of the implementation only one process of xmobar can-  acquire the dbus. This is handled on a first-come-first-served-  basis, meaning that the first process will get the dbus-  interface. Other processes will run without further problems, yet-  have no dbus interface.+  SignalType= can now be sent over dbus to xmobar. +  Due to current limitations of the implementation only one process of+  xmobar can acquire the dbus. This is handled on a+  first-come-first-served basis, meaning that the first process will+  get the dbus interface. Other processes will run without further+  problems, yet have no dbus interface.+   - Bus Name: =org.Xmobar.Control=   - Object Path: =/org/Xmobar/Control=   - Member Name: Any of SignalType, e.g. =string:Reveal=@@ -450,7 +451,7 @@       --print-reply \       '/org/Xmobar/Control' \       org.Xmobar.Control.SendSignal \-      "string:Toggle 0"+      "string:SetAlpha 192"   #+end_src    It is also possible to send multiple signals at once:@@ -463,7 +464,8 @@    The =Toggle=, =Reveal=, and =Hide= signals take an additional integer   argument that denotes an initial delay, in tenths of a second,-  before the command takes effect.+  before the command takes effect, while =SetAlpha= takes a new alpha+  value (also an integer, between 0 and 255) as argument. -  See [[window-managers.org::*Example of using][Interfacing with window managers]] for an example of how to use+  See [[./window-managers.org::*Example of using][Interfacing with window managers]] for an example of how to use   the DBus interface from xmonad.
readme.org view
@@ -11,7 +11,8 @@ extensibility through plugins.  It is also able to write to standard output, in a variety of formats. -These are some xmobar [[file:doc/screenshots][screenshots]] using the author's configuration:+These are some xmobar [[file:doc/screenshots][screenshots]] using one of the authors'+configuration:  [[file:doc/screenshots/xmobar-top.png]] @@ -169,6 +170,9 @@    - If you want to write your own plugins, see [[./doc/write-your-own-plugin.org][Write your own plugin]]. +  - For elaborated examples of how to use xmobar as a Haskell library+    to create your monitors, see [[https://codeberg.org/jao/xmobar-config][this repo at jao/xmobar-config]].+   - To understand the internal mysteries of xmobar you may try reading     [[https://wiki.haskell.org/X_window_programming_in_Haskell][this tutorial]] on X Window Programming in Haskell. @@ -182,39 +186,28 @@   Alex Ameen, Axel Angel, Dhananjay Balan, Claudio Bley, Dragos Boca,   Ben Boeckel, Ivan Brennan, Duncan Burke, Roman Cheplyaka, Patrick   Chilton, Antoine Eiche, Nathaniel Wesley Filardo, Guy Gastineau,-  John Goerzen, Reto Hablützel, Juraj Hercek, Tomáš Janoušek, Ada-  Joule, Spencer Janssen, Roman Joost, Pavel Kalugin, Jochen Keil, Sam-  Kirby, Lennart Kolmodin, Krzysztof Kosciuszkiewicz, Dmitry-  Kurochkin, Todd Lunter, Vanessa McHale, Robert J. Macomber, Dmitry-  Malikov, David McLean, Joan MIlev, Marcin Mikołajczyk, Dino Morelli,-  Tony Morris, Eric Mrak, Thiago Negri, Edward O'Callaghan, Svein Ove,-  Martin Perner, Jens Petersen, Alexander Polakov, Sibi Prabakaran,-  Pavan Rikhi, Petr Rockai, Andrew Emmanuel Rosa, Sackville-West, Amir-  Saeid, Markus Scherer, Daniel Schüssler, Olivier Schneider,-  Alexander Shabalin, Valentin Shirokov, Peter Simons, Alexander-  Solovyov, Will Song, John Soo, 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, Nikolay-  Yakimov, Edward Z. Yang, Leo Zhang, Norbert Zeh, and Michal-  Zielonka.--*** Thanks--  *Andrea Rossato*:--  Thanks to Robert Manea and Spencer Janssen for their help in-  understanding how X works. They gave me suggestions on how to solve many-  problems with xmobar.--  Thanks to Claus Reinke for make me understand existential types (or at-  least for letting me think I grasp existential types...;-).--  *jao*:--  Thanks to Andrea for creating xmobar in the first place, and for giving-  me the chance to contribute.+  John Goerzen, Patrick Günther, Reto Hablützel, Juraj Hercek, Tomáš+  Janoušek, Ada Joule, Spencer Janssen, Roman Joost, Pavel Kalugin,+  Jochen Keil, Sam Kirby, Lennart Kolmodin, Krzysztof Kosciuszkiewicz,+  Dmitry Kurochkin, Todd Lunter, Vanessa McHale, Robert J. Macomber,+  Dmitry Malikov, David McLean, Joan MIlev, Marcin Mikołajczyk, Dino+  Morelli, Tony Morris, Eric Mrak, Thiago Negri, Edward O'Callaghan,+  Svein Ove, Martin Perner, Jens Petersen, Alexander Polakov, Sibi+  Prabakaran, Pavan Rikhi, Petr Rockai, Andrew Emmanuel Rosa,+  Sackville-West, Amir Saeid, Markus Scherer, Daniel Schüssler,+  Olivier Schneider, Alexander Shabalin, Valentin Shirokov, Peter+  Simons, Alexander Solovyov, Will Song, John Soo, 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, Nikolay Yakimov, Edward Z. Yang, Leo Zhang, Norbert Zeh, and+  Michał Zielonka. +  Andrea wants to thank Robert Manea and Spencer Janssen for their+  help in understanding how X works. They gave him suggestions on how+  to solve many problems with xmobar.  He also thanks Claus Reinke for+  making him understand existential types (or at least for letting him+  think he grasps existential types...;-).  * License 
src/Xmobar/Plugins/Monitors.hs view
@@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Xmobar.Plugins.Monitors--- Copyright   :  (c) 2010, 2011, 2012, 2013, 2017, 2018, 2019, 2020 Jose Antonio Ortega Ruiz+-- Copyright   :  (c) 2010-2013, 2017-2020, 2022 Jose Antonio Ortega Ruiz --                (c) 2007-10 Andrea Rossato -- License     :  BSD-style (see LICENSE) --@@ -30,6 +30,7 @@ import Xmobar.Plugins.Monitors.MultiCpu import Xmobar.Plugins.Monitors.Batt import Xmobar.Plugins.Monitors.Bright+import Xmobar.Plugins.Monitors.Load import Xmobar.Plugins.Monitors.Thermal import Xmobar.Plugins.Monitors.ThermalZone import Xmobar.Plugins.Monitors.CpuFreq@@ -65,6 +66,7 @@               | Battery      Args        Rate               | DiskU        DiskSpec    Args Rate               | DiskIO       DiskSpec    Args Rate+              | Load         Args        Rate               | Thermal      Zone        Args Rate               | ThermalZone  ZoneNo      Args Rate               | Memory       Args        Rate@@ -124,6 +126,7 @@ #endif     alias (Network i _ _) = i     alias (DynNetwork _ _) = "dynnetwork"+    alias (Load _ _) = "load"     alias (Thermal z _ _) = z     alias (ThermalZone z _ _) = "thermal" ++ show z     alias (Memory _ _) = "memory"@@ -176,6 +179,7 @@     start (Thermal z a r) = runM (a ++ [z]) thermalConfig runThermal r     start (ThermalZone z a r) =       runM (a ++ [show z]) thermalZoneConfig runThermalZone r+    start (Load a r) = runM a loadConfig runLoad 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
src/Xmobar/Plugins/Monitors/Batt/Linux.hs view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Plugins.Monitors.Batt.Linux--- Copyright   :  (c) 2010, 2011, 2012, 2013, 2015, 2016, 2018, 2019 Jose A Ortega+-- Copyright   :  (c) 2010-2013, 2015, 2016, 2018, 2019, 2022 Jose A Ortega --                (c) 2010 Andrea Rossato, Petr Rockai -- License     :  BSD-style (see LICENSE) --@@ -15,7 +15,7 @@  module Xmobar.Plugins.Monitors.Batt.Linux (readBatteries) where -import Xmobar.Plugins.Monitors.Batt.Common (BattOpts(..)+import Xmobar.Plugins.Monitors.Batt.Common ( BattOpts(..)                                            , Result(..)                                            , Status(..)                                            , maybeAlert)@@ -23,22 +23,73 @@ import Control.Monad (unless) import Control.Exception (SomeException, handle) import System.FilePath ((</>))-import System.IO (IOMode(ReadMode), hGetLine, withFile)-import System.Posix.Files (fileExist)+import System.IO (IOMode(ReadMode), hGetLine, withFile, Handle) import Data.List (sort, sortBy, group) import Data.Maybe (fromMaybe) import Data.Ord (comparing) import Text.Read (readMaybe)  data Files = Files-  { fFull :: String-  , fNow :: String+  { fEFull :: String+  , fCFull :: String+  , fEFullDesign :: String+  , fCFullDesign :: String+  , fENow :: String+  , fCNow :: String   , fVoltage :: String+  , fVoltageMin :: String   , fCurrent :: String+  , fPower :: String   , fStatus :: String-  , isCurrent :: Bool-  } | NoFiles deriving Eq+  , fBat :: String+  } deriving Eq +-- the default basenames of the possibly available attributes exposed+-- by the kernel+defaultFiles :: Files+defaultFiles = Files+  { fEFull = "energy_full"+  , fCFull = "charge_full"+  , fEFullDesign = "energy_full_design"+  , fCFullDesign = "charge_full_design"+  , fENow = "energy_now"+  , fCNow = "charge_now"+  , fVoltage = "voltage_now"+  , fVoltageMin = "voltage_min_design"+  , fCurrent = "current_now"+  , fPower = "power_now"+  , fStatus = "status"+  , fBat = "BAT0"+  }++type FilesAccessor = Files -> String++sysDir :: FilePath+sysDir = "/sys/class/power_supply"++battFile :: FilesAccessor -> Files -> FilePath+battFile accessor files = sysDir </> fBat files </> accessor files++grabNumber :: (Num a, Read a) => FilesAccessor -> Files -> IO (Maybe a)+grabNumber = grabFile (fmap read . hGetLine)++grabString :: FilesAccessor -> Files -> IO (Maybe String)+grabString = grabFile hGetLine++-- grab file contents returning Nothing if the file doesn't exist or+-- any other error occurs+grabFile :: (Handle -> IO a) -> FilesAccessor -> Files -> IO (Maybe a)+grabFile readMode accessor files =+  handle (onFileError Nothing) (withFile f ReadMode (fmap Just . readMode))+  where f = battFile accessor files++onFileError :: a -> SomeException -> IO a+onFileError returnOnError = const (return returnOnError)++-- get the filenames for a given battery name+batteryFiles :: String -> Files+batteryFiles bat = defaultFiles { fBat = bat }+ data Battery = Battery   { full :: !Float   , now :: !Float@@ -46,56 +97,79 @@   , status :: !String   } -sysDir :: FilePath-sysDir = "/sys/class/power_supply"+haveAc :: FilePath -> IO Bool+haveAc f =+  handle (onFileError False) $+    withFile (sysDir </> f) ReadMode (fmap (== "1") . hGetLine) -safeFileExist :: String -> String -> IO Bool-safeFileExist d f = handle noErrors $ fileExist (d </> f)-  where noErrors = const (return False) :: SomeException -> IO Bool+-- retrieve the currently drawn power in Watt+-- sc is a scaling factor which by kernel documentation must be 1e6+readBatPower :: Float -> Files -> IO (Maybe Float)+readBatPower sc f =+    do pM <- grabNumber fPower f+       cM <- grabNumber fCurrent f+       vM <- grabNumber fVoltage f+       return $ case (pM, cM, vM) of+           (Just pVal, _, _) -> Just $ pVal / sc+           (_, Just cVal, Just vVal) -> Just $ cVal * vVal / (sc * sc)+           (_, _, _) -> Nothing -batteryFiles :: String -> IO Files-batteryFiles bat =-  do is_charge <- exists "charge_now"-     is_energy <- if is_charge then return False else exists "energy_now"-     is_power <- exists "power_now"-     plain <- exists (if is_charge then "charge_full" else "energy_full")-     let cf = if is_power then "power_now" else "current_now"-         sf = if plain then "" else "_design"-     return $ case (is_charge, is_energy) of-       (True, _) -> files "charge" cf sf is_power-       (_, True) -> files "energy" cf sf is_power-       _ -> NoFiles-  where prefix = sysDir </> bat-        exists = safeFileExist prefix-        files ch cf sf ip = Files { fFull = prefix </> ch ++ "_full" ++ sf-                                  , fNow = prefix </> ch ++ "_now"-                                  , fCurrent = prefix </> cf-                                  , fVoltage = prefix </> "voltage_now"-                                  , fStatus = prefix </> "status"-                                  , isCurrent = not ip}+-- retrieve the maximum capacity in Watt hours+-- sc is a scaling factor which by kernel documentation must be 1e6+-- on getting the voltage: using voltage_min_design will probably underestimate+-- the actual energy content of the battery and using voltage_now will probably+-- overestimate it.+readBatCapacityFull :: Float -> Files -> IO (Maybe Float)+readBatCapacityFull sc f =+    do cM  <- grabNumber fCFull f+       eM  <- grabNumber fEFull f+       cdM <- grabNumber fCFullDesign f+       edM <- grabNumber fEFullDesign f+       -- not sure if Voltage or VoltageMin is more accurate and if both+       -- are always available+       vM  <- grabNumber fVoltageMin f+       return $ case (eM, cM, edM, cdM, vM) of+           (Just eVal, _, _, _, _)         -> Just $ eVal        / sc+           (_, Just cVal, _, _, Just vVal) -> Just $ cVal * vVal / (sc * sc)+           (_, _, Just eVal, _, _)         -> Just $ eVal        / sc+           (_, _, _, Just cVal, Just vVal) -> Just $ cVal * vVal / (sc * sc)+           (_, _, _, _, _) -> Nothing -haveAc :: FilePath -> IO Bool-haveAc f =-  handle onError $ withFile (sysDir </> f) ReadMode (fmap (== "1") . hGetLine)-  where onError = const (return False) :: SomeException -> IO Bool+-- retrieve the current capacity in Watt hours+-- sc is a scaling factor which by kernel documentation must be 1e6+-- on getting the voltage: using voltage_min_design will probably underestimate+-- the actual energy content of the battery and using voltage_now will probably+-- overestimate it.+readBatCapacityNow :: Float -> Files -> IO (Maybe Float)+readBatCapacityNow sc f =+    do cM  <- grabNumber fCNow f+       eM  <- grabNumber fENow f+       vM  <- grabNumber fVoltageMin f -- not sure if Voltage or+                                       -- VoltageMin is more accurate+                                       -- and if both are always+                                       -- available+       return $ case (eM, cM, vM) of+           (Just eVal, _, _)         -> Just $ eVal        / sc+           (_, Just cVal, Just vVal) -> Just $ cVal * vVal / (sc * sc)+           (_, _, _) -> Nothing +readBatStatus :: Files -> IO (Maybe String)+readBatStatus = grabString fStatus++-- collect all relevant battery values with defaults of not available readBattery :: Float -> Files -> IO Battery-readBattery _ NoFiles = return $ Battery 0 0 0 "Unknown" readBattery sc files =-    do a <- grab $ fFull files-       b <- grab $ fNow files-       d <- grab $ fCurrent files-       s <- grabs $ fStatus files-       let sc' = if isCurrent files then sc / 10 else sc-           a' = max a b -- sometimes the reported max charge is lower than-       return $ Battery (3600 * a' / sc') -- wattseconds-                        (3600 * b / sc') -- wattseconds-                        (abs d / sc') -- watts+    do cFull <- withDef 0 readBatCapacityFull+       cNow <- withDef 0 readBatCapacityNow+       pwr <- withDef 0 readBatPower+       s <- withDef "Unknown" (const readBatStatus)+       let cFull' = max cFull cNow -- sometimes the reported max+                                   -- charge is lower than+       return $ Battery (3600 * cFull') -- wattseconds+                        (3600 * cNow) -- wattseconds+                        (abs pwr) -- watts                         s -- string: Discharging/Charging/Full-    where grab f = handle onError $ withFile f ReadMode (fmap read . hGetLine)-          onError = const (return (-1)) :: SomeException -> IO Float-          grabs f = handle onError' $ withFile f ReadMode hGetLine-          onError' = const (return "Unknown") :: SomeException -> IO String+         where withDef d reader = fromMaybe d `fmap` reader sc files  -- sortOn is only available starting at ghc 7.10 sortOn :: Ord b => (a -> b) -> [a] -> [a]@@ -107,12 +181,11 @@  readBatteries :: BattOpts -> [String] -> IO Result readBatteries opts bfs =-    do bfs' <- mapM batteryFiles bfs-       let bfs'' = filter (/= NoFiles) bfs'+    do let bfs'' = map batteryFiles bfs        bats <- mapM (readBattery (scale opts)) (take 3 bfs'')        ac <- haveAc (onlineFile opts)        let sign = if ac then 1 else -1-           ft = sum (map full bats)+           ft = sum (map full bats) -- total capacity when full            left = if ft > 0 then sum (map now bats) / ft else 0            watts = sign * sum (map power bats)            time = if watts == 0 then 0 else max 0 (sum $ map time' bats)
src/Xmobar/Plugins/Monitors/Common/Files.hs view
@@ -14,7 +14,9 @@ -- ----------------------------------------------------------------------------- -module Xmobar.Plugins.Monitors.Common.Files (checkedDataRetrieval) where+module Xmobar.Plugins.Monitors.Common.Files ( checkedDataRetrieval+                                            , checkedDataRead)+where  #if __GLASGOW_HASKELL__ < 800 import Control.Applicative@@ -48,6 +50,11 @@     else Just <$> (     parseTemplate                     =<< mapM (showWithColors fmt . trans . read) pairs                   )++checkedDataRead :: [[String]] -> Monitor [Double]+checkedDataRead paths = concat <$> mapM readData paths+  where readData path = map (read . snd) . sortBy (compare `on` fst) <$>+                         (mapM readFiles =<< findFilesAndLabel path Nothing)  -- | Represents the different types of path components data Comp = Fix String
src/Xmobar/Plugins/Monitors/CpuFreq.hs view
@@ -22,7 +22,8 @@ -- get more cpu frequencies. cpuFreqConfig :: IO MConfig cpuFreqConfig =-  mkMConfig "Freq: <cpu0>" (map ((++) "cpu" . show) [0 :: Int ..])+  mkMConfig "Freq: <cpu0>"+            (["max", "min", "avg"] ++ map ((++) "cpu" . show) [0 :: Int ..])   -- |@@ -32,12 +33,14 @@ runCpuFreq _ = do   suffix <- getConfigValue useSuffix   ddigits <- getConfigValue decDigits-  let path = ["/sys/devices/system/cpu/cpu", "/cpufreq/scaling_cur_freq"]+  let paths = ["/sys/devices/system/cpu/cpu", "/cpufreq/scaling_cur_freq"]       divisor = 1e6 :: Double       fmt x | x < 1 = if suffix then mhzFmt x ++ "MHz"                                 else ghzFmt x             | otherwise = ghzFmt x ++ if suffix then "GHz" else ""       mhzFmt x = show (round (x * 1000) :: Integer)       ghzFmt = showDigits ddigits-  failureMessage <- getConfigValue naString-  checkedDataRetrieval failureMessage [path] Nothing (/divisor) fmt+      sts xs = [maximum xs, minimum xs, sum xs / fromIntegral (length xs)]+  vs <- checkedDataRead [paths]+  if null vs then getConfigValue naString+  else mapM (showWithColors fmt . (/divisor)) (sts vs ++ vs) >>= parseTemplate
+ src/Xmobar/Plugins/Monitors/Load.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE CPP #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  Plugins.Monitors.Load+-- Copyright   :  Finn Lawler+-- License     :  BSD-style (see LICENSE)+--+-- Author      :  Finn Lawler <flawler@cs.tcd.ie>+-- Maintainer  :  jao <mail@jao.io>+-- Stability   :  unstable+-- Portability :  unportable+--+-- A load average monitor for Xmobar.  Adapted from+-- Xmobar.Plugins.Monitors.Thermal by Juraj Hercek.+--+-----------------------------------------------------------------------------++module Xmobar.Plugins.Monitors.Load (loadConfig, runLoad) where++import Xmobar.Plugins.Monitors.Common+import Xmobar.Plugins.Monitors.Load.Common (Result(..))++#if defined(freebsd_HOST_OS)+import qualified Xmobar.Plugins.Monitors.Load.FreeBSD as ML+#else+import qualified Xmobar.Plugins.Monitors.Load.Linux as ML+#endif+++-- | Default configuration.+loadConfig :: IO MConfig+loadConfig = mkMConfig "Load: <load1>" ["load1", "load5", "load15"]+++-- | Retrieves load information.  Returns the monitor string parsed+-- according to template (either default or user specified).+runLoad :: [String] -> Monitor String+runLoad _ = do+  result <- io ML.fetchLoads+  case result of+    Result loads ->+      do+        d <- getConfigValue decDigits+        parseTemplate =<< mapM (showWithColors (showDigits d)) loads+    NA -> getConfigValue naString
+ src/Xmobar/Plugins/Monitors/Load/Common.hs view
@@ -0,0 +1,21 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Plugins.Monitors.Load.Common+-- Copyright   :  Finn Lawler+-- License     :  BSD-style (see LICENSE)+--+-- Author      :  Finn Lawler <flawler@cs.tcd.ie>+-- Maintainer  :  jao <mail@jao.io>+-- Stability   :  unstable+-- Portability :  unportable+--+-- A load average monitor for Xmobar.  Adapted from+-- Xmobar.Plugins.Monitors.Thermal by Juraj Hercek.+--+-----------------------------------------------------------------------------++module Xmobar.Plugins.Monitors.Load.Common (+  Result(..)+  ) where++data Result = Result [Float] | NA
+ src/Xmobar/Plugins/Monitors/Load/FreeBSD.hsc view
@@ -0,0 +1,58 @@+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE CApiFFI #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Plugins.Monitors.Load.FreeBSD+-- Copyright   :  Finn Lawler+-- License     :  BSD-style (see LICENSE)+--+-- Author      :  Finn Lawler <flawler@cs.tcd.ie>+-- Maintainer  :  jao <mail@jao.io>+-- Stability   :  unstable+-- Portability :  unportable+--+-- A load average monitor for Xmobar.  Adapted from+-- Xmobar.Plugins.Monitors.Thermal by Juraj Hercek.+--+-----------------------------------------------------------------------------++module Xmobar.Plugins.Monitors.Load.FreeBSD (fetchLoads) where++import Xmobar.Plugins.Monitors.Load.Common (Result(..))+import Foreign.C.Types (CUInt, CUIntMax)+import Foreign.Marshal.Array (peekArray)+import Foreign.Ptr (plusPtr)+import Foreign.Storable (Storable, alignment, peek, peekByteOff, poke, sizeOf)+import System.BSD.Sysctl (sysctlPeek)++#include <sys/resource.h>+++data LoadAvg = LoadAvg {loads :: [Float]}+++calcLoad :: CUInt -> CUIntMax -> Float+calcLoad l s = ((fromIntegral . toInteger) l) / ((fromIntegral . toInteger) s)+++instance Storable LoadAvg where+  alignment _ = #{alignment struct loadavg}+  sizeOf _    = #{size struct loadavg}+  peek ptr    = do+    load_values <- peekArray 3 $ #{ptr struct loadavg, ldavg} ptr  :: IO [CUInt]+    scale <- #{peek struct loadavg, fscale} ptr :: IO CUIntMax+    let+      l1 = calcLoad (load_values !! 0) scale+      l5 = calcLoad (load_values !! 1) scale+      l15 = calcLoad (load_values !! 2) scale++    return $ LoadAvg{loads = [l1, l5, l15]}++  poke _ _    = pure ()+++fetchLoads :: IO Result+fetchLoads = do+  res <- sysctlPeek "vm.loadavg" :: IO LoadAvg+  return $ Result (loads res)
+ src/Xmobar/Plugins/Monitors/Load/Linux.hs view
@@ -0,0 +1,37 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Plugins.Monitors.Load.Linux+-- Copyright   :  Finn Lawler+-- License     :  BSD-style (see LICENSE)+--+-- Author      :  Finn Lawler <flawler@cs.tcd.ie>+-- Maintainer  :  jao <mail@jao.io>+-- Stability   :  unstable+-- Portability :  unportable+--+-- A load average monitor for Xmobar.  Adapted from+-- Xmobar.Plugins.Monitors.Thermal by Juraj Hercek.+--+-----------------------------------------------------------------------------++module Xmobar.Plugins.Monitors.Load.Linux (fetchLoads) where++import Xmobar.Plugins.Monitors.Load.Common (Result(..))+import qualified Data.ByteString.Lazy.Char8 as B+import System.Posix.Files (fileExist)++-- | Parses the contents of a loadavg proc file, returning+-- the list of load averages+parseLoadAvgs :: B.ByteString -> Result+parseLoadAvgs =+  Result . map (read . B.unpack) . take 3 . B.words . head . B.lines++fetchLoads :: IO Result+fetchLoads = do+  let file = "/proc/loadavg"++  exists <- fileExist file+  if exists then+    parseLoadAvgs <$> B.readFile file+    else+    return NA
src/Xmobar/Plugins/Monitors/MPD.hs view
@@ -95,7 +95,8 @@  parseMPD :: M.Response M.Status -> M.Response (Maybe M.Song) -> MOpts             -> Monitor [String]-parseMPD (Left _) _ _ = return $ "N/A": repeat ""+parseMPD (Left _) _ _ =+  getConfigValue naString >>= \na -> return $ na : repeat "" parseMPD (Right st) song opts = do   songData <- parseSong song   bar <- showPercentBar (100 * b) b
src/Xmobar/Plugins/Monitors/Mem.hs view
@@ -13,7 +13,7 @@ -- ----------------------------------------------------------------------------- -module Xmobar.Plugins.Monitors.Mem (memConfig, runMem, totalMem, usedMem) where+module Xmobar.Plugins.Monitors.Mem (memConfig, runMem) where  import Xmobar.Plugins.Monitors.Common import System.Console.GetOpt@@ -29,6 +29,7 @@   { usedIconPattern :: Maybe IconPattern   , freeIconPattern :: Maybe IconPattern   , availableIconPattern :: Maybe IconPattern+  , scale :: Float   }  defaultOpts :: MemOpts@@ -36,6 +37,7 @@   { usedIconPattern = Nothing   , freeIconPattern = Nothing   , availableIconPattern = Nothing+  , scale = 1.0   }  options :: [OptDescr (MemOpts -> MemOpts)]@@ -46,31 +48,29 @@      o { freeIconPattern = Just $ parseIconPattern x }) "") ""   , Option "" ["available-icon-pattern"] (ReqArg (\x o ->      o { availableIconPattern = Just $ parseIconPattern x }) "") ""+  , Option "" ["scale"] (ReqArg (\x o -> o { scale = read x }) "") ""   ]  memConfig :: IO MConfig memConfig = mkMConfig-       "Mem: <usedratio>% (<cache>M)" -- template+       "Mem: <usedratio>% (<cache>M)"        ["usedbar", "usedvbar", "usedipat", "freebar", "freevbar", "freeipat",         "availablebar", "availablevbar", "availableipat",         "usedratio", "freeratio", "availableratio",-        "total", "free", "buffer", "cache", "available", "used"] -- available replacements--totalMem :: IO Float-totalMem = fmap ((*1024) . (!!1)) MM.parseMEM--usedMem :: IO Float-usedMem = fmap ((*1024) . (!!6)) MM.parseMEM+        "total", "free", "buffer", "cache", "available", "used"]  formatMem :: MemOpts -> [Float] -> Monitor [String] formatMem opts (r:fr:ar:xs) =-    do let f = showDigits 0-           mon i x = [showPercentBar (100 * x) x, showVerticalBar (100 * x) x, showIconPattern i x]+    do d <- getConfigValue decDigits+       let f = showDigits d+           mon i x = [ showPercentBar (100 * x) x+                     , showVerticalBar (100 * x) x+                     , showIconPattern i x]        sequence $ mon (usedIconPattern opts) r            ++ mon (freeIconPattern opts) fr            ++ mon (availableIconPattern opts) ar            ++ map showPercentWithColors [r, fr, ar]-           ++ map (showWithColors f) xs+           ++ map (showWithColors f . (/ scale opts)) xs formatMem _ _ = replicate 10 `fmap` getConfigValue naString  runMem :: [String] -> Monitor String
src/Xmobar/Plugins/Monitors/Mem/Linux.hs view
@@ -23,11 +23,14 @@ parseMEM =     do file <- fileMEM        let content = map words $ take 8 $ lines file-           info = M.fromList $ map (\line -> (head line, (read $ line !! 1 :: Float) / 1024)) content-           [total, free, buffer, cache] = map (info M.!) ["MemTotal:", "MemFree:", "Buffers:", "Cached:"]+           info = M.fromList $ map (+             \line -> (head line, (read $ line !! 1 :: Float) / 1024)) content+           [total, free, buffer, cache] =+             map (info M.!) ["MemTotal:", "MemFree:", "Buffers:", "Cached:"]            available = M.findWithDefault (free + buffer + cache) "MemAvailable:" info            used = total - available            usedratio = used / total            freeratio = free / total            availableratio = available / total-       return [usedratio, freeratio, availableratio, total, free, buffer, cache, available, used]+       return [ usedratio, freeratio, availableratio+              , total, free, buffer, cache, available, used]
src/Xmobar/Plugins/Monitors/MultiCoreTemp.hs view
@@ -16,9 +16,12 @@  import Xmobar.Plugins.Monitors.Common import Control.Monad (filterM)+import Data.Char (isDigit)+import Data.List (isPrefixOf) import System.Console.GetOpt import System.Directory ( doesDirectoryExist                         , doesFileExist+                        , listDirectory                         )  -- | Declare Options.@@ -75,13 +78,32 @@                     , "avg" , "avgpc" , "avgbar" , "avgvbar" , "avgipat"                     ] ++ map (("core" ++) . show) [0 :: Int ..] +-- | Returns all paths in dir matching the predicate.+getMatchingPathsInDir :: FilePath -> (String -> Bool) -> IO [FilePath]+getMatchingPathsInDir dir f = do exists <- doesDirectoryExist dir+                                 if exists+                                    then do+                                      files <- filter f <$> listDirectory dir+                                      return $ fmap (\file -> dir ++ "/" ++ file) files+                                    else return [] +-- | Given a prefix, suffix, and path string, return true if the path string+-- format is prefix ++ numeric ++ suffix.+numberedPathMatcher :: String -> String -> String -> Bool+numberedPathMatcher prefix suffix path =+    prefix `isPrefixOf` path+    && not (null digits)+    && afterDigits == suffix+  where afterPrefix = drop (length prefix) path+        digits = takeWhile isDigit afterPrefix+        afterDigits = dropWhile isDigit afterPrefix+ -- | Returns the first coretemp.N path found. coretempPath :: IO (Maybe String)-coretempPath = do xs <- filterM doesDirectoryExist ps-                  return (if null xs then Nothing else Just $ head xs)-  where ps = [ "/sys/bus/platform/devices/coretemp." ++ show (x :: Int) ++ "/"-             | x <- [0..9] ]+coretempPath = do ps <- getMatchingPathsInDir "/sys/bus/platform/devices" coretempMatcher+                  xs <- filterM doesDirectoryExist ps+                  return (if null xs then Nothing else Just $ head xs ++ "/")+  where coretempMatcher = numberedPathMatcher "coretemp." ""  -- | Returns the first hwmonN in coretemp path found or the ones in sys/class. hwmonPaths :: IO [String]@@ -89,10 +111,10 @@                 let (sc, path) = case p of                                    Just s -> (False, s)                                    Nothing -> (True, "/sys/class/")-                let cps  = [ path ++ "hwmon/hwmon" ++ show (x :: Int) ++ "/"-                           | x <- [0..9] ]+                cps <- getMatchingPathsInDir (path ++ "hwmon") hwmonMatcher                 ecps <- filterM doesDirectoryExist cps                 return $ if sc || null ecps then ecps else [head ecps]+  where hwmonMatcher = numberedPathMatcher "hwmon" ""  -- | Checks Labels, if they refer to a core and returns Strings of core- -- temperatures.@@ -100,11 +122,11 @@ corePaths s = do ps <- case s of                         Just pth -> return [pth]                         _ -> hwmonPaths-                 let cps = [p ++ "temp" ++ show (x :: Int) ++ "_label"-                           | x <- [0..9], p <- ps ]+                 cps <- concat <$> traverse (`getMatchingPathsInDir` corePathMatcher) ps                  ls <- filterM doesFileExist cps                  cls <- filterM isLabelFromCore ls                  return $ map labelToCore cls+  where corePathMatcher = numberedPathMatcher "temp" "_label"  -- | Checks if Label refers to a core. isLabelFromCore :: FilePath -> IO Bool
src/Xmobar/Plugins/Monitors/Swap.hs view
@@ -24,9 +24,8 @@ #endif  swapConfig :: IO MConfig-swapConfig = mkMConfig-        "Swap: <usedratio>%"                    -- template-        ["usedratio", "total", "used", "free"] -- available replacements+swapConfig = mkMConfig "Swap: <usedratio>%"+                       ["usedratio", "total", "used", "free"]  formatSwap :: [Float] -> Monitor [String] formatSwap (r:xs) = do@@ -34,7 +33,7 @@   other <- mapM (showWithColors (showDigits d)) xs   ratio <- showPercentWithColors r   return $ ratio:other-formatSwap _ = return $ replicate 4 "N/A"+formatSwap _ = replicate 4 `fmap` getConfigValue naString  runSwap :: [String] -> Monitor String runSwap _ =
src/Xmobar/Plugins/Monitors/Thermal.hs view
@@ -36,4 +36,4 @@         then do number <- io $ fmap ((read :: String -> Int) . stringParser (1, 0)) (B.readFile file)                 thermal <- showWithColors show number                 parseTemplate [  thermal ]-        else return $ "Thermal (" ++ zone ++ "): N/A"+        else getConfigValue naString
src/Xmobar/Plugins/Monitors/Top.hs view
@@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Plugins.Monitors.Top--- Copyright   :  (c) 2010, 2011, 2012, 2013, 2014, 2018 Jose A Ortega Ruiz+-- Copyright   :  (c) 2010, 2011, 2012, 2013, 2014, 2018, 2022 Jose A Ortega Ruiz -- License     :  BSD-style (see LICENSE) -- -- Maintainer  :  Jose A Ortega Ruiz <jao@gnu.org>@@ -127,7 +127,8 @@   (no, ps, ms) <- io $ topProcesses tref scale   pstr <- showTimeInfos ps   mstr <- showMemInfos ms-  parseTemplate $ show no : concat (zipWith (++) pstr mstr) ++ repeat "N/A"+  na <- getConfigValue naString+  parseTemplate $ show no : concat (zipWith (++) pstr mstr) ++ repeat na  startTop :: [String] -> Int -> (String -> IO ()) -> IO () startTop a r cb = do
src/Xmobar/System/Signal.hs view
@@ -46,6 +46,7 @@                 | Hide   Int                 | Reveal Int                 | Toggle Int+                | SetAlpha Int                 | TogglePersistent                 | Action Button Position     deriving (Read, Show)
src/Xmobar/X11/Loop.hs view
@@ -39,6 +39,7 @@  import Xmobar.System.Signal import Xmobar.Config.Types ( persistent+                           , alpha                            , font                            , additionalFonts                            , textOffset@@ -145,6 +146,8 @@           TogglePersistent -> signalLoop             xc { config = cfg { persistent = not $ persistent cfg } } as signal tv++         SetAlpha a -> signalLoop xc { config = cfg { alpha = a}} as signal tv           Action but x -> action but x 
xmobar.cabal view
@@ -1,5 +1,5 @@ name:               xmobar-version:            0.42+version:            0.43 homepage:           https://github.com/jaor/xmobar synopsis:           A Minimalistic Text Based Status Bar description: 	    Xmobar is a minimalistic text based status bar.@@ -167,6 +167,8 @@                    Xmobar.Plugins.Monitors.CpuFreq,                    Xmobar.Plugins.Monitors.Disk,                    Xmobar.Plugins.Monitors.Disk.Common,+                   Xmobar.Plugins.Monitors.Load,+                   Xmobar.Plugins.Monitors.Load.Common,                    Xmobar.Plugins.Monitors.Mem,                    Xmobar.Plugins.Monitors.MultiCoreTemp,                    Xmobar.Plugins.Monitors.MultiCpu,@@ -189,7 +191,7 @@                   X11 >= 1.6.1,                   aeson >= 1.4.7.1,                   async,-                  base >= 4.11.0 && < 4.16,+                  base >= 4.11.0 && < 4.17,                   bytestring >= 0.10.8.2,                   containers,                   directory,@@ -311,6 +313,7 @@        other-modules: Xmobar.Plugins.Monitors.Batt.FreeBSD,                       Xmobar.Plugins.Monitors.Cpu.FreeBSD,                       Xmobar.Plugins.Monitors.Disk.FreeBSD,+                      Xmobar.Plugins.Monitors.Load.FreeBSD,                       Xmobar.Plugins.Monitors.Mem.FreeBSD,                       Xmobar.Plugins.Monitors.Net.FreeBSD,                       Xmobar.Plugins.Monitors.Swap.FreeBSD,@@ -320,6 +323,7 @@        other-modules: Xmobar.Plugins.Monitors.Batt.Linux,                       Xmobar.Plugins.Monitors.Cpu.Linux,                       Xmobar.Plugins.Monitors.Disk.Linux,+                      Xmobar.Plugins.Monitors.Load.Linux,                       Xmobar.Plugins.Monitors.Mem.Linux,                       Xmobar.Plugins.Monitors.Net.Linux,                       Xmobar.Plugins.Monitors.Swap.Linux,