twitch-0.1.7.2: src/Twitch/Internal.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleInstances #-}
module Twitch.Internal where
import System.FilePath ( FilePath )
import Control.Monad.Trans.State as State
( State, put, modify, execState, get )
import qualified Twitch.Rule as Rule
( addF, modifyF, deleteF, nameF )
import Twitch.Rule ( Rule )
import Data.String ( IsString(..) )
import Control.Applicative -- satisfy GHC < 7.10
import Data.Monoid -- satisfy GHC < 7.10
import Data.Semigroup as S -- satisfy GHC < 8.0
import Prelude hiding (FilePath)
-- | A polymorphic 'Dep'. Exported for completeness, ignore.
newtype DepM a = DepM { unDepM :: State [Rule] a}
deriving ( Functor
, Applicative
, Monad
)
instance S.Semigroup (DepM a) where
x <> y = x >> y
instance Monoid a => Monoid (DepM a) where
mempty = return mempty
mappend = (<>)
-- | This is the key type of the package, it is where rules are accumulated.
type Dep = DepM ()
instance IsString Dep where
fromString = addRule . fromString
runDep :: Dep -> [Rule]
runDep = runDepWithState mempty
runDepWithState :: [Rule] -> Dep -> [Rule]
runDepWithState xs = flip execState xs . unDepM
addRule :: Rule -> Dep
addRule r = DepM $ State.modify (r :)
modHeadRule :: Dep -> (Rule -> Rule) -> Dep
modHeadRule (DepM dep) f = DepM $ do
dep
get >>= \res -> case res of
x:xs -> put $ f x : xs
r -> put r
-- Infix API -----------------------------------------------------------------
infixl 8 |+, |%, |-, |>, |#
(|+), (|%), (|-), (|>) :: Dep -> (FilePath -> IO a) -> Dep
-- | Add a \'add\' callback
-- ex.
--
-- > "*.png" |+ addToManifest
x |+ f = modHeadRule x $ Rule.addF f
-- | Add a \'modify\' callback
-- ex.
--
-- > "*.c" |% [s|gcc -o$directory$basename.o $path|]
x |% f = modHeadRule x $ Rule.modifyF f
-- | Add a \'delete' callback
-- ex.
--
-- > "*.c" |- [s|gcc -o$directory$basename.o $path|]
x |- f = modHeadRule x $ Rule.deleteF f
-- | Add the same callback for the \'add\' and the \'modify\' events.
-- ex.
--
-- > "*.md" |> [s|pandoc -t html $path|]
--
-- Defined as: x '|>' f = x '|+' f '|%' f
x |> f = x |+ f |% f
-- | Set the name of a rule. Useful for debugging when logging is enabled.
-- Rules names default to the glob pattern.
-- ex.
--
-- > "*.md" |> [s|pandoc -t html $path|] |# "markdown to html"
(|#) :: Dep -> String -> Dep
r |# p = modHeadRule r $ Rule.nameF p
-- Prefix API -----------------------------------------------------------------
add, modify, delete, addModify :: (FilePath -> IO a) -> Dep -> Dep
-- | Add a \'add\' callback
-- ex.
--
-- > add addToManifest "*.png"
add = flip (|+)
-- | Add a \'modify\' callback
-- ex.
--
-- > mod [s|gcc -o$directory$basename.o $path|] "*.c"
modify = flip (|%)
-- | Add a \'delete' callback
-- ex.
--
-- > delete [s|gcc -o$directory$basename.o $path|] "*.c"
delete = flip (|-)
-- | Add the same callback for the \'add\' and the \'modify\' events.
-- ex.
--
-- > addModify [s|pandoc -t html $path|] "*.md"
addModify = flip (|>)
-- | Set the name of a rule. Useful for debugging when logging is enabled.
-- Rules names default to the glob pattern.
-- ex.
--
-- > name "markdown to html" $ addModify [s|pandoc -t html $path|] "*.md"
name :: String -> Dep -> Dep
name = flip (|#)