{-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses, DeriveDataTypeable #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  XMonad.Util.WindowPropertiesRE
-- Copyright   :  (c) 2011 Ilya Portnov <portnov84@rambler.ru>
-- License     :  BSD3-style (see LICENSE)
--
-- Maintainer  :  Ilya Portnov <portnov84@rambler.ru>
-- Stability   :  unstable
-- Portability :  unportable
--
-- Similar to XMonad.Util.WindowProperties, but uses posix regular expressions matching
-- instead of exact match.
--
-----------------------------------------------------------------------------
module XMonad.Util.WindowPropertiesRE
  (PropertyRE (..),
   (~?),
   propertyToQueryRE, hasPropertyRE
  ) where

import Text.Regex.Posix ((=~))

import XMonad

import XMonad.Actions.TagWindows
import XMonad.Util.WindowProperties
import XMonad.Layout.LayoutBuilder

-- | A wrapper for X.U.WindowProperties.Property.
-- Checks using regular expression.
data PropertyRE = RE Property
  deriving (Show,Read,Typeable)

-- | Regular expressions matching for ManageHooks
(~?) :: (Functor f) => f String -> String -> f Bool
q ~? x = fmap (=~ x) q

-- | Similar to XMonad.Util.WindowProperties.propertyToQuery, 
-- but uses regexp match instead of exact match
propertyToQueryRE :: Property -> Query Bool
propertyToQueryRE (Title s) = title ~? s
propertyToQueryRE (Resource s) = resource ~? s
propertyToQueryRE (ClassName s) = className ~? s
propertyToQueryRE (Role s) = stringProperty "WM_WINDOW_ROLE" ~? s
propertyToQueryRE (Machine s) = stringProperty "WM_CLIENT_MACHINE" ~? s
propertyToQueryRE (And p1 p2) = propertyToQueryRE p1 <&&> propertyToQueryRE p2
propertyToQueryRE (Or p1 p2) = propertyToQueryRE p1 <||> propertyToQueryRE p2
propertyToQueryRE (Not p) = not `fmap` propertyToQueryRE p
propertyToQueryRE (Const b) = return b
propertyToQueryRE (Tagged s) = ask >>= \w -> liftX (any (=~ s) `fmap` getTags w)

-- | Does given window have this property?
hasPropertyRE :: PropertyRE -> Window -> X Bool
hasPropertyRE (RE p) w = runQuery (propertyToQueryRE p) w

instance Predicate PropertyRE Window where
  alwaysTrue _ = RE (Const True)
  checkPredicate = hasPropertyRE

