diff options
34 files changed, 962 insertions, 589 deletions
diff --git a/.woodpecker.yml b/.woodpecker.yml deleted file mode 100644 index f8aeae3..0000000 --- a/.woodpecker.yml +++ /dev/null @@ -1,20 +0,0 @@ -matrix: - GHC_VERSION: - - 9.6 - - 9.4 - - 8 - -steps: - test: - image: haskell:${GHC_VERSION} - commands: - - apt-get update - - apt-get install -y xorg-dev libxrandr-dev libpango1.0-dev - - apt-get install -y libasound2-dev libxpm-dev libmpd-dev - - apt-get install -y hspec-discover hlint - - - hlint src - - - cabal update - - cabal test --enable-tests -fall_extensions - - cabal test --enable-tests -fall_extensions -f-with_xrender diff --git a/.woodpecker/build.yaml b/.woodpecker/build.yaml new file mode 100644 index 0000000..ef33379 --- /dev/null +++ b/.woodpecker/build.yaml @@ -0,0 +1,32 @@ +when: + - event: [push, pull_request, manual] + +matrix: + GHC: + # - '9.14' currently broken due to: https://github.com/gtk2hs/gtk2hs/issues/348 + # - '9.12' currently broken due to: https://github.com/gtk2hs/gtk2hs/issues/348 + - '9.10' + - '9.8' + - '9.6' + +steps: + - name: hlint + image: haskell:${GHC} + commands: + - apt-get update && apt-get install -y hlint + - hlint src + + - name: build-and-test + image: haskell:${GHC} + commands: + - apt-get update + - >- + apt-get install -y + xorg-dev libxrandr-dev libpango1.0-dev + libasound2-dev libxpm-dev libmpd-dev + hspec-discover + - cabal update + - cabal build all --only-dependencies --enable-tests -fall_extensions --disable-documentation + - cabal build all --enable-tests -fall_extensions --disable-documentation + - cabal test all --enable-tests -fall_extensions --disable-documentation + - cabal test all --enable-tests -fall_extensions -f-with_xrender --disable-documentation diff --git a/changelog.md b/changelog.md index 2e82e6e..404d59f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,7 +1,33 @@ -## Version 0.49 (unreleased) +## Version 0.51.1 (June, 2026) + +- Missing upper bounds for dependencies + +## Version 0.51 (June, 2026) + +- Improvements for `PacmanUpdates` (thanks, Enrico Maria and Alexander) +- Fixes and improvements to `Accordion` (thanks, Enrico Maria) +- Fixes to `Batt` (thanks, Leana) +- Fix BadDrawable crash when wallpaper setters free the root pixmap while + alpha is 255 (thanks, Ashesh) +- base dependency relaxed to 4.21 + +## Version 0.50 (June, 2025) + +- New plugins: `PacmanUpdates` (thanks, Alexander) +- `ArchUpdates` deprecated in favor of `PacmanUpdates` + - a deprecation notice will be shown to users of that plugin in the bar in + the zero updates case +- `Accordion`: new constructor to allow short version to have plugins too +- `Swap`: update for FreeBSD 15 +- `MPD` compiled again by default with `all_extensions`. + +## 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) diff --git a/doc/plugins.org b/doc/plugins.org index 21a9452..ecc9507 100644 --- a/doc/plugins.org +++ b/doc/plugins.org @@ -306,8 +306,8 @@ "--", "-O", "<fc=green>On</fc> - ", "-i", "", "-L", "-15", "-H", "-5", "-l", "red", "-m", "blue", "-h", "green", - "-a", "notify-send -u critical 'Battery running out!!'", - "-A", "3"] + "-a", "notify-once \"xmobar\" -u critical 'Battery running out!!' \"$XMOBAR_BATT_LEFT% Remains\"", + "-A", "6"] 600 #+end_src @@ -316,7 +316,22 @@ separator affect how =<watts>= is displayed. For this monitor, neither the generic nor the specific options have any effect on =<timeleft>=. We are also telling the monitor to execute the unix command - =notify-send= when the percentage left in the battery reaches 6%. + =notify-once= when the percentage left in the battery reaches 6%. + + =XMOBAR_BATT_LEFT= environment variable is made available to the program being called. + You can use it to make the alert message more informative. It is an integer between 0 and 100. + + =notify-once= is a bash wrapper script provided with the =xmobar= package. + =xmobar= will run the notification command according to the refresh period, + this has the effect of spamming the notification tray if calling =notify-send= directly. + =notify-once= script deduplicates the notification by indicating to =notify-send= + the last notification we want to replace. + See [[https://codeberg.org/xmobar/xmobar/issues/746][#746]] for more information. + Note that your notification daemon should handle notification replacement + for this to work. Whether the replacement resets the timeout is also handled by the + notification daemon. + For example, the =wired-notify= implementation has =replacing_enabled= + and =replacing_resets_timeout= configuration options [[https://github.com/Toqozz/wired-notify/wiki/Config]]. It is also possible to specify template variables in the =-O= and =-o= switches, as in the following example: @@ -1077,8 +1092,8 @@ ** Music monitors *** =MPD Args RefreshRate= - - This monitor will only be compiled if you ask for it using the - =with_mpd= flag. It needs [[http://hackage.haskell.org/package/libmpd/][libmpd]] 5.0 or later (available on Hackage). + - This monitor will only be compiled if you ask for it using the =with_mpd= + flag. It needs [[http://hackage.haskell.org/package/libmpd/][libmpd]] 0.10.1 or later (available on Hackage). - Aliases to =mpd= @@ -1353,21 +1368,99 @@ the display of those numeric fields. - Default template: =Up: <days>d <hours>h <minutes>m= -*** =ArchUpdates (Zero, One, Many) Rate= +*** =PacmanUpdates (Zero, One, Many, Error) Rate= - - Aliases to =arch= + - *This constructor is deprecated. Use =PacmanUpdatesK=, =PacmanUpdatesPredicateK=, or =PacmanUpdatesNoK= instead.* + - Aliases to =pacman= - =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 + - =Many=: a =String= to use when several updates are available; it can contain a =?= character as a placeholder for the number of updates. + - =Error=: a =String= to use when pacman fails for unkown reasons (e.g. + network error) - Example: #+begin_src haskell - ArchUpdates ("<fc=green>up to date</fc>", - "<fc=yellow>1 update</fc>, - "<fc=red>? updates</fc>") + PacmanUpdates ("<fc=green>up to date</fc>", + "<fc=yellow>1 update</fc>, + "<fc=red>? updates</fc>", + "<fc=red>!Pacman Error!</fc>") 600 #+end_src +*** =PacmanUpdatesK Rate KernName (Bool -> Either String (Int, Bool) -> String)= + + - Aliases to =pacman= + - =KernName=: a =String= containing the name of the kernel package, e.g. `linux`, `linux-lts`, … + - =(Bool -> Either String (Int, Bool) -> String)=: a function producing the + string to be shown by the plugin; it is fed with a `Bool` telling whether + the running kernel is older than the installed kernel, and an `Int` and + `Bool` telling the number of available updates and whether one of them is a + kernel update (or an error message if `checkupdates` fails). + - Example: + #+begin_src haskell + PacmanUpdatesK + 600 + "linux" + $ \oldKern mayb -> (if oldKern then "Running old kernel!" else "") ++ + case mayb of + Left _ -> "Some error occurred!" + Right (0, False) -> "Up to date" + Right (n, pendingK) | n >= 1 -> show n ++ " updates available" + ++ if pendingK then " including a kernel update" else "" + _ -> error "This is impossible" + #+end_src + +*** =PacmanUpdatesPredicateK Rate IsKernelUpdate (Bool -> Either String (Int, Bool) -> String)= + + - Aliases to =pacman= + - =IsKernelUpdate=: a =String -> Bool= predicate that receives each available + package name and returns =True= for kernel packages. This is useful for + distributions with versioned kernel package names, such as Manjaro's + =linux618= or =linux70= packages. + - =(Bool -> Either String (Int, Bool) -> String)=: a function producing the + string to be shown by the plugin; it is fed with a =Bool= telling whether + the running kernel is older than the installed kernel, and an =Int= and + =Bool= telling the number of available updates and whether one of them + matches the kernel predicate (or an error message if =checkupdates= fails). + - Example: + This example requires =import Data.Char (isDigit)= and + =import Data.List (stripPrefix)= in your configuration. + #+begin_src haskell + PacmanUpdatesPredicateK + 600 + ( \packageName -> + case stripPrefix "linux" packageName of + Just n -> not (null n) && all isDigit n + Nothing -> False + ) + $ \oldKern mayb -> (if oldKern then "Running old kernel!" else "") ++ + case mayb of + Left _ -> "Some error occurred!" + Right (0, False) -> "Up to date" + Right (n, pendingK) | n >= 1 -> show n ++ " updates available" + ++ if pendingK then " including a kernel update" else "" + _ -> error "This is impossible" + #+end_src + +*** =PacmanUpdatesNoK Rate (Bool -> Either String Int -> String)= + + - Aliases to =pacman= + - =(Bool -> Either String Int -> String)=: a function producing the + string to be shown by the plugin; it is fed with a `Bool` telling whether + the running kernel is older than the installed kernel, and an `Int` telling + the number of available updates (or an error message if `checkupdates` fails). + - Example: + #+begin_src haskell + PacmanUpdatesNoK + 600 + $ \oldKern mayb -> (if oldKern then "Running old kernel!" else "") ++ + case mayb of + Left _ -> "Some error occurred!" + Right 0 -> "" + Right n | n >= 1 -> show n ++ " updates available" + _ -> error "impossible" + #+end_src + *** =makeAccordion Tuning [Runnable]= - Wraps other =Runnable= plugins and makes them all collapsible to a single string: @@ -1390,6 +1483,11 @@ - =initial=: =Bool= to tell whether the accordion is initially expanded (defaults to =True=). - =[Runnable]=: a list of =Runnable= plugins +*** =makeAccordion' Tuning [Runnable] [Runnable]= + + - Like =makeAccordion=, but it accepts two distinct lists of runnables to be shown in the two states. + - One possible usage is to have a long-vs-short rather than an expanded-vs-collapsed policy, but it's up to you. + * Interfacing with window managers :PROPERTIES: :CUSTOM_ID: interfacing-with-window-managers diff --git a/etc/notify-once.sh b/etc/notify-once.sh new file mode 100644 index 0000000..1c46401 --- /dev/null +++ b/etc/notify-once.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -euo pipefail + +help() { + echo "notify-send: send deduplicated notifications" + echo "Usage: notify-once <name> [ARGS]" + echo " ARGS are arguments passed directly to notify-send" +} + +if [ $# -lt 1 ]; then + echo "Should get at least one argument, a name" >&2 + help + exit 1 +fi +APPNAME="$1" +shift + +ID_PATH="/tmp/notify-state-$APPNAME" + +if [ -e "$ID_PATH" ]; then + # Exists, replace + ID=$(cat "$ID_PATH") + ID=$(notify-send -r "$ID" -p "$@") +else + # Doesn't exist, create + ID=$(notify-send -p "$@") +fi + +# Store new ID +echo "$ID" >"$ID_PATH" diff --git a/nix/flake.lock b/nix/flake.lock index 3f272ee..c4d98f4 100644 --- a/nix/flake.lock +++ b/nix/flake.lock @@ -53,11 +53,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1728018373, - "narHash": "sha256-NOiTvBbRLIOe5F6RbHaAh6++BNjsb149fGZd1T4+KBg=", + "lastModified": 1781074563, + "narHash": "sha256-md8WlXOlfnIeHeOScMTTHFyf2d6iaTwPl2apR5EQ3P4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bc947f541ae55e999ffdb4013441347d83b00feb", + "rev": "9ae611a455b90cf061d8f332b977e387bda8e1ca", "type": "github" }, "original": { diff --git a/nix/flake.nix b/nix/flake.nix index b422c9a..2c0dbfb 100644 --- a/nix/flake.nix +++ b/nix/flake.nix @@ -17,7 +17,7 @@ overrides = prev.lib.composeExtensions (old.overrides or (_: _: { })) ( hself: hsuper: { xmobar = prev.haskell.lib.compose.dontCheck ( - hself.callCabal2nix "xmobar" (git-ignore-nix.lib.gitignoreSource ./.) { } + hself.callCabal2nix "xmobar" (git-ignore-nix.lib.gitignoreSource ../.) { } ); } ); @@ -32,15 +32,15 @@ let pkgs = import nixpkgs { inherit system overlays; }; dynamicLibraries = with pkgs; [ - xorg.libX11 - xorg.libXrandr - xorg.libXrender - xorg.libXScrnSaver - xorg.libXext - xorg.libXft - xorg.libXpm.out - xorg.libXrandr - xorg.libXrender + libX11 + libXrandr + libXrender + libXScrnSaver + libXext + libXft + libXpm.out + libXrandr + libXrender ]; in { diff --git a/nix/readme.org b/nix/readme.org index d83d232..6a492e5 100644 --- a/nix/readme.org +++ b/nix/readme.org @@ -29,7 +29,7 @@ Here is how to set it up: home.stateversion = "24.05"; imports = [ - inputs.nixmobar.homemodules.mainmodule + inputs.nixmobar.homeModules.mainmodule # Other imports go here. ]; @@ -67,7 +67,7 @@ Here is how to set it up: Run MultiCoreTemp ["-t", "<fc=#bd93f9><fn=1>\xf2c9</fn></fc><avg>°", "-L", "60", "-H", "95", "-l", "white", "-n", "white", "-h", "red"] 50, Run CatInt 0 "/sys/class/hwmon/hwmon4/fan1_input" [] 50, Run MultiCpu ["-t", "<fc=#bd93f9><fn=1>\xf4bc</fn></fc> <vbar0><vbar1><vbar2><vbar3><vbar4><vbar5><vbar6><vbar7>", "-w", "99", "-L", "3", "-H", "50", "--normal", "green", "--high", "red"] 10, - Run BatteryP ["BAT0"] ["-t", "<fc=#bd93f9><fn=1></fn></fc><left>%", "-L", "10", "-H", "80", "-p", "3", "--", "-O", "<fc=green>On</fc> - ", "-i", "", "-L", "-15", "-H", "-5", "-l", "red", "-m", "blue", "-h", "green", "-a", "notify-send -u critical 'Battery running out!!'", "-A", "3"] 600, + Run BatteryP ["BAT0"] ["-t", "<fc=#bd93f9><fn=1></fn></fc><left>%", "-L", "10", "-H", "80", "-p", "3", "--", "-O", "<fc=green>On</fc> - ", "-i", "", "-L", "-15", "-H", "-5", "-l", "red", "-m", "blue", "-h", "green", "-a", "notify-once \"xmobar\" -u critical 'Battery running out!!'", "-A", "3"] 600, Run Alsa "default" "Master" ["-t", "<fc=#bd93f9><fn=1>\xf028</fn></fc> <volume>%"], Run Date "%a %_d %b %H:%M:%S" "date" 10, Run Load ["-t", "<fc=#bd93f9><fn=0>L</fn></fc><load1>", "-L", "1", "-H", "3", "-d", "2"] 300, @@ -5,8 +5,8 @@ <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 href="https://ci.codeberg.org/repos/17487" target="_blank"> + <img src="https://ci.codeberg.org/api/badges/17487/status.svg" alt="status-badge" /> </a> </p> #+end_export @@ -31,13 +31,11 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. * Breaking news - - Starting with version 0.47.1, we are excluding MPD from the extensions - included with ~all_extensions~ when GHC version is 9.4 or greater, because - that seems to break cabal compilation. However, it's been reported that - in some installations compilation with ~libmpd~ works fine: just add - explicitly the ~with_mpd~ flag to include MPD and check for yourself. - Compilation with stack has also been reported to work. Please see the - comments in issue #679 for details. + - Starting with version 0.51, we introduced a new GHC support policy: xmobar + officially supports only the GHC versions that upstream marks as /suitable + for use/ in the [[https://gitlab.haskell.org/ghc/ghc/-/wikis/GHC-status][official GHC status overview]]. + At the time of writing, this means GHC versions from 9.6 to 9.14. + - Starting with version 0.45, we use cairo/pango as our drawing engine (instead of plain X11/Xft). From a user's point of view, that change should be mostly transparent, except for the facts that it's allowed @@ -102,9 +100,6 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. cabal install xmobar -fall_extensions #+end_src - Starting with version 0.35.1, xmobar requires at least GHC version - 8.4.x. to build. See [[https://codeberg.org/xmobar/xmobar/issues/461][this issue]] for more information. - See [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/compiling.org#optional-features][here]] for a list of optional compilation flags that will enable some optional plugins. @@ -173,24 +168,24 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. the greater xmobar and Haskell communities. In particular, xmobar incorporates patches by Kostas Agnantis, Mohammed - Alshiekh, Alex Ameen, Axel Angel, Enrico Maria De Angelis, Dhananjay Balan, + Alshiekh, Ashesh Ambasta, Alex Ameen, Axel Angel, Enrico Maria De Angelis, 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, Jonathan Grochowski, Patrick Günther, Reto Hablützel, Corey Halpin, Juraj Hercek, Jaroslaw Jantura, Tomáš Janoušek, Ada - Joule, Spencer Janssen, Roman Joost, Pavel Kalugin, Jochen Keil, Sam Kirby, + Joule, Spencer Janssen, Léana 江, 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, Ulrik de Muelenaere, 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. + Mrak, Thiago Negri, Edward O'Callaghan, Svein Ove, Martin Perner, Alexander + Pankoff, 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 @@ -198,11 +193,20 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. existential types (or at least for letting him think he grasps existential types...;-). +* Contributing +** Generative AI (LLMs) + +Use of generative AI (LLMs, diffusion models and similar technology) is not +acceptable for contributions to or interactions with the xmobar project. + +This includes words, images and code, as well as bug reports, commit +messages, email (mailing list or private) and IRC messages. + * License 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-2026 Jose Antonio Ortega Ruiz Copyright © 2007-2010 Andrea Rossato diff --git a/src/Xmobar.hs b/src/Xmobar.hs index 5aa748a..5a31d80 100644 --- a/src/Xmobar.hs +++ b/src/Xmobar.hs @@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Xmobar --- Copyright : (c) 2011, 2012, 2013, 2014, 2015, 2017, 2018, 2019, 2022 Jose Antonio Ortega Ruiz +-- Copyright : (c) 2011-2015, 2017-2019, 2022, 2025 Jose Antonio Ortega Ruiz -- (c) 2007 Andrea Rossato -- License : BSD-style (see LICENSE) -- @@ -19,15 +19,13 @@ module Xmobar (xmobar , xmobarMain , defaultConfig , configFromArgs - , tenthSeconds , Runnable (..) - , Exec (..) , Command (..) , SignalType (..) + , module Xmobar.Run.Exec , 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 @@ -45,6 +43,7 @@ module Xmobar (xmobar #endif , module Xmobar.Plugins.NotmuchMail , module Xmobar.Plugins.Monitors + , module Xmobar.Plugins.PacmanUpdates , module Xmobar.Plugins.PipeReader , module Xmobar.Plugins.MarqueePipeReader , module Xmobar.Plugins.StdinReader @@ -56,7 +55,6 @@ 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 @@ -74,6 +72,7 @@ import Xmobar.Plugins.Mail import Xmobar.Plugins.MBox #endif import Xmobar.Plugins.Monitors +import Xmobar.Plugins.PacmanUpdates import Xmobar.Plugins.PipeReader import Xmobar.Plugins.StdinReader import Xmobar.Plugins.MarqueePipeReader diff --git a/src/Xmobar/App/Compile.hs b/src/Xmobar/App/Compile.hs index 5d1f48d..e5b08b7 100644 --- a/src/Xmobar/App/Compile.hs +++ b/src/Xmobar/App/Compile.hs @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.App.Compile --- Copyright: (c) 2018 Jose Antonio Ortega Ruiz +-- Copyright: (c) 2018, 2026 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org @@ -20,8 +20,8 @@ module Xmobar.App.Compile(recompile, trace, xmessage) where import Control.Monad.IO.Class -import Control.Exception.Extensible (bracket, SomeException(..)) -import qualified Control.Exception.Extensible as E +import Control.Exception (SomeException(..)) +import qualified Control.Exception as E import Control.Monad (filterM, when) import Data.List ((\\)) import System.FilePath((</>), takeExtension) @@ -141,7 +141,7 @@ recompile confDir dataDir execName force verb = liftIO $ do else shouldRecompile verb src bin lib if sc then do - status <- bracket (openFile err WriteMode) hClose $ + status <- withFile err WriteMode $ \errHandle -> waitForProcess =<< if useScript diff --git a/src/Xmobar/App/Opts.hs b/src/Xmobar/App/Opts.hs index 36da745..5196b3c 100644 --- a/src/Xmobar/App/Opts.hs +++ b/src/Xmobar/App/Opts.hs @@ -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-2026 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org @@ -61,7 +61,7 @@ options = , Option "v" ["verbose"] (NoArg Verbose) "Emit verbose debugging messages" , Option "r" ["recompile"] (NoArg Recompile) "Force recompilation" , Option "V" ["version"] (NoArg Version) "Show version information" - , Option "T" ["text"] (OptArg TextOutput "color") + , Option "T" ["text"] (OptArg TextOutput "format") "Write text-only output to stdout. Plain/Ansi/Pango/Swaybar" , Option "f" ["font"] (ReqArg Font "font name") "Font name" , Option "N" ["add-font"] (ReqArg AddFont "font name") @@ -116,7 +116,7 @@ usage = usageInfo header options ++ footer info :: String info = "xmobar " ++ showVersion version - ++ "\n (C) 2010 - 2024 Jose A Ortega Ruiz" + ++ "\n (C) 2010 - 2026 Jose A Ortega Ruiz" ++ "\n (C) 2007 - 2010 Andrea Rossato\n " ++ mail ++ "\n" ++ license ++ "\n" diff --git a/src/Xmobar/Plugins/Accordion.hs b/src/Xmobar/Plugins/Accordion.hs index 6377928..ce15cee 100644 --- a/src/Xmobar/Plugins/Accordion.hs +++ b/src/Xmobar/Plugins/Accordion.hs @@ -1,4 +1,5 @@ {-# LANGUAGE TupleSections, FlexibleContexts #-} +{-# LANGUAGE RecordWildCards #-} ----------------------------------------------------------------------------- -- | @@ -15,18 +16,19 @@ -- ----------------------------------------------------------------------------- -module Xmobar.Plugins.Accordion (defaultTuning, makeAccordion, Tuning(..)) where +module Xmobar.Plugins.Accordion (defaultTuning, makeAccordion, makeAccordion', Tuning(..)) where -import Control.Concurrent.Async (withAsync) +import Control.Concurrent.Async (concurrently_, mapConcurrently_) 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 Control.Monad.Extra (whenM) +import Control.Monad (forever, join) +import Control.Monad.IO.Class (liftIO, MonadIO) +import Control.Monad.Reader (MonadReader, runReaderT, ask) +import Control.Monad.State.Strict (MonadState, evalStateT, get, modify') +import Data.IORef (atomicModifyIORef', newIORef, readIORef, IORef) +import GHC.IO.Handle.FD (withFileBlocking) import System.Directory (removeFile) -import System.Exit (ExitCode(..)) +import System.IO (IOMode(ReadMode), hGetContents') import System.Process (readProcessWithExitCode) import Xmobar.Run.Exec (Exec(..), tenthSeconds) @@ -38,10 +40,14 @@ import Xmobar.Run.Exec (Exec(..), tenthSeconds) data Accordion a = Accordion { tuning :: Tuning , plugins :: [a] + , shortPlugins :: [a] } deriving (Show, Read) makeAccordion :: Exec a => Tuning -> [a] -> Accordion a -makeAccordion t rs = Accordion { tuning = t, plugins = rs } +makeAccordion t rs = Accordion { tuning = t, plugins = rs, shortPlugins = [] } + +makeAccordion' :: Exec a => Tuning -> [a] -> [a] -> Accordion a +makeAccordion' t rs rs' = Accordion { tuning = t, plugins = rs, shortPlugins = rs' } data Tuning = Tuning { alias' :: String @@ -58,40 +64,49 @@ defaultTuning = Tuning { , 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 +instance Exec a => Exec (Accordion a) where + alias (Accordion Tuning{..} _ _) = alias' + start (Accordion Tuning{..} runnables shortRunnables) cb = do + clicked <- newIORef False (_, 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)) + concurrently_ (forever $ do "" <- withFileBlocking pipe ReadMode hGetContents' + atomicModifyIORef' clicked (const (True, ()))) + (do + strRefs <- mapM (newIORef . const "") runnables + strRefs' <- mapM (newIORef . const "") shortRunnables + let processClick = forever (do liftIO (tenthSeconds 1) + whenM (liftIO $ readIORef clicked) + (do liftIO $ clear clicked + modify' not) + get >>= loop pipe) + `runReaderT` (strRefs, strRefs') + `evalStateT` initial + let startRunnables = zipWith start + (runnables ++ shortRunnables) + (map writeToRef $ strRefs ++ strRefs') + parallel_ $ processClick:startRunnables) `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' + loop :: (MonadIO m, + MonadState Bool m, + MonadReader ([IORef String], [IORef String]) m) + => String -> Bool -> m () + loop pipe bool = do + (strRefs, strRefs') <- ask + text <- join <$> mapM (liftIO . readIORef) (if bool then strRefs else strRefs') + liftIO $ cb $ text ++ attachClick pipe (if bool then shrink else expand) + parallel_ = mapConcurrently_ id + +writeToRef :: IORef a -> a -> IO () +writeToRef strRef = atomicModifyIORef' strRef . const . (,()) + +clear :: IORef Bool -> IO () +clear = (`atomicModifyIORef'` const (False, ())) + +removeLinebreak :: [a] -> [a] +removeLinebreak = init + +attachClick :: String -> String -> String +attachClick file icon = "<action=`echo -n > " ++ file ++ "`>" ++ icon ++ "</action>" diff --git a/src/Xmobar/Plugins/ArchUpdates.hs b/src/Xmobar/Plugins/ArchUpdates.hs deleted file mode 100644 index f803d0f..0000000 --- a/src/Xmobar/Plugins/ArchUpdates.hs +++ /dev/null @@ -1,41 +0,0 @@ -{-# 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" diff --git a/src/Xmobar/Plugins/EWMH.hs b/src/Xmobar/Plugins/EWMH.hs index 78f1cc0..9b583ea 100644 --- a/src/Xmobar/Plugins/EWMH.hs +++ b/src/Xmobar/Plugins/EWMH.hs @@ -232,7 +232,7 @@ updateClientList _ = do where unmanage w = asks display >>= \d -> liftIO $ selectInput d w 0 listen w = asks display >>= \d -> liftIO $ selectInput d w propertyChangeMask - update w = mapM_ (($ w) . snd) clientHandlers + update w = mapM_ (`snd` w) clientHandlers modifyClient :: Window -> (Client -> Client) -> M () modifyClient w f = modify (\s -> s { clients = Map.alter f' w $ clients s }) diff --git a/src/Xmobar/Plugins/MarqueePipeReader.hs b/src/Xmobar/Plugins/MarqueePipeReader.hs index 075503c..a6d590e 100644 --- a/src/Xmobar/Plugins/MarqueePipeReader.hs +++ b/src/Xmobar/Plugins/MarqueePipeReader.hs @@ -60,7 +60,7 @@ writer txt sep len rate chan cb = do 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 diff --git a/src/Xmobar/Plugins/Monitors/Batt/Common.hs b/src/Xmobar/Plugins/Monitors/Batt/Common.hs index ddb2b8c..31caabc 100644 --- a/src/Xmobar/Plugins/Monitors/Batt/Common.hs +++ b/src/Xmobar/Plugins/Monitors/Batt/Common.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE TypeApplications #-} ----------------------------------------------------------------------------- -- | -- Module : Plugins.Monitors.Batt.Common @@ -18,7 +19,8 @@ module Xmobar.Plugins.Monitors.Batt.Common (BattOpts(..) , Status(..) , maybeAlert) where -import System.Process (spawnCommand, waitForProcess) +import System.Environment +import System.Process (waitForProcess, withCreateProcess, shell, CreateProcess(env)) import Control.Monad (unless, void) import Xmobar.Plugins.Monitors.Common @@ -54,4 +56,11 @@ maybeAlert opts left = case onLowAction opts of Nothing -> return () Just x -> unless (isNaN left || actionThreshold opts < 100 * left) - $ void $ spawnCommand (x ++ " &") >>= waitForProcess + $ runCmd =<< mkShellCmd x + where + mkShellCmd command = do + selfEnv <- getEnvironment + pure (shell command) { env = Just $ ("XMOBAR_BATT_LEFT", show @Int $ round $ 100 * left) : selfEnv + } + runCmd c = withCreateProcess c $ \_ _ _ ph -> + void $ waitForProcess ph diff --git a/src/Xmobar/Plugins/Monitors/Batt/Linux.hs b/src/Xmobar/Plugins/Monitors/Batt/Linux.hs index 5389be0..d95b902 100644 --- a/src/Xmobar/Plugins/Monitors/Batt/Linux.hs +++ b/src/Xmobar/Plugins/Monitors/Batt/Linux.hs @@ -199,5 +199,5 @@ readBatteries opts bfs = | time == 0 = Idle | ac = Charging | otherwise = Discharging - unless ac (maybeAlert opts left) + unless (racst == Charging || racst == Idle) $ maybeAlert opts left return $ if isNaN left then NA else Result left watts time racst diff --git a/src/Xmobar/Plugins/Monitors/Bright.hs b/src/Xmobar/Plugins/Monitors/Bright.hs index 12790e1..9c61fb2 100644 --- a/src/Xmobar/Plugins/Monitors/Bright.hs +++ b/src/Xmobar/Plugins/Monitors/Bright.hs @@ -54,11 +54,12 @@ data Files = Files { fCurr :: String , fMax :: String } | NoFiles + deriving Show brightFiles :: BrightOpts -> IO Files brightFiles opts = do is_curr <- fileExist $ fCurr files - is_max <- fileExist $ fCurr files + is_max <- fileExist $ fMax files return (if is_curr && is_max then files else NoFiles) where prefix = sysDir </> subDir opts files = Files { fCurr = prefix </> currBright opts diff --git a/src/Xmobar/Plugins/Monitors/Disk/FreeBSD.hsc b/src/Xmobar/Plugins/Monitors/Disk/FreeBSD.hsc index 296ba6c..b5530f1 100644 --- a/src/Xmobar/Plugins/Monitors/Disk/FreeBSD.hsc +++ b/src/Xmobar/Plugins/Monitors/Disk/FreeBSD.hsc @@ -39,7 +39,7 @@ import Xmobar.Plugins.Monitors.Disk.Common ( , Path ) -import qualified Control.Exception.Extensible as E +import qualified Control.Exception as E import qualified Data.List as DL import qualified Data.Map as DM import qualified Data.Set as DS diff --git a/src/Xmobar/Plugins/Monitors/MPD.hs b/src/Xmobar/Plugins/Monitors/MPD.hs index 7ecbc0c..b091147 100644 --- a/src/Xmobar/Plugins/Monitors/MPD.hs +++ b/src/Xmobar/Plugins/Monitors/MPD.hs @@ -109,8 +109,9 @@ parseMPD (Right st) song opts = do si = stateGlyph s opts vol = int2str $ fromMaybe 0 (M.stVolume st) (p, t) = fromMaybe (0, 0) (M.stTime st) - [lap, len, remain] = map showTime - [floor p, floor t, max 0 (floor t - floor p)] + lap = showTime $ floor p + len = showTime $ floor t + remain = showTime $ max 0 (floor t - floor p) b = if t > 0 then realToFrac $ p / t else 0 plen = int2str $ M.stPlaylistLength st ppos = maybe "" (int2str . (+1)) $ M.stSongPos st diff --git a/src/Xmobar/Plugins/Monitors/Mpris.hs b/src/Xmobar/Plugins/Monitors/Mpris.hs index ee30ad3..eb9595b 100644 --- a/src/Xmobar/Plugins/Monitors/Mpris.hs +++ b/src/Xmobar/Plugins/Monitors/Mpris.hs @@ -28,7 +28,7 @@ import qualified DBus.Client as DC 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 @@ makeList version md = map getStr (fieldsList version) where "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) diff --git a/src/Xmobar/Plugins/Monitors/Swap/FreeBSD.hsc b/src/Xmobar/Plugins/Monitors/Swap/FreeBSD.hsc index 9c74e36..90c58c1 100644 --- a/src/Xmobar/Plugins/Monitors/Swap/FreeBSD.hsc +++ b/src/Xmobar/Plugins/Monitors/Swap/FreeBSD.hsc @@ -71,11 +71,10 @@ instance Storable SwapData where poke _ _ = pure () - isEnabled :: IO Bool isEnabled = do - enabled <- sysctlReadUInt "vm.swap_enabled" - return $ enabled == 1 + nswapdev <- sysctlReadUInt "vm.nswapdev" + return $ nswapdev > 0 parseMEM' :: Bool -> IO [Float] parseMEM' False = return [] diff --git a/src/Xmobar/Plugins/Monitors/Top.hs b/src/Xmobar/Plugins/Monitors/Top.hs index 3bfe6fd..b2e573b 100644 --- a/src/Xmobar/Plugins/Monitors/Top.hs +++ b/src/Xmobar/Plugins/Monitors/Top.hs @@ -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 Xmobar.Plugins.Monitors.Common 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 @@ showInfo nm sms mms = do sortTop :: [(String, Float)] -> [(String, Float)] -sortTop = sortBy (flip (comparing snd)) +sortTop = sortBy (comparing (Down . snd)) showMemInfo :: Float -> MemInfo -> Monitor [String] showMemInfo scale (nm, rss) = diff --git a/src/Xmobar/Plugins/PacmanUpdates.hs b/src/Xmobar/Plugins/PacmanUpdates.hs new file mode 100644 index 0000000..ea14454 --- /dev/null +++ b/src/Xmobar/Plugins/PacmanUpdates.hs @@ -0,0 +1,165 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE TypeFamilyDependencies #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE ViewPatterns #-} + +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- + +{- | +Module : Plugins.Monitors.PacmanUpdates +Copyright : (c) 2024, 2026 Enrico Maria De Angelis + , (c) 2025 Alexander Pankoff + , (c) 2026 Enrico Maria De Angelis +License : BSD-style (see LICENSE) + +Maintainer : Enrico Maria De Angelis <enricomaria.dean6elis@gmail.com> +Stability : unstable +Portability : unportable + +A Pacman updates availablility plugin for Xmobar. It also informs whether a kernel update is +available (provided the name of the kernel package), and whether the running kernel is older +than the installed one. +-} +module Xmobar.Plugins.PacmanUpdates ( +#if __GLASGOW_HASKELL__ >= 908 + {-# DEPRECATED "This ctor is DEPRECATED; please use `PacmanUpdates` type and `PacmanUpdatesK`, `PacmanUpdatesPredicateK` and `PacmanUpdatesNoK` constructors instead." #-} +#endif + pattern PacmanUpdates + , PacmanUpdates () + , PacmanUpdatesKernelCheck (..) + , pattern PacmanUpdatesK + , pattern PacmanUpdatesPredicateK + , pattern PacmanUpdatesNoK) where + +import System.Exit (ExitCode (..)) +import System.Process (readProcessWithExitCode) +import Xmobar.Plugins.Command (Rate) +import Xmobar.Run.Exec +import Data.Tuple.Extra (fst3) +import Data.Kind (Type) +import Data.Functor ((<&>)) +import Data.Void (Void) +import Control.Arrow ((&&&)) +import qualified Data.Vector as V + +-- | Deprecated plugin ctor (will be deleted in 2027). +-- Use `PacmanUpdatesK`, `PacmanUpdatesPredicateK`, or `PacmanUpdatesNoK` instead. +pattern PacmanUpdates :: (String, String, String, String) -- ^ `String`s to be shown for 0, 1, ≥ 2 updates, + -- and for error respectively (in the 3rd string, for + -- ≥ 2 updates, any occurrence of the '?' character + -- is a placeholder for the number of available updates). + -> Rate -- ^ `Rate` of update (see [Xmobar doc](https://codeberg.org/xmobar/xmobar/src/commit/39fd70308c3aef5402abe7152ade76ff7bb331bb/src/Xmobar/Plugins/Command.hs#L34)). + -> PacmanUpdates NoKernelCheck +pattern PacmanUpdates irrelevant <- (error "PacmanUpdates: PacmanUpdates is a build-only pattern synonym (a ctor synonym)." -> irrelevant) + where PacmanUpdates zome r + = let (z, o, m, e) = zome + printer = const + $ (++ deprecationNote) + . \case Left _ -> e + Right 0 -> z + Right 1 -> o + Right n -> m >>= \c -> if c == '?' + then show n + else pure c + deprecationNote = " <fc=#ff0000>(<action=`xdg-open https://codeberg.org/xmobar/xmobar/pulls/765`>" + ++ "deprecated plugin, click here</action>)</fc>" + in PacmanUpdatesNoK r printer + + +-- | Different types of kernel checks. +data PacmanUpdatesKernelCheck = NoKernelCheck | PredicateKernelCheck + +-- | PacmanUpdates plugin parametrized over the `PacmanUpdatesKernelCheck` kind. +data PacmanUpdates (b :: PacmanUpdatesKernelCheck) + = Make -- ^ Constructor. + Rate -- ^ `Rate` of update (see [Xmobar doc](https://codeberg.org/xmobar/xmobar/src/commit/39fd70308c3aef5402abe7152ade76ff7bb331bb/src/Xmobar/Plugins/Command.hs#L34)). + (Arg b) -- ^ Optional further argument. See instances of `Updates`. + (Printer b) -- ^ Printer. See instances of `Updates` for its signature. + +instance Show (PacmanUpdates b) where + show = error "PacmanUpdates: Show instance is stub" + +instance Read (PacmanUpdates b) where + readsPrec = error "PacmanUpdates: Read instance is stub" + +instance Updates b => Exec (PacmanUpdates (b :: PacmanUpdatesKernelCheck)) where + alias = const "pacman" + rate (Make r _ _) = r + run = Xmobar.Plugins.PacmanUpdates.run' + +class Updates (b :: PacmanUpdatesKernelCheck) where + -- | See `Updates`'s instances. + type Arg b = (a :: Type) | a -> b + -- | See `Updates`'s instances. + type Printer b = (p :: Type) | p -> b + -- | This is the implementation of `Xmobar.Run.Exec.run`. + run' :: PacmanUpdates b -> IO String + +-- | No additional argument required for constructing the plugin; +-- the user-provided printer is fed with a `Bool` telling whether +-- the system is running an outdated kernel, and an `Int` telling +-- the number of available updates (or `Left` if an error occurred +-- when calling `checkupdates`). +instance Updates NoKernelCheck where + type Arg NoKernelCheck = Void + type Printer NoKernelCheck = Bool -> Either String Int -> String + run' (Make _ _ printer) + = printer + <$> kernIsOld + <*> (fmap V.length <$> checkUpdates) + +-- | Constructing the plugin requires an additional `String -> Bool` predicate +-- that receives each available package name and returns `True` for kernel +-- packages; the user-provided printer is fed with a `Bool` telling whether the +-- system is running an outdated kernel, and an `(Int, Bool)` pair telling the +-- number of available updates and whether one of these is a kernel update (or +-- `Left` if an error occurred when calling `checkupdates`). +instance Updates PredicateKernelCheck where + type Arg PredicateKernelCheck = String -> Bool + type Printer PredicateKernelCheck = Bool -> Either String (Int, Bool) -> String + run' (Make _ checkKern printer) + = printer + <$> kernIsOld + <*> (fmap (V.length &&& V.any checkKern) <$> checkUpdates) + +-- | Pattern synonym to construct a `PacmanUpdates PredicateKernelCheck` that +-- detects updates for packages matched by the given @(String -> Bool)@ +-- predicate. This can be used to detect kernel updates for distributions +-- with versioned kernel package names (e.g. Manjaro's @linux618@) +pattern PacmanUpdatesPredicateK :: Rate -> Arg PredicateKernelCheck -> Printer PredicateKernelCheck -> PacmanUpdates PredicateKernelCheck +pattern PacmanUpdatesPredicateK r a p = Make r a p + +-- | A convenience wrapper around PacmanUpdatesPredicateK with the predicate @(== kernName)@ +-- Construction only: the kernel name cannot be recovered when matching. +pattern PacmanUpdatesK :: Rate -> String -> Printer PredicateKernelCheck -> PacmanUpdates PredicateKernelCheck +pattern PacmanUpdatesK r kernName p <- + (error "PacmanUpdatesK: build-only pattern synonym (a ctor synonym)." -> (r, kernName, p)) + where PacmanUpdatesK r kernName p = PacmanUpdatesPredicateK r (== kernName) p + +-- | Pattern synonym used to construct a `PacmanUpdates NoKernelCheck`. +pattern PacmanUpdatesNoK :: Rate -> Printer NoKernelCheck -> PacmanUpdates NoKernelCheck +pattern PacmanUpdatesNoK r p <- Make r _ p + where PacmanUpdatesNoK r p = Make r undefined p + +checkUpdates :: IO (Either String (V.Vector String)) +checkUpdates = readProcessWithExitCode "checkupdates" [] "" + <&> \case (ExitFailure 2, "", "") -> Right V.empty + (ExitSuccess, stdout, "") + -> let pkgName = takeWhile (/= ' ') + pkgs = V.fromList $ fmap pkgName $ lines stdout + in case V.length pkgs of + 0 -> impossible + _ -> Right pkgs + (ExitFailure 1, _, _) -> Left "checkupdates: unknown cause of failure." + _ -> impossible + +kernIsOld :: IO Bool +kernIsOld = (/= ExitSuccess) . exitCode <$> readProcessWithExitCode "modinfo" ["-n", "i915"] "" + where exitCode = fst3 + +impossible :: a +impossible = error "This is impossible, according to my knowledge." diff --git a/src/Xmobar/Run/Actions.hs b/src/Xmobar/Run/Actions.hs index cbc10c5..a9afed9 100644 --- a/src/Xmobar/Run/Actions.hs +++ b/src/Xmobar/Run/Actions.hs @@ -16,7 +16,7 @@ module Xmobar.Run.Actions ( Button , runAction' , stripActions) where -import System.Process (spawnCommand, waitForProcess) +import System.Process (shell, withCreateProcess, waitForProcess) import Control.Monad (void) import Text.Regex (Regex, subRegex, mkRegex, matchRegex) import Data.Word (Word32) @@ -26,11 +26,12 @@ type Button = Word32 data Action = Spawn [Button] String deriving (Eq, Read, Show) runAction :: Action -> IO () -runAction (Spawn _ s) = void $ spawnCommand (s ++ " &") >>= waitForProcess +runAction (Spawn _ s) = withCreateProcess (shell s) $ \_ _ _ ph -> + void $ waitForProcess ph -- | Run action with stdout redirected to stderr runAction' :: Action -> IO () -runAction' (Spawn _ s) = void $ spawnCommand (s ++ " 1>&2 &") >>= waitForProcess +runAction' (Spawn btn s) = runAction (Spawn btn (s ++ " 1>&2")) stripActions :: String -> String stripActions s = case matchRegex actionRegex s of diff --git a/src/Xmobar/Run/Loop.hs b/src/Xmobar/Run/Loop.hs index bda41ff..6775961 100644 --- a/src/Xmobar/Run/Loop.hs +++ b/src/Xmobar/Run/Loop.hs @@ -57,7 +57,7 @@ type LoopFunction = TMVar SignalType -> TVar [String] -> IO () loop :: Config -> LoopFunction -> IO () loop conf looper = withDeferSignals $ do - cls <- mapM (parseTemplate (commands conf) (sepChar conf)) + let cls = map (parseTemplate (commands conf) (sepChar conf)) (splitTemplate (alignSep conf) (template conf)) let confSig = unSignalChan (signal conf) sig <- maybe newEmptyTMVarIO pure confSig diff --git a/src/Xmobar/Run/Template.hs b/src/Xmobar/Run/Template.hs index 68feacb..0e066dc 100644 --- a/src/Xmobar/Run/Template.hs +++ b/src/Xmobar/Run/Template.hs @@ -50,21 +50,20 @@ templateParser s = many $ templateStringParser s -- | Actually runs the template parsers over a (segment of) a template -- string, returning a list of runnables with their prefix and suffix. -parseTemplate :: [Runnable] -> String -> String -> IO [(Runnable,String,String)] +parseTemplate :: [Runnable] -> String -> String -> [(Runnable,String,String)] parseTemplate c sepChar s = - do str <- case parse (templateParser sepChar) "" s of - Left _ -> return [("", s, "")] - Right x -> return x - let cl = map alias c - m = Map.fromList $ zip cl c - return $ combine c m str + let str = case parse (templateParser sepChar) "" s of + Left _ -> [("", s, "")] + Right x -> x + cl = map alias c + m = Map.fromList $ zip cl c + in combine m str -- | Given a finite "Map" and a parsed template produce the resulting -- output string. -combine :: [Runnable] -> Map.Map String Runnable -> [(String, String, String)] - -> [(Runnable,String,String)] -combine _ _ [] = [] -combine c m ((ts,s,ss):xs) = (com, s, ss) : combine c m xs +combine :: Map.Map String Runnable -> [(String, String, String)] -> [(Runnable,String,String)] +combine _ [] = [] +combine m ((ts,s,ss):xs) = (com, s, ss) : combine m xs where com = Map.findWithDefault dflt ts m dflt = Run $ Com ts [] [] 10 diff --git a/src/Xmobar/Run/Types.hs b/src/Xmobar/Run/Types.hs index bb573c8..8b9caa4 100644 --- a/src/Xmobar/Run/Types.hs +++ b/src/Xmobar/Run/Types.hs @@ -1,4 +1,5 @@ {-# LANGUAGE TypeOperators, CPP #-} +{-# LANGUAGE DataKinds #-} ------------------------------------------------------------------------------ -- | -- Module: Xmobar.Run.Types @@ -19,7 +20,7 @@ module Xmobar.Run.Types(runnableTypes) where import {-# SOURCE #-} Xmobar.Run.Runnable() -import Xmobar.Plugins.ArchUpdates +import Xmobar.Plugins.PacmanUpdates import Xmobar.Plugins.Command import Xmobar.Plugins.Monitors import Xmobar.Plugins.Date @@ -60,7 +61,6 @@ infixr :*: runnableTypes :: Command :*: Monitors :*: Date :*: PipeReader :*: BufferedPipeReader :*: CommandReader :*: StdinReader :*: XMonadLog :*: EWMH :*: Kbd :*: Locks :*: NotmuchMail :*: - ArchUpdates :*: #ifdef INOTIFY Mail :*: MBox :*: #endif diff --git a/src/Xmobar/X11/Loop.hs b/src/Xmobar/X11/Loop.hs index 2dfb34d..0425cff 100644 --- a/src/Xmobar/X11/Loop.hs +++ b/src/Xmobar/X11/Loop.hs @@ -170,7 +170,7 @@ updateConfigPosition disp cfg = 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 diff --git a/src/Xmobar/X11/XRender.hsc b/src/Xmobar/X11/XRender.hsc index 5ad0391..4e4d448 100644 --- a/src/Xmobar/X11/XRender.hsc +++ b/src/Xmobar/X11/XRender.hsc @@ -91,22 +91,28 @@ drawBackground d p bgc alpha (Rectangle x y wid ht) = do withRenderFill d (XRenderColor 0 0 0 (257 * alpha)) (render pictOpSrc bgfill pic) - -- Handle transparency - internAtom d "_XROOTPMAP_ID" False >>= \xid -> - let xroot = defaultRootWindow d in - alloca $ \x1 -> - alloca $ \x2 -> - alloca $ \x3 -> - alloca $ \x4 -> - alloca $ \pprop -> do - xGetWindowProperty d xroot xid 0 1 False 20 x1 x2 x3 x4 pprop - prop <- peek pprop - when (prop /= nullPtr) $ do - rootbg <- peek (castPtr prop) :: IO Pixmap - xFree prop - withRenderPicture d rootbg $ \bgpic -> - withRenderFill d (XRenderColor 0 0 0 (0xFFFF - 257 * alpha)) - (render pictOpAdd bgpic pic) + -- Handle pseudo-transparency by compositing the root pixmap. + -- Skip entirely when alpha == 255 (fully opaque) since the blend + -- factor would be zero, making this a no-op. More importantly, + -- the root pixmap (_XROOTPMAP_ID) can be freed at any time by + -- wallpaper setters like feh (via XKillClient), causing a + -- BadDrawable crash in XRenderCreatePicture if we touch it. + when (alpha < 255) $ + internAtom d "_XROOTPMAP_ID" False >>= \xid -> + let xroot = defaultRootWindow d in + alloca $ \x1 -> + alloca $ \x2 -> + alloca $ \x3 -> + alloca $ \x4 -> + alloca $ \pprop -> do + xGetWindowProperty d xroot xid 0 1 False 20 x1 x2 x3 x4 pprop + prop <- peek pprop + when (prop /= nullPtr) $ do + rootbg <- peek (castPtr prop) :: IO Pixmap + xFree prop + withRenderPicture d rootbg $ \bgpic -> + withRenderFill d (XRenderColor 0 0 0 (0xFFFF - 257 * alpha)) + (render pictOpAdd bgpic pic) -- | Parses color into XRender color (allocation not necessary!) parseRenderColor :: Display -> String -> IO XRenderColor @@ -1,5 +1,5 @@ -# ghc 8.10.7 -resolver: lts-18.20 +# ghc-9.10.3 +resolver: lts-24.45 packages: - . @@ -11,11 +11,6 @@ flags: extra-deps: - netlink-1.1.1.0 - - libmpd-0.9.2.0 - - cairo-0.13.8.2 - - pango-0.13.8.2 - - glib-0.13.8.2 - - gtk2hs-buildtools-0.13.8.3 nix: packages: - alsaLib diff --git a/test/Xmobar/Plugins/Monitors/CpuSpec.hs b/test/Xmobar/Plugins/Monitors/CpuSpec.hs index 3d07dee..b415179 100644 --- a/test/Xmobar/Plugins/Monitors/CpuSpec.hs +++ b/test/Xmobar/Plugins/Monitors/CpuSpec.hs @@ -6,24 +6,38 @@ module Xmobar.Plugins.Monitors.CpuSpec import Test.Hspec import Xmobar.Plugins.Monitors.Common import Xmobar.Plugins.Monitors.Cpu + import Data.List +import Text.Regex.TDFA((=~)) main :: IO () main = hspec spec +withFc :: String -> String +withFc s = "((<fc=(green|red)>)?" ++ s ++ "(</fc>)?)" + +withFcDigits :: String -> String -> String +withFcDigits prefix suffix = prefix ++ digits ++ suffix + where digits = withFc "([0-9][0-9]?|-0)" -- in CI computers, -0 is a value + spec :: Spec spec = describe "CPU Spec" $ do + it "uses the correct regexps" $ + do "Cpu: -0%" `shouldSatisfy` (=~ withFcDigits "Cpu: " "%") + "Cpu: 12" `shouldSatisfy` (=~ withFcDigits "Cpu: " "") + "Cpu: <fc=red>12</fc>" `shouldSatisfy` (=~ withFcDigits "Cpu: " "") + "Cpu: <fc=green>12</fc> -0" `shouldSatisfy` (=~ withFcDigits "Cpu: (" ")+") it "works with total template" $ do let args = ["-L","3","-H","50","--normal","green","--high","red", "-t", "Cpu: <total>%"] cpuArgs <- getArguments args cpuValue <- runCpu cpuArgs - cpuValue `shouldSatisfy` (\item -> "Cpu:" `isPrefixOf` item) + cpuValue `shouldSatisfy` (=~ withFcDigits "Cpu: " "%") it "works with bar template" $ do let args = ["-L","3","-H","50","--normal","green","--high","red", "-t", "Cpu: <total>% <bar>"] cpuArgs <- getArguments args cpuValue <- runCpu cpuArgs - cpuValue `shouldSatisfy` (all (`elem` ":#") . last . words) + cpuValue `shouldSatisfy` ((=~ (withFc "#+" ++ "?:*")) . last . words) it "works with no icon pattern template" $ do let args = ["-L","3","-H","50","--normal","green","--high","red", "-t", "Cpu: <total>% <bar>", "--", "--load-icon-pattern", "<icon=bright_%%.xpm/>"] cpuArgs <- getArguments args @@ -38,4 +52,5 @@ spec = do let args = ["-L","3","-H","50","--normal","green","--high","red", "-t", "Cpu: <user> <nice> <iowait>"] cpuArgs <- getArguments args cpuValue <- runCpu cpuArgs - cpuValue `shouldSatisfy` (\item -> "Cpu:" `isPrefixOf` cpuValue) + cpuValue `shouldSatisfy` (=~ withFcDigits "Cpu:( " ")+") + diff --git a/xmobar.cabal b/xmobar.cabal index 0b548b1..e7ed69c 100644 --- a/xmobar.cabal +++ b/xmobar.cabal @@ -1,433 +1,471 @@ +cabal-version: >=1.10 name: xmobar -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. - . - Inspired by the Ion3 status bar, it supports similar - features, like dynamic color management, output templates, - and extensibility through plugins. -category: System +version: 0.51.1 license: BSD3 license-file: license -author: Andrea Rossato and Jose A. Ortega Ruiz maintainer: Jose A. Ortega Ruiz <jao@gnu.org> +author: Andrea Rossato and Jose A. Ortega Ruiz +homepage: https://codeberg.org/xmobar/xmobar bug-reports: https://codeberg.org/xmobar/xmobar/issues -cabal-version: >= 1.10 -build-type: Simple +synopsis: A Minimalistic Text Based Status Bar +description: + Xmobar is a minimalistic text based status bar. + . + Inspired by the Ion3 status bar, it supports similar + features, like dynamic color management, output templates, + and extensibility through plugins. -extra-source-files: readme.org, changelog.md, - doc/quick-start.org, - doc/plugins.org, - doc/compiling.org, - doc/using-haskell.org, - etc/padding-icon.sh, - etc/xmobar.config, - etc/xmobar.hs, - etc/xmonadpropwrite.hs, - etc/xmobar.el +category: System +build-type: Simple +extra-source-files: + readme.org + changelog.md + doc/quick-start.org + doc/plugins.org + doc/compiling.org + doc/using-haskell.org + etc/padding-icon.sh + etc/xmobar.config + etc/xmobar.hs + etc/xmonadpropwrite.hs + etc/xmobar.el + etc/notify-once.sh source-repository head - type: git - location: git://codeberg.org/xmobar/xmobar.git - branch: master + type: git + location: https://codeberg.org/xmobar/xmobar.git + branch: master flag with_xrender - description: Use XRender for alpha background pseudo-transparency. - default: True + description: Use XRender for alpha background pseudo-transparency. flag with_inotify - description: inotify support (modern Linux only). Required for the Mail and MBox plugins. - default: False + description: + inotify support (modern Linux only). Required for the Mail and MBox plugins. + + default: False flag with_iwlib - description: Wireless info support via Wext ioctls (deprecated). Required for the Wireless plugin, needs iwlib installed. - default: False + description: + Wireless info support via Wext ioctls (deprecated). Required for the Wireless plugin, needs iwlib installed. + + default: False flag with_nl80211 - description: Wireless info support via nl80211. Required for the Wireless plugin on systems running Linux, the kernel. - default: False + description: + Wireless info support via nl80211. Required for the Wireless plugin on systems running Linux, the kernel. + + default: False flag with_mpd - description: MPD support. Needs libmpd installed. - default: False + description: MPD support. Needs libmpd installed. + default: False flag all_extensions - description: Includes all optional extensions. - default: False + description: Includes all optional extensions. + default: False flag with_alsa - description: Use alsa-mixer to get the volume from soundcards. - default: False + description: Use alsa-mixer to get the volume from soundcards. + default: False flag with_datezone - description: Enables localized date support. - default: False + description: Enables localized date support. + default: False flag with_mpris - description: MPRIS v1, v2 support. - default: False + description: MPRIS v1, v2 support. + default: False flag with_dbus - description: Publish a service on the session bus for controlling xmobar. - default: False + description: + Publish a service on the session bus for controlling xmobar. + + default: False flag with_xpm - description: Enable usage of xpm for icons. - default: False + description: Enable usage of xpm for icons. + default: False flag with_threaded - description: Use threaded runtime. Required for timer coalescing (less power usage). - default: False + description: + Use threaded runtime. Required for timer coalescing (less power usage). + + default: False flag with_rtsopts - description: Use -with-rtsopts=-V0 to reduce wakeups. - default: True + description: Use -with-rtsopts=-V0 to reduce wakeups. flag with_shared - description: Use shared libraries. Required when dependencies are built as shared libraries. - default: False + description: + Use shared libraries. Required when dependencies are built as shared libraries. + + default: False flag with_weather - description: Enable weather plugin. - default: True + description: Enable weather plugin. flag with_uvmeter - description: UVMeter only useful to australians. - default: False + description: UVMeter only useful to australians. + default: False flag with_kraken - description: Enable Kraken plugin. - default: False + description: Enable Kraken plugin. + default: False library + exposed-modules: + Xmobar + Xmobar.Plugins.Accordion + Xmobar.Plugins.Monitors.Common.Types + Xmobar.Plugins.Monitors.Common.Run + Xmobar.Plugins.Monitors.Common + Xmobar.Plugins.Monitors.Cpu + + hs-source-dirs: src + other-modules: + Paths_xmobar + Xmobar.Config.Types + Xmobar.Config.Parse + Xmobar.Config.Template + Xmobar.Run.Types + Xmobar.Run.Timer + Xmobar.Run.Template + Xmobar.Run.Exec + Xmobar.Run.Runnable + Xmobar.Run.Actions + Xmobar.Run.Loop + Xmobar.Draw.Boxes + Xmobar.Draw.Cairo + Xmobar.Draw.Types + Xmobar.App.Config + Xmobar.App.Main + Xmobar.App.Opts + Xmobar.App.Compile + Xmobar.System.Utils + Xmobar.System.StatFS + Xmobar.System.Environment + Xmobar.System.Localize + Xmobar.System.Signal + Xmobar.System.Kbd + Xmobar.Text.Ansi + Xmobar.Text.Loop + Xmobar.Text.Pango + Xmobar.Text.Swaybar + Xmobar.Text.SwaybarClicks + Xmobar.Text.Output + Xmobar.X11.Bitmap + Xmobar.X11.CairoSurface + Xmobar.X11.ColorCache + Xmobar.X11.Draw + Xmobar.X11.Events + Xmobar.X11.Loop + Xmobar.X11.Text + Xmobar.X11.Types + Xmobar.X11.Window + Xmobar.Plugins.Command + Xmobar.Plugins.BufferedPipeReader + Xmobar.Plugins.CommandReader + Xmobar.Plugins.Date + Xmobar.Plugins.EWMH + Xmobar.Plugins.HandleReader + Xmobar.Plugins.QueueReader + Xmobar.Plugins.PacmanUpdates + Xmobar.Plugins.PipeReader + Xmobar.Plugins.MarqueePipeReader + Xmobar.Plugins.StdinReader + Xmobar.Plugins.XMonadLog + Xmobar.Plugins.Kbd + Xmobar.Plugins.Locks + Xmobar.Plugins.NotmuchMail + Xmobar.Plugins.Monitors + Xmobar.Plugins.Monitors.Batt + Xmobar.Plugins.Monitors.Batt.Common + Xmobar.Plugins.Monitors.Common.Output + Xmobar.Plugins.Monitors.Common.Parsers + Xmobar.Plugins.Monitors.Common.Files + Xmobar.Plugins.Monitors.CoreTemp + Xmobar.Plugins.Monitors.K10Temp + Xmobar.Plugins.Monitors.Cpu.Common + 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 + Xmobar.Plugins.Monitors.Net + Xmobar.Plugins.Monitors.Net.Common + Xmobar.Plugins.Monitors.Swap + Xmobar.Plugins.Monitors.Thermal + Xmobar.Plugins.Monitors.ThermalZone + Xmobar.Plugins.Monitors.Top + Xmobar.Plugins.Monitors.Top.Common + Xmobar.Plugins.Monitors.Uptime + Xmobar.Plugins.Monitors.Bright + Xmobar.Plugins.Monitors.CatInt + default-language: Haskell2010 - hs-source-dirs: src - - exposed-modules: Xmobar, - Xmobar.Plugins.Accordion, - Xmobar.Plugins.Monitors.Common.Types, - Xmobar.Plugins.Monitors.Common.Run, - Xmobar.Plugins.Monitors.Common, - Xmobar.Plugins.Monitors.Cpu - - other-modules: Paths_xmobar, - Xmobar.Config.Types, - Xmobar.Config.Parse, - Xmobar.Config.Template, - Xmobar.Run.Types, - Xmobar.Run.Timer, - Xmobar.Run.Template, - Xmobar.Run.Exec, - Xmobar.Run.Runnable - Xmobar.Run.Actions, - Xmobar.Run.Loop, - Xmobar.Draw.Boxes, - Xmobar.Draw.Cairo, - Xmobar.Draw.Types, - Xmobar.App.Config, - Xmobar.App.Main, - Xmobar.App.Opts, - Xmobar.App.Compile, - Xmobar.System.Utils, - Xmobar.System.StatFS, - Xmobar.System.Environment, - Xmobar.System.Localize, - Xmobar.System.Signal, - Xmobar.System.Kbd, - Xmobar.Text.Ansi, - Xmobar.Text.Loop, - Xmobar.Text.Pango, - Xmobar.Text.Swaybar, - Xmobar.Text.SwaybarClicks, - Xmobar.Text.Output, - Xmobar.X11.Bitmap, - Xmobar.X11.CairoSurface, - Xmobar.X11.ColorCache, - Xmobar.X11.Draw, - Xmobar.X11.Events, - Xmobar.X11.Loop, - Xmobar.X11.Text, - Xmobar.X11.Types, - Xmobar.X11.Window, - Xmobar.Plugins.ArchUpdates, - Xmobar.Plugins.Command, - Xmobar.Plugins.BufferedPipeReader, - Xmobar.Plugins.CommandReader, - Xmobar.Plugins.Date, - Xmobar.Plugins.EWMH, - Xmobar.Plugins.HandleReader, - Xmobar.Plugins.QueueReader, - Xmobar.Plugins.PipeReader, - Xmobar.Plugins.MarqueePipeReader, - Xmobar.Plugins.StdinReader, - Xmobar.Plugins.XMonadLog, - Xmobar.Plugins.Kbd, - Xmobar.Plugins.Locks, - Xmobar.Plugins.NotmuchMail, - Xmobar.Plugins.Monitors, - Xmobar.Plugins.Monitors.Batt, - Xmobar.Plugins.Monitors.Batt.Common, - Xmobar.Plugins.Monitors.Common.Output, - Xmobar.Plugins.Monitors.Common.Parsers, - Xmobar.Plugins.Monitors.Common.Files, - Xmobar.Plugins.Monitors.CoreTemp, - Xmobar.Plugins.Monitors.K10Temp, - Xmobar.Plugins.Monitors.Cpu.Common, - 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, - Xmobar.Plugins.Monitors.Net, - Xmobar.Plugins.Monitors.Net.Common, - Xmobar.Plugins.Monitors.Swap, - Xmobar.Plugins.Monitors.Thermal, - Xmobar.Plugins.Monitors.ThermalZone, - Xmobar.Plugins.Monitors.Top, - Xmobar.Plugins.Monitors.Top.Common, - Xmobar.Plugins.Monitors.Uptime, - Xmobar.Plugins.Monitors.Bright, - Xmobar.Plugins.Monitors.CatInt - - extra-libraries: Xrandr Xrender - - ghc-options: -funbox-strict-fields -Wall -fno-warn-unused-do-bind + extra-libraries: + Xrandr + Xrender + ghc-options: -funbox-strict-fields -Wall -fno-warn-unused-do-bind build-depends: - aeson >= 1.4.7.1, - async, - base >= 4.11.0 && < 4.20, - bytestring >= 0.10.8.2, - cairo >= 0.13, - colour >= 2.3.6, - containers, - directory, - extra, - extensible-exceptions == 0.1.*, - filepath, - mtl >= 2.1 && < 2.4, - old-locale, - pango >= 0.13, - parsec == 3.1.*, - parsec-numbers >= 0.1.0, - process, - regex-compat, - stm >= 2.3 && < 2.6, - time, - transformers, - unix, - utf8-string >= 0.3 && < 1.1, - X11 >= 1.6.1 - - if impl(ghc < 8.0.2) - -- Disable building with GHC before 8.0.2. - -- Due to a cabal bug, do not use buildable: False, - -- but instead give it an impossible constraint. - -- See: https://github.com/haskell-infra/hackage-trustees/issues/165 - build-depends: unsupported-ghc-version > 1 && < 1 + aeson >=1.4.7.1 && <2.4, + async <2.3, + base >=4.18.0 && <4.22, + bytestring >=0.10.8.2 && <0.13, + cairo >=0.13 && <0.14, + colour >=2.3.6 && <2.4, + containers <0.9, + directory <1.4, + extra <1.9, + filepath <1.6, + mtl >=2.1 && <2.4, + old-locale <1.1, + pango >=0.13 && <0.14, + parsec >=3.1 && <3.2, + parsec-numbers >=0.1.0 && <0.2, + process <1.7, + regex-compat <0.96, + stm >=2.3 && <2.6, + time <1.17, + transformers <0.7, + unix <2.9, + utf8-string >=0.3 && <1.1, + vector <0.14, + X11 >=1.6.1 && <1.11 + + if impl(ghc <9.6.0) + build-depends: unsupported-ghc-version >=1 && <1 if flag(with_threaded) - -- -threaded is a workaround for 100% CPU busy loop - -- (http://hackage.haskell.org/trac/ghc/ticket/4934). - -- See also comments in https://codeberg.org/xmobar/xmobar/pulls/36 - cpp-options: -DTHREADED_RUNTIME + cpp-options: -DTHREADED_RUNTIME if flag(with_rtsopts) - cpp-options: -DRTSOPTS + cpp-options: -DRTSOPTS if flag(with_shared) - cpp-options: -DSHARED_LIBRARIES + cpp-options: -DSHARED_LIBRARIES if flag(with_xrender) - build-depends: X11-xft >= 0.2 - other-modules: Xmobar.X11.XRender - cpp-options: -DXRENDER + cpp-options: -DXRENDER + other-modules: Xmobar.X11.XRender + build-depends: X11-xft >=0.2 && <0.4 - if flag(with_inotify) || flag(all_extensions) - build-depends: hinotify >= 0.3 && < 0.5 - other-modules: Xmobar.Plugins.Mail, Xmobar.Plugins.MBox - cpp-options: -DINOTIFY + if (flag(with_inotify) || flag(all_extensions)) + cpp-options: -DINOTIFY + other-modules: + Xmobar.Plugins.Mail + Xmobar.Plugins.MBox - if flag(with_iwlib) || flag(with_nl80211) || flag(all_extensions) - other-modules: Xmobar.Plugins.Monitors.Wireless + build-depends: hinotify >=0.3 && <0.5 + + if ((flag(with_iwlib) || flag(with_nl80211)) || flag(all_extensions)) + other-modules: Xmobar.Plugins.Monitors.Wireless if flag(with_iwlib) - extra-libraries: iw - build-depends: iwlib >= 0.1.0 && < 0.2 - cpp-options: -DIWLIB - - if !flag(with_iwlib) && (flag(with_nl80211) || flag(all_extensions)) - build-depends: netlink >= 1.1.1.0, - cereal >= 0.5.8.1 - cpp-options: -DUSE_NL80211 - - if flag(with_mpd) || (flag(all_extensions) && impl(ghc < 9.4)) - build-depends: libmpd >= 0.9.2.0 - other-modules: Xmobar.Plugins.Monitors.MPD - cpp-options: -DLIBMPD - - if flag(with_alsa) || flag(all_extensions) - build-depends: alsa-mixer >= 0.3 && < 0.4 - build-depends: alsa-core == 0.5.*, - process >= 1.4.3.0 - other-modules: Xmobar.Plugins.Monitors.Volume, - Xmobar.Plugins.Monitors.Alsa - cpp-options: -DALSA - - if flag(with_datezone) || flag(all_extensions) - build-depends: timezone-olson >= 0.2 && < 0.3, timezone-series == 0.1.* - other-modules: Xmobar.Plugins.DateZone - cpp-options: -DDATEZONE - - if flag(with_mpris) || flag(all_extensions) - build-depends: dbus >= 1 - other-modules: Xmobar.Plugins.Monitors.Mpris - cpp-options: -DMPRIS - - if flag(with_dbus) || flag(all_extensions) - build-depends: dbus >= 1 - other-modules: Xmobar.System.DBus - cpp-options: -DDBUS - - if flag(with_xpm) || flag(all_extensions) - extra-libraries: Xpm - other-modules: Xmobar.X11.XPMFile - cpp-options: -DXPM - - if flag(with_weather) || flag(all_extensions) - other-modules: Xmobar.Plugins.Monitors.Weather - cpp-options: -DWEATHER - build-depends: http-conduit, http-types, http-client-tls + cpp-options: -DIWLIB + extra-libraries: iw + build-depends: iwlib >=0.1.0 && <0.2 + + if (!flag(with_iwlib) && (flag(with_nl80211) || flag(all_extensions))) + cpp-options: -DUSE_NL80211 + build-depends: + netlink >=1.1.1.0, + cereal >=0.5.8.1 + + if (flag(with_mpd) || flag(all_extensions)) + cpp-options: -DLIBMPD + other-modules: Xmobar.Plugins.Monitors.MPD + build-depends: libmpd >=0.10.0.1 && <0.11 + + if (flag(with_alsa) || flag(all_extensions)) + cpp-options: -DALSA + other-modules: + Xmobar.Plugins.Monitors.Volume + Xmobar.Plugins.Monitors.Alsa + + build-depends: + alsa-mixer >=0.3 && <0.4, + alsa-core >=0.5 && <0.6, + process >=1.4.3.0 && <1.7 + + if (flag(with_datezone) || flag(all_extensions)) + cpp-options: -DDATEZONE + other-modules: Xmobar.Plugins.DateZone + build-depends: + timezone-olson >=0.2 && <0.3, + timezone-series >=0.1 && <0.2 + + if (flag(with_mpris) || flag(all_extensions)) + cpp-options: -DMPRIS + other-modules: Xmobar.Plugins.Monitors.Mpris + build-depends: dbus >=1 && <1.5 + + if (flag(with_dbus) || flag(all_extensions)) + cpp-options: -DDBUS + other-modules: Xmobar.System.DBus + build-depends: dbus >=1 && <1.5 + + if (flag(with_xpm) || flag(all_extensions)) + cpp-options: -DXPM + other-modules: Xmobar.X11.XPMFile + extra-libraries: Xpm + + if (flag(with_weather) || flag(all_extensions)) + cpp-options: -DWEATHER + other-modules: Xmobar.Plugins.Monitors.Weather + build-depends: + http-conduit <2.4, + http-types <0.13, + http-client-tls <0.5 if flag(with_uvmeter) - other-modules: Xmobar.Plugins.Monitors.UVMeter - build-depends: http-conduit, http-types - cpp-options: -DUVMETER + cpp-options: -DUVMETER + other-modules: Xmobar.Plugins.Monitors.UVMeter + build-depends: + http-conduit, + http-types if flag(with_kraken) - other-modules: Xmobar.Plugins.Kraken - build-depends: aeson == 1.5.6.* - , text == 1.2.4.* - , unordered-containers == 0.2.14.* - , vector == 0.12.3.* - , wuss == 1.1.* - , websockets == 0.12.* - cpp-options: -DKRAKEN + cpp-options: -DKRAKEN + other-modules: Xmobar.Plugins.Kraken + build-depends: + aeson >=1.5.6 && <1.5.7, + text >=1.2.4 && <1.2.5, + unordered-containers >=0.2.14 && <0.2.15, + vector >=0.12.3 && <0.12.4, + wuss >=1.1 && <1.2, + websockets >=0.12 && <0.13 if os(freebsd) - -- enables freebsd specific code - extra-libraries: procstat - , kvm - , geom - build-depends: bsd-sysctl - 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, - Xmobar.Plugins.Monitors.Top.FreeBSD, - Xmobar.Plugins.Monitors.Uptime.FreeBSD + 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 + Xmobar.Plugins.Monitors.Top.FreeBSD + Xmobar.Plugins.Monitors.Uptime.FreeBSD + + extra-libraries: + procstat + kvm + geom + + build-depends: bsd-sysctl <1.1 + else - 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, - Xmobar.Plugins.Monitors.Top.Linux, - Xmobar.Plugins.Monitors.Uptime.Linux + 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 + Xmobar.Plugins.Monitors.Top.Linux + Xmobar.Plugins.Monitors.Uptime.Linux executable xmobar - default-language: Haskell2010 - hs-source-dirs: app - main-is: Main.hs - build-depends: X11, - async, - base, - containers, - directory, - filepath, - parsec, - unix, - xmobar - - ghc-options: -funbox-strict-fields -Wall -fno-warn-unused-do-bind + main-is: Main.hs + hs-source-dirs: app + default-language: Haskell2010 + ghc-options: -funbox-strict-fields -Wall -fno-warn-unused-do-bind + build-depends: + X11 <1.11, + async <2.3, + base, + containers <0.9, + directory <1.4, + filepath <1.6, + parsec, + unix <2.9, + xmobar if flag(with_rtsopts) - ghc-options: -with-rtsopts=-V0 + ghc-options: -with-rtsopts=-V0 if flag(with_threaded) - ghc-options: -threaded - cpp-options: -DTHREADED_RUNTIME + cpp-options: -DTHREADED_RUNTIME + ghc-options: -threaded test-suite XmobarTest - default-language: Haskell2010 - type: exitcode-stdio-1.0 - hs-source-dirs: src, test - main-is: Spec.hs - build-depends: X11, - async, - base, - bytestring, - containers, - directory, - filepath, - hspec == 2.*, - mtl, - old-locale, - parsec, - parsec-numbers, - process, - regex-compat, - stm, - temporary, - time, - transformers, - unix, - xmobar - - other-modules: Xmobar.Plugins.Monitors.CommonSpec - Xmobar.Plugins.Monitors.Common - Xmobar.Plugins.Monitors.Common.Parsers - Xmobar.Plugins.Monitors.Common.Types - Xmobar.Plugins.Monitors.Common.Output - Xmobar.Plugins.Monitors.Common.Files - Xmobar.Plugins.Monitors.Cpu - Xmobar.Plugins.Monitors.Cpu.Common - Xmobar.Plugins.Monitors.CpuSpec - Xmobar.Plugins.Monitors.Common.Run - Xmobar.Run.Exec - Xmobar.Run.Timer - Xmobar.System.Signal - - if flag(with_alsa) || flag(all_extensions) - build-depends: alsa-mixer, - alsa-core, - process >= 1.4.3.0 - other-modules: Xmobar.Plugins.Monitors.Volume - Xmobar.Plugins.Monitors.Alsa - Xmobar.Plugins.Monitors.AlsaSpec - - cpp-options: -DALSA - - if os(freebsd) - -- enables freebsd specific code - build-depends: bsd-sysctl - other-modules: Xmobar.Plugins.Monitors.Cpu.FreeBSD - else - other-modules: Xmobar.Plugins.Monitors.Cpu.Linux + type: exitcode-stdio-1.0 + main-is: Spec.hs + hs-source-dirs: src test + other-modules: + Xmobar.Plugins.Monitors.CommonSpec + Xmobar.Plugins.Monitors.Common + Xmobar.Plugins.Monitors.Common.Parsers + Xmobar.Plugins.Monitors.Common.Types + Xmobar.Plugins.Monitors.Common.Output + Xmobar.Plugins.Monitors.Common.Files + Xmobar.Plugins.Monitors.Cpu + Xmobar.Plugins.Monitors.Cpu.Common + Xmobar.Plugins.Monitors.CpuSpec + Xmobar.Plugins.Monitors.Common.Run + Xmobar.Run.Exec + Xmobar.Run.Timer + Xmobar.System.Signal + + default-language: Haskell2010 + build-depends: + X11 <1.11, + async <2.3, + base, + bytestring <0.13, + containers <0.9, + directory <1.4, + filepath <1.6, + hspec >=2 && <3, + mtl, + old-locale <1.1, + parsec, + parsec-numbers <0.2, + process <1.7, + regex-compat <0.96, + regex-tdfa <1.4, + stm, + temporary <1.4, + time <1.17, + transformers <0.7, + unix <2.9, + xmobar + + if (flag(with_alsa) || flag(all_extensions)) + cpp-options: -DALSA + other-modules: + Xmobar.Plugins.Monitors.Volume + Xmobar.Plugins.Monitors.Alsa + Xmobar.Plugins.Monitors.AlsaSpec + + build-depends: + alsa-mixer, + alsa-core, + process >=1.4.3.0 && <1.7 + + if os(freebsd) + other-modules: Xmobar.Plugins.Monitors.Cpu.FreeBSD + build-depends: bsd-sysctl + + else + other-modules: Xmobar.Plugins.Monitors.Cpu.Linux benchmark xmobarbench - type: exitcode-stdio-1.0 - main-is: main.hs - hs-source-dirs: bench - ghc-options: -funbox-strict-fields -Wall -fno-warn-unused-do-bind -O2 - build-depends: base, gauge, mtl, time, xmobar - default-language: Haskell2010 + type: exitcode-stdio-1.0 + main-is: main.hs + hs-source-dirs: bench + default-language: Haskell2010 + ghc-options: -funbox-strict-fields -Wall -fno-warn-unused-do-bind + build-depends: + base, + gauge, + mtl, + time <1.17, + xmobar |
