From 32ffca599e5e3d76573c3ac5514501e0612208e1 Mon Sep 17 00:00:00 2001 From: Yecine Megdiche Date: Fri, 22 Jan 2021 20:01:04 +0100 Subject: [PATCH] Added more loggers - `logWhenActive` to have loggers active only when a certain screen is active. - `logTitleOnScreen`, `logCurrentOnScreen` and `logLayoutOnScreen` as screen-specific variants of `logTitle`, `logCurrent`, `logLayout` - `logConst` to log a constant `String` - `logMaybe` and `.|` to combine loggers. --- CHANGES.md | 6 ++++ XMonad/Util/Loggers.hs | 78 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4348897a..b6531dd8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -304,6 +304,12 @@ * `XMonad.Util.Loggers` - Make `battery` and `loadAvg` distro-independent. + - Added `logTitleOnScreen`, `logCurrentOnScreen` and `logLayoutOnScreen` + as screen-specific variants of `logTitle`, `logCurrent` and `logLayout`. + - Added `logWhenActive` to have loggers active only when a certain + screen is active. + - Added `logConst` to log a constant `String`, and `logDefault` (infix: `.|`) + to combine loggers. * `XMonad.Hooks.DynamicLog` - Added `xmobarBorder` function to create borders around strings. diff --git a/XMonad/Util/Loggers.hs b/XMonad/Util/Loggers.hs index c0e42378..f45e260d 100644 --- a/XMonad/Util/Loggers.hs +++ b/XMonad/Util/Loggers.hs @@ -32,7 +32,11 @@ module XMonad.Util.Loggers ( -- * XMonad Loggers -- $xmonad , logCurrent, logLayout, logTitle - + , logConst, logDefault, (.|) + -- * XMonad: Screen-specific Loggers + -- $xmonad-screen + , logCurrentOnScreen, logLayoutOnScreen + , logTitleOnScreen, logWhenActive -- * Formatting Utilities -- $format , onLogger @@ -43,7 +47,7 @@ module XMonad.Util.Loggers ( ) where -import XMonad (liftIO) +import XMonad (liftIO, Window) import XMonad.Core import qualified XMonad.StackSet as W import XMonad.Hooks.DynamicLog @@ -51,7 +55,7 @@ import XMonad.Util.Font (Align (..)) import XMonad.Util.NamedWindows (getName) import Control.Exception as E -import Data.List (isPrefixOf, isSuffixOf) +import Data.List (find, isPrefixOf, isSuffixOf) import Data.Maybe (fromMaybe) import System.Directory (getDirectoryContents) import System.IO @@ -125,7 +129,7 @@ battery = logCmd "acpi | sed -r 's/.*?: (.*%).*/\\1/; s/[dD]ischarging, ([0-9]+% -- For more information see something like -- . date :: String -> Logger -date fmt = io $ do cal <- (getClockTime >>= toCalendarTime) +date fmt = io $ do cal <- getClockTime >>= toCalendarTime return . Just $ formatCalendarTime defaultTimeLocale fmt cal -- | Get the load average. This assumes that you have a @@ -182,6 +186,70 @@ logLayout = withWindowSet $ return . Just . ld logCurrent :: Logger logCurrent = withWindowSet $ return . Just . W.currentTag +-- | Log the given string, as is. +logConst :: String -> Logger +logConst = return . Just + +-- | If the first logger returns @Nothing@, the default logger is used. +-- For example, to display a quote when no windows are on the screen, +-- you can do: +-- +-- > logDefault logTitle (logConst "Hey, you, you're finally awake.") +logDefault :: Logger -> Logger -> Logger +logDefault l d = l >>= maybe d logConst + +-- | An infix operator for 'logDefault', which can be more convenient to +-- combine multiple loggers. +-- +-- > logTitle .| logWhenActive 0 (logConst "*") .| logConst "There's nothing here" +(.|) :: Logger -> Logger -> Logger +(.|) = logDefault + +-- $xmonad-screen +-- It is also possible to bind loggers like 'logTitle' to a specific screen. For +-- example, using @logTitleOnScreen 1@ will log the title of the focused window +-- on screen 1, even if screen 1 is not currently active. + +-- | Only display the 'Logger' if the screen with the given 'ScreenId' is +-- active. +-- For example, this can be used to create a marker that is only displayed +-- when the primary screen is active. +-- +-- > logWhenActive 0 (logConst "*") +logWhenActive :: ScreenId -> Logger -> Logger +logWhenActive n l = do + c <- withWindowSet $ return . W.screen . W.current + if n == c then l else return Nothing + +-- | Get the title (name) of the focused window, on the given screen. +logTitleOnScreen :: ScreenId -> Logger +logTitleOnScreen = + withScreen + $ traverse (fmap show . getName) + . (W.focus <$>) + . W.stack + . W.workspace + +-- | Get the name of the visible workspace on the given screen. +logCurrentOnScreen :: ScreenId -> Logger +logCurrentOnScreen = withScreen $ logConst . W.tag . W.workspace + +-- | Get the name of the current layout on the given screen. +logLayoutOnScreen :: ScreenId -> Logger +logLayoutOnScreen = + withScreen $ logConst . description . W.layout . W.workspace + +-- | A shortcut to a screen +type WindowScreen = W.Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail + +-- | A helper function to create screen-specific loggers. +withScreen :: (WindowScreen -> Logger) -> ScreenId -> Logger +withScreen f n = do + ss <- withWindowSet $ return . W.screens + case find ((== n) . W.screen) ss of + Just s -> f s + Nothing -> pure $ Nothing + -- $format -- Combine logger formatting functions to make your -- 'XMonad.Hooks.DynamicLog.ppExtras' more colorful and readable. @@ -192,7 +260,7 @@ logCurrent = withWindowSet $ return . Just . W.currentTag -- > myLogHook = dynamicLogWithPP def { -- > -- skipped -- > , ppExtras = [lLoad, lTitle, logSp 3, wrapL "[" "]" $ date "%a %d %b"] --- > , ppOrder = \(ws,l,_,xs) -> [l,ws] ++ xs +-- > , ppOrder = \(ws:l:_:xs) -> [l,ws] ++ xs -- > } -- > where -- > -- lTitle = fixedWidthL AlignCenter "." 99 . dzenColorL "cornsilk3" "" . padL . shortenL 80 $ logTitle