on master help sign in
Split Rules module, add documentation
commitdd81433d74579848e6853eb5a1500535c378c808 authorJasper Van der Jeugt <jaspervdj@gmail.com> dateFri 11 Feb 2011, 13:30 (16 years ago) parent2dfe7f6
6 files changed+118−67
hakyll.cabal+1 src/Hakyll/Core/CompiledItem.hs+7−2 src/Hakyll/Core/Compiler.hs+1−1 src/Hakyll/Core/Rules.hs+38−63 src/Hakyll/Core/Rules/Internal.hs+70 src/Hakyll/Core/Run.hs+1−1
hakyll.cabal+1
@@ -89,3 +89,4 @@ library
8989 Hakyll.Web.Page.Internal
9090 Hakyll.Core.Compiler.Internal
9191 Hakyll.Core.DirectedGraph.Internal
92+ Hakyll.Core.Rules.Internal
src/Hakyll/Core/CompiledItem.hs+7−2
@@ -1,6 +1,11 @@
11-- | A module containing a box datatype representing a compiled item. This
2−-- item can be of any type, given that a few restrictions hold (e.g. we want
3−-- a 'Typeable' instance to perform type-safe casts).
2+-- item can be of any type, given that a few restrictions hold:
3+--
4+-- * we need a 'Typeable' instance to perform type-safe casts;
5+--
6+-- * we need a 'Binary' instance so we can serialize these items to the cache;
7+--
8+-- * we need a 'Writable' instance so the results can be saved.
49--
510{-# LANGUAGE ExistentialQuantification #-}
611module Hakyll.Core.CompiledItem
src/Hakyll/Core/Compiler.hs+1−1
@@ -38,7 +38,7 @@ import Hakyll.Core.Writable
3838import Hakyll.Core.ResourceProvider
3939import Hakyll.Core.Compiler.Internal
4040import Hakyll.Core.Store
41−import Hakyll.Core.Rules
41+import Hakyll.Core.Rules.Internal
4242import Hakyll.Core.Routes
4343
4444-- | Run a compiler, yielding the resulting target and it's dependencies. This
src/Hakyll/Core/Rules.hs+38−63
@@ -1,13 +1,19 @@
1−-- | This module provides a monadic DSL in which the user can specify the
2−-- different rules used to run the compilers
1+-- | This module provides a declarative DSL in which the user can specify the
2+-- different rules used to run the compilers.
3+--
4+-- The convention is to just list all items in the 'RulesM' monad, routes and
5+-- compilation rules.
6+--
7+-- A typical usage example would be:
8+--
9+-- > main = hakyll $ do
10+-- > route "posts/*" (setExtension "html")
11+-- > compile "posts/*" someCompiler
312--
413{-# LANGUAGE GeneralizedNewtypeDeriving, OverloadedStrings #-}
514module Hakyll.Core.Rules
6− ( CompileRule (..)
7− , RuleSet (..)
8− , RulesM
15+ ( RulesM
916 , Rules
10− , runRules
1117 , compile
1218 , create
1319 , route
@@ -15,12 +21,12 @@ module Hakyll.Core.Rules
1521 , metaCompileWith
1622 ) where
1723
18−import Control.Applicative (Applicative, (<$>))
19−import Control.Monad.Writer (WriterT, execWriterT, tell)
20−import Control.Monad.Reader (ReaderT, runReaderT, ask)
24+import Control.Applicative ((<$>))
25+import Control.Monad.Writer (tell)
26+import Control.Monad.Reader (ask)
2127import Control.Arrow (second, (>>>), arr, (>>^))
22−import Control.Monad.State (State, evalState, get, put)
23−import Data.Monoid (Monoid, mempty, mappend)
28+import Control.Monad.State (get, put)
29+import Data.Monoid (mempty)
2430
2531import Data.Typeable (Typeable)
2632import Data.Binary (Binary)
@@ -32,53 +38,7 @@ import Hakyll.Core.Compiler.Internal
3238import Hakyll.Core.Routes
3339import Hakyll.Core.CompiledItem
3440import Hakyll.Core.Writable
35−
36−-- | Output of a compiler rule
37−--
38−-- * The compiler will produce a simple item. This is the most common case.
39−--
40−-- * The compiler will produce more compilers. These new compilers need to be
41−-- added to the runtime if possible, since other items might depend upon them.
42−--
43−data CompileRule = CompileRule CompiledItem
44− | MetaCompileRule [(Identifier, Compiler () CompileRule)]
45−
46−-- | A collection of rules for the compilation process
47−--
48−data RuleSet = RuleSet
49− { rulesRoutes :: Routes
50− , rulesCompilers :: [(Identifier, Compiler () CompileRule)]
51− }
52−
53−instance Monoid RuleSet where
54− mempty = RuleSet mempty mempty
55− mappend (RuleSet r1 c1) (RuleSet r2 c2) =
56− RuleSet (mappend r1 r2) (mappend c1 c2)
57−
58−-- | Rule state
59−--
60−data RuleState = RuleState
61− { rulesMetaCompilerIndex :: Int
62− } deriving (Show)
63−
64−-- | The monad used to compose rules
65−--
66−newtype RulesM a = RulesM
67− { unRulesM :: ReaderT ResourceProvider (WriterT RuleSet (State RuleState)) a
68− } deriving (Monad, Functor, Applicative)
69−
70−-- | Simplification of the RulesM type; usually, it will not return any
71−-- result.
72−--
73−type Rules = RulesM ()
74−
75−-- | Run a Rules monad, resulting in a 'RuleSet'
76−--
77−runRules :: Rules -> ResourceProvider -> RuleSet
78−runRules rules provider =
79− evalState (execWriterT $ runReaderT (unRulesM rules) provider) state
80− where
81− state = RuleState {rulesMetaCompilerIndex = 0}
41+import Hakyll.Core.Rules.Internal
8242
8343-- | Add a route
8444--
@@ -95,10 +55,11 @@ tellCompilers compilers = RulesM $ tell $ RuleSet mempty $
9555 where
9656 boxCompiler = (>>> arr compiledItem >>> arr CompileRule)
9757
98−-- | Add a compilation rule
58+-- | Add a compilation rule to the rules.
9959--
10060-- This instructs all resources matching the given pattern to be compiled using
101−-- the given compiler
61+-- the given compiler. When no resources match the given pattern, nothing will
62+-- happen. In this case, you might want to have a look at 'create'.
10263--
10364compile :: (Binary a, Typeable a, Writable a)
10465 => Pattern -> Compiler () a -> Rules
@@ -108,18 +69,32 @@ compile pattern compiler = RulesM $ do
10869
10970-- | Add a compilation rule
11071--
111−-- This sets a compiler for the given identifier
72+-- This sets a compiler for the given identifier. No resource is needed, since
73+-- we are creating the item from scratch.
11274--
11375create :: (Binary a, Typeable a, Writable a)
11476 => Identifier -> Compiler () a -> Rules
11577create identifier compiler = tellCompilers [(identifier, compiler)]
11678
117−-- | Add a route
79+-- | Add a route.
80+--
81+-- This adds a route for all items matching the given pattern.
11882--
11983route :: Pattern -> Routes -> Rules
12084route pattern route' = tellRoute $ ifMatch pattern route'
12185
122−-- | Add a compiler that produces other compilers over time
86+-- | Apart from regular compilers, one is also able to specify metacompilers.
87+-- Metacompilers are a special class of compilers: they are compilers which
88+-- produce other compilers.
89+--
90+-- And indeed, we can see that the first argument to 'metaCompile' is a
91+-- 'Compiler' which produces a list of ('Identifier', 'Compiler') pairs. The
92+-- idea is simple: 'metaCompile' produces a list of compilers, and the
93+-- corresponding identifiers.
94+--
95+-- For simple hakyll systems, it is no need for this construction. More
96+-- formally, it is only needed when the content of one or more items determines
97+-- which items must be rendered.
12398--
12499metaCompile :: (Binary a, Typeable a, Writable a)
125100 => Compiler () [(Identifier, Compiler () a)]
src/Hakyll/Core/Rules/Internal.hsnew file+70
@@ -0,0 +1,70 @@
1+-- | Internal rules module for types which are not exposed to the user
2+--
3+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4+module Hakyll.Core.Rules.Internal
5+ ( CompileRule (..)
6+ , RuleSet (..)
7+ , RuleState (..)
8+ , RulesM (..)
9+ , Rules
10+ , runRules
11+ ) where
12+
13+import Control.Applicative (Applicative)
14+import Control.Monad.Writer (WriterT, execWriterT)
15+import Control.Monad.Reader (ReaderT, runReaderT)
16+import Control.Monad.State (State, evalState)
17+import Data.Monoid (Monoid, mempty, mappend)
18+
19+import Hakyll.Core.ResourceProvider
20+import Hakyll.Core.Identifier
21+import Hakyll.Core.Compiler.Internal
22+import Hakyll.Core.Routes
23+import Hakyll.Core.CompiledItem
24+
25+-- | Output of a compiler rule
26+--
27+-- * The compiler will produce a simple item. This is the most common case.
28+--
29+-- * The compiler will produce more compilers. These new compilers need to be
30+-- added to the runtime if possible, since other items might depend upon them.
31+--
32+data CompileRule = CompileRule CompiledItem
33+ | MetaCompileRule [(Identifier, Compiler () CompileRule)]
34+
35+-- | A collection of rules for the compilation process
36+--
37+data RuleSet = RuleSet
38+ { rulesRoutes :: Routes
39+ , rulesCompilers :: [(Identifier, Compiler () CompileRule)]
40+ }
41+
42+instance Monoid RuleSet where
43+ mempty = RuleSet mempty mempty
44+ mappend (RuleSet r1 c1) (RuleSet r2 c2) =
45+ RuleSet (mappend r1 r2) (mappend c1 c2)
46+
47+-- | Rule state
48+--
49+data RuleState = RuleState
50+ { rulesMetaCompilerIndex :: Int
51+ } deriving (Show)
52+
53+-- | The monad used to compose rules
54+--
55+newtype RulesM a = RulesM
56+ { unRulesM :: ReaderT ResourceProvider (WriterT RuleSet (State RuleState)) a
57+ } deriving (Monad, Functor, Applicative)
58+
59+-- | Simplification of the RulesM type; usually, it will not return any
60+-- result.
61+--
62+type Rules = RulesM ()
63+
64+-- | Run a Rules monad, resulting in a 'RuleSet'
65+--
66+runRules :: Rules -> ResourceProvider -> RuleSet
67+runRules rules provider =
68+ evalState (execWriterT $ runReaderT (unRulesM rules) provider) state
69+ where
70+ state = RuleState {rulesMetaCompilerIndex = 0}
src/Hakyll/Core/Run.hs+1−1
@@ -25,7 +25,7 @@ import Hakyll.Core.Compiler
2525import Hakyll.Core.Compiler.Internal
2626import Hakyll.Core.ResourceProvider
2727import Hakyll.Core.ResourceProvider.FileResourceProvider
28−import Hakyll.Core.Rules
28+import Hakyll.Core.Rules.Internal
2929import Hakyll.Core.DirectedGraph
3030import Hakyll.Core.DirectedGraph.DependencySolver
3131import Hakyll.Core.Writable