    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Actions.SwapWorkspaces
    -- Description :  Swap workspace tags without having to move individual windows.
    -- Copyright   :  (c) Devin Mullins <me@twifkak.com>
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  Devin Mullins <me@twifkak.com>
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Lets you swap workspace tags, so you can keep related ones next to
    -- each other, without having to move individual windows.
    --
    -----------------------------------------------------------------------------

    module XMonad.Actions.SwapWorkspaces (
                                         -- * Usage
                                         -- $usage
                                         swapWithCurrent,
                                         swapTo,
                                         swapWorkspaces,
                                         Direction1D(..)
                                        ) where

    import XMonad (windows, X())
    import XMonad.StackSet
    import XMonad.Actions.CycleWS
    import XMonad.Util.WorkspaceCompare

    -- $usage
    -- Add this import to your @xmonad.hs@:
    --
    -- > import XMonad.Actions.SwapWorkspaces
    --
    -- Then throw something like this in your keys definition:
    --
    -- > ++
    -- > [((modm .|. controlMask, k), windows $ swapWithCurrent i)
    -- >     | (i, k) <- zip workspaces [xK_1 ..]]
    --
    -- After installing this update, if you're on workspace 1, hitting mod-ctrl-5
    -- will swap workspaces 1 and 5.
    --
    -- For detailed instructions on editing your key bindings, see
    -- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.

    -- | Swaps the currently focused workspace with the given workspace tag, via
    --   @swapWorkspaces@.
    swapWithCurrent :: Eq i => i -> StackSet i l a s sd -> StackSet i l a s sd
    swapWithCurrent :: forall i l a s sd.
    Eq i =>
    i -> StackSet i l a s sd -> StackSet i l a s sd
    swapWithCurrent i
    t StackSet i l a s sd
    s = i -> i -> StackSet i l a s sd -> StackSet i l a s sd
    forall i l a s sd.
    Eq i =>
    i -> i -> StackSet i l a s sd -> StackSet i l a s sd
    swapWorkspaces i
    t (StackSet i l a s sd -> i
    forall i l a s sd. StackSet i l a s sd -> i
    currentTag StackSet i l a s sd
    s) StackSet i l a s sd
    s

    -- | Say @swapTo Next@ or @swapTo Prev@ to move your current workspace.
    -- This is an @X ()@ so can be hooked up to your keybindings directly.
    swapTo :: Direction1D -> X ()
    swapTo :: Direction1D -> X ()
    swapTo Direction1D
    dir = X WorkspaceSort -> Direction1D -> WSType -> Int -> X WorkspaceId
    findWorkspace X WorkspaceSort
    getSortByIndex Direction1D
    dir WSType
    anyWS Int
    1 X WorkspaceId -> (WorkspaceId -> X ()) -> X ()
    forall a b. X a -> (a -> X b) -> X b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (WindowSet -> WindowSet) -> X ()
    windows ((WindowSet -> WindowSet) -> X ())
    -> (WorkspaceId -> WindowSet -> WindowSet) -> WorkspaceId -> X ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WorkspaceId -> WindowSet -> WindowSet
    forall i l a s sd.
    Eq i =>
    i -> StackSet i l a s sd -> StackSet i l a s sd
    swapWithCurrent

    -- | Takes two workspace tags and an existing XMonad.StackSet and returns a new
    --   one with the two corresponding workspaces' tags swapped.
    swapWorkspaces :: Eq i => i -> i -> StackSet i l a s sd -> StackSet i l a s sd
    swapWorkspaces :: forall i l a s sd.
    Eq i =>
    i -> i -> StackSet i l a s sd -> StackSet i l a s sd
    swapWorkspaces i
    t1 i
    t2 = (Workspace i l a -> Workspace i l a)
    -> StackSet i l a s sd -> StackSet i l a s sd
    forall i l a s sd.
    (Workspace i l a -> Workspace i l a)
    -> StackSet i l a s sd -> StackSet i l a s sd
    mapWorkspace Workspace i l a -> Workspace i l a
    forall {l} {a}. Workspace i l a -> Workspace i l a
    swap
        where swap :: Workspace i l a -> Workspace i l a
    swap Workspace i l a
    w
                | Workspace i l a -> i
    forall i l a. Workspace i l a -> i
    tag Workspace i l a
    w i -> i -> Bool
    forall a. Eq a => a -> a -> Bool
    == i
    t1 = Workspace i l a
    w { tag = t2 }
                | Workspace i l a -> i
    forall i l a. Workspace i l a -> i
    tag Workspace i l a
    w i -> i -> Bool
    forall a. Eq a => a -> a -> Bool
    == i
    t2 = Workspace i l a
    w { tag = t1 }
                | Bool
    otherwise = Workspace i l a
    w