{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE LambdaCase   #-}
--------------------------------------------------------------------
-- |
-- Module      :  XMonad.Prelude
-- Description :  Utility functions and re-exports.
-- Copyright   :  slotThe <soliditsallgood@mailbox.org>
-- License     :  BSD3-style (see LICENSE)
--
-- Maintainer  :  slotThe <soliditsallgood@mailbox.org>
--
-- Utility functions and re-exports for a more ergonomic developing
-- experience.  Users themselves will not find much use here.
--
--------------------------------------------------------------------
module XMonad.Prelude (
    module Exports,
    fi,
    chunksOf,
    (.:),
    (!?),
    NonEmpty((:|)),
    notEmpty,
    safeGetWindowAttributes,
) where

import Foreign (alloca, peek)
import XMonad

import Control.Applicative as Exports
import Control.Monad       as Exports
import Data.Bool           as Exports
import Data.Char           as Exports
import Data.Foldable       as Exports
import Data.Function       as Exports
import Data.Functor        as Exports
import Data.List           as Exports
import Data.Maybe          as Exports
import Data.Monoid         as Exports
import Data.Traversable    as Exports

import Data.List.NonEmpty (NonEmpty((:|)))
import GHC.Stack

-- | Short for 'fromIntegral'.
fi :: (Integral a, Num b) => a -> b
fi :: a -> b
fi = a -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral

-- | Given a maximum length, splits a list into sublists
--
-- >>> chunksOf 5 (take 30 $ repeat 'a')
-- ["aaaaa","aaaaa","aaaaa","aaaaa","aaaaa","aaaaa"]
chunksOf :: Int -> [a] -> [[a]]
chunksOf :: Int -> [a] -> [[a]]
chunksOf Int
_ [] = []
chunksOf Int
i [a]
xs = [a]
chunk [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: Int -> [a] -> [[a]]
forall a. Int -> [a] -> [[a]]
chunksOf Int
i [a]
rest
  where !([a]
chunk, [a]
rest) = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
i [a]
xs

-- | Safe version of '(!!)'.
(!?) :: [a] -> Int -> Maybe a
!? :: [a] -> Int -> Maybe a
(!?) [a]
xs Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Maybe a
forall a. Maybe a
Nothing
          | Bool
otherwise = [a] -> Maybe a
forall a. [a] -> Maybe a
listToMaybe ([a] -> Maybe a) -> [a] -> Maybe a
forall a b. (a -> b) -> a -> b
$ Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
n [a]
xs

-- | Multivariant composition.
--
-- > f .: g ≡ (f .) . g ≡ \c d -> f (g c d)
(.:) :: (a -> b) -> (c -> d -> a) -> c -> d -> b
.: :: (a -> b) -> (c -> d -> a) -> c -> d -> b
(.:) = ((d -> a) -> d -> b) -> (c -> d -> a) -> c -> d -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (((d -> a) -> d -> b) -> (c -> d -> a) -> c -> d -> b)
-> ((a -> b) -> (d -> a) -> d -> b)
-> (a -> b)
-> (c -> d -> a)
-> c
-> d
-> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b) -> (d -> a) -> d -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.)

-- | 'Data.List.NonEmpty.fromList' with a better error message. Useful to
-- silence GHC's Pattern match(es) are non-exhaustive warning in places where
-- the programmer knows it's always non-empty, but it's infeasible to express
-- that in the type system.
notEmpty :: HasCallStack => [a] -> NonEmpty a
notEmpty :: [a] -> NonEmpty a
notEmpty [] = [Char] -> NonEmpty a
forall a. HasCallStack => [Char] -> a
error [Char]
"unexpected empty list"
notEmpty (a
x:[a]
xs) = a
x a -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:| [a]
xs

-- | A safe version of 'Graphics.X11.Extras.getWindowAttributes'.
safeGetWindowAttributes :: Window -> X (Maybe WindowAttributes)
safeGetWindowAttributes :: Window -> X (Maybe WindowAttributes)
safeGetWindowAttributes Window
w = (Display -> X (Maybe WindowAttributes))
-> X (Maybe WindowAttributes)
forall a. (Display -> X a) -> X a
withDisplay ((Display -> X (Maybe WindowAttributes))
 -> X (Maybe WindowAttributes))
-> (Display -> X (Maybe WindowAttributes))
-> X (Maybe WindowAttributes)
forall a b. (a -> b) -> a -> b
$ \Display
dpy -> IO (Maybe WindowAttributes) -> X (Maybe WindowAttributes)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO (Maybe WindowAttributes) -> X (Maybe WindowAttributes))
-> ((Ptr WindowAttributes -> IO (Maybe WindowAttributes))
    -> IO (Maybe WindowAttributes))
-> (Ptr WindowAttributes -> IO (Maybe WindowAttributes))
-> X (Maybe WindowAttributes)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ptr WindowAttributes -> IO (Maybe WindowAttributes))
-> IO (Maybe WindowAttributes)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr WindowAttributes -> IO (Maybe WindowAttributes))
 -> X (Maybe WindowAttributes))
-> (Ptr WindowAttributes -> IO (Maybe WindowAttributes))
-> X (Maybe WindowAttributes)
forall a b. (a -> b) -> a -> b
$ \Ptr WindowAttributes
p ->
  Display -> Window -> Ptr WindowAttributes -> IO Status
xGetWindowAttributes Display
dpy Window
w Ptr WindowAttributes
p IO Status
-> (Status -> IO (Maybe WindowAttributes))
-> IO (Maybe WindowAttributes)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Status
0 -> Maybe WindowAttributes -> IO (Maybe WindowAttributes)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe WindowAttributes
forall a. Maybe a
Nothing
    Status
_ -> WindowAttributes -> Maybe WindowAttributes
forall a. a -> Maybe a
Just (WindowAttributes -> Maybe WindowAttributes)
-> IO WindowAttributes -> IO (Maybe WindowAttributes)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr WindowAttributes -> IO WindowAttributes
forall a. Storable a => Ptr a -> IO a
peek Ptr WindowAttributes
p