Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Adding `bird help` with some useful information

Don't create hard to delete directories like `--help` by changing `bird MyApp` to `bird new MyApp`
Don't die if `bird` is called with no arguments
  • Loading branch information...
commit a5d61201ce101a4eddb05a30664068fb0aaf3f5f 1 parent 14a9a08
Jason Dew jasondew authored committed
Showing with 50 additions and 39 deletions.
  1. +20 −22 README.markdown
  2. +30 −17 bin/bird.hs
42 README.markdown
View
@@ -1,11 +1,11 @@
# Bird
-A sinatra-ish web framework written in haskell, riding on top of Hack.
+A sinatra-ish web framework written in haskell, riding on top of Hack.
## Why?
-Sinatra has a beautiful, simple, elegant syntax, but it's essentially an attempt to bring pattern matching to a language never intended for
-pattern matching. Why not attempt something similar in a language with not just beautiful pattern matching, but with all the declarative
+Sinatra has a beautiful, simple, elegant syntax, but it's essentially an attempt to bring pattern matching to a language never intended for
+pattern matching. Why not attempt something similar in a language with not just beautiful pattern matching, but with all the declarative
bells and whistles: lazy evaluation, first-class functions, currying, polymorphism?
## Install
@@ -16,7 +16,7 @@ Note: make sure $HOME/.cabal/bin is in your PATH.
## Create an app
- λ bird StarWars
+ λ bird new StarWars
## Compile your app
@@ -25,7 +25,7 @@ Note: make sure $HOME/.cabal/bin is in your PATH.
[1 of 2] Compiling StarWars ( StarWars.hs, StarWars.o )
[2 of 2] Compiling Main ( Main.hs, Main.o )
Linking Main ...
- λ
+ λ
## Start your app (runs on port 3000)
@@ -33,38 +33,36 @@ Note: make sure $HOME/.cabal/bin is in your PATH.
λ bird fly
## Try it out
-
+
λ curl http://localhost:3000
Hello, Bird!
-
+
λ curl http://localhost:3000?name=Luke
Hello, Luke
-
-
## Improvise!
-
+
-- StarWars.bird.hs
import Data.String.Utils (join)
-
+
get ["droids"] = do
body "These aren't the droids you're looking for. Move along."
status 404
- get ("force":xs) = do
+ get ("force":xs) = do
body $ "May the force be with you " ++ (join ", " xs) ++ "!"
-
+
get [] = do
name <- param "name"
body $ "Greetings, " ++ (maybe "Jedi!" id name)
now recompile your app and start it flying:
- λ bird nest
- λ bird fly &
-
+ λ bird nest
+ λ bird fly &
+
λ curl -i http://localhost:3000/force/Han/Chewie
-
+
HTTP/1.1 200 OK
Connection: close
Content-Type: text/html
@@ -74,7 +72,7 @@ now recompile your app and start it flying:
May the force be with you Han, Chewie!
λ curl -i http://localhost:3000/droids
-
+
HTTP/1.1 404 Not Found
Connection: close
Content-Type: text/html
@@ -86,12 +84,12 @@ now recompile your app and start it flying:
## API
-You have four functions to implement: get, post, put, and delete. They each accept a Bird Request.
+You have four functions to implement: get, post, put, and delete. They each accept a Bird Request.
+
+Inside the function body, you can use the following methods (don't worry, this list will grow):
-Inside the function body, you can use the following methods (don't worry, this list will grow):
-
param :: String -> Maybe String
- -- ex: for the request GET /droids?name=c3po,
+ -- ex: for the request GET /droids?name=c3po,
-- then `p <- param "name"' would bind the value `Just "c3po"' to the variable "p"
body :: String -> BirdResponder ()
47 bin/bird.hs
View
@@ -6,49 +6,63 @@ import List
main = do
args <- getArgs
- runArg $ head args
+ runArg args
-runArg a =
- case a of
- "nest" -> do
+runArg arguments =
+ case arguments of
+ ["help"] -> printHelp
+ ["--help"] -> printHelp
+ ["nest"] -> do
appModuleNamePath <- getCurrentDirectory
- appModuleName <- return $ head . reverse $ split '/' appModuleNamePath
+ appModuleName <- return $ head . reverse $ split '/' appModuleNamePath
partialRouteFile <- readFile $ appModuleName ++ ".bird.hs"
writeFile (appModuleName ++ ".hs") ((appModulePrelude appModuleName)++ "\n" ++ partialRouteFile ++ "\n" ++ appModuleEpilogue)
system "ghc --make -O2 Main.hs"
files <- getDirectoryContents appModuleNamePath
- system $ "rm *.o *.hi " ++ appModuleName ++ ".hs"
+ system $ "rm *.o *.hi " ++ appModuleName ++ ".hs"
renameFile "Main" appModuleName
return ()
- "fly" -> do
+ ["fly"] -> do
appModuleNamePath <- getCurrentDirectory
- appModuleName <- return $ head . reverse $ split '/' appModuleNamePath
+ appModuleName <- return $ head . reverse $ split '/' appModuleNamePath
system $ "./" ++ appModuleName
return ()
- appName -> createBirdApp appName
+ ["new", appName] -> createBirdApp appName
+ (action:_) -> do
+ putStrLn $ "Unrecognized action: " ++ (show action) ++ "\n"
+ printHelp
+ [] -> printHelp
-appModulePrelude appModuleName =
+printHelp = do
+ putStrLn $ "Usage: bird action [options]\n\n" ++
+ " Actions:\n" ++
+ " new -> create a new Bird app, takes the name as an argument, for example `bird create StarWars`\n" ++
+ " nest -> compile your Bird app\n" ++
+ " fly -> expose your Bird app to the world (on port 3000)\n"
+
+appModulePrelude appModuleName =
"--This file is generated by bird. It will be overwritten the next time you run 'bird nest'. Edit at your own peril.\n" ++
"module " ++ appModuleName ++ " where\n" ++
- "import Bird\n\n"
+ "import Bird\n\n"
-appModuleEpilogue =
+appModuleEpilogue =
"get _ = status 404\n" ++
"post _ = status 404\n" ++
"put _ = status 404\n" ++
"delete _ = status 404\n"
-
+
createBirdApp a = do
createDirectory a
writeFile (a ++ "/" ++ a ++ ".bird.hs") (routeFile a)
writeFile (a ++ "/" ++ "Main.hs") (mainFile a)
+ putStrLn $ "A fresh Bird app has been created in " ++ a ++ "."
routeFile a = "get [] = body \"Hello, Bird!\""
-mainFile a =
+mainFile a =
"import Hack\n" ++
- "import qualified Hack as Hack\n" ++
+ "import qualified Hack as Hack\n" ++
"import Hack.Handler.Happstack\n" ++
"import Bird\n" ++
"import qualified Bird as Bird\n" ++
@@ -74,7 +88,7 @@ mainFile a =
" Bird.POST -> post $ path r\n" ++
" Bird.PUT -> put $ path r\n" ++
" Bird.DELETE -> delete $ path r\n\n" ++
-
+
"main = run app\n"
split :: Char -> String -> [String]
@@ -84,4 +98,3 @@ split d s
where
(t, s'') = break (== d) findSep
findSep = dropWhile (== d) s
-
Please sign in to comment.
Something went wrong with that request. Please try again.