    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Actions.PerWindowKeys
    -- Description :  Define key-bindings on a per-window basis.
    -- Copyright   :  (c) Wilson Sales, 2019
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  Wilson Sales <spoonm@spoonm.org>
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Define key-bindings on a per-window basis.
    --
    -----------------------------------------------------------------------------

    module XMonad.Actions.PerWindowKeys (
                                        -- * Usage
                                        -- $usage
                                        bindAll,
                                        bindFirst
                                       ) where

    import XMonad

    -- $usage
    --
    -- You can use this module with the following in your @xmonad.hs@:
    --
    -- >  import XMonad.Actions.PerWindowKeys
    --
    -- >   ,((0, xK_F2), bindFirst [(className =? "firefox", spawn "dmenu"), (isFloat, withFocused $ windows . W.sink)])
    --
    -- >   ,((0, xK_F3), bindAll [(isDialog, kill), (pure True, doSomething)])
    --
    -- If you want an action that will always run, but also want to do something for
    -- other queries, you can use @'bindAll' [(query1, action1), ..., (pure True,
    -- alwaysDoThisAction)]@.
    --
    -- Similarly, if you want a default action to be run if all the others failed,
    -- you can use @'bindFirst' [(query1, action1), ..., (pure True,
    -- doThisIfTheOthersFail)]@.
    --
    -- For detailed instructions on editing your key bindings, see
    -- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.

    -- | Run an action if a Query holds true. Doesn't stop at the first one that
    -- does, however, and could potentially run all actions.
    bindAll :: [(Query Bool, X ())] -> X ()
    bindAll :: [(Query Bool, X ())] -> X ()
    bindAll = ((Query Bool, X ()) -> X ()) -> [(Query Bool, X ())] -> X ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (Query Bool, X ()) -> X ()
    choose where
      choose :: (Query Bool, X ()) -> X ()
    choose (Query Bool
    mh,X ()
    action) = (Window -> X ()) -> X ()
    withFocused ((Window -> X ()) -> X ()) -> (Window -> X ()) -> X ()
    forall a b. (a -> b) -> a -> b
    $ \Window
    w -> X Bool -> X () -> X ()
    whenX (Query Bool -> Window -> X Bool
    forall a. Query a -> Window -> X a
    runQuery Query Bool
    mh Window
    w) X ()
    action

    -- | Run the action paired with the first Query that holds true.
    bindFirst :: [(Query Bool, X ())] -> X ()
    bindFirst :: [(Query Bool, X ())] -> X ()
    bindFirst = (Window -> X ()) -> X ()
    withFocused ((Window -> X ()) -> X ())
    -> ([(Query Bool, X ())] -> Window -> X ())
    -> [(Query Bool, X ())]
    -> X ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [(Query Bool, X ())] -> Window -> X ()
    chooseOne

    chooseOne :: [(Query Bool, X ())] -> Window -> X ()
    chooseOne :: [(Query Bool, X ())] -> Window -> X ()
    chooseOne [] Window
    _ = () -> X ()
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    chooseOne ((Query Bool
    mh,X ()
    a):[(Query Bool, X ())]
    bs) Window
    w = do
      Bool
    c <- Query Bool -> Window -> X Bool
    forall a. Query a -> Window -> X a
    runQuery Query Bool
    mh Window
    w
      if Bool
    c then X ()
    a
           else [(Query Bool, X ())] -> Window -> X ()
    chooseOne [(Query Bool, X ())]
    bs Window
    w