module Text.Casing where

import Data.Char
import Data.List (intercalate)
import Data.Text (Text, split)
import qualified Data.Text as T

upper :: Text -> Text
upper :: Text -> Text
upper t :: Text
t = Char -> Text -> Text
T.cons (Char -> Char
toUpper (Char -> Char) -> Char -> Char
forall a b. (a -> b) -> a -> b
$ Text -> Char
T.head Text
t) (Text -> Text
T.tail Text
t)

upper' :: String -> String
upper' :: String -> String
upper' (x :: Char
x : xs :: String
xs) = Char -> Char
toUpper Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: String
xs

lower :: String -> String
lower :: String -> String
lower t :: String
t = (Char -> Char
toLower (Char -> Char) -> Char -> Char
forall a b. (a -> b) -> a -> b
$ String -> Char
forall a. [a] -> a
head String
t) Char -> String -> String
forall a. a -> [a] -> [a]
: (String -> String
forall a. [a] -> [a]
tail String
t)

lower' :: Text -> Text
lower' :: Text -> Text
lower' t :: Text
t = Char -> Text -> Text
T.cons (Char -> Char
toLower (Char -> Char) -> Char -> Char
forall a b. (a -> b) -> a -> b
$ Text -> Char
T.head Text
t) (Text -> Text
T.tail Text
t)

splitOn' :: (Char -> Bool) -> String -> [String]
splitOn' :: (Char -> Bool) -> String -> [String]
splitOn' p :: Char -> Bool
p t :: String
t = String -> [String]
go String
t
  where
    go1 :: String -> String -> (String, String)
go1 s :: String
s "" = (String -> String
forall a. [a] -> [a]
reverse String
s, "")
    go1 "" (x :: Char
x : xs :: String
xs) = String -> String -> (String, String)
go1 [Char
x] String
xs
    go1 s :: String
s s' :: String
s'@(x :: Char
x : xs :: String
xs) = if Bool -> Bool
not (Char -> Bool
p Char
x) then String -> String -> (String, String)
go1 (Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: String
s) String
xs else (String -> String
forall a. [a] -> [a]
reverse String
s, String
s')
    go :: String -> [String]
go x :: String
x =
      let (s :: String
s, rest :: String
rest) = String -> String -> (String, String)
go1 "" String
x
       in if String
rest String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== "" then [String
s] else String
s String -> [String] -> [String]
forall a. a -> [a] -> [a]
: String -> [String]
go String
rest

snakeToCamel :: Text -> Text
snakeToCamel :: Text -> Text
snakeToCamel t :: Text
t =
  let (x :: Text
x : xs :: [Text]
xs) = (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= "") ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Text -> [Text]
split (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '_') Text
t
   in [Text] -> Text
T.concat (Text -> Text
lower' Text
x Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: (Text -> Text) -> [Text] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Text
upper [Text]
xs)

camelToSnake :: String -> String
camelToSnake :: String -> String
camelToSnake t :: String
t =
  let l :: [String]
l = (Char -> Bool) -> String -> [String]
splitOn' Char -> Bool
isUpper String
t
   in String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate "_" ((String -> String) -> [String] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> String
lower [String]
l)