mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-08-21 23:13:48 -07:00
X.H.DynamicIcons: Use ppRename - simpler, better interop with other modules
This ports DynamicIcons to the recently introduced ppRename mechanism, which means DynamicIcons can now safely be combined with clickablePP, workspaceNamesPP and marshallPP. This also fixes DynamicIcons not working properly with urgent workspaces due to forgotten ppUrgent counterpart in data Icon. Also, ppVisibleNoWindows wouldn't work properly. The code is now considerably simpler, but we lost the ability to use different icons depending on whether the workspace is visible/hidden/urgent/etc. If anyone needs that, it can be worked around by using some markup that is later interpreted in ppVisible/ppHidden/ppUrgent/etc. Related: https://github.com/xmonad/xmonad-contrib/pull/481
This commit is contained in:
@@ -18,11 +18,11 @@ module XMonad.Hooks.DynamicIcons (
|
|||||||
-- $usage
|
-- $usage
|
||||||
|
|
||||||
-- * Creating Dynamic Icons
|
-- * Creating Dynamic Icons
|
||||||
dynamicLogIconsWithPP, dynamicIconsPP,
|
dynamicLogIconsWithPP, appIcon,
|
||||||
|
|
||||||
-- * Data Types
|
-- * Customization
|
||||||
appIcon, IconSet,
|
dynamicIconsPP, getWorkspaceIcons,
|
||||||
IconConfig(..), Icon(..),
|
IconConfig(..),
|
||||||
iconsFmtAppend, iconsFmtReplace, wrapUnwords,
|
iconsFmtAppend, iconsFmtReplace, wrapUnwords,
|
||||||
|
|
||||||
) where
|
) where
|
||||||
@@ -32,8 +32,9 @@ import qualified XMonad.StackSet as S
|
|||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
|
|
||||||
import XMonad.Hooks.DynamicLog
|
import XMonad.Hooks.DynamicLog
|
||||||
|
import Data.Functor ((<&>))
|
||||||
import Data.Traversable (for)
|
import Data.Traversable (for)
|
||||||
import Control.Monad ((<=<))
|
import Control.Monad ((<=<), (>=>))
|
||||||
|
|
||||||
-- $usage
|
-- $usage
|
||||||
-- Dynamically changes a 'Workspace's 'WorkspaceId' based on the 'Window's inside the Workspace.
|
-- Dynamically changes a 'Workspace's 'WorkspaceId' based on the 'Window's inside the Workspace.
|
||||||
@@ -65,48 +66,20 @@ import Control.Monad ((<=<))
|
|||||||
-- NOTE: You can use any string you want here. The example shown here, uses NerdFont Icons to represent open applications
|
-- NOTE: You can use any string you want here. The example shown here, uses NerdFont Icons to represent open applications
|
||||||
|
|
||||||
|
|
||||||
-- | Custom datatype for custom icons based on the state of the 'Workspace'
|
-- | Shortcut for configuring single icons.
|
||||||
-- For example,
|
appIcon :: String -> Query [String]
|
||||||
--
|
appIcon = pure . pure
|
||||||
-- > Icon "<bold>discord</bold>" "<bold>discord</bold>" "discord" ""
|
|
||||||
--
|
|
||||||
-- Then you can add it to your IconSet.
|
|
||||||
--
|
|
||||||
-- > icons :: IconSet
|
|
||||||
-- > icons = mconcat
|
|
||||||
-- > [ className =? "discord" --> pure [Icon "<bold>discord</bold>" "<bold>discord</bold>" "discord" ""]
|
|
||||||
-- > ]
|
|
||||||
data Icon = Icon
|
|
||||||
{ iconCurrent :: !String -- ^ If the 'Workspace' is the current workspace
|
|
||||||
, iconVisible :: !String -- ^ If the 'Workspace' is visible (Xinerama only)
|
|
||||||
, iconHidden :: !String -- ^ If the 'Workspace' isnt visible but still has windows
|
|
||||||
, iconHiddenNoWindows :: !String -- ^ If the 'Workspace' isnt visible and has no windows
|
|
||||||
}
|
|
||||||
|
|
||||||
-- | The set of Icons to use
|
|
||||||
type IconSet = Query [Icon]
|
|
||||||
|
|
||||||
baseIconSet :: String -> Icon
|
|
||||||
baseIconSet x =
|
|
||||||
Icon { iconCurrent = x
|
|
||||||
, iconVisible = x
|
|
||||||
, iconHidden = x
|
|
||||||
, iconHiddenNoWindows = x
|
|
||||||
}
|
|
||||||
|
|
||||||
-- | Create an 'IconSet' from a 'String'
|
|
||||||
appIcon :: String -> IconSet
|
|
||||||
appIcon x = pure [baseIconSet x]
|
|
||||||
|
|
||||||
-- | Adjusts the 'PP' and then runs 'dynamicLogWithPP'
|
-- | Adjusts the 'PP' and then runs 'dynamicLogWithPP'
|
||||||
dynamicLogIconsWithPP :: IconSet -- ^ The 'IconSet' to use
|
dynamicLogIconsWithPP :: Query [String] -- ^ The 'IconSet' to use
|
||||||
-> PP -- ^ The 'PP' to alter
|
-> PP -- ^ The 'PP' to alter
|
||||||
-> X () -- ^ The resulting 'X' action
|
-> X () -- ^ The resulting 'X' action
|
||||||
dynamicLogIconsWithPP iconset = dynamicLogWithPP <=< dynamicIconsPP def{ iconConfigIcons = iconset }
|
dynamicLogIconsWithPP q = dynamicLogWithPP <=< dynamicIconsPP def{ iconConfigIcons = q }
|
||||||
|
|
||||||
-- | Datatype for expanded 'Icon' configurations
|
-- | Datatype for expanded 'Icon' configurations
|
||||||
data IconConfig = IconConfig
|
data IconConfig = IconConfig
|
||||||
{ iconConfigIcons :: IconSet -- ^ The 'IconSet' to use
|
{ iconConfigIcons :: Query [String]
|
||||||
|
-- ^ What icons to use for each window.
|
||||||
, iconConfigFmt :: WorkspaceId -> [String] -> String
|
, iconConfigFmt :: WorkspaceId -> [String] -> String
|
||||||
-- ^ How to format the result, see 'iconsFmtReplace', 'iconsFmtAppend'.
|
-- ^ How to format the result, see 'iconsFmtReplace', 'iconsFmtAppend'.
|
||||||
}
|
}
|
||||||
@@ -166,20 +139,17 @@ wrapUnwords l r xs = wrap l r (unwords xs)
|
|||||||
-- | Modify "XMonad.Hooks.DynamicLog"\'s pretty-printing format to augment
|
-- | Modify "XMonad.Hooks.DynamicLog"\'s pretty-printing format to augment
|
||||||
-- workspace names with icons based on the contents (windows) of the workspace.
|
-- workspace names with icons based on the contents (windows) of the workspace.
|
||||||
dynamicIconsPP :: IconConfig -> PP -> X PP
|
dynamicIconsPP :: IconConfig -> PP -> X PP
|
||||||
dynamicIconsPP IconConfig{..} pp = do
|
dynamicIconsPP ic pp = getWorkspaceIcons ic <&> \ren -> pp{ ppRename = ppRename pp >=> ren }
|
||||||
icons <- getWorkspaceIcons iconConfigIcons
|
|
||||||
pure $ pp
|
|
||||||
{ ppCurrent = ppSection ppCurrent iconCurrent icons
|
|
||||||
, ppVisible = ppSection ppVisible iconVisible icons
|
|
||||||
, ppHidden = ppSection ppHidden iconHidden icons
|
|
||||||
, ppHiddenNoWindows = ppSection ppHiddenNoWindows iconHiddenNoWindows icons
|
|
||||||
}
|
|
||||||
where
|
|
||||||
ppSection ppField icField icons wks =
|
|
||||||
ppField pp $ iconConfigFmt wks $ map icField $ M.findWithDefault [] wks icons
|
|
||||||
|
|
||||||
getWorkspaceIcons :: IconSet -> X (M.Map WorkspaceId [Icon])
|
-- | Returns a function for 'ppRename' that augments workspaces with icons
|
||||||
getWorkspaceIcons iconSet = do
|
-- according to the provided 'IconConfig'.
|
||||||
|
getWorkspaceIcons :: IconConfig -> X (String -> WindowSpace -> String)
|
||||||
|
getWorkspaceIcons IconConfig{..} = fmt <$> getWorkspaceIcons' iconConfigIcons
|
||||||
|
where
|
||||||
|
fmt icons s w = iconConfigFmt s (M.findWithDefault [] (S.tag w) icons)
|
||||||
|
|
||||||
|
getWorkspaceIcons' :: Query [String] -> X (M.Map WorkspaceId [String])
|
||||||
|
getWorkspaceIcons' q = do
|
||||||
ws <- gets (S.workspaces . windowset)
|
ws <- gets (S.workspaces . windowset)
|
||||||
is <- for ws $ foldMap (runQuery iconSet) . S.integrate' . S.stack
|
is <- for ws $ foldMap (runQuery q) . S.integrate' . S.stack
|
||||||
pure $ M.fromList (zip (map S.tag ws) is)
|
pure $ M.fromList (zip (map S.tag ws) is)
|
||||||
|
Reference in New Issue
Block a user