xmobar 0.48.1 → 0.49
raw patch · 14 files changed
+224/−35 lines, 14 filesdep ~base
Dependency ranges changed: base
Files
- changelog.md +8/−0
- doc/plugins.org +43/−6
- readme.org +1/−4
- src/Xmobar.hs +4/−0
- src/Xmobar/App/Opts.hs +2/−2
- src/Xmobar/Plugins/Accordion.hs +97/−0
- src/Xmobar/Plugins/ArchUpdates.hs +41/−0
- src/Xmobar/Plugins/MarqueePipeReader.hs +1/−1
- src/Xmobar/Plugins/Monitors/Mpris.hs +5/−5
- src/Xmobar/Plugins/Monitors/Top.hs +3/−3
- src/Xmobar/Plugins/Monitors/Weather.hs +10/−9
- src/Xmobar/Run/Types.hs +2/−0
- src/Xmobar/X11/Loop.hs +3/−3
- xmobar.cabal +4/−2
changelog.md view
@@ -1,3 +1,11 @@+## Version 0.49 (April, 2025)++- New plugins: `ArchUpdates` and `Accordion` (thanks, Enrico Maria)+- New template variable `weatherS` for `WeatherX`.+- New Nix flake (thanks, refaelsh)+- `MPRIS`: Fix for duration reported by Spotify (thanks, Claudio)+- Base dep up to 4.20 (thanks, Alexander)+ ## Version 0.48.1 (May, 2024) - Removing for now mouse support for `Kbd`, which can be recovered by
doc/plugins.org view
@@ -1268,9 +1268,11 @@ - Works in the same way as =Weather=, but takes an additional argument, a list of pairs from sky conditions to their replacement (typically a unicode string or an icon specification).- - Use the variable =skyConditionS= to display the replacement of the- corresponding sky condition. All other =Weather= template variables- are available as well.+ - Use the variable =skyConditionS= or =weatherS= to display the replacement of+ the corresponding sky condition. =weatherS= uses the string returned by+ =weather= to look up a replacement, and, if that one is not found, it+ looks up the value of =skyConditionS=. All other =Weather= template+ variables are available as well. For example: @@ -1321,7 +1323,7 @@ #+begin_src haskell Run UVMeter "Brisbane" ["-H", "3", "-L", "3", "--low", "green", "--high", "red"] 900 #+end_src-** Other monitors+** Other monitors and plugins *** =CatInt n filename= - Reads and displays an integer from the file whose path is =filename=@@ -1351,6 +1353,43 @@ the display of those numeric fields. - Default template: =Up: <days>d <hours>h <minutes>m= +*** =ArchUpdates (Zero, One, Many) Rate=++ - Aliases to =arch=+ - =Zero=: a =String= to use when the system is up to date.+ - =One=: a =String= to use when only one update is available.+ - =Many=: a =String= to use when several updates are available; it must contain+ a =?= character as a placeholder for the number of updates.+ - Example:+ #+begin_src haskell+ ArchUpdates ("<fc=green>up to date</fc>",+ "<fc=yellow>1 update</fc>,+ "<fc=red>? updates</fc>")+ 600+ #+end_src++*** =makeAccordion Tuning [Runnable]=++ - Wraps other =Runnable= plugins and makes them all collapsible to a single string:++ [[file:accordion.gif]]++ - Aliases to =alias' tuning=, being =tuning= of type =Tuning=, so one can use multiple such "accordions"+ - **Disclaimer**: This only works for Haskell =xmobar.hs=+ - =Tuning=: the "settings", for which a default value is provided,+ #+begin_src haskell+ defaultTuning = Tuning {+ alias' = "accordion"+ , initial = True+ , expand = "<>"+ , shrink = "><"+ }+ #+end_src+ - =expand=: =String= shown when the accordion is contracted (defaults to ="<>"=).+ - =shrink=: =String= shown when the accordion is expanded (defaults to ="><"=).+ - =initial=: =Bool= to tell whether the accordion is initially expanded (defaults to =True=).+ - =[Runnable]=: a list of =Runnable= plugins+ * Interfacing with window managers :PROPERTIES: :CUSTOM_ID: interfacing-with-window-managers@@ -1574,8 +1613,6 @@ updates. It is thus necessary to enable =-threaded= when compiling xmonad configuration (=xmonad.hs=), e.g. by using a custom =~/.xmonad/build= script.-- * Executing external commands
readme.org view
@@ -5,9 +5,6 @@ <a href="http://hackage.haskell.org/package/xmobar"> <img src="https://img.shields.io/hackage/v/xmobar.svg" alt="hackage"/> </a>- <a href="https://ci.codeberg.org/xmobar/xmobar">- <img src="https://ci.codeberg.org/api/badges/xmobar/xmobar/status.svg" alt="ci"/>- </a> </p> #+end_export @@ -203,6 +200,6 @@ This software is released under a BSD-style license. See [[https://codeberg.org/xmobar/xmobar/src/branch/master/license][license]] for more details. - Copyright © 2010-2024 Jose Antonio Ortega Ruiz+ Copyright © 2010-2025 Jose Antonio Ortega Ruiz Copyright © 2007-2010 Andrea Rossato
src/Xmobar.hs view
@@ -26,6 +26,8 @@ , SignalType (..) , module Xmobar.Config.Types , module Xmobar.Config.Parse+ , module Xmobar.Plugins.Accordion+ , module Xmobar.Plugins.ArchUpdates , module Xmobar.Plugins.BufferedPipeReader , module Xmobar.Plugins.CommandReader , module Xmobar.Plugins.Date@@ -53,6 +55,8 @@ import Xmobar.Run.Exec import Xmobar.Config.Types import Xmobar.Config.Parse+import Xmobar.Plugins.Accordion+import Xmobar.Plugins.ArchUpdates import Xmobar.Plugins.Command import Xmobar.Plugins.BufferedPipeReader import Xmobar.Plugins.CommandReader
src/Xmobar/App/Opts.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.App.Opts--- Copyright: (c) 2018, 2019, 2020, 2022, 2023, 2024 Jose Antonio Ortega Ruiz+-- Copyright: (c) 2018, 2019, 2020, 2022, 2023, 2024, 2025 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org@@ -116,7 +116,7 @@ info :: String info = "xmobar " ++ showVersion version- ++ "\n (C) 2010 - 2024 Jose A Ortega Ruiz"+ ++ "\n (C) 2010 - 2025 Jose A Ortega Ruiz" ++ "\n (C) 2007 - 2010 Andrea Rossato\n " ++ mail ++ "\n" ++ license ++ "\n"
+ src/Xmobar/Plugins/Accordion.hs view
@@ -0,0 +1,97 @@+{-# LANGUAGE TupleSections, FlexibleContexts #-}++-----------------------------------------------------------------------------+-- |+-- Module : Plugins.Monitors.Accordion+-- Copyright : (c) 2024 Enrico Maria De Angelis+-- License : BSD-style (see LICENSE)+--+-- Maintainer : Enrico Maria De Angelis <enricomaria.dean6elis@gmail.com>+-- Stability : unstable+-- Portability : unportable+--+-- A plugin to group adjacent plugins and make them, as a whole, shrinkable to+-- an alternate text upon clicking.+--+-----------------------------------------------------------------------------++module Xmobar.Plugins.Accordion (defaultTuning, makeAccordion, Tuning(..)) where++import Control.Concurrent.Async (withAsync)+import Control.Exception (finally)+import Control.Monad (forever, join, when)+import Control.Monad.IO.Class (liftIO)+import Control.Monad.Reader (runReaderT, ask)+import Control.Monad.State.Strict (evalStateT, get, modify')+import Data.IORef (atomicModifyIORef', newIORef, readIORef)+import Data.Maybe (isJust)+import System.Directory (removeFile)+import System.Exit (ExitCode(..))+import System.Process (readProcessWithExitCode)+import Xmobar.Run.Exec (Exec(..), tenthSeconds)++-- TODO: Ideally, I'd have just `Accordion`, and not `Tuning`, but since+-- `Accordion` is polymorphic, I can't have a `defaultAccordion` constructor+-- with `plugins = []`, because that leaves `a` undetermined.+-- So I have move all non-polymorphic typed members in `Tuning`, allowing for+-- default values at least for those members.+data Accordion a = Accordion {+ tuning :: Tuning+ , plugins :: [a]+} deriving (Show, Read)++makeAccordion :: Exec a => Tuning -> [a] -> Accordion a+makeAccordion t rs = Accordion { tuning = t, plugins = rs }++data Tuning = Tuning {+ alias' :: String+ , initial :: Bool+ , expand :: String+ , shrink :: String+} deriving (Read, Show)++defaultTuning :: Tuning+defaultTuning = Tuning {+ alias' = "accordion"+ , initial = True+ , expand = "<>"+ , shrink = "><"+}++instance (Exec a, Read a, Show a) => Exec (Accordion a) where+ alias (Accordion Tuning { alias' = name } _) = name+ start (Accordion Tuning { initial = initial'+ , expand = expand'+ , shrink = shrink' }+ runnables)+ cb = do+ clicked <- newIORef Nothing+ (_, n, _) <- readProcessWithExitCode "uuidgen" [] ""+ let pipe = "/tmp/accordion-" ++ removeLinebreak n+ (_, _, _) <- readProcessWithExitCode "mkfifo" [pipe] ""+ withAsync (forever $ do (ret, _, _) <- readProcessWithExitCode "cat" [pipe] ""+ case ret of+ ExitSuccess -> atomicModifyIORef' clicked (const (Just (), ()))+ ExitFailure _ -> error "how is this possible?")+ (const $ do+ srefs <- mapM (newIORef . const "") runnables+ foldr (\(runnable, sref) acc -> withAsync (start runnable (writeToRef sref)) (const acc))+ (forever (do liftIO (tenthSeconds 1)+ clicked' <- liftIO $ readIORef clicked+ when (isJust clicked')+ (do liftIO $ clear clicked+ modify' not)+ b <- get+ if b then loop pipe else liftIO $ cb (click pipe expand'))+ `runReaderT` srefs `evalStateT` initial')+ (zip runnables srefs))+ `finally` removeFile pipe+ where+ click file icon = "<action=`echo 1 > " ++ file ++ "`>" ++ icon ++ "</action>"+ clear = (`atomicModifyIORef'` const (Nothing, ()))+ removeLinebreak = init+ writeToRef strRef = atomicModifyIORef' strRef . const . (,())+ loop p = do+ srefs <- ask+ text <- join <$> mapM (liftIO . readIORef) srefs+ liftIO $ cb $ text ++ click p shrink'
+ src/Xmobar/Plugins/ArchUpdates.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE CPP #-}++-----------------------------------------------------------------------------+-- |+-- Module : Plugins.Monitors.ArchUpdates+-- Copyright : (c) 2024 Enrico Maria De Angelis+-- License : BSD-style (see LICENSE)+--+-- Maintainer : Enrico Maria De Angelis <enricomaria.dean6elis@gmail.com>+-- Stability : unstable+-- Portability : unportable+--+-- An ArchLinux updates availablility plugin for Xmobar+--+-----------------------------------------------------------------------------++module Xmobar.Plugins.ArchUpdates (ArchUpdates(..)) where++import System.Exit (ExitCode(..))+import System.Process (readProcessWithExitCode)+import Xmobar.Run.Exec+import Xmobar.Plugins.Command (Rate)++data ArchUpdates = ArchUpdates (String, String, String) Rate+ deriving (Read, Show)++instance Exec ArchUpdates where+ alias (ArchUpdates _ _) = "arch"+ rate (ArchUpdates _ r) = r+ run (ArchUpdates (z, o, m) _) = do+ (exit, stdout, _) <- readProcessWithExitCode "checkupdates" [] ""+ return $ case exit of+ ExitFailure 2 -> z--ero updates+ ExitFailure 1 -> "pacman: Unknown cause of failure."+ ExitSuccess -> case length $ lines stdout of+ 0 -> impossible+ 1 -> o+ n -> m >>= \c -> if c == '?' then show n else pure c+ _ -> impossible+ where+ impossible = error "This is impossible based on pacman manpage"
src/Xmobar/Plugins/MarqueePipeReader.hs view
@@ -60,7 +60,7 @@ Nothing -> tenthSeconds rate >> writer (drop 1 txt) sep len rate chan cb toInfTxt :: String -> String -> String-toInfTxt line sep = concat (repeat $ line ++ " " ++ sep ++ " ")+toInfTxt line sep = cycle (line ++ " " ++ sep ++ " ") checkPipe :: FilePath -> IO () checkPipe file = handle (\(SomeException _) -> waitForPipe) $ do
src/Xmobar/Plugins/Monitors/Mpris.hs view
@@ -28,7 +28,7 @@ import Control.Arrow ((***)) import Data.Maybe ( fromJust ) import Data.Int ( Int32, Int64 )-import Data.Word ( Word32 )+import Data.Word ( Word32, Word64 ) import System.IO.Unsafe ( unsafePerformIO ) import Control.Exception (try)@@ -136,17 +136,17 @@ "xesam:trackNumber" -> printf "%02d" num _ -> (show::Int32 -> String) num pw32 v = printf "%02d" (fromVar v::Word32)- plen str v = let num = fromVar v in- case str of+ plen str num = case str of "mpris:length" -> formatTime (num `div` 1000000)- _ -> (show::Int64 -> String) num+ _ -> show num getStr str = case lookup str md of Nothing -> "" Just v -> case variantType v of TypeString -> fromVar v TypeInt32 -> pInt str v TypeWord32 -> pw32 v- TypeInt64 -> plen str v+ TypeWord64 -> plen str (fromVar v :: Word64)+ TypeInt64 -> plen str (fromVar v :: Int64) TypeArray TypeString -> let x = arrayItems (fromVar v) in if null x then "" else fromVar (head x)
src/Xmobar/Plugins/Monitors/Top.hs view
@@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Plugins.Monitors.Top--- Copyright : (c) 2010, 2011, 2012, 2013, 2014, 2018, 2022 Jose A Ortega Ruiz+-- Copyright : (c) 2010-2014, 2018, 2022, 2025 Jose A Ortega Ruiz -- License : BSD-style (see LICENSE) -- -- Maintainer : Jose A Ortega Ruiz <jao@gnu.org>@@ -20,7 +20,7 @@ import Data.IORef (newIORef, readIORef, writeIORef) import Data.List (sortBy)-import Data.Ord (comparing)+import Data.Ord (comparing, Down (..)) import Data.Time.Clock (getCurrentTime, diffUTCTime) import Xmobar.Plugins.Monitors.Top.Common (@@ -66,7 +66,7 @@ sortTop :: [(String, Float)] -> [(String, Float)]-sortTop = sortBy (flip (comparing snd))+sortTop = sortBy (comparing (Down . snd)) showMemInfo :: Float -> MemInfo -> Monitor [String] showMemInfo scale (nm, rss) =
src/Xmobar/Plugins/Monitors/Weather.hs view
@@ -66,6 +66,7 @@ , "skyCondition" , "skyConditionS" , "weather"+ , "weatherS" , "tempC" , "tempF" , "dewPointC"@@ -221,23 +222,23 @@ errHandler :: CE.SomeException -> IO String errHandler _ = return "<Could not retrieve data>" -formatSk :: Eq p => [(p, p)] -> p -> p-formatSk ((a,b):sks) sk = if a == sk then b else formatSk sks sk-formatSk [] sk = sk- formatWeather :: WeatherOpts -- ^ Formatting options from the cfg file -> [(String,String)] -- ^ 'SkyConditionS' for 'WeatherX' -> [WeatherInfo] -- ^ The actual weather info -> Monitor String-formatWeather opts sks [WI st ss y m d h (WindInfo wc wa wm wk wkh wms) v sk we tC tF dC dF r p] =- do cel <- showWithColors show tC+formatWeather opts sks [WI st ss y m d h wind v sk we tC tF dC dF r p] =+ do let WindInfo wc wa wm wk wkh wms = wind+ cel <- showWithColors show tC far <- showWithColors show tF- let sk' = formatSk sks (map toLower sk)- we' = showWeather (weatherString opts) we+ let we' = showWeather (weatherString opts) we+ sk' = findSk sks (map toLower sk) we'+ we'' = findSk sks (map toLower we') sk' parseTemplate [st, ss, y, m, d, h, wc, wa, wm, wk, wkh- , wms, v, sk, sk', we', cel, far+ , wms, v, sk, sk', we', we'', cel, far , show dC, show dF, show r , show p ]+ where findSk ((a,b):xs) x df = if a == x then b else findSk xs x df+ findSk [] _ df = df formatWeather _ _ _ = getConfigValue naString -- | Show the 'weather' field with a default string in case it was empty.
src/Xmobar/Run/Types.hs view
@@ -19,6 +19,7 @@ module Xmobar.Run.Types(runnableTypes) where import {-# SOURCE #-} Xmobar.Run.Runnable()+import Xmobar.Plugins.ArchUpdates import Xmobar.Plugins.Command import Xmobar.Plugins.Monitors import Xmobar.Plugins.Date@@ -59,6 +60,7 @@ runnableTypes :: Command :*: Monitors :*: Date :*: PipeReader :*: BufferedPipeReader :*: CommandReader :*: StdinReader :*: XMonadLog :*: EWMH :*: Kbd :*: Locks :*: NotmuchMail :*:+ ArchUpdates :*: #ifdef INOTIFY Mail :*: MBox :*: #endif
src/Xmobar/X11/Loop.hs view
@@ -170,7 +170,7 @@ runActions :: D.Actions -> A.Button -> X11.Position -> IO () runActions actions button pos = mapM_ A.runAction $- filter (\(A.Spawn b _) -> button `elem` b) $- concatMap (\(a,_,_) -> a) $- filter (\(_, from, to) -> pos' >= from && pos' <= to) actions+ concatMap+ (filter (\ (A.Spawn b _) -> button `elem` b) . (\ (a, _, _) -> a))+ (filter (\ (_, from, to) -> pos' >= from && pos' <= to) actions) where pos' = fromIntegral pos
xmobar.cabal view
@@ -1,5 +1,5 @@ name: xmobar-version: 0.48.1+version: 0.49 homepage: https://codeberg.org/xmobar/xmobar synopsis: A Minimalistic Text Based Status Bar description: Xmobar is a minimalistic text based status bar.@@ -105,6 +105,7 @@ hs-source-dirs: src exposed-modules: Xmobar,+ Xmobar.Plugins.Accordion, Xmobar.Plugins.Monitors.Common.Types, Xmobar.Plugins.Monitors.Common.Run, Xmobar.Plugins.Monitors.Common,@@ -149,6 +150,7 @@ Xmobar.X11.Text, Xmobar.X11.Types, Xmobar.X11.Window,+ Xmobar.Plugins.ArchUpdates, Xmobar.Plugins.Command, Xmobar.Plugins.BufferedPipeReader, Xmobar.Plugins.CommandReader,@@ -198,7 +200,7 @@ build-depends: aeson >= 1.4.7.1, async,- base >= 4.11.0 && < 4.20,+ base >= 4.11.0 && < 4.21, bytestring >= 0.10.8.2, cairo >= 0.13, colour >= 2.3.6,