on master help sign in
Merge pull request #12 from tazjin/master
1600aaeEvan Czaplicki
Examples/elm-yesod/Main.hs+11−4
@@ -13,7 +13,7 @@ data ElmTest = ElmTest
13-- embedding an external elm file (note: no spaces!)
13-- embedding an external elm file (note: no spaces!)
14mousePage = [elmFile|elm_source/mouse.elm|]
14mousePage = [elmFile|elm_source/mouse.elm|]
15
15
16−rootPage = [elmFile|elm_source/index.elm|]
16+rootPage mouse clock shapes = [elmFile|elm_source/index.elm|]
17
17
18clockPage = [elmFile|elm_source/clock.elm|]
18clockPage = [elmFile|elm_source/clock.elm|]
19
19
@@ -55,10 +55,17 @@ getShapesR = defaultLayout $ do
55 setTitle "Simple shapes"
55 setTitle "Simple shapes"
56 generateWidget shapesPage
56 generateWidget shapesPage
57
57
58+-- URLs are rendered manually and then passed on to the function containing
59+-- the elm QuasiQuoter.
58getRootR :: Handler RepHtml
60getRootR :: Handler RepHtml
61+getRootR = do
62+ render <- getUrlRender
59−getRootR = defaultLayout $ do
63+ defaultLayout $ do
64+ let mouse = render MouseR
65+ clock = render ClockR
66+ shapes = render ShapesR
60− setTitle "Welcome!"
67+ setTitle "Welcome!"
61− generateWidget rootPage
68+ generateWidget $ rootPage mouse clock shapes
62
69
63
70
64-- Our Yesod instance contains the default layout, which inserts the elm-min.js
71-- Our Yesod instance contains the default layout, which inserts the elm-min.js
Examples/elm-yesod/elm_source/index.elm+3−3
@@ -26,9 +26,9 @@ info w = List.map (\f -> f ()) . List.intersperse (\x -> plainText "&nbsp;") . L
26 , text $ toText "Rendering Yesod's type-safe URLs is not yet possible, but will be implemented as the currently " ++
26 , text $ toText "Rendering Yesod's type-safe URLs is not yet possible, but will be implemented as the currently " ++
27 toText "very simple QuasiQuoter is extended."
27 toText "very simple QuasiQuoter is extended."
28 , section "More examples:"
28 , section "More examples:"
29− , text $ toText "- " ++ link "/mouse" (toText "A simple mouse input example")
29+ , text $ toText "- " ++ link ^{mouse} (toText "A simple mouse input example")
30− , text $ toText "- " ++ link "/clock" (toText "An animated analog clock")
30+ , text $ toText "- " ++ link ^{clock} (toText "An animated analog clock")
31− , text $ toText "- " ++ link "/shapes" (toText "Some simple rendered shapes")
31+ , text $ toText "- " ++ link ^{shapes} (toText "Some simple rendered shapes")
32 ]
32 ]
33
33
34body outer inner = width outer . box 2 . flow down . (:) (plainText "&nbsp;") $ info inner
34body outer inner = width outer . box 2 . flow down . (:) (plainText "&nbsp;") $ info inner
elm/Elm.cabal+7−3
@@ -1,6 +1,6 @@
1
1
2Name: Elm
2Name: Elm
3−Version: 0.1.1.8
3+Version: 0.1.2
4Synopsis: The Elm language module.
4Synopsis: The Elm language module.
5Description: Elm aims to make client-side web-development more pleasant.
5Description: Elm aims to make client-side web-development more pleasant.
6 It is a statically/strongly typed, functional reactive
6 It is a statically/strongly typed, functional reactive
@@ -64,7 +64,8 @@ Library
64 Language.Elm.CompileToJS,
64 Language.Elm.CompileToJS,
65 Language.Elm.ExtractNoscript,
65 Language.Elm.ExtractNoscript,
66 Language.Elm.Initialize,
66 Language.Elm.Initialize,
67− Language.Elm.GenerateHtml
67+ Language.Elm.GenerateHtml,
68+ Language.Elm.Quasi
68 Hs-Source-Dirs: src, src/Parse, src/Types
69 Hs-Source-Dirs: src, src/Parse, src/Types
69 other-modules: Ast,
70 other-modules: Ast,
70 Guid,
71 Guid,
@@ -91,4 +92,7 @@ Library
91 blaze-html == 0.5.0.*,
92 blaze-html == 0.5.0.*,
92 blaze-markup == 0.5.1.*,
93 blaze-markup == 0.5.1.*,
93 deepseq,
94 deepseq,
94− template-haskell
95+ template-haskell,
96+ haskell-src-meta == 0.5.*,
97+ text,
98+ attoparsec == 0.10.*
elm/src/Language/Elm.hs+1−33
@@ -1,4 +1,3 @@
1−{-# LANGUAGE QuasiQuotes, TemplateHaskell #-}
2{- | This module re-exports the modules necessary for compiling Elm code into the
1{- | This module re-exports the modules necessary for compiling Elm code into the
3 respective HTML, JS and CSS code.
2 respective HTML, JS and CSS code.
4
3
@@ -19,35 +18,4 @@ import Language.Elm.CompileToJS
19import Language.Elm.ExtractNoscript
18import Language.Elm.ExtractNoscript
20import Language.Elm.Initialize
19import Language.Elm.Initialize
21import Language.Elm.GenerateHtml
20import Language.Elm.GenerateHtml
22−import Language.Haskell.TH
21+import Language.Elm.Quasi
23−import Language.Haskell.TH.Quote
24−
25−{- | This QuasiQuoter allows for literal embedding of elm source code within
26− Haskell files. It is not responsible for the actual compilation Process.
27− Usage:
28−
29− @
30− elmPage = [elm|
31− main = image \"someImage.jpg\"
32− |]
33− @
34−
35− How the elm code is compiled depends on how you intend to use it.
36− Example uses are the included 'generateHtml' function as well as the
37− "Language.Elm.Yesod" module.
38−-}
39−elm :: QuasiQuoter
40−elm = QuasiQuoter {quoteExp = \s -> [|s|] }
41−
42−{- | elmFile is a quoteFile wrapper around the 'elm' QuasiQuoter and allows for
43− external elm source files to be embedded.
44− Usage:
45−
46− @
47− [elmFile|elm-source/page.elm|]
48− @
49−
50− Please note that no spaces should be added before and after the filename.
51−-}
52−elmFile :: QuasiQuoter
53−elmFile = quoteFile elm
elm/src/Language/Elm/Quasi.hsnew file+93
@@ -0,0 +1,93 @@
1+{-# LANGUAGE TemplateHaskell, OverloadedStrings #-}
2+{-# OPTIONS_GHC -fno-warn-missing-fields #-}
3+
4+module Language.Elm.Quasi (elm, elmFile) where
5+
6+import Language.Haskell.TH.Quote
7+import Language.Haskell.TH
8+import Language.Haskell.Meta (parseExp)
9+
10+import Data.Attoparsec.Text
11+import Data.Text as T (Text, pack, unpack, strip)
12+
13+{- | This QuasiQuoter allows for literal embedding of elm source code within
14+ Haskell files. It is not responsible for the actual compilation Process.
15+ Usage:
16+
17+ @
18+ elmPage = [elm|
19+ main = image \"someImage.jpg\"
20+ |]
21+ @
22+
23+ It also allows for simple variable interpolation using the ^{...} syntax.
24+ This is intended for e.g. embedding pre-rendered type-safe URLs.
25+ All interpolated variables must be a member of the Show typeclass. This
26+ is not tested with more complicated expressions, so it is recommended to
27+ restrict usage of interpolation to pre-calculated variables.
28+
29+ Example:
30+
31+ > let google = "http://google.com"
32+ > in [elm|
33+ > main = text $ link ^{google} (toText "Google")
34+ > |]
35+
36+
37+ How the elm code is compiled depends on how you intend to use it.
38+ Example uses are the included 'generateHtml' function as well as the
39+ "Language.Elm.Yesod" module.
40+-}
41+elm :: QuasiQuoter
42+elm = QuasiQuoter
43+ { quoteExp = \s ->
44+ let chunks = flip map (getQChunks s) $ \c ->
45+ case c of
46+ S t -> [| t |]
47+ E t -> let Right e = parseExp t in appE [| show |] (return e)
48+ in appE [| concat |] (listE chunks)
49+ }
50+
51+{- | elmFile is a quoteFile wrapper around the 'elm' QuasiQuoter and allows for
52+ external elm source files to be embedded.
53+ Usage:
54+
55+ @
56+ [elmFile|elm-source/page.elm|]
57+ @
58+
59+ Please note that no spaces should be added before and after the filename.
60+-}
61+elmFile :: QuasiQuoter
62+elmFile = quoteFile elm
63+
64+data QChunk =
65+ S String -- ^ A literal string
66+ | E String -- ^ An expression (must be of the Show typeclass)
67+ deriving (Show, Eq)
68+
69+
70+{- thanks to mikeplus64 for providing an example QuasiQuoter that I could look at while writing this :) -}
71+getQChunks :: String -> [QChunk]
72+getQChunks si = let i = T.pack si
73+ Right m = parseOnly parser (strip i) in m
74+ where
75+ parser = go []
76+
77+ go s = do
78+ txt <- takeTill (== '^')
79+ evt <- choice [expression, fmap (S . T.unpack) takeText]
80+ end <- atEnd
81+ if end
82+ then return $ filter (not . blank) $ reverse (evt:(S . T.unpack) txt:s)
83+ else go (evt:(S . T.unpack) txt:s)
84+
85+ blank (S "") = True
86+ blank (E "") = True
87+ blank _ = False
88+
89+ expression = do
90+ string "^{"
91+ expr <- takeTill (== '}')
92+ char '}'
93+ return $ (E . T.unpack) expr