Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Rudimentary support for partials

  • Loading branch information...
commit 500bc7770e9ab6d7635e399894b788202e6a276d 1 parent 0eb1d45
Stephen Paul Weber authored August 18, 2012

Showing 1 changed file with 45 additions and 28 deletions. Show diff stats Hide diff stats

  1. 73  mustache2hs.hs
73  mustache2hs.hs
@@ -49,6 +49,7 @@ data Mustache =
49 49
 	MuVar        Text Bool |
50 50
 	MuSection    Text MuTree |
51 51
 	MuSectionInv Text MuTree |
  52
+	MuPartial    Text |
52 53
 	MuComment
53 54
 	deriving (Show, Eq)
54 55
 
@@ -62,6 +63,7 @@ parser = do
62 63
 			comment <|>
63 64
 			sectionInv <|>
64 65
 			section <|>
  66
+			partial <|>
65 67
 			tripleVar <|>
66 68
 			ampVar <|>
67 69
 			mustache (var True) <|>
@@ -83,6 +85,10 @@ parser = do
83 85
 	sectionPiece c = mustache $ do
84 86
 		_ <- char c
85 87
 		name
  88
+	partial = mustache $ do
  89
+		_ <- char '>'
  90
+		skipSpace
  91
+		MuPartial <$> takeWhile1 (/='}')
86 92
 	tripleVar = mustache $ do
87 93
 		_ <- char '{'
88 94
 		v <- var False
@@ -140,12 +146,12 @@ originalMustache = mconcat . map origOne
140 146
 		]
141 147
 	origOne _ = mempty
142 148
 
143  
-codeGenTree :: (Show a, Enum a) => Text -> String -> Records -> MuTree -> State a Builder
  149
+codeGenTree :: (Show a, Enum a) => Text -> String -> Records -> MuTree -> State a (Builder, [Text])
144 150
 codeGenTree fname rname recs tree = do
145  
-	let Just rec = lookup rname recs
146  
-	(code, helpers) <- (second concat . unzip) <$>
147  
-		mapM (codeGen (rname,rec) recs) tree
148  
-	return $ mconcat [
  151
+	let rec = recordMustExist $ lookup rname recs
  152
+	(code, helpers', partials) <- unzip3 <$> mapM (codeGen (rname,rec) recs) tree
  153
+	let helpers = concat helpers'
  154
+	return (mconcat [
149 155
 			Builder.fromText fname,
150 156
 			Builder.fromString " escapeFunction ctx@(",
151 157
 			pattern rec,
@@ -154,8 +160,10 @@ codeGenTree fname rname recs tree = do
154 160
 			Builder.fromString "]\n",
155 161
 			if null helpers then mempty else Builder.fromString "\twhere\n\t",
156 162
 			mintercalate wsep helpers
157  
-		]
  163
+		], concat partials)
158 164
 	where
  165
+	recordMustExist (Just r) = r
  166
+	recordMustExist _ = error ("No record named: " ++ rname)
159 167
 	pattern rec = mconcat [
160 168
 			Builder.fromString rname,
161 169
 			Builder.fromString " {",
@@ -169,17 +177,17 @@ codeGenTree fname rname recs tree = do
169 177
 	wsep = Builder.fromString "\n\t"
170 178
 	comma = Builder.fromString ", "
171 179
 
172  
-codeGen :: (Show a, Enum a) => (String,Record) -> Records -> Mustache -> State a (Builder, [Builder])
173  
-codeGen _ _ (MuText txt) = return (Builder.fromShow (T.unpack txt), [])
  180
+codeGen :: (Show a, Enum a) => (String,Record) -> Records -> Mustache -> State a (Builder, [Builder], [Text])
  181
+codeGen _ _ (MuText txt) = return (Builder.fromShow (T.unpack txt), [], [])
174 182
 codeGen _ _ (MuVar name False) = return (mconcat [
175 183
 		Builder.fromString "fromMaybe mempty ",
176 184
 		Builder.fromText name
177  
-	], [])
  185
+	], [], [])
178 186
 codeGen _ _ (MuVar name True) = return (mconcat [
179 187
 		Builder.fromString "fromMaybe mempty (escapeFunction (",
180 188
 		Builder.fromText name,
181 189
 		Builder.fromString "))"
182  
-	], [])
  190
+	], [], [])
183 191
 codeGen (rname,rec) recs (MuSection name stree)
184 192
 	| lookup name rec == Just MuLambda =
185 193
 		return (mconcat [
@@ -188,56 +196,64 @@ codeGen (rname,rec) recs (MuSection name stree)
188 196
 				Builder.fromShow $ BS.toString $
189 197
 					Builder.toByteString $ originalMustache stree,
190 198
 				Builder.fromString " )"
191  
-			], [])
  199
+			], [], [])
192 200
 	| otherwise = do
193 201
 		id <- get
194 202
 		modify succ
195 203
 		let nm = name `mappend` T.pack (show id)
196 204
 		case lookup name rec of
197 205
 			Just (MuList rname) -> do
198  
-				helper <- codeGenTree nm rname recs stree
  206
+				(helper, partials) <- codeGenTree nm rname recs stree
199 207
 				return (mconcat [
200 208
 						Builder.fromString "map (",
201 209
 						Builder.fromText nm,
202 210
 						Builder.fromString " escapeFunction) ",
203 211
 						Builder.fromText name
204  
-					], [helper])
  212
+					], [helper], partials)
205 213
 			_ -> do
206  
-				helper <- codeGenTree nm rname recs stree
  214
+				(helper, partials) <- codeGenTree nm rname recs stree
207 215
 				return (mconcat [
208 216
 						Builder.fromString "case ",
209 217
 						Builder.fromText name,
210 218
 						Builder.fromString " of { Just _ -> (",
211 219
 						Builder.fromText nm,
212 220
 						Builder.fromString " escapeFunction ctx); _ -> mempty }"
213  
-					], [helper])
  221
+					], [helper], partials)
214 222
 codeGen (rname,rec) recs (MuSectionInv name stree) = do
215 223
 	id <- get
216 224
 	modify succ
217 225
 	let nm = name `mappend` T.pack (show id)
218  
-	helper <- codeGenTree nm rname recs stree
  226
+	(helper, partials) <- codeGenTree nm rname recs stree
219 227
 	return (mconcat [
220 228
 			Builder.fromString "if foldr (\\_ _ -> False) True ",
221 229
 			Builder.fromText name,
222 230
 			Builder.fromString " then ",
223 231
 			Builder.fromText nm,
224 232
 			Builder.fromString " escapeFunction ctx else mempty"
225  
-		], [helper])
226  
-codeGen _ _ _ = return mempty
  233
+		], [helper], partials)
  234
+codeGen (rname,rec) recs (MuPartial name) =
  235
+	let fname = takeBaseName $ T.unpack name in
  236
+	return (mconcat [
  237
+		Builder.fromString fname,
  238
+		Builder.fromString " escapeFunction ctx"
  239
+	], [], [name])
  240
+codeGen _ _ _ = return (mempty, [], [])
227 241
 
228  
-codeGenFile :: Records -> FilePath -> IO [FilePath]
  242
+codeGenFile :: Records -> FilePath -> IO (Builder, [FilePath])
229 243
 codeGenFile recs input = do
230 244
 	Right tree <- parseOnly parser <$> T.readFile input
231 245
 	let name = takeBaseName input
232 246
 	let fname = T.pack name
233 247
 	let rname = (toUpper $ head name) : tail (name ++ "Record")
234  
-	Builder.toByteStringIO BS.putStr $ evalState (codeGenTree fname rname recs tree) 0
235  
-	return []
  248
+	let (builder, partials) = evalState (codeGenTree fname rname recs tree) 0
  249
+	return (builder, map T.unpack partials)
236 250
 
237  
-codeGenFiles :: Records -> [FilePath] -> IO ()
238  
-codeGenFiles _ [] = return ()
239  
-codeGenFiles recs inputs =
240  
-		(concat <$> mapM (codeGenFile recs) inputs) >>= codeGenFiles recs
  251
+codeGenFiles :: Records -> [FilePath] -> IO Builder
  252
+codeGenFiles _ [] = return mempty
  253
+codeGenFiles recs inputs = do
  254
+		(builders, partials) <- unzip <$> mapM (codeGenFile recs) inputs
  255
+		builder <- codeGenFiles recs (concat partials)
  256
+		return $ (mconcat builders) `mappend` builder
241 257
 
242 258
 main :: IO ()
243 259
 main = do
@@ -248,9 +264,10 @@ main = do
248 264
 		_ | null args -> usage errors >> exitFailure
249 265
 		_ -> main' (getRecordModules flags) args
250 266
 	where
251  
-	main' recordModules inputs =
252  
-		(concat <$> mapM (fmap extractRecords . readFile) recordModules)
253  
-			>>= (`codeGenFiles` inputs)
  267
+	main' recordModules inputs = do
  268
+		recs <- concat <$> mapM (fmap extractRecords . readFile) recordModules
  269
+		builder <- codeGenFiles recs inputs
  270
+		Builder.toByteStringIO BS.putStr builder
254 271
 	getRecordModules = foldr (\x ms -> case x of
255 272
 			RecordModule m -> m : ms
256 273
 			_ -> ms

0 notes on commit 500bc77

Please sign in to comment.
Something went wrong with that request. Please try again.