on 6b5c299 help sign in
hakyll/src/Hakyll/Core/Compiler.hs
145 lines 5.3 kB history raw
1--------------------------------------------------------------------------------
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE ScopedTypeVariables #-}
4module Hakyll.Core.Compiler
5 ( Compiler
6 , getUnderlying
7 , makeItem
8 , getRoute
9 , getMetadata
10 , getResourceBody
11 , getResourceString
12 , getResourceLBS
13 , getResourceWith
14 , require
15 , requireBody
16 , requireAll
17 , cached
18 , unsafeCompiler
19 , debugCompiler
20 ) where
23--------------------------------------------------------------------------------
24import Control.Applicative ((<$>))
25import Data.Binary (Binary)
26import Data.ByteString.Lazy (ByteString)
27import Data.Typeable (Typeable)
28import Prelude hiding (id, (.))
29import System.Environment (getProgName)
32--------------------------------------------------------------------------------
33import Hakyll.Core.Compiler.Internal
34import Hakyll.Core.Compiler.Require
35import Hakyll.Core.Dependencies
36import Hakyll.Core.Identifier
37import Hakyll.Core.Item
38import Hakyll.Core.Logger as Logger
39import Hakyll.Core.Metadata
40import Hakyll.Core.Provider
41import Hakyll.Core.Routes
42import qualified Hakyll.Core.Store as Store
45--------------------------------------------------------------------------------
46-- | Get the underlying identifier. Only use this if you know what you're doing.
47getUnderlying :: Compiler Identifier
48getUnderlying = compilerUnderlying <$> compilerAsk
51--------------------------------------------------------------------------------
52makeItem :: a -> Compiler (Item a)
53makeItem x = do
54 identifier <- getUnderlying
55 return $ Item identifier x
58--------------------------------------------------------------------------------
59-- | Get the route for a specified item
60getRoute :: Identifier -> Compiler (Maybe FilePath)
61getRoute identifier = do
62 routes <- compilerRoutes <$> compilerAsk
63 return $ runRoutes routes identifier
67--------------------------------------------------------------------------------
68getMetadata :: Identifier -> Compiler Metadata
69getMetadata identifier = do
70 provider <- compilerProvider <$> compilerAsk
71 compilerTellDependencies [IdentifierDependency identifier]
72 compilerUnsafeIO $ resourceMetadata provider identifier
75--------------------------------------------------------------------------------
76-- | Get the body of the underlying resource
77getResourceBody :: Compiler (Item String)
78getResourceBody = getResourceWith resourceBody
81--------------------------------------------------------------------------------
82-- | Get the resource we are compiling as a string
83getResourceString :: Compiler (Item String)
84getResourceString = getResourceWith $ const resourceString
87--------------------------------------------------------------------------------
88-- | Get the resource we are compiling as a lazy bytestring
89getResourceLBS :: Compiler (Item ByteString)
90getResourceLBS = getResourceWith $ const resourceLBS
93--------------------------------------------------------------------------------
94-- | Overloadable function for 'getResourceString' and 'getResourceLBS'
95getResourceWith :: (Provider -> Identifier -> IO a) -> Compiler (Item a)
96getResourceWith reader = do
97 provider <- compilerProvider <$> compilerAsk
98 id' <- compilerUnderlying <$> compilerAsk
99 let filePath = toFilePath id'
100 if resourceExists provider id'
101 then compilerUnsafeIO $ Item id' <$> reader provider id'
102 else compilerThrow $ error' filePath
103 where
104 error' fp = "Hakyll.Core.Compiler.getResourceWith: resource " ++
105 show fp ++ " not found"
108--------------------------------------------------------------------------------
109cached :: (Binary a, Typeable a)
110 => String
111 -> Compiler a
112 -> Compiler a
113cached name compiler = do
114 id' <- compilerUnderlying <$> compilerAsk
115 store <- compilerStore <$> compilerAsk
116 provider <- compilerProvider <$> compilerAsk
117 modified <- compilerUnsafeIO $ resourceModified provider id'
118 if modified
119 then do
120 x <- compiler
121 compilerUnsafeIO $ Store.set store [name, show id'] x
122 return x
123 else do
124 compilerTellCacheHits 1
125 x <- compilerUnsafeIO $ Store.get store [name, show id']
126 progName <- compilerUnsafeIO getProgName
127 case x of Store.Found x' -> return x'
128 _ -> compilerThrow (error' progName)
129 where
130 error' progName =
131 "Hakyll.Core.Compiler.cached: Cache corrupt! " ++
132 "Try running: " ++ progName ++ " clean"
135--------------------------------------------------------------------------------
136unsafeCompiler :: IO a -> Compiler a
137unsafeCompiler = compilerUnsafeIO
140--------------------------------------------------------------------------------
141-- | Compiler for debugging purposes
142debugCompiler :: String -> Compiler ()
143debugCompiler msg = do
144 logger <- compilerLogger <$> compilerAsk
145 compilerUnsafeIO $ Logger.debug logger msg