Skip to content

Commit

Permalink
Deprecate runOnWorkspaces in favour of traverseWorkspaces
Browse files Browse the repository at this point in the history
`runOnWorkspaces` was a questionable existence in various ways:

  * It traversed the workspaces in a unexpected, nonstandard order.

  * It needlessly utilised a non-exhaustive pattern match, abusing
    first `MonadFail` then irrefutability to evade warning.

  * It was used nowhere in contrib, once in core---that sole use with a
    pure function.

  * Even after generalisation, it still has a bad type, both misleading and
    lacking in parametricity. Specialising the `StackSet` traversal to the
    `WindowSet` in `XState` gives the function too much power, and suggests
    that it's using that power to provide special support for `WindowSet`
    modifications when in fact it does no such thing.

To resolve these issues, the workspace traversal logic is written as
`traverseWorkspaces` in `X.StackSet`, and `mapWorkspaces` written atop
that via `Identity`. The latter then replaces the sole use of
`runOnWorkspaces`, condemning it to deprecation.
  • Loading branch information
LSLeary committed Dec 19, 2022
1 parent 2bf9487 commit 7e03677
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Breaking Changes

* Deprecated `runOnWorkspaces`.

* MVDT:

* The type of `runX` has changed.
Expand All @@ -28,6 +30,8 @@

### Enhancements

* X.StackSet now provides `mapWorkspaces` and `traverseWorkspaces`.

* MVDT:

* X actions can now be combined without performing spurious refreshes.
Expand Down
11 changes: 5 additions & 6 deletions src/XMonad/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE BlockArguments #-}

-----------------------------------------------------------------------------
-- |
Expand Down Expand Up @@ -473,13 +474,11 @@ xmessage msg = void . xfork $ do

-- | This is basically a map function, running a function in the 'X' monad on
-- each workspace with the output of that function being the modified workspace.
{-# DEPRECATED runOnWorkspaces "Use `traverseWorkspaces`." #-}
runOnWorkspaces :: MonadState XState m => (WindowSpace -> m WindowSpace) -> m ()
runOnWorkspaces job = do
ws <- gets windowset
h <- mapM job $ hidden ws
~(c:v) <- mapM (\s -> (\w -> s { workspace = w}) <$> job (workspace s))
$ current ws : visible ws
modify $ \s -> s { windowset = ws { current = c, visible = v, hidden = h } }
runOnWorkspaces job = withWindowSet \ws -> do
ws' <- traverseWorkspaces job ws
modify \st -> st{ windowset = ws' }

-- | All the directories that xmonad will use. They will be used for
-- the following purposes:
Expand Down
2 changes: 1 addition & 1 deletion src/XMonad/Operations.hs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ respace
=> WorkspaceId -> (WindowSpace -> WindowSpace) -> m ()
respace i f = do
visibles <- gets (fmap (W.tag . W.workspace) . W.screens . windowset)
runOnWorkspaces \ww -> pure if W.tag ww == i
norefresh . windows $ W.mapWorkspaces \ww -> if W.tag ww == i
then f ww
else ww
when (i `elem` visibles) refresh
Expand Down
21 changes: 21 additions & 0 deletions src/XMonad/StackSet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ module XMonad.StackSet (
-- * Modifying the stackset
-- $modifyStackset
insertUp, delete, delete', filter,
mapWorkspaces, traverseWorkspaces,
-- * Setting the master window
-- $settingMW
swapUp, swapDown, swapMaster, shiftMaster, modify, modify', float, sink, -- needed by users
Expand All @@ -54,6 +55,8 @@ module XMonad.StackSet (

import Prelude hiding (filter)
import Control.Applicative.Backwards (Backwards (Backwards, forwards))
import Data.Functor ((<&>))
import Data.Functor.Identity
import Data.Foldable (foldr, toList)
import Data.Maybe (listToMaybe,isJust,fromMaybe)
import qualified Data.List as L (deleteBy,find,splitAt,filter,nub)
Expand Down Expand Up @@ -517,6 +520,24 @@ delete' w s = s { current = removeFromScreen (current s)
where removeFromWorkspace ws = ws { stack = stack ws >>= filter (/=w) }
removeFromScreen scr = scr { workspace = removeFromWorkspace (workspace scr) }

-- | Map over the 'Workspace's of a 'StackSet'.
mapWorkspaces
:: (Workspace i l a -> Workspace i' l' a)
-> StackSet i l a sid sd -> StackSet i' l' a sid sd
mapWorkspaces f = runIdentity . traverseWorkspaces (Identity . f)

-- | 'traverse' the 'Workspace's of a 'StackSet'.
traverseWorkspaces
:: Applicative f
=> (Workspace i l a -> f (Workspace i' l' a))
-> StackSet i l a sid sd -> f (StackSet i' l' a sid sd)
traverseWorkspaces f s = StackSet
<$> onScreen (current s)
<*> traverse onScreen (visible s)
<*> traverse f (hidden s)
<*> pure (floating s)
where onScreen scr = f (workspace scr) <&> \w -> scr{ workspace = w }

------------------------------------------------------------------------

-- | Given a window, and its preferred rectangle, set it as floating
Expand Down

0 comments on commit 7e03677

Please sign in to comment.