    -----------------------------------------------------------------------------
    -- |
    -- Module       : XMonad.Actions.FocusNth
    -- Copyright    : (c) Karsten Schoelzel <kuser@gmx.de>
    -- License      : BSD
    --
    -- Maintainer   : Karsten Schoelzel <kuser@gmx.de>
    -- Stability    : stable
    -- Portability  : unportable
    --
    -- Focus the nth window of the current workspace.
    -----------------------------------------------------------------------------

    module XMonad.Actions.FocusNth (
                     -- * Usage
                     -- $usage
                     focusNth,focusNth',
                     swapNth,swapNth') where

    import XMonad.StackSet
    import XMonad

    -- $usage
    -- Add the import to your @~\/.xmonad\/xmonad.hs@:
    --
    -- > import XMonad.Actions.FocusNth
    --
    -- Then add appropriate keybindings, for example:
    --
    -- > -- mod4-[1..9] @@ Switch to window N
    -- > ++ [((modm, k), focusNth i)
    -- >     | (i, k) <- zip [0 .. 8] [xK_1 ..]]
    --
    -- For detailed instructions on editing your key bindings, see
    -- "XMonad.Doc.Extending#Editing_key_bindings".

    -- | Give focus to the nth window of the current workspace.
    focusNth :: Int -> X ()
    focusNth :: Int -> X ()
    focusNth = (WindowSet -> WindowSet) -> X ()
    windows ((WindowSet -> WindowSet) -> X ())
    -> (Int -> WindowSet -> WindowSet) -> Int -> X ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Stack Window -> Stack Window) -> WindowSet -> WindowSet
    forall a i l s sd.
    (Stack a -> Stack a) -> StackSet i l a s sd -> StackSet i l a s sd
    modify' ((Stack Window -> Stack Window) -> WindowSet -> WindowSet)
    -> (Int -> Stack Window -> Stack Window)
    -> Int
    -> WindowSet
    -> WindowSet
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Stack Window -> Stack Window
    forall a. Int -> Stack a -> Stack a
    focusNth'

    focusNth' :: Int -> Stack a -> Stack a
    focusNth' :: Int -> Stack a -> Stack a
    focusNth' n :: Int
    n s :: Stack a
    s@(Stack _ ls :: [a]
    ls rs :: [a]
    rs) | (Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0) Bool -> Bool -> Bool
    || (Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length([a]
    ls) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length([a]
    rs)) = Stack a
    s
                                  | Bool
    otherwise = Int -> [a] -> Stack a
    forall a. Int -> [a] -> Stack a
    listToStack Int
    n (Stack a -> [a]
    forall a. Stack a -> [a]
    integrate Stack a
    s)

    -- | Swap current window with nth. Focus stays in the same position
    swapNth :: Int -> X ()
    swapNth :: Int -> X ()
    swapNth = (WindowSet -> WindowSet) -> X ()
    windows ((WindowSet -> WindowSet) -> X ())
    -> (Int -> WindowSet -> WindowSet) -> Int -> X ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Stack Window -> Stack Window) -> WindowSet -> WindowSet
    forall a i l s sd.
    (Stack a -> Stack a) -> StackSet i l a s sd -> StackSet i l a s sd
    modify' ((Stack Window -> Stack Window) -> WindowSet -> WindowSet)
    -> (Int -> Stack Window -> Stack Window)
    -> Int
    -> WindowSet
    -> WindowSet
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Stack Window -> Stack Window
    forall a. Int -> Stack a -> Stack a
    swapNth'

    swapNth' :: Int -> Stack a -> Stack a
    swapNth' :: Int -> Stack a -> Stack a
    swapNth' n :: Int
    n s :: Stack a
    s@(Stack c :: a
    c l :: [a]
    l r :: [a]
    r)
      | (Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0) Bool -> Bool -> Bool
    || (Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    l Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    r) Bool -> Bool -> Bool
    || (Int
    n Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    l) = Stack a
    s
      | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    l = let (nl :: [a]
    nl, nc :: a
    nc:nr :: [a]
    nr) = Int -> [a] -> ([a], [a])
    forall a. Int -> [a] -> ([a], [a])
    splitAt ([a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    l Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1) [a]
    l in a -> [a] -> [a] -> Stack a
    forall a. a -> [a] -> [a] -> Stack a
    Stack a
    nc ([a]
    nl [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ a
    c a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a]
    nr) [a]
    r
      | Bool
    otherwise    = let (nl :: [a]
    nl, nc :: a
    nc:nr :: [a]
    nr) = Int -> [a] -> ([a], [a])
    forall a. Int -> [a] -> ([a], [a])
    splitAt (Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    l Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1) [a]
    r in a -> [a] -> [a] -> Stack a
    forall a. a -> [a] -> [a] -> Stack a
    Stack a
    nc [a]
    l ([a]
    nl [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ a
    c a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a]
    nr)

    listToStack :: Int -> [a] -> Stack a
    listToStack :: Int -> [a] -> Stack a
    listToStack n :: Int
    n l :: [a]
    l = a -> [a] -> [a] -> Stack a
    forall a. a -> [a] -> [a] -> Stack a
    Stack a
    t [a]
    ls [a]
    rs
     where
        (t :: a
    t:rs :: [a]
    rs)    = Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    drop Int
    n [a]
    l
        ls :: [a]
    ls        = [a] -> [a]
    forall a. [a] -> [a]
    reverse (Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take Int
    n [a]
    l)