xmobar 0.42 → 0.43
raw patch · 22 files changed
+479/−139 lines, 22 filesdep ~base
Dependency ranges changed: base
Files
- changelog.md +19/−2
- doc/plugins.org +47/−2
- doc/quick-start.org +11/−9
- readme.org +26/−33
- src/Xmobar/Plugins/Monitors.hs +5/−1
- src/Xmobar/Plugins/Monitors/Batt/Linux.hs +127/−54
- src/Xmobar/Plugins/Monitors/Common/Files.hs +8/−1
- src/Xmobar/Plugins/Monitors/CpuFreq.hs +7/−4
- src/Xmobar/Plugins/Monitors/Load.hs +46/−0
- src/Xmobar/Plugins/Monitors/Load/Common.hs +21/−0
- src/Xmobar/Plugins/Monitors/Load/FreeBSD.hsc +58/−0
- src/Xmobar/Plugins/Monitors/Load/Linux.hs +37/−0
- src/Xmobar/Plugins/Monitors/MPD.hs +2/−1
- src/Xmobar/Plugins/Monitors/Mem.hs +12/−12
- src/Xmobar/Plugins/Monitors/Mem/Linux.hs +6/−3
- src/Xmobar/Plugins/Monitors/MultiCoreTemp.hs +30/−8
- src/Xmobar/Plugins/Monitors/Swap.hs +3/−4
- src/Xmobar/Plugins/Monitors/Thermal.hs +1/−1
- src/Xmobar/Plugins/Monitors/Top.hs +3/−2
- src/Xmobar/System/Signal.hs +1/−0
- src/Xmobar/X11/Loop.hs +3/−0
- xmobar.cabal +6/−2
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,