Merge pull request #171 from freezeboy/transform-function-name

Replace functionName with an array, and use functionRenamer to build …
This commit is contained in:
Alp Mestanogullari 2015-07-29 12:03:18 +02:00
commit dc902e2f58
9 changed files with 50 additions and 25 deletions

View file

@ -21,11 +21,11 @@ counterApp.controller('CounterCtrl', ['$scope', '$http', '$interval', function (
var publishCounter = function (response) { $scope.counter = response.value; }; var publishCounter = function (response) { $scope.counter = response.value; };
$scope.getCounter = function() { $scope.getCounter = function() {
getcounter($http) getCounter($http)
.success(publishCounter); .success(publishCounter);
} }
$scope.incCounter = function() { $scope.incCounter = function() {
postcounter($http) postCounter($http)
.success(publishCounter); .success(publishCounter);
} }

View file

@ -20,11 +20,11 @@ counterApp.controller('CounterCtrl', function ($scope,counterSvc, $interval) {
var publishCounter = function (response) { $scope.counter = response.value; }; var publishCounter = function (response) { $scope.counter = response.value; };
$scope.getCounter = function() { $scope.getCounter = function() {
counterSvc.getcounter() counterSvc.getCounter()
.success(publishCounter); .success(publishCounter);
} }
$scope.incCounter = function() { $scope.incCounter = function() {
counterSvc.postcounter() counterSvc.postCounter()
.success(publishCounter); .success(publishCounter);
} }

View file

@ -17,11 +17,11 @@
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
// we get the current value stored by the server when the page is loaded // we get the current value stored by the server when the page is loaded
getcounter(updateCounter, alert); getCounter(updateCounter, alert);
// we update the value every 1sec, in the same way // we update the value every 1sec, in the same way
window.setInterval(function() { window.setInterval(function() {
getcounter(updateCounter, alert); getCounter(updateCounter, alert);
}, 1000); }, 1000);
}); });
@ -33,7 +33,7 @@ function updateCounter(response)
// when the button is clicked, ask the server to increase // when the button is clicked, ask the server to increase
// the value by one // the value by one
$('#inc').click(function() { $('#inc').click(function() {
postcounter(updateCounter, alert); postCounter(updateCounter, alert);
}); });
</script> </script>
</body> </body>

View file

@ -16,11 +16,11 @@
<script type="text/javascript"> <script type="text/javascript">
window.addEventListener('load', function() { window.addEventListener('load', function() {
// we get the current value stored by the server when the page is loaded // we get the current value stored by the server when the page is loaded
getcounter(updateCounter, alert); getCounter(updateCounter, alert);
// we update the value every 1sec, in the same way // we update the value every 1sec, in the same way
window.setInterval(function() { window.setInterval(function() {
getcounter(updateCounter, alert); getCounter(updateCounter, alert);
}, 1000); }, 1000);
}); });
@ -32,7 +32,7 @@ function updateCounter(response)
// when the button is clicked, ask the server to increase // when the button is clicked, ask the server to increase
// the value by one // the value by one
document.getElementById('inc').addEventListener('click', function() { document.getElementById('inc').addEventListener('click', function() {
postcounter(updateCounter, alert); postCounter(updateCounter, alert);
}); });
</script> </script>
</body> </body>

View file

@ -79,6 +79,11 @@ module Servant.JS
CommonGeneratorOptions(..) CommonGeneratorOptions(..)
, defCommonGeneratorOptions , defCommonGeneratorOptions
, -- * Function renamers
concatCase
, snakeCase
, camelCase
, -- * Vanilla Javascript code generation , -- * Vanilla Javascript code generation
vanillaJS vanillaJS
, vanillaJSWith , vanillaJSWith

View file

@ -123,7 +123,7 @@ generateAngularJSWith ngOptions opts req = "\n" <>
fsep = if hasService then ":" else " =" fsep = if hasService then ":" else " ="
fname = namespace <> (functionRenamer opts $ req ^. funcName) fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
method = req ^. reqMethod method = req ^. reqMethod
url = if url' == "'" then "'/'" else url' url = if url' == "'" then "'/'" else url'

View file

@ -14,7 +14,7 @@ module Servant.JS.Internal where
import Control.Applicative import Control.Applicative
#endif #endif
import Control.Lens import Control.Lens
import Data.Char (toLower) import Data.Char (toLower, toUpper)
import qualified Data.CharSet as Set import qualified Data.CharSet as Set
import qualified Data.CharSet.Unicode.Category as Set import qualified Data.CharSet.Unicode.Category as Set
import Data.List import Data.List
@ -29,7 +29,7 @@ import Servant.API
-- customize the output -- customize the output
data CommonGeneratorOptions = CommonGeneratorOptions data CommonGeneratorOptions = CommonGeneratorOptions
{ {
functionRenamer :: String -> String -- ^ function transforming function names functionNameBuilder :: FunctionName -> String -- ^ function generating function names
, requestBody :: String -- ^ name used when a user want to send the request body (to let you redefine it) , requestBody :: String -- ^ name used when a user want to send the request body (to let you redefine it)
, successCallback :: String -- ^ name of the callback parameter when the request was successful , successCallback :: String -- ^ name of the callback parameter when the request was successful
, errorCallback :: String -- ^ name of the callback parameter when the request reported an error , errorCallback :: String -- ^ name of the callback parameter when the request reported an error
@ -41,7 +41,7 @@ data CommonGeneratorOptions = CommonGeneratorOptions
-- --
-- @ -- @
-- > defCommonGeneratorOptions = CommonGeneratorOptions -- > defCommonGeneratorOptions = CommonGeneratorOptions
-- > { functionRenamer = id -- > { functionNameBuilder = camelCase
-- > , requestBody = "body" -- > , requestBody = "body"
-- > , successCallback = "onSuccess" -- > , successCallback = "onSuccess"
-- > , errorCallback = "onError" -- > , errorCallback = "onError"
@ -52,7 +52,7 @@ data CommonGeneratorOptions = CommonGeneratorOptions
defCommonGeneratorOptions :: CommonGeneratorOptions defCommonGeneratorOptions :: CommonGeneratorOptions
defCommonGeneratorOptions = CommonGeneratorOptions defCommonGeneratorOptions = CommonGeneratorOptions
{ {
functionRenamer = id functionNameBuilder = camelCase
, requestBody = "body" , requestBody = "body"
, successCallback = "onSuccess" , successCallback = "onSuccess"
, errorCallback = "onError" , errorCallback = "onError"
@ -60,6 +60,25 @@ defCommonGeneratorOptions = CommonGeneratorOptions
, urlPrefix = "" , urlPrefix = ""
} }
-- | Function name builder that simply concat each part together
concatCase :: FunctionName -> String
concatCase = concat
-- | Function name builder using the snake_case convention.
-- each part is separated by a single underscore character.
snakeCase :: FunctionName -> String
snakeCase = intercalate "_"
-- | Function name builder using the CamelCase convention.
-- each part begins with an upper case character.
camelCase :: FunctionName -> String
camelCase [] = ""
camelCase (p:ps) = concat $ p : camelCase' ps
where camelCase' [] = []
camelCase' (r:rs) = capitalize r : camelCase' rs
capitalize [] = []
capitalize (x:xs) = toUpper x : xs
type Arg = String type Arg = String
-- A 'JavascriptGenerator' just takes the data found in the API type -- A 'JavascriptGenerator' just takes the data found in the API type
@ -149,7 +168,7 @@ data Url = Url
defUrl :: Url defUrl :: Url
defUrl = Url [] [] defUrl = Url [] []
type FunctionName = String type FunctionName = [String]
type Method = String type Method = String
data AjaxReq = AjaxReq data AjaxReq = AjaxReq
@ -226,7 +245,7 @@ paramToStr qarg notTheEnd =
where name = qarg ^. argName where name = qarg ^. argName
defReq :: AjaxReq defReq :: AjaxReq
defReq = AjaxReq defUrl "GET" [] False "" defReq = AjaxReq defUrl "GET" [] False []
type family Elem (a :: *) (ls::[*]) :: Constraint where type family Elem (a :: *) (ls::[*]) :: Constraint where
Elem a '[] = 'False ~ 'True Elem a '[] = 'False ~ 'True
@ -252,6 +271,7 @@ instance (KnownSymbol sym, HasJS sublayout)
javascriptFor Proxy req = javascriptFor Proxy req =
javascriptFor (Proxy :: Proxy sublayout) $ javascriptFor (Proxy :: Proxy sublayout) $
req & reqUrl.path <>~ [Segment (Cap str) []] req & reqUrl.path <>~ [Segment (Cap str) []]
& funcName %~ (++ ["by", str])
where str = symbolVal (Proxy :: Proxy sym) where str = symbolVal (Proxy :: Proxy sym)
@ -259,14 +279,14 @@ instance Elem JSON list => HasJS (Delete list a) where
type JS (Delete list a) = AjaxReq type JS (Delete list a) = AjaxReq
javascriptFor Proxy req = javascriptFor Proxy req =
req & funcName %~ ("delete" <>) req & funcName %~ ("delete" :)
& reqMethod .~ "DELETE" & reqMethod .~ "DELETE"
instance Elem JSON list => HasJS (Get list a) where instance Elem JSON list => HasJS (Get list a) where
type JS (Get list a) = AjaxReq type JS (Get list a) = AjaxReq
javascriptFor Proxy req = javascriptFor Proxy req =
req & funcName %~ ("get" <>) req & funcName %~ ("get" :)
& reqMethod .~ "GET" & reqMethod .~ "GET"
instance (KnownSymbol sym, HasJS sublayout) instance (KnownSymbol sym, HasJS sublayout)
@ -283,14 +303,14 @@ instance Elem JSON list => HasJS (Post list a) where
type JS (Post list a) = AjaxReq type JS (Post list a) = AjaxReq
javascriptFor Proxy req = javascriptFor Proxy req =
req & funcName %~ ("post" <>) req & funcName %~ ("post" :)
& reqMethod .~ "POST" & reqMethod .~ "POST"
instance Elem JSON list => HasJS (Put list a) where instance Elem JSON list => HasJS (Put list a) where
type JS (Put list a) = AjaxReq type JS (Put list a) = AjaxReq
javascriptFor Proxy req = javascriptFor Proxy req =
req & funcName %~ ("put" <>) req & funcName %~ ("put" :)
& reqMethod .~ "PUT" & reqMethod .~ "PUT"
instance (KnownSymbol sym, HasJS sublayout) instance (KnownSymbol sym, HasJS sublayout)
@ -358,7 +378,7 @@ instance HasJS Raw where
type JS Raw = Method -> AjaxReq type JS Raw = Method -> AjaxReq
javascriptFor Proxy req method = javascriptFor Proxy req method =
req & funcName %~ ((toLower <$> method) <>) req & funcName %~ ((toLower <$> method) :)
& reqMethod .~ method & reqMethod .~ method
instance (Elem JSON list, HasJS sublayout) => HasJS (ReqBody list a :> sublayout) where instance (Elem JSON list, HasJS sublayout) => HasJS (ReqBody list a :> sublayout) where
@ -375,7 +395,7 @@ instance (KnownSymbol path, HasJS sublayout)
javascriptFor Proxy req = javascriptFor Proxy req =
javascriptFor (Proxy :: Proxy sublayout) $ javascriptFor (Proxy :: Proxy sublayout) $
req & reqUrl.path <>~ [Segment (Static str) []] req & reqUrl.path <>~ [Segment (Static str) []]
& funcName %~ (str <>) & funcName %~ (++ [str])
where str = map (\c -> if c == '.' then '_' else c) $ symbolVal (Proxy :: Proxy path) where str = map (\c -> if c == '.' then '_' else c) $ symbolVal (Proxy :: Proxy path)

View file

@ -76,7 +76,7 @@ generateJQueryJSWith opts req = "\n" <>
namespace = if null (moduleName opts) namespace = if null (moduleName opts)
then "var " then "var "
else (moduleName opts) <> "." else (moduleName opts) <> "."
fname = namespace <> (functionRenamer opts $ req ^. funcName) fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
method = req ^. reqMethod method = req ^. reqMethod
url = if url' == "'" then "'/'" else url' url = if url' == "'" then "'/'" else url'

View file

@ -83,7 +83,7 @@ generateVanillaJSWith opts req = "\n" <>
namespace = if null (moduleName opts) namespace = if null (moduleName opts)
then "var " then "var "
else (moduleName opts) <> "." else (moduleName opts) <> "."
fname = namespace <> (functionRenamer opts $ req ^. funcName) fname = namespace <> (functionNameBuilder opts $ req ^. funcName)
method = req ^. reqMethod method = req ^. reqMethod
url = if url' == "'" then "'/'" else url' url = if url' == "'" then "'/'" else url'