{-# LANGUAGE OverloadedStrings #-}
module Servant.Foreign.Inflections
  ( concatCase
  , snakeCase
  , camelCase
    -- lenses
  , concatCaseL
  , snakeCaseL
  , camelCaseL
  ) where


import           Control.Lens             hiding
                 (cons)
import qualified Data.Char                as C
import           Data.Monoid
import           Data.Text                hiding
                 (map)
import           Prelude                  hiding
                 (head, tail)
import           Servant.Foreign.Internal

-- | Simply concat each part of the FunctionName together.
--
-- @[ "get", "documents", "by", "id" ] → "getdocumentsbyid"@
concatCase :: FunctionName -> Text
concatCase :: FunctionName -> Text
concatCase = Getting Text FunctionName Text -> FunctionName -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text FunctionName Text
Getter FunctionName Text
concatCaseL

concatCaseL :: Getter FunctionName Text
concatCaseL :: (Text -> f Text) -> FunctionName -> f FunctionName
concatCaseL = ([Text] -> f [Text]) -> FunctionName -> f FunctionName
Iso' FunctionName [Text]
_FunctionName (([Text] -> f [Text]) -> FunctionName -> f FunctionName)
-> ((Text -> f Text) -> [Text] -> f [Text])
-> (Text -> f Text)
-> FunctionName
-> f FunctionName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Text] -> Text) -> (Text -> f Text) -> [Text] -> f [Text]
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat

-- | Use the snake_case convention.
-- Each part is separated by a single underscore character.
--
-- @[ "get", "documents", "by", "id" ] → "get_documents_by_id"@
snakeCase :: FunctionName -> Text
snakeCase :: FunctionName -> Text
snakeCase = Getting Text FunctionName Text -> FunctionName -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text FunctionName Text
Getter FunctionName Text
snakeCaseL

snakeCaseL :: Getter FunctionName Text
snakeCaseL :: (Text -> f Text) -> FunctionName -> f FunctionName
snakeCaseL = ([Text] -> f [Text]) -> FunctionName -> f FunctionName
Iso' FunctionName [Text]
_FunctionName (([Text] -> f [Text]) -> FunctionName -> f FunctionName)
-> ((Text -> f Text) -> [Text] -> f [Text])
-> (Text -> f Text)
-> FunctionName
-> f FunctionName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Text] -> Text) -> (Text -> f Text) -> [Text] -> f [Text]
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to (Text -> [Text] -> Text
intercalate Text
"_")

-- | Use the camelCase convention.
-- The first part is lower case, every other part starts with an upper case character.
--
-- @[ "get", "documents", "by", "id" ] → "getDocumentsById"@
camelCase :: FunctionName -> Text
camelCase :: FunctionName -> Text
camelCase = Getting Text FunctionName Text -> FunctionName -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text FunctionName Text
Getter FunctionName Text
camelCaseL

camelCaseL :: Getter FunctionName Text
camelCaseL :: (Text -> f Text) -> FunctionName -> f FunctionName
camelCaseL = ([Text] -> f [Text]) -> FunctionName -> f FunctionName
Iso' FunctionName [Text]
_FunctionName (([Text] -> f [Text]) -> FunctionName -> f FunctionName)
-> ((Text -> f Text) -> [Text] -> f [Text])
-> (Text -> f Text)
-> FunctionName
-> f FunctionName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Text] -> Text) -> (Text -> f Text) -> [Text] -> f [Text]
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to [Text] -> Text
convert
  where
    convert :: [Text] -> Text
convert []     = Text
""
    convert (Text
p:[Text]
ps) = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ Text
p Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
capitalize [Text]
ps
    capitalize :: Text -> Text
capitalize Text
""   = Text
""
    capitalize Text
name = Char -> Char
C.toUpper (Text -> Char
head Text
name) Char -> Text -> Text
`cons` Text -> Text
tail Text
name