{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE MultiWayIf #-} module Data.Text.Titlecase ( Titlecase , titlecase ) where import Prelude (Int, ($), (==), (||), (&&), succ, otherwise) import qualified Data.List as List import Data.Text hiding (toTitle) import Data.Text.Titlecase.Internal -- | Capitalize all English words except 'articles' (a, an, the), -- coordinating 'conjunctions' (for, and, nor, but, or, yet, so), and -- 'prepositions' (unless they begin or end the title). The -- 'prepositions' are taken from this list: -- . titlecase :: Text -> Titlecase titlecase t = Titlecase $ go 1 ws where ws :: [Text] ws = words t isFirst i = i == 1 isLast i = i == List.length ws go :: Int -> [Text] -> Text go _ [] = "" go i (a:b:c:d:tt) = parse4 i a b c d tt go i (a:b:c :tt) = parse3 i a b c tt go i (a:b :tt) = parse2 i a b tt go i (a :tt) = parse1 i a tt parse4 i a b c d tt = if isFourWordPreposition a b c d then if | isFirst i && List.null tt -> unwords [toTitle a, b, c, toTitle d] | isFirst i -> unwords [toTitle a, b, c, d] <#> go (succ i) tt | List.null tt -> unwords [ a, b, c, toTitle d] | otherwise -> unwords [ a, b, c, d] <#> go (succ i) tt else parse3 i a b c (d:tt) parse3 i a b c tt = if isThreeWordPreposition a b c then if | isFirst i && List.null tt -> unwords [toTitle a, b, toTitle c] | isFirst i -> unwords [toTitle a, b, c] <#> go (succ i) tt | List.null tt -> unwords [ a, b, toTitle c] | otherwise -> unwords [ a, b, c] <#> go (succ i) tt else parse2 i a b (c:tt) parse2 i a b tt = if isTwoWordPreposition a b then if | isFirst i && List.null tt -> unwords [toTitle a, toTitle b] | isFirst i -> unwords [toTitle a, b] <#> go (succ i) tt | List.null tt -> unwords [ a, toTitle b] | otherwise -> unwords [ a, b] <#> go (succ i) tt else parse1 i a (b:tt) parse1 i a tt = if isOneWordPreposition a || isConjunction a || isArticle a then if isFirst i || isLast i then toTitle a <#> go (succ i) tt else a <#> go (succ i) tt else toTitle a <#> go (succ i) tt