on master help sign in
Add a toTitle function
104c422Bryan O'Sullivan
Data/Text.hs+23
@@ -79,6 +79,7 @@ module Data.Text
79 , toCaseFold
79 , toCaseFold
80 , toLower
80 , toLower
81 , toUpper
81 , toUpper
82+ , toTitle
82
83
83 -- ** Justification
84 -- ** Justification
84 , justifyLeft
85 , justifyLeft
@@ -679,6 +680,28 @@ toUpper :: Text -> Text
679toUpper t = unstream (S.toUpper (stream t))
680toUpper t = unstream (S.toUpper (stream t))
680{-# INLINE toUpper #-}
681{-# INLINE toUpper #-}
681
682
683+-- | /O(n)/ Convert a string to title case, using simple case
684+-- conversion.
685+--
686+-- Unlike the other case conversion functions, this function does not
687+-- convert every letter of its input. Instead, the first letter is
688+-- converted to title case, as is every subsequent letter that
689+-- immediately follows a non-letter.
690+--
691+-- The result string may be longer than the input string. For example,
692+-- the Latin small ligature fl (U+FB02) is converted to the
693+-- sequence Latin capital letter F (U+0046) followed by Latin small
694+-- letter l (U+006C).
695+--
696+-- /Note/: this function does not take language or culture specific
697+-- rules into account. For instance, in English, different style
698+-- guides disagree on whether the book name \"The Hill of the Red
699+-- Fox\" is correctly title cased—but this function will
700+-- capitalize /every/ word.
701+toTitle :: Text -> Text
702+toTitle t = unstream (S.toTitle (stream t))
703+{-# INLINE toTitle #-}
704+
682-- | /O(n)/ Left-justify a string to the given length, using the
705-- | /O(n)/ Left-justify a string to the given length, using the
683-- specified fill character on the right. Subject to fusion.
706-- specified fill character on the right. Subject to fusion.
684-- Performs replacement on invalid scalar values.
707-- Performs replacement on invalid scalar values.
Data/Text/Fusion/Common.hs+37−2
@@ -42,6 +42,7 @@ module Data.Text.Fusion.Common
42 -- $case
42 -- $case
43 , toCaseFold
43 , toCaseFold
44 , toLower
44 , toLower
45+ , toTitle
45 , toUpper
46 , toUpper
46
47
47 -- ** Justification
48 -- ** Justification
@@ -102,13 +103,15 @@ module Data.Text.Fusion.Common
102
103
103import Prelude (Bool(..), Char, Eq(..), Int, Integral, Maybe(..),
104import Prelude (Bool(..), Char, Eq(..), Int, Integral, Maybe(..),
104 Ord(..), Ordering(..), String, (.), ($), (+), (-), (*), (++),
105 Ord(..), Ordering(..), String, (.), ($), (+), (-), (*), (++),
105− (&&), fromIntegral, otherwise)
106+ (&&), fromIntegral, not, otherwise)
106import qualified Data.List as L
107import qualified Data.List as L
107import qualified Prelude as P
108import qualified Prelude as P
108import Data.Bits (shiftL)
109import Data.Bits (shiftL)
110+import Data.Char (isLetter)
109import Data.Int (Int64)
111import Data.Int (Int64)
110import Data.Text.Fusion.Internal
112import Data.Text.Fusion.Internal
111−import Data.Text.Fusion.CaseMapping (foldMapping, lowerMapping, upperMapping)
113+import Data.Text.Fusion.CaseMapping (foldMapping, lowerMapping, titleMapping,
114+ upperMapping)
112import Data.Text.Fusion.Size
115import Data.Text.Fusion.Size
113import GHC.Prim (Addr#, chr#, indexCharOffAddr#, ord#)
116import GHC.Prim (Addr#, chr#, indexCharOffAddr#, ord#)
114import GHC.Types (Char(..), Int(..))
117import GHC.Types (Char(..), Int(..))
@@ -432,6 +435,38 @@ toLower :: Stream Char -> Stream Char
432toLower = caseConvert lowerMapping
435toLower = caseConvert lowerMapping
433{-# INLINE [0] toLower #-}
436{-# INLINE [0] toLower #-}
434
437
438+-- | /O(n)/ Convert a string to title case, using simple case
439+-- conversion.
440+--
441+-- Unlike the other case conversion functions, this function does not
442+-- convert every letter of its input. Instead, the first letter is
443+-- converted to title case, as is every subsequent letter that
444+-- immediately follows a non-letter.
445+--
446+-- The result string may be longer than the input string. For example,
447+-- the Latin small ligature fl (U+FB02) is converted to the
448+-- sequence Latin capital letter F (U+0046) followed by Latin small
449+-- letter l (U+006C).
450+--
451+-- /Note/: this function does not take language or culture specific
452+-- rules into account. For instance, in English, different style
453+-- guides disagree on whether the book name \"The Hill of the Red
454+-- Fox\" is correctly title cased—but this function will
455+-- capitalize /every/ word.
456+toTitle :: Stream Char -> Stream Char
457+toTitle (Stream next0 s0 len) = Stream next (CC (False :*: s0) '\0' '\0') len
458+ where
459+ next (CC (letter :*: s) '\0' _) =
460+ case next0 s of
461+ Done -> Done
462+ Skip s' -> Skip (CC (letter :*: s') '\0' '\0')
463+ Yield c s'
464+ | not letter && letter' -> titleMapping c (letter' :*: s')
465+ | otherwise -> Yield c (CC (letter' :*: s') '\0' '\0')
466+ where letter' = isLetter c
467+ next (CC s a b) = Yield a (CC s b '\0')
468+{-# INLINE [0] toTitle #-}
469+
435justifyLeftI :: Integral a => a -> Char -> Stream Char -> Stream Char
470justifyLeftI :: Integral a => a -> Char -> Stream Char -> Stream Char
436justifyLeftI k c (Stream next0 s0 len) =
471justifyLeftI k c (Stream next0 s0 len) =
437 Stream next (s0 :*: S1 :*: 0) (larger (fromIntegral k) len)
472 Stream next (s0 :*: S1 :*: 0) (larger (fromIntegral k) len)
Data/Text/Lazy.hs+24
@@ -86,6 +86,7 @@ module Data.Text.Lazy
86 , toCaseFold
86 , toCaseFold
87 , toLower
87 , toLower
88 , toUpper
88 , toUpper
89+ , toTitle
89
90
90 -- ** Justification
91 -- ** Justification
91 , justifyLeft
92 , justifyLeft
@@ -697,6 +698,29 @@ toUpper :: Text -> Text
697toUpper t = unstream (S.toUpper (stream t))
698toUpper t = unstream (S.toUpper (stream t))
698{-# INLINE toUpper #-}
699{-# INLINE toUpper #-}
699
700
701+
702+-- | /O(n)/ Convert a string to title case, using simple case
703+-- conversion.
704+--
705+-- Unlike the other case conversion functions, this function does not
706+-- convert every letter of its input. Instead, the first letter is
707+-- converted to title case, as is every subsequent letter that
708+-- immediately follows a non-letter.
709+--
710+-- The result string may be longer than the input string. For example,
711+-- the Latin small ligature fl (U+FB02) is converted to the
712+-- sequence Latin capital letter F (U+0046) followed by Latin small
713+-- letter l (U+006C).
714+--
715+-- /Note/: this function does not take language or culture specific
716+-- rules into account. For instance, in English, different style
717+-- guides disagree on whether the book name \"The Hill of the Red
718+-- Fox\" is correctly title cased—but this function will
719+-- capitalize /every/ word.
720+toTitle :: Text -> Text
721+toTitle t = unstream (S.toTitle (stream t))
722+{-# INLINE toTitle #-}
723+
700-- | /O(n)/ 'foldl', applied to a binary operator, a starting value
724-- | /O(n)/ 'foldl', applied to a binary operator, a starting value
701-- (typically the left-identity of the operator), and a 'Text',
725-- (typically the left-identity of the operator), and a 'Text',
702-- reduces the 'Text' using the binary operator, from left to right.
726-- reduces the 'Text' using the binary operator, from left to right.