Skip to content

Commit

Permalink
Allow generating Routes and/or PathHelpers
Browse files Browse the repository at this point in the history
Basically, make route generation optional.  The primary motivation for
this is so that path helpers can be placed into a second file that is
CPP #include into your application, to avoid recursive dependencies at
least until <http://hackage.haskell.org/trac/ghc/ticket/1409> is solved.
  • Loading branch information
singpolyma committed Aug 18, 2012
1 parent df6e8df commit 308a45a
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 15 deletions.
2 changes: 1 addition & 1 deletion README
Expand Up @@ -13,7 +13,7 @@ Example:
> GET /post/: => showPost
> PUT /* => updateSomething

> ./routeGenerator -m SomeModule routes.txt
> ./routeGenerator -r -m SomeModule routes.txt

Will generate routes that map the correct HTTP verb (which you should
pass as a prepended "path segment" to your Dispatch) and path to
Expand Down
2 changes: 1 addition & 1 deletion example/Makefile
Expand Up @@ -2,4 +2,4 @@ Main: Main.hs Application.hs Routes.hs
ghc $^

Routes.hs: routes
../dist/build/routeGenerator/routeGenerator -m Application -n 1 -p $^ > $@
../dist/build/routeGenerator/routeGenerator -rp -m Application -n 1 $^ > $@
2 changes: 1 addition & 1 deletion route-generator.cabal
Expand Up @@ -29,7 +29,7 @@ description:
> GET /post/: => showPost
> PUT /* => updateSomething
.
> ./routeGenerator -m SomeModule routes.txt
> ./routeGenerator -r -m SomeModule routes.txt
.
Will generate routes that map the correct HTTP verb (which you should
pass as a prepended "path segment" to your Dispatch) and path to
Expand Down
37 changes: 25 additions & 12 deletions routeGenerator.hs
Expand Up @@ -17,21 +17,22 @@ import qualified Data.Text.IO as T
import Data.Attoparsec.Text
import Control.Applicative

data Flag = Help | PathHelpers | NArgs Int | Mod String deriving (Show, Read, Eq)
data Flag = Help | PathHelpers | Routes | NArgs Int | Mod String deriving (Show, Read, Eq)

flags :: [OptDescr Flag]
flags = [
Option ['r'] ["routes"] (NoArg Routes) "Generate routes.",
Option ['p'] ["pathHelpers"] (NoArg PathHelpers) "Generate actionPath helper functions.",
Option ['m'] ["module"] (ReqArg Mod "MODULE") "Implementation module to import.",
Option ['n'] ["nArgs"] (ReqArg (NArgs . read) "NARGS") "Number of arguments the `route` function takes.",
Option ['p'] ["pathHelpers"] (NoArg PathHelpers) "Generate actionPath helper functions.",
Option ['h'] ["help"] (NoArg Help) "Show this help text."
]

usage :: [String] -> IO ()
usage errors = do
mapM_ (hPutStrLn stderr) errors
name <- getProgName
hPutStrLn stderr $ usageInfo (name ++ " [-m MODULE] [-n NARGS] [-p] <input-file>") flags
hPutStrLn stderr $ usageInfo (name ++ " -r -p [-m MODULE] [-n NARGS] <input-file>") flags

data Route = Route {
method :: Text,
Expand Down Expand Up @@ -155,28 +156,40 @@ main = do
_ | Help `elem` flags -> usage errors
(_, _:_) -> usage errors >> exitFailure
_ | length args /= 1 -> usage errors >> exitFailure
_ | (Routes `notElem` flags) && (PathHelpers `notElem` flags) -> do
hPutStrLn stderr "Must pass -r or -p"
usage errors >> exitFailure
_ -> main' (head args) flags
where
main' input flags = do
Right routes <- fmap (parseOnly parser) $ T.readFile input

putStrLn "module Routes where"
putStrLn ""
when (Routes `elem` flags) $ do
putStrLn "module Routes where"
putStrLn ""

mapM_ (\flag -> case flag of
Mod m -> putStrLn $ "import " ++ m
_ -> return ()
) flags
putStrLn "import Data.List (intercalate)"
putStrLn "import Control.Monad (ap)"
putStrLn "import Data.Text (pack, unpack)"
putStrLn "import Network.URI (URI(..))"
putStrLn "import Web.PathPieces (fromPathPiece, toPathPiece)"
putStrLn "import Yesod.Routes.Dispatch (Route(..), Piece(Static, Dynamic))"

when (Routes `elem` flags) $ do
putStrLn "import Control.Monad (ap)"
putStrLn "import Data.Text (pack)"
putStrLn "import Web.PathPieces (fromPathPiece)"
putStrLn "import Yesod.Routes.Dispatch (Route(..), Piece(Static, Dynamic))"

when (PathHelpers `elem` flags) $ do
putStrLn "import Data.List (intercalate)"
putStrLn "import Network.URI (URI(..))"
putStrLn "import Data.Text (unpack)"
putStrLn "import Web.PathPieces (toPathPiece)"

putStrLn ""

let nArgs = getNArgs flags
when (PathHelpers `elem` flags) (emitPathHelpers routes nArgs)
emitRoutes routes nArgs
when (Routes `elem` flags) (emitRoutes routes nArgs)

getNArgs = foldr (\flag n -> case (n,flag) of
(0, NArgs n) -> n
Expand Down

0 comments on commit 308a45a

Please sign in to comment.