Add xmobarProp, statusBarProp, and statusBarPropTo

In an effort to modernize XMonad.Hooks.DynamicLog (and thus to stop
recommending pipes as the best way to interface with xmobar), implement
property log based solutions for the most important functions.  Sadly
dzen does not seem to support this kind of interfacing with xmonad.

The descriptions of xmobar, statusBar, and statusBar' have been updated
to reflect that they should be seen as secondary choices.
This commit is contained in:
slotThe
2020-11-17 17:42:03 +01:00
parent 35e794b1b2
commit 9b6c098c9c

View File

@@ -25,7 +25,10 @@ module XMonad.Hooks.DynamicLog (
-- * Drop-in loggers -- * Drop-in loggers
dzen, dzen,
dzenWithFlags, dzenWithFlags,
xmobarProp,
xmobar, xmobar,
statusBarProp,
statusBarPropTo,
statusBar, statusBar,
statusBar', statusBar',
dynamicLog, dynamicLog,
@@ -62,20 +65,23 @@ module XMonad.Hooks.DynamicLog (
import Codec.Binary.UTF8.String (encodeString) import Codec.Binary.UTF8.String (encodeString)
import Control.Applicative (liftA2) import Control.Applicative (liftA2)
import Control.Monad (msum) import Control.Monad (msum)
import Data.Char ( isSpace, ord ) import Data.Char (isSpace, ord)
import Data.List (intersperse, stripPrefix, isPrefixOf, sortBy) import Data.List (intersperse, isPrefixOf, sortBy, stripPrefix)
import Data.Maybe ( isJust, catMaybes, mapMaybe, fromMaybe ) import Data.Map (Map)
import Data.Ord ( comparing ) import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe)
import qualified Data.Map as M import Data.Ord (comparing)
import qualified Data.Map as M
import qualified XMonad.StackSet as S import qualified XMonad.StackSet as S
import Foreign.C (CChar) import Foreign.C (CChar)
import XMonad import XMonad
import XMonad.Util.WorkspaceCompare
import XMonad.Util.NamedWindows import XMonad.Util.NamedWindows
import XMonad.Util.Run import XMonad.Util.Run
import XMonad.Util.SpawnOnce (spawnOnce)
import XMonad.Util.WorkspaceCompare
import XMonad.Layout.LayoutModifier import XMonad.Layout.LayoutModifier
import XMonad.Hooks.UrgencyHook import XMonad.Hooks.UrgencyHook
@@ -201,22 +207,55 @@ dzen conf = dzenWithFlags flags conf
bg = "'#3f3c6d'" bg = "'#3f3c6d'"
flags = "-e 'onstart=lower' -dock -w 400 -ta l -fg " ++ fg ++ " -bg " ++ bg flags = "-e 'onstart=lower' -dock -w 400 -ta l -fg " ++ fg ++ " -bg " ++ bg
-- | Run xmonad with a property-based xmobar status bar set to some nice
-- | Run xmonad with a xmobar status bar set to some nice defaults. -- defaults.
-- --
-- > main = xmonad =<< xmobar myConfig -- > main = xmonad =<< xmobar myConfig
-- > -- >
-- > myConfig = def { ... } -- > myConfig = def { ... }
-- --
xmobarProp :: LayoutClass l Window
=> XConfig l -> IO (XConfig (ModifiedLayout AvoidStruts l))
xmobarProp conf = statusBarProp "xmobar" xmobarPP toggleStrutsKey conf
-- | This function works like 'xmobarProp', but uses pipes instead of property
-- logs.
--
-- This works pretty much the same as 'dzen' function above. -- This works pretty much the same as 'dzen' function above.
-- --
xmobar :: LayoutClass l Window xmobar :: LayoutClass l Window
=> XConfig l -> IO (XConfig (ModifiedLayout AvoidStruts l)) => XConfig l -> IO (XConfig (ModifiedLayout AvoidStruts l))
xmobar conf = statusBar "xmobar" xmobarPP toggleStrutsKey conf xmobar conf = statusBar "xmobar" xmobarPP toggleStrutsKey conf
-- | Modifies the given base configuration to launch the given status bar, -- | Modifies the given base configuration to launch the given status bar, send
-- send status information to that bar, and allocate space on the screen edges -- status information to that bar (via property logs), and allocate space on the
-- for the bar. -- screen edges for the bar.
statusBarProp :: LayoutClass l Window
=> String -- ^ the command line to launch the status bar
-> PP -- ^ the pretty printing options
-> (XConfig Layout -> (KeyMask, KeySym))
-- ^ the desired key binding to toggle bar visibility
-> XConfig l -- ^ the base config
-> IO (XConfig (ModifiedLayout AvoidStruts l))
statusBarProp = statusBarPropTo "_XMONAD_LOG"
-- | Like 'statusBarProp', but one is able to specify the property to be written
-- to. This property is of type @UTF8_STRING@. The string must have been
-- processed by 'encodeString' ('dynamicLogString' does this).
statusBarPropTo :: LayoutClass l Window
=> String -- ^ Property to write the string to
-> String -- ^ the command line to launch the status bar
-> PP -- ^ the pretty printing options
-> (XConfig Layout -> (KeyMask, KeySym))
-- ^ the desired key binding to toggle bar visibility
-> XConfig l -- ^ the base config
-> IO (XConfig (ModifiedLayout AvoidStruts l))
statusBarPropTo prop cmd pp =
makeStatusBar
(xmonadPropLog' prop =<< dynamicLogString pp)
(spawnOnce cmd)
-- | Like 'statusBarProp', but uses pipes instead of property logs.
statusBar :: LayoutClass l Window statusBar :: LayoutClass l Window
=> String -- ^ the command line to launch the status bar => String -- ^ the command line to launch the status bar
-> PP -- ^ the pretty printing options -> PP -- ^ the pretty printing options
@@ -224,10 +263,12 @@ statusBar :: LayoutClass l Window
-- ^ the desired key binding to toggle bar visibility -- ^ the desired key binding to toggle bar visibility
-> XConfig l -- ^ the base config -> XConfig l -- ^ the base config
-> IO (XConfig (ModifiedLayout AvoidStruts l)) -> IO (XConfig (ModifiedLayout AvoidStruts l))
statusBar cmd pp = statusBar' cmd (return pp) statusBar cmd pp k conf = do
h <- spawnPipe cmd
makeStatusBar (dynamicLogWithPP pp{ ppOutput = hPutStrLn h }) mempty k conf
-- | Like 'statusBar' with the pretty printing options embedded in the -- | Like 'statusBar' with the pretty printing options embedded in the
-- X monad. The X PP value is re-executed every time the 'logHook' runs. -- 'X' monad. The X PP value is re-executed every time the 'logHook' runs.
-- Useful if printing options need to be modified dynamically. -- Useful if printing options need to be modified dynamically.
statusBar' :: LayoutClass l Window statusBar' :: LayoutClass l Window
=> String -- ^ the command line to launch the status bar => String -- ^ the command line to launch the status bar
@@ -238,15 +279,29 @@ statusBar' :: LayoutClass l Window
-> IO (XConfig (ModifiedLayout AvoidStruts l)) -> IO (XConfig (ModifiedLayout AvoidStruts l))
statusBar' cmd xpp k conf = do statusBar' cmd xpp k conf = do
h <- spawnPipe cmd h <- spawnPipe cmd
return $ docks $ conf makeStatusBar
{ layoutHook = avoidStruts (layoutHook conf) (xpp >>= \pp -> dynamicLogWithPP pp{ ppOutput = hPutStrLn h })
, logHook = do mempty
logHook conf k
pp <- xpp conf
dynamicLogWithPP pp { ppOutput = hPutStrLn h }
, keys = liftA2 M.union keys' (keys conf) -- | Helper function to make status bars. This should not be used on its own;
} -- use 'statusBarProp' or 'statusBar' (or their respective variants) instead.
where makeStatusBar :: LayoutClass l Window
=> X () -- ^ 'logHook' to execute
-> X () -- ^ 'startupHook' to execute
-> (XConfig Layout -> (KeyMask, KeySym))
-- ^ the desired key binding to toggle bar visibility
-> XConfig l -- ^ the base config
-> IO (XConfig (ModifiedLayout AvoidStruts l))
makeStatusBar lh sh k conf = pure $ docks $ conf
{ layoutHook = avoidStruts (layoutHook conf)
, logHook = logHook conf *> lh
, keys = (<>) <$> keys' <*> keys conf
, startupHook = startupHook conf *> sh
}
where
keys' :: XConfig Layout -> Map (KeyMask, KeySym) (X ())
keys' = (`M.singleton` sendMessage ToggleStruts) . k keys' = (`M.singleton` sendMessage ToggleStruts) . k
-- | Write a string to a property on the root window. This property is of -- | Write a string to a property on the root window. This property is of