From c01ad63112c707cc04ffb9fae5a59e66f7e7c314 Mon Sep 17 00:00:00 2001 From: Freezeboy Date: Mon, 27 Jul 2015 13:55:30 +0200 Subject: [PATCH 1/4] Replace functionName with an array, and use functionRenamer to build the real function name --- servant-js/src/Servant/JS.hs | 5 ++++ servant-js/src/Servant/JS/Internal.hs | 43 +++++++++++++++++++-------- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/servant-js/src/Servant/JS.hs b/servant-js/src/Servant/JS.hs index 1367fffd..8dfb1e37 100644 --- a/servant-js/src/Servant/JS.hs +++ b/servant-js/src/Servant/JS.hs @@ -79,6 +79,11 @@ module Servant.JS CommonGeneratorOptions(..) , defCommonGeneratorOptions + , -- * Function renamers + concatRenamer + , snakeCaseRenamer + , camelCaseRenamer + , -- * Vanilla Javascript code generation vanillaJS , vanillaJSWith diff --git a/servant-js/src/Servant/JS/Internal.hs b/servant-js/src/Servant/JS/Internal.hs index 909df8d2..2a3eee88 100644 --- a/servant-js/src/Servant/JS/Internal.hs +++ b/servant-js/src/Servant/JS/Internal.hs @@ -14,7 +14,7 @@ module Servant.JS.Internal where import Control.Applicative #endif import Control.Lens -import Data.Char (toLower) +import Data.Char (toLower, toUpper) import qualified Data.CharSet as Set import qualified Data.CharSet.Unicode.Category as Set import Data.List @@ -29,7 +29,7 @@ import Servant.API -- customize the output data CommonGeneratorOptions = CommonGeneratorOptions { - functionRenamer :: String -> String -- ^ function transforming function names + functionRenamer :: FunctionName -> String -- ^ function transforming function names , 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 , errorCallback :: String -- ^ name of the callback parameter when the request reported an error @@ -40,7 +40,7 @@ data CommonGeneratorOptions = CommonGeneratorOptions -- -- @ -- > defCommonGeneratorOptions = CommonGeneratorOptions --- > { functionRenamer = id +-- > { functionRenamer = concatRenamer -- > , requestBody = "body" -- > , successCallback = "onSuccess" -- > , errorCallback = "onError" @@ -50,12 +50,31 @@ data CommonGeneratorOptions = CommonGeneratorOptions defCommonGeneratorOptions :: CommonGeneratorOptions defCommonGeneratorOptions = CommonGeneratorOptions { - functionRenamer = id + functionRenamer = concatRenamer , requestBody = "body" , successCallback = "onSuccess" , errorCallback = "onError" , moduleName = "" } + +-- | Function renamer that simply concat each part together +concatRenamer :: FunctionName -> String +concatRenamer = concat + +-- | Function renamer using the snake_case convention. +-- each part is separated by a single underscore character. +snakeCaseRenamer :: FunctionName -> String +snakeCaseRenamer = intercalate "_" + +-- | Function renamer using the CamelCase convention. +-- each part begins with an upper case character. +camelCaseRenamer :: FunctionName -> String +camelCaseRenamer [] = "" +camelCaseRenamer (p:ps) = concat $ p : camelCaseRenamer' ps + where camelCaseRenamer' [] = [] + camelCaseRenamer' (r:rs) = capitalize r : camelCaseRenamer' rs + capitalize [] = [] + capitalize (x:xs) = toUpper x : xs type Arg = String @@ -146,7 +165,7 @@ data Url = Url defUrl :: Url defUrl = Url [] [] -type FunctionName = String +type FunctionName = [String] type Method = String data AjaxReq = AjaxReq @@ -223,7 +242,7 @@ paramToStr qarg notTheEnd = where name = qarg ^. argName defReq :: AjaxReq -defReq = AjaxReq defUrl "GET" [] False "" +defReq = AjaxReq defUrl "GET" [] False [] type family Elem (a :: *) (ls::[*]) :: Constraint where Elem a '[] = 'False ~ 'True @@ -256,14 +275,14 @@ instance Elem JSON list => HasJS (Delete list a) where type JS (Delete list a) = AjaxReq javascriptFor Proxy req = - req & funcName %~ ("delete" <>) + req & funcName %~ ("delete" :) & reqMethod .~ "DELETE" instance Elem JSON list => HasJS (Get list a) where type JS (Get list a) = AjaxReq javascriptFor Proxy req = - req & funcName %~ ("get" <>) + req & funcName %~ ("get" :) & reqMethod .~ "GET" instance (KnownSymbol sym, HasJS sublayout) @@ -280,14 +299,14 @@ instance Elem JSON list => HasJS (Post list a) where type JS (Post list a) = AjaxReq javascriptFor Proxy req = - req & funcName %~ ("post" <>) + req & funcName %~ ("post" :) & reqMethod .~ "POST" instance Elem JSON list => HasJS (Put list a) where type JS (Put list a) = AjaxReq javascriptFor Proxy req = - req & funcName %~ ("put" <>) + req & funcName %~ ("put" :) & reqMethod .~ "PUT" instance (KnownSymbol sym, HasJS sublayout) @@ -355,7 +374,7 @@ instance HasJS Raw where type JS Raw = Method -> AjaxReq javascriptFor Proxy req method = - req & funcName %~ ((toLower <$> method) <>) + req & funcName %~ ((toLower <$> method) :) & reqMethod .~ method instance (Elem JSON list, HasJS sublayout) => HasJS (ReqBody list a :> sublayout) where @@ -372,7 +391,7 @@ instance (KnownSymbol path, HasJS sublayout) javascriptFor Proxy req = javascriptFor (Proxy :: Proxy sublayout) $ req & reqUrl.path <>~ [Segment (Static str) []] - & funcName %~ (str <>) + & funcName %~ (++ [str]) where str = map (\c -> if c == '.' then '_' else c) $ symbolVal (Proxy :: Proxy path) From ef13160d8b6f81c6d8268e7d6433789f39249a4a Mon Sep 17 00:00:00 2001 From: Freezeboy Date: Tue, 28 Jul 2015 16:41:07 +0200 Subject: [PATCH 2/4] Rename functionRenamer and default to CameCase --- servant-js/examples/www/angular/index.html | 4 +-- servant-js/examples/www/jquery/index.html | 6 ++--- servant-js/examples/www/vanilla/index.html | 6 ++--- servant-js/src/Servant/JS.hs | 6 ++--- servant-js/src/Servant/JS/Angular.hs | 2 +- servant-js/src/Servant/JS/Internal.hs | 30 +++++++++++----------- servant-js/src/Servant/JS/JQuery.hs | 2 +- servant-js/src/Servant/JS/Vanilla.hs | 2 +- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/servant-js/examples/www/angular/index.html b/servant-js/examples/www/angular/index.html index 81ce491a..46ecf5ae 100644 --- a/servant-js/examples/www/angular/index.html +++ b/servant-js/examples/www/angular/index.html @@ -21,11 +21,11 @@ counterApp.controller('CounterCtrl', ['$scope', '$http', '$interval', function ( var publishCounter = function (response) { $scope.counter = response.value; }; $scope.getCounter = function() { - getcounter($http) + getCounter($http) .success(publishCounter); } $scope.incCounter = function() { - postcounter($http) + postCounter($http) .success(publishCounter); } diff --git a/servant-js/examples/www/jquery/index.html b/servant-js/examples/www/jquery/index.html index 48c7d652..eb1a5b6c 100644 --- a/servant-js/examples/www/jquery/index.html +++ b/servant-js/examples/www/jquery/index.html @@ -17,11 +17,11 @@ diff --git a/servant-js/examples/www/vanilla/index.html b/servant-js/examples/www/vanilla/index.html index 245172ab..9f663ae8 100644 --- a/servant-js/examples/www/vanilla/index.html +++ b/servant-js/examples/www/vanilla/index.html @@ -16,11 +16,11 @@ diff --git a/servant-js/src/Servant/JS.hs b/servant-js/src/Servant/JS.hs index 8dfb1e37..23835d21 100644 --- a/servant-js/src/Servant/JS.hs +++ b/servant-js/src/Servant/JS.hs @@ -80,9 +80,9 @@ module Servant.JS , defCommonGeneratorOptions , -- * Function renamers - concatRenamer - , snakeCaseRenamer - , camelCaseRenamer + concatCase + , snakeCase + , camelCase , -- * Vanilla Javascript code generation vanillaJS diff --git a/servant-js/src/Servant/JS/Angular.hs b/servant-js/src/Servant/JS/Angular.hs index 68ff0a27..2b0066aa 100644 --- a/servant-js/src/Servant/JS/Angular.hs +++ b/servant-js/src/Servant/JS/Angular.hs @@ -123,7 +123,7 @@ generateAngularJSWith ngOptions opts req = "\n" <> fsep = if hasService then ":" else " =" - fname = namespace <> (functionRenamer opts $ req ^. funcName) + fname = namespace <> (functionNameBuilder opts $ req ^. funcName) method = req ^. reqMethod url = if url' == "'" then "'/'" else url' diff --git a/servant-js/src/Servant/JS/Internal.hs b/servant-js/src/Servant/JS/Internal.hs index 2a3eee88..a101f235 100644 --- a/servant-js/src/Servant/JS/Internal.hs +++ b/servant-js/src/Servant/JS/Internal.hs @@ -29,7 +29,7 @@ import Servant.API -- customize the output data CommonGeneratorOptions = CommonGeneratorOptions { - functionRenamer :: FunctionName -> 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) , 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 @@ -40,7 +40,7 @@ data CommonGeneratorOptions = CommonGeneratorOptions -- -- @ -- > defCommonGeneratorOptions = CommonGeneratorOptions --- > { functionRenamer = concatRenamer +-- > { functionNameBuilder = camelCase -- > , requestBody = "body" -- > , successCallback = "onSuccess" -- > , errorCallback = "onError" @@ -50,29 +50,29 @@ data CommonGeneratorOptions = CommonGeneratorOptions defCommonGeneratorOptions :: CommonGeneratorOptions defCommonGeneratorOptions = CommonGeneratorOptions { - functionRenamer = concatRenamer + functionNameBuilder = camelCase , requestBody = "body" , successCallback = "onSuccess" , errorCallback = "onError" , moduleName = "" } --- | Function renamer that simply concat each part together -concatRenamer :: FunctionName -> String -concatRenamer = concat +-- | Function name builder that simply concat each part together +concatCase :: FunctionName -> String +concatCase = concat --- | Function renamer using the snake_case convention. +-- | Function name builder using the snake_case convention. -- each part is separated by a single underscore character. -snakeCaseRenamer :: FunctionName -> String -snakeCaseRenamer = intercalate "_" +snakeCase :: FunctionName -> String +snakeCase = intercalate "_" --- | Function renamer using the CamelCase convention. +-- | Function name builder using the CamelCase convention. -- each part begins with an upper case character. -camelCaseRenamer :: FunctionName -> String -camelCaseRenamer [] = "" -camelCaseRenamer (p:ps) = concat $ p : camelCaseRenamer' ps - where camelCaseRenamer' [] = [] - camelCaseRenamer' (r:rs) = capitalize r : camelCaseRenamer' rs +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 diff --git a/servant-js/src/Servant/JS/JQuery.hs b/servant-js/src/Servant/JS/JQuery.hs index be36792e..0231bb97 100644 --- a/servant-js/src/Servant/JS/JQuery.hs +++ b/servant-js/src/Servant/JS/JQuery.hs @@ -76,7 +76,7 @@ generateJQueryJSWith opts req = "\n" <> namespace = if null (moduleName opts) then "var " else (moduleName opts) <> "." - fname = namespace <> (functionRenamer opts $ req ^. funcName) + fname = namespace <> (functionNameBuilder opts $ req ^. funcName) method = req ^. reqMethod url = if url' == "'" then "'/'" else url' diff --git a/servant-js/src/Servant/JS/Vanilla.hs b/servant-js/src/Servant/JS/Vanilla.hs index c9b0fb49..ee632f95 100644 --- a/servant-js/src/Servant/JS/Vanilla.hs +++ b/servant-js/src/Servant/JS/Vanilla.hs @@ -83,7 +83,7 @@ generateVanillaJSWith opts req = "\n" <> namespace = if null (moduleName opts) then "var " else (moduleName opts) <> "." - fname = namespace <> (functionRenamer opts $ req ^. funcName) + fname = namespace <> (functionNameBuilder opts $ req ^. funcName) method = req ^. reqMethod url = if url' == "'" then "'/'" else url' From 3f538b547dec72edd97a18bff12a9153cdfd3ad3 Mon Sep 17 00:00:00 2001 From: Freezeboy Date: Tue, 28 Jul 2015 16:43:09 +0200 Subject: [PATCH 3/4] CamelCase for Angular Service --- servant-js/examples/www/angular/service.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/servant-js/examples/www/angular/service.html b/servant-js/examples/www/angular/service.html index 0131f4bc..8408ce61 100644 --- a/servant-js/examples/www/angular/service.html +++ b/servant-js/examples/www/angular/service.html @@ -20,11 +20,11 @@ counterApp.controller('CounterCtrl', function ($scope,counterSvc, $interval) { var publishCounter = function (response) { $scope.counter = response.value; }; $scope.getCounter = function() { - counterSvc.getcounter() + counterSvc.getCounter() .success(publishCounter); } $scope.incCounter = function() { - counterSvc.postcounter() + counterSvc.postCounter() .success(publishCounter); } From 116d7bf22b0721eeabd1ea1b1b22296f9b800757 Mon Sep 17 00:00:00 2001 From: Freezeboy Date: Tue, 28 Jul 2015 19:47:41 +0200 Subject: [PATCH 4/4] Add capture in function name --- servant-js/src/Servant/JS/Internal.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/servant-js/src/Servant/JS/Internal.hs b/servant-js/src/Servant/JS/Internal.hs index a101f235..36064a59 100644 --- a/servant-js/src/Servant/JS/Internal.hs +++ b/servant-js/src/Servant/JS/Internal.hs @@ -268,6 +268,7 @@ instance (KnownSymbol sym, HasJS sublayout) javascriptFor Proxy req = javascriptFor (Proxy :: Proxy sublayout) $ req & reqUrl.path <>~ [Segment (Cap str) []] + & funcName %~ (++ ["by", str]) where str = symbolVal (Proxy :: Proxy sym)