@@ -15,7 +15,6 @@
1515--
1616-- License : BSD-style
1717-- Maintainer : bos@serpentine.com
18−-- Stability : experimental
1918-- Portability : GHC
2019--
2120-- A time and space-efficient implementation of Unicode text.
@@ -32,8 +31,9 @@
3231--
3332-- To use an extended and very rich family of functions for working
3433-- with Unicode text (including normalization, regular expressions,
35−-- non-standard encodings, text breaking, and locales), see
36−-- <http://hackage.haskell.org/package/text-icu the text-icu package >.
34+-- non-standard encodings, text breaking, and locales), see the
35+-- <http://hackage.haskell.org/package/text-icu text-icu package >.
36+--
3737
3838module Data.Text
3939 (
@@ -43,6 +43,9 @@ module Data.Text
4343 -- * Acceptable data
4444 -- $replacement
4545
46+ -- * Definition of character
47+ -- $character_definition
48+
4649 -- * Fusion
4750 -- $fusion
4851
@@ -60,6 +63,7 @@ module Data.Text
6063 , snoc
6164 , append
6265 , uncons
66+ , unsnoc
6367 , head
6468 , last
6569 , tail
@@ -246,6 +250,18 @@ import qualified GHC.Exts as Exts
246250import Text.Printf (PrintfArg, formatArg, formatString)
247251#endif
248252
253+-- $character_definition
254+--
255+-- This package uses the term /character/ to denote Unicode /code points/.
256+--
257+-- Note that this is not the same thing as a grapheme (e.g. a
258+-- composition of code points that form one visual symbol). For
259+-- instance, consider the grapheme \"ä\". This symbol has two
260+-- Unicode representations: a single code-point representation
261+-- @U+00E4@ (the @LATIN SMALL LETTER A WITH DIAERESIS@ code point),
262+-- and a two code point representation @U+0061@ (the \"@A@\" code
263+-- point) and @U+0308@ (the @COMBINING DIAERESIS@ code point).
264+
249265-- $strict
250266--
251267-- This package provides both strict and lazy 'Text' types. The
@@ -334,9 +350,13 @@ instance Read Text where
334350 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
335351
336352#if MIN_VERSION_base(4,9,0)
337−-- Semigroup orphan instances for older GHCs are provided by
338−-- 'semigroups` package
339−
353+-- | Non-orphan 'Semigroup' instance only defined for
354+-- @base-4.9.0.0@ and later; orphan instances for older GHCs are
355+-- provided by
356+-- the [semigroups](http://hackage.haskell.org/package/semigroups)
357+-- package
358+--
359+-- @since 1.2.2.0
340360instance Semigroup Text where
341361 (<>) = append
342362#endif
@@ -354,6 +374,7 @@ instance IsString Text where
354374 fromString = pack
355375
356376#if __GLASGOW_HASKELL__ >= 708
377+-- | @since 1.2.0.0
357378instance Exts.IsList Text where
358379 type Item Text = Char
359380 fromList = pack
@@ -364,6 +385,7 @@ instance Exts.IsList Text where
364385instance NFData Text where rnf !_ = ()
365386#endif
366387
388+-- | @since 1.2.1.0
367389instance Binary Text where
368390 put t = put (encodeUtf8 t)
369391 get = do
@@ -397,6 +419,8 @@ instance Data Text where
397419
398420#if MIN_VERSION_base(4,7,0)
399421-- | Only defined for @base-4.7.0.0@ and later
422+--
423+-- @since 1.2.2.0
400424instance PrintfArg Text where
401425 formatArg txt = formatString $ unpack txt
402426#endif
@@ -545,6 +569,19 @@ init (Text arr off len) | len <= 0 = emptyError "init"
545569 unstream (S.init (stream t)) = init t
546570 #-}
547571
572+-- | /O(1)/ Returns all but the last character and the last character of a
573+-- 'Text', or 'Nothing' if empty.
574+--
575+-- @since 1.2.3.0
576+unsnoc :: Text -> Maybe (Text, Char)
577+unsnoc (Text arr off len)
578+ | len <= 0 = Nothing
579+ | n < 0xDC00 || n > 0xDFFF = Just (text arr off (len-1), unsafeChr n)
580+ | otherwise = Just (text arr off (len-2), U16.chr2 n0 n)
581+ where n = A.unsafeIndex arr (off+len-1)
582+ n0 = A.unsafeIndex arr (off+len-2)
583+{-# INLINE [1] unsnoc #-}
584+
548585-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
549586-- fusion.
550587null :: Text -> Bool
@@ -624,8 +661,15 @@ compareLength t n = S.compareLengthI (stream t) n
624661-- -----------------------------------------------------------------------------
625662-- * Transformations
626663-- | /O(n)/ 'map' @f@ @t@ is the 'Text' obtained by applying @f@ to
627−-- each element of @t@. Subject to fusion. Performs replacement on
628−-- invalid scalar values.
664+-- each element of @t@.
665+--
666+-- Example:
667+--
668+-- >>> let message = pack "I am not angry. Not at all."
669+-- >>> T.map (\c -> if c == '.' then '!' else c) message
670+-- "I am not angry! Not at all!"
671+--
672+-- Subject to fusion. Performs replacement on invalid scalar values.
629673map :: (Char -> Char) -> Text -> Text
630674map f t = unstream (S.map (safe . f) (stream t))
631675{-# INLINE [1] map #-}
@@ -633,18 +677,36 @@ map f t = unstream (S.map (safe . f) (stream t))
633677-- | /O(n)/ The 'intercalate' function takes a 'Text' and a list of
634678-- 'Text's and concatenates the list after interspersing the first
635679-- argument between each element of the list.
680+--
681+-- Example:
682+--
683+-- >>> T.intercalate "NI!" ["We", "seek", "the", "Holy", "Grail"]
684+-- "WeNI!seekNI!theNI!HolyNI!Grail"
636685intercalate :: Text -> [Text] -> Text
637686intercalate t = concat . (F.intersperse t)
638687{-# INLINE intercalate #-}
639688
640689-- | /O(n)/ The 'intersperse' function takes a character and places it
641−-- between the characters of a 'Text'. Subject to fusion. Performs
642−-- replacement on invalid scalar values.
690+-- between the characters of a 'Text'.
691+--
692+-- Example:
693+--
694+-- >>> T.intersperse '.' "SHIELD"
695+-- "S.H.I.E.L.D"
696+--
697+-- Subject to fusion. Performs replacement on invalid scalar values.
643698intersperse :: Char -> Text -> Text
644699intersperse c t = unstream (S.intersperse (safe c) (stream t))
645700{-# INLINE intersperse #-}
646701
647−-- | /O(n)/ Reverse the characters of a string. Subject to fusion.
702+-- | /O(n)/ Reverse the characters of a string.
703+--
704+-- Example:
705+--
706+-- >>> T.reverse "desrever"
707+-- "reversed"
708+--
709+-- Subject to fusion.
648710reverse :: Text -> Text
649711reverse t = S.reverse (stream t)
650712{-# INLINE reverse #-}
@@ -663,12 +725,14 @@ reverse t = S.reverse (stream t)
663725-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
664726-- be replaced recursively:
665727--
666−-- > replace "oo" "foo" "oo" == "foo"
728+-- >>> replace "oo" "foo" "oo"
729+-- "foo"
667730--
668731-- In cases where several instances of @needle@ overlap, only the
669732-- first one will be replaced:
670733--
671−-- > replace "ofo" "bar" "ofofo" == "barfo"
734+-- >>> replace "ofo" "bar" "ofofo"
735+-- "barfo"
672736--
673737-- In (unlikely) bad cases, this function's time complexity degrades
674738-- towards /O(n*m)/.
@@ -782,6 +846,8 @@ toUpper t = unstream (S.toUpper (stream t))
782846-- guides disagree on whether the book name \"The Hill of the Red
783847-- Fox\" is correctly title cased—but this function will
784848-- capitalize /every/ word.
849+--
850+-- @since 1.0.0.0
785851toTitle :: Text -> Text
786852toTitle t = unstream (S.toTitle (stream t))
787853{-# INLINE toTitle #-}
@@ -792,8 +858,11 @@ toTitle t = unstream (S.toTitle (stream t))
792858--
793859-- Examples:
794860--
795−-- > justifyLeft 7 'x' "foo" == "fooxxxx"
796−-- > justifyLeft 3 'x' "foobar" == "foobar"
861+-- >>> justifyLeft 7 'x' "foo"
862+-- "fooxxxx"
863+--
864+-- >>> justifyLeft 3 'x' "foobar"
865+-- "foobar"
797866justifyLeft :: Int -> Char -> Text -> Text
798867justifyLeft k c t
799868 | len >= k = t
@@ -814,8 +883,11 @@ justifyLeft k c t
814883--
815884-- Examples:
816885--
817−-- > justifyRight 7 'x' "bar" == "xxxxbar"
818−-- > justifyRight 3 'x' "foobar" == "foobar"
886+-- >>> justifyRight 7 'x' "bar"
887+-- "xxxxbar"
888+--
889+-- >>> justifyRight 3 'x' "foobar"
890+-- "foobar"
819891justifyRight :: Int -> Char -> Text -> Text
820892justifyRight k c t
821893 | len >= k = t
@@ -829,7 +901,8 @@ justifyRight k c t
829901--
830902-- Examples:
831903--
832−-- > center 8 'x' "HS" = "xxxHSxxx"
904+-- >>> center 8 'x' "HS"
905+-- "xxxHSxxx"
833906center :: Int -> Char -> Text -> Text
834907center k c t
835908 | len >= k = t
@@ -844,6 +917,14 @@ center k c t
844917-- of its 'Text' argument. Note that this function uses 'pack',
845918-- 'unpack', and the list version of transpose, and is thus not very
846919-- efficient.
920+--
921+-- Examples:
922+--
923+-- >>> transpose ["green","orange"]
924+-- ["go","rr","ea","en","ng","e"]
925+--
926+-- >>> transpose ["blue","red"]
927+-- ["br","le","ud","e"]
847928transpose :: [Text] -> [Text]
848929transpose ts = P.map pack (L.transpose (P.map unpack ts))
849930
@@ -1088,7 +1169,10 @@ iterN n t@(Text _arr _off len) = loop 0 0
10881169--
10891170-- Examples:
10901171--
1091−-- > takeEnd 3 "foobar" == "bar"
1172+-- >>> takeEnd 3 "foobar"
1173+-- "bar"
1174+--
1175+-- @since 1.1.1.0
10921176takeEnd :: Int -> Text -> Text
10931177takeEnd n t@(Text arr off len)
10941178 | n <= 0 = empty
@@ -1099,8 +1183,8 @@ takeEnd n t@(Text arr off len)
10991183iterNEnd :: Int -> Text -> Int
11001184iterNEnd n t@(Text _arr _off len) = loop (len-1) n
11011185 where loop i !m
1186+ | m <= 0 = i+1
11021187 | i <= 0 = 0
1103− | m <= 1 = i
11041188 | otherwise = loop (i+d) (m-1)
11051189 where d = reverseIter_ t i
11061190
@@ -1127,7 +1211,10 @@ drop n t@(Text arr off len)
11271211--
11281212-- Examples:
11291213--
1130−-- > dropEnd 3 "foobar" == "foo"
1214+-- >>> dropEnd 3 "foobar"
1215+-- "foo"
1216+--
1217+-- @since 1.1.1.0
11311218dropEnd :: Int -> Text -> Text
11321219dropEnd n t@(Text arr off len)
11331220 | n <= 0 = t
@@ -1157,7 +1244,10 @@ takeWhile p t@(Text arr off len) = loop 0
11571244-- satisfy @p@. Subject to fusion.
11581245-- Examples:
11591246--
1160−-- > takeWhileEnd (=='o') "foo" == "oo"
1247+-- >>> takeWhileEnd (=='o') "foo"
1248+-- "oo"
1249+--
1250+-- @since 1.2.2.0
11611251takeWhileEnd :: (Char -> Bool) -> Text -> Text
11621252takeWhileEnd p t@(Text arr off len) = loop (len-1) len
11631253 where loop !i !l | l <= 0 = t
@@ -1196,7 +1286,8 @@ dropWhile p t@(Text arr off len) = loop 0 0
11961286--
11971287-- Examples:
11981288--
1199−-- > dropWhileEnd (=='.') "foo..." == "foo"
1289+-- >>> dropWhileEnd (=='.') "foo..."
1290+-- "foo"
12001291dropWhileEnd :: (Char -> Bool) -> Text -> Text
12011292dropWhileEnd p t@(Text arr off len) = loop (len-1) len
12021293 where loop !i !l | l <= 0 = empty
@@ -1314,9 +1405,14 @@ tails t | null t = [empty]
13141405--
13151406-- Examples:
13161407--
1317−-- > splitOn "\r\n" "a\r\nb\r\nd\r\ne" == ["a","b","d","e"]
1318−-- > splitOn "aaa" "aaaXaaaXaaaXaaa" == ["","X","X","X",""]
1319−-- > splitOn "x" "x" == ["",""]
1408+-- >>> splitOn "\r\n" "a\r\nb\r\nd\r\ne"
1409+-- ["a","b","d","e"]
1410+--
1411+-- >>> splitOn "aaa" "aaaXaaaXaaaXaaa"
1412+-- ["","X","X","X",""]
1413+--
1414+-- >>> splitOn "x" "x"
1415+-- ["",""]
13201416--
13211417-- and
13221418--
@@ -1352,8 +1448,11 @@ splitOn pat@(Text _ _ l) src@(Text arr off len)
13521448-- resulting components do not contain the separators. Two adjacent
13531449-- separators result in an empty component in the output. eg.
13541450--
1355−-- > split (=='a') "aabbaca" == ["","","bb","c",""]
1356−-- > split (=='a') "" == [""]
1451+-- >>> split (=='a') "aabbaca"
1452+-- ["","","bb","c",""]
1453+--
1454+-- >>> split (=='a') ""
1455+-- [""]
13571456split :: (Char -> Bool) -> Text -> [Text]
13581457split _ t@(Text _off _arr 0) = [t]
13591458split p t = loop t
@@ -1366,8 +1465,11 @@ split p t = loop t
13661465-- element may be shorter than the other chunks, depending on the
13671466-- length of the input. Examples:
13681467--
1369−-- > chunksOf 3 "foobarbaz" == ["foo","bar","baz"]
1370−-- > chunksOf 4 "haskell.org" == ["hask","ell.","org"]
1468+-- >>> chunksOf 3 "foobarbaz"
1469+-- ["foo","bar","baz"]
1470+--
1471+-- >>> chunksOf 4 "haskell.org"
1472+-- ["hask","ell.","org"]
13711473chunksOf :: Int -> Text -> [Text]
13721474chunksOf k = go
13731475 where
@@ -1412,8 +1514,11 @@ filter p t = unstream (S.filter p (stream t))
14121514--
14131515-- Examples:
14141516--
1415−-- > breakOn "::" "a::b::c" ==> ("a", "::b::c")
1416−-- > breakOn "/" "foobar" ==> ("foobar", "")
1517+-- >>> breakOn "::" "a::b::c"
1518+-- ("a","::b::c")
1519+--
1520+-- >>> breakOn "/" "foobar"
1521+-- ("foobar","")
14171522--
14181523-- Laws:
14191524--
@@ -1441,7 +1546,8 @@ breakOn pat src@(Text arr off len)
14411546-- up to and including the last match of @needle@. The second is the
14421547-- remainder of @haystack@, following the match.
14431548--
1444−-- > breakOnEnd "::" "a::b::c" ==> ("a::b::", "c")
1549+-- >>> breakOnEnd "::" "a::b::c"
1550+-- ("a::b::","c")
14451551breakOnEnd :: Text -> Text -> (Text, Text)
14461552breakOnEnd pat src = (reverse b, reverse a)
14471553 where (a,b) = breakOn (reverse pat) (reverse src)
@@ -1456,10 +1562,11 @@ breakOnEnd pat src = (reverse b, reverse a)
14561562--
14571563-- Examples:
14581564--
1459−-- > breakOnAll "::" ""
1460−-- > ==> []
1461−-- > breakOnAll "/" "a/b/c/"
1462−-- > ==> [("a", "/b/c/"), ("a/b", "/c/"), ("a/b/c", "/")]
1565+-- >>> breakOnAll "::" ""
1566+-- []
1567+--
1568+-- >>> breakOnAll "/" "a/b/c/"
1569+-- [("a","/b/c/"),("a/b","/c/"),("a/b/c","/")]
14631570--
14641571-- In (unlikely) bad cases, this function's time complexity degrades
14651572-- towards /O(n*m)/.
@@ -1658,9 +1765,14 @@ isInfixOf needle haystack
16581765--
16591766-- Examples:
16601767--
1661−-- > stripPrefix "foo" "foobar" == Just "bar"
1662−-- > stripPrefix "" "baz" == Just "baz"
1663−-- > stripPrefix "foo" "quux" == Nothing
1768+-- >>> stripPrefix "foo" "foobar"
1769+-- Just "bar"
1770+--
1771+-- >>> stripPrefix "" "baz"
1772+-- Just "baz"
1773+--
1774+-- >>> stripPrefix "foo" "quux"
1775+-- Nothing
16641776--
16651777-- This is particularly useful with the @ViewPatterns@ extension to
16661778-- GHC, as follows:
@@ -1685,9 +1797,14 @@ stripPrefix p@(Text _arr _off plen) t@(Text arr off len)
16851797--
16861798-- Examples:
16871799--
1688−-- > commonPrefixes "foobar" "fooquux" == Just ("foo","bar","quux")
1689−-- > commonPrefixes "veeble" "fetzer" == Nothing
1690−-- > commonPrefixes "" "baz" == Nothing
1800+-- >>> commonPrefixes "foobar" "fooquux"
1801+-- Just ("foo","bar","quux")
1802+--
1803+-- >>> commonPrefixes "veeble" "fetzer"
1804+-- Nothing
1805+--
1806+-- >>> commonPrefixes "" "baz"
1807+-- Nothing
16911808commonPrefixes :: Text -> Text -> Maybe (Text,Text,Text)
16921809commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
16931810 where
@@ -1704,9 +1821,14 @@ commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
17041821--
17051822-- Examples:
17061823--
1707−-- > stripSuffix "bar" "foobar" == Just "foo"
1708−-- > stripSuffix "" "baz" == Just "baz"
1709−-- > stripSuffix "foo" "quux" == Nothing
1824+-- >>> stripSuffix "bar" "foobar"
1825+-- Just "foo"
1826+--
1827+-- >>> stripSuffix "" "baz"
1828+-- Just "baz"
1829+--
1830+-- >>> stripSuffix "foo" "quux"
1831+-- Nothing
17101832--
17111833-- This is particularly useful with the @ViewPatterns@ extension to
17121834-- GHC, as follows:
@@ -1753,3 +1875,12 @@ copy (Text arr off len) = Text (A.run go) 0 len
17531875 marr <- A.new len
17541876 A.copyI marr 0 arr off len
17551877 return marr
1878+
1879+
1880+-------------------------------------------------
1881+-- NOTE: the named chunk below used by doctest;
1882+-- verify the doctests via `doctest -fobject-code Data/Text.hs`
1883+
1884+-- $setup
1885+-- >>> :set -XOverloadedStrings
1886+-- >>> import qualified Data.Text as T