mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-05-19 11:30:22 -07:00
With XDG support so firmly ingrained now, it's about time we stop hard-coding the configuration path in the docs.
178 lines
6.1 KiB
Haskell
178 lines
6.1 KiB
Haskell
-----------------------------------------------------------------------------
|
|
-- |
|
|
-- Module : XMonad.Actions.DynamicWorkspaceGroups
|
|
-- Description : Dynamically manage workspace groups in multi-head setups.
|
|
-- Copyright : (c) Brent Yorgey 2009
|
|
-- License : BSD-style (see LICENSE)
|
|
--
|
|
-- Maintainer : <byorgey@gmail.com>
|
|
-- Stability : experimental
|
|
-- Portability : unportable
|
|
--
|
|
-- Dynamically manage \"workspace groups\", sets of workspaces being
|
|
-- used together for some common task or purpose, to allow switching
|
|
-- between workspace groups in a single action. Note that this only
|
|
-- makes sense for multi-head setups.
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
module XMonad.Actions.DynamicWorkspaceGroups
|
|
( -- * Usage
|
|
-- $usage
|
|
|
|
WSGroupId
|
|
|
|
, addRawWSGroup
|
|
, addWSGroup
|
|
, addCurrentWSGroup
|
|
, forgetWSGroup
|
|
, viewWSGroup
|
|
|
|
, promptWSGroupView
|
|
, promptWSGroupAdd
|
|
, promptWSGroupForget
|
|
|
|
, WSGPrompt
|
|
-- * TopicSpace Integration
|
|
-- $topics
|
|
, viewTopicGroup
|
|
, promptTopicGroupView
|
|
) where
|
|
|
|
import Control.Arrow ((&&&))
|
|
import qualified Data.Map as M
|
|
|
|
import XMonad
|
|
import XMonad.Prelude (find, for_)
|
|
import qualified XMonad.StackSet as W
|
|
|
|
import XMonad.Prompt
|
|
import qualified XMonad.Util.ExtensibleState as XS
|
|
import XMonad.Actions.TopicSpace
|
|
|
|
-- $usage
|
|
-- You can use this module by importing it into your @xmonad.hs@ file:
|
|
--
|
|
-- > import XMonad.Actions.DynamicWorkspaceGroups
|
|
--
|
|
-- Then add keybindings like the following (this example uses
|
|
-- "XMonad.Util.EZConfig"-style keybindings, but this is not necessary):
|
|
--
|
|
-- > , ("M-y n", promptWSGroupAdd myXPConfig "Name this group: ")
|
|
-- > , ("M-y g", promptWSGroupView myXPConfig "Go to group: ")
|
|
-- > , ("M-y d", promptWSGroupForget myXPConfig "Forget group: ")
|
|
--
|
|
|
|
type WSGroup = [(ScreenId,WorkspaceId)]
|
|
|
|
type WSGroupId = String
|
|
|
|
newtype WSGroupStorage = WSG { unWSG :: M.Map WSGroupId WSGroup }
|
|
deriving (Read, Show)
|
|
|
|
withWSG :: (M.Map WSGroupId WSGroup -> M.Map WSGroupId WSGroup) -> WSGroupStorage -> WSGroupStorage
|
|
withWSG f = WSG . f . unWSG
|
|
|
|
instance ExtensionClass WSGroupStorage where
|
|
initialValue = WSG M.empty
|
|
extensionType = PersistentExtension
|
|
|
|
-- | Add a new workspace group of the given name, mapping to an
|
|
-- explicitly specified association between screen IDs and workspace
|
|
-- names. This function could be useful for, say, creating some
|
|
-- standard workspace groups in your startup hook.
|
|
addRawWSGroup :: WSGroupId -> [(ScreenId, WorkspaceId)] -> X ()
|
|
addRawWSGroup name = XS.modify . withWSG . M.insert name
|
|
|
|
-- | Add a new workspace group with the given name.
|
|
addWSGroup :: WSGroupId -> [WorkspaceId] -> X ()
|
|
addWSGroup name wids = withWindowSet $ \w -> do
|
|
let wss = map ((W.tag . W.workspace) &&& W.screen) $ W.screens w
|
|
wmap = mapM (strength . (flip lookup wss &&& id)) wids
|
|
for_ wmap (addRawWSGroup name)
|
|
where strength (ma, b) = ma >>= \a -> return (a,b)
|
|
|
|
-- | Give a name to the current workspace group.
|
|
addCurrentWSGroup :: WSGroupId -> X ()
|
|
addCurrentWSGroup name = withWindowSet $ \w ->
|
|
addWSGroup name $ map (W.tag . W.workspace) (reverse $ W.current w : W.visible w)
|
|
|
|
-- | Delete the named workspace group from the list of workspace
|
|
-- groups. Note that this has no effect on the workspaces involved;
|
|
-- it simply forgets the given name.
|
|
forgetWSGroup :: WSGroupId -> X ()
|
|
forgetWSGroup = XS.modify . withWSG . M.delete
|
|
|
|
-- | View the workspace group with the given name.
|
|
viewWSGroup :: WSGroupId -> X ()
|
|
viewWSGroup = viewGroup (windows . W.greedyView)
|
|
|
|
-- | Internal function for viewing a group.
|
|
viewGroup :: (WorkspaceId -> X ()) -> WSGroupId -> X ()
|
|
viewGroup fview name = do
|
|
WSG m <- XS.get
|
|
for_ (M.lookup name m) $
|
|
mapM_ (uncurry (viewWS fview))
|
|
|
|
-- | View the given workspace on the given screen, using the provided function.
|
|
viewWS :: (WorkspaceId -> X ()) -> ScreenId -> WorkspaceId -> X ()
|
|
viewWS fview sid wid = do
|
|
mw <- findScreenWS sid
|
|
case mw of
|
|
Just w -> do
|
|
windows $ W.view w
|
|
fview wid
|
|
Nothing -> return ()
|
|
|
|
-- | Find the workspace which is currently on the given screen.
|
|
findScreenWS :: ScreenId -> X (Maybe WorkspaceId)
|
|
findScreenWS sid = withWindowSet $
|
|
return . fmap (W.tag . W.workspace) . find ((==sid) . W.screen) . W.screens
|
|
|
|
newtype WSGPrompt = WSGPrompt String
|
|
|
|
instance XPrompt WSGPrompt where
|
|
showXPrompt (WSGPrompt s) = s
|
|
|
|
-- | Prompt for a workspace group to view.
|
|
promptWSGroupView :: XPConfig -> String -> X ()
|
|
promptWSGroupView = promptGroupView viewWSGroup
|
|
|
|
-- | Internal function for making a prompt to view a workspace group
|
|
promptGroupView :: (WSGroupId -> X ()) -> XPConfig -> String -> X ()
|
|
promptGroupView fview xp s = do
|
|
gs <- fmap (M.keys . unWSG) XS.get
|
|
mkXPrompt (WSGPrompt s) xp (mkComplFunFromList' xp gs) fview
|
|
|
|
-- | Prompt for a name for the current workspace group.
|
|
promptWSGroupAdd :: XPConfig -> String -> X ()
|
|
promptWSGroupAdd xp s =
|
|
mkXPrompt (WSGPrompt s) xp (const $ return []) addCurrentWSGroup
|
|
|
|
-- | Prompt for a workspace group to forget.
|
|
promptWSGroupForget :: XPConfig -> String -> X ()
|
|
promptWSGroupForget xp s = do
|
|
gs <- fmap (M.keys . unWSG) XS.get
|
|
mkXPrompt (WSGPrompt s) xp (mkComplFunFromList' xp gs) forgetWSGroup
|
|
|
|
-- $topics
|
|
-- You can use this module with "XMonad.Actions.TopicSpace" — just replace
|
|
-- 'promptWSGroupView' with 'promptTopicGroupView':
|
|
--
|
|
-- > , ("M-y n", promptWSGroupAdd myXPConfig "Name this group: ")
|
|
-- > , ("M-y g", promptTopicGroupView myTopicConfig myXPConfig "Go to group: ")
|
|
-- > , ("M-y d", promptWSGroupForget myXPConfig "Forget group: ")
|
|
--
|
|
-- It's also a good idea to replace 'spawn' with
|
|
-- 'XMonad.Actions.SpawnOn.spawnOn' or 'XMonad.Actions.SpawnOn.spawnHere' in
|
|
-- your topic actions, so everything is spawned where it should be.
|
|
|
|
-- | Prompt for a workspace group to view, treating the workspaces as topics.
|
|
promptTopicGroupView :: TopicConfig -> XPConfig -> String -> X ()
|
|
promptTopicGroupView = promptGroupView . viewTopicGroup
|
|
|
|
-- | View the workspace group with the given name, treating the workspaces as
|
|
-- topics.
|
|
viewTopicGroup :: TopicConfig -> WSGroupId -> X ()
|
|
viewTopicGroup = viewGroup . switchTopic
|