{-# LANGUAGE PatternSynonyms #-}
module Panfiguration.Case
    ( Case(..)
    , camel
    , snake
    , pattern SNAKE
    , pattern KEBAB
    , kebab
    -- * Operation
    , split
    , join
    , convert
    )
    where

import Data.Char
import qualified Data.List.Split as S
import Data.List (intercalate)

data Case = Delimiter String
    | AsIs
    | Camel
    | LowerCamel
    | Upper Case
    | Lower Case
    | Prefixed String Case

camel :: Case
camel :: Case
camel = Case
LowerCamel

snake :: Case
snake :: Case
snake = Case -> Case
Lower forall a b. (a -> b) -> a -> b
$ String -> Case
Delimiter String
"_"

pattern SNAKE :: Case
pattern $bSNAKE :: Case
$mSNAKE :: forall {r}. Case -> ((# #) -> r) -> ((# #) -> r) -> r
SNAKE = Upper (Delimiter "_")

kebab :: Case
kebab :: Case
kebab = Case -> Case
Lower forall a b. (a -> b) -> a -> b
$ String -> Case
Delimiter String
"-"

pattern KEBAB :: Case
pattern $bKEBAB :: Case
$mKEBAB :: forall {r}. Case -> ((# #) -> r) -> ((# #) -> r) -> r
KEBAB = Upper (Delimiter "-")

split :: Case -> String -> [String]
split :: Case -> String -> [String]
split Case
AsIs = forall (f :: * -> *) a. Applicative f => a -> f a
pure
split (Delimiter String
d) = forall a. Eq a => [a] -> [a] -> [[a]]
S.splitOn String
d
split Case
Camel = String -> [String]
splitCamel
split Case
LowerCamel = String -> [String]
splitCamel
split (Lower Case
c) = Case -> String -> [String]
split Case
c
split (Upper Case
c) = Case -> String -> [String]
split Case
c
split (Prefixed String
p Case
c) = \String
str -> case Case -> String -> [String]
split Case
c String
str of
    String
x : [String]
xs | String
x forall a. Eq a => a -> a -> Bool
== String
p -> [String]
xs
    [String]
xs -> [String]
xs

splitCamel :: String -> [String]
splitCamel :: String -> [String]
splitCamel = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> String -> [String]
bravo String
"") forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> [String]
alpha String
"" where
    alpha :: String -> String -> [String]
alpha String
"" String
"" = []
    alpha String
buf String
"" = [forall a. [a] -> [a]
reverse String
buf]
    alpha String
buf (Char
x:Char
u:Char
l:String
xs) | Char -> Bool
isUpper Char
u Bool -> Bool -> Bool
&& Char -> Bool
isLower Char
l = forall a. [a] -> [a]
reverse (Char
x forall a. a -> [a] -> [a]
: String
buf) forall a. a -> [a] -> [a]
: String -> String -> [String]
alpha [Char
l, Char
u] String
xs
    alpha String
buf (Char
x:String
xs) = String -> String -> [String]
alpha (Char
x forall a. a -> [a] -> [a]
: String
buf) String
xs
    
    bravo :: String -> String -> [String]
bravo String
"" String
"" = []
    bravo String
buf String
"" = [forall a. [a] -> [a]
reverse String
buf]
    bravo String
buf (Char
l:Char
u:String
xs) | Char -> Bool
isLower Char
l Bool -> Bool -> Bool
&& Char -> Bool
isUpper Char
u = forall a. [a] -> [a]
reverse (Char
l forall a. a -> [a] -> [a]
: String
buf) forall a. a -> [a] -> [a]
: String -> String -> [String]
bravo [Char
u] String
xs
    bravo String
buf (Char
x:String
xs) = String -> String -> [String]
bravo (Char
x forall a. a -> [a] -> [a]
: String
buf) String
xs

join :: Case -> [String] -> String
join :: Case -> [String] -> String
join Case
AsIs [String]
xs = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
xs
join (Delimiter String
d) [String]
xs = forall a. [a] -> [[a]] -> [a]
intercalate String
d [String]
xs
join Case
Camel [String]
xs = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap String -> String
capitalise [String]
xs
join Case
LowerCamel (String
x : [String]
xs) = String
x forall a. Semigroup a => a -> a -> a
<> forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap String -> String
capitalise [String]
xs
join Case
LowerCamel [] = String
""
join (Upper Case
c) [String]
xs = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper forall a b. (a -> b) -> a -> b
$ Case -> [String] -> String
join Case
c [String]
xs
join (Lower Case
c) [String]
xs = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower forall a b. (a -> b) -> a -> b
$ Case -> [String] -> String
join Case
c [String]
xs
join (Prefixed String
str Case
c) [String]
xs = Case -> [String] -> String
join Case
c forall a b. (a -> b) -> a -> b
$ String
str forall a. a -> [a] -> [a]
: [String]
xs
 
capitalise :: String -> String
capitalise :: String -> String
capitalise (Char
x : String
xs) = Char -> Char
toUpper Char
x forall a. a -> [a] -> [a]
: String
xs
capitalise String
xs = String
xs

convert :: Case -> Case -> String -> String
convert :: Case -> Case -> String -> String
convert Case
c Case
d = Case -> [String] -> String
join Case
d forall b c a. (b -> c) -> (a -> b) -> a -> c
. Case -> String -> [String]
split Case
c