@@ -15,7 +15,6 @@
16-- License : BSD-style
16-- License : BSD-style
17-- Maintainer : bos@serpentine.com
17-- Maintainer : bos@serpentine.com
18−-- Stability : experimental
19-- Portability : GHC
18-- Portability : GHC
21-- A time and space-efficient implementation of Unicode text.
20-- A time and space-efficient implementation of Unicode text.
@@ -32,8 +31,9 @@
33-- To use an extended and very rich family of functions for working
32-- To use an extended and very rich family of functions for working
34-- with Unicode text (including normalization, regular expressions,
33-- with Unicode text (including normalization, regular expressions,
35−-- non-standard encodings, text breaking, and locales), see
34+-- non-standard encodings, text breaking, and locales), see the
36−-- <http://hackage.haskell.org/package/text-icu the text-icu package >.
35+-- <http://hackage.haskell.org/package/text-icu text-icu package >.
38module Data.Text
38module Data.Text
@@ -43,6 +43,9 @@ module Data.Text
43 -- * Acceptable data
43 -- * Acceptable data
44 -- $replacement
44 -- $replacement
46+ -- * Definition of character
47+ -- $character_definition
46 -- * Fusion
49 -- * Fusion
47 -- $fusion
50 -- $fusion
@@ -60,6 +63,7 @@ module Data.Text
@@ -298,6 +302,17 @@ unpackCString# addr# = Text $ SJS.unstream (SJS.streamCString# addr#)
298 = singleton a #-}
302 = singleton a #-}
300---------------------------------------------------------------------
304---------------------------------------------------------------------
305+-- $character_definition
307+-- This package uses the term /character/ to denote Unicode /code points/.
309+-- Note that this is not the same thing as a grapheme (e.g. a
310+-- composition of code points that form one visual symbol). For
311+-- instance, consider the grapheme \"ä\". This symbol has two
312+-- Unicode representations: a single code-point representation
313+-- @U+00E4@ (the @LATIN SMALL LETTER A WITH DIAERESIS@ code point),
314+-- and a two code point representation @U+0061@ (the \"@A@\" code
315+-- point) and @U+0308@ (the @COMBINING DIAERESIS@ code point).
302-- $strict
317-- $strict
@@ -392,9 +407,13 @@ instance Read Text where
392 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
407 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
394#if MIN_VERSION_base(4,9,0)
409#if MIN_VERSION_base(4,9,0)
410+-- | Non-orphan 'Semigroup' instance only defined for
395−-- Semigroup orphan instances for older GHCs are provided by
411+-- @base-4.9.0.0@ and later; orphan instances for older GHCs are
413+-- the [semigroups](http://hackage.haskell.org/package/semigroups)
396−-- 'semigroups` package
414+-- package
398instance Semigroup Text where
417instance Semigroup Text where
399 (<>) = append
418 (<>) = append
@@ -412,6 +431,7 @@ instance IsString Text where
412 fromString = pack
431 fromString = pack
414#if __GLASGOW_HASKELL__ >= 708
433#if __GLASGOW_HASKELL__ >= 708
415instance Exts.IsList Text where
435instance Exts.IsList Text where
416 type Item Text = Char
436 type Item Text = Char
417 fromList = pack
437 fromList = pack
@@ -422,6 +442,7 @@ instance Exts.IsList Text where
422instance NFData Text where rnf !_ = ()
442instance NFData Text where rnf !_ = ()
425instance Binary Text where
446instance Binary Text where
426 put t = put (encodeUtf8 t)
447 put t = put (encodeUtf8 t)
@@ -455,6 +476,8 @@ instance Data Text where
456#if MIN_VERSION_base(4,7,0)
477#if MIN_VERSION_base(4,7,0)
457-- | Only defined for @base-4.7.0.0@ and later
478-- | Only defined for @base-4.7.0.0@ and later
458instance PrintfArg Text where
481instance PrintfArg Text where
459 formatArg t = formatString $ unpack t
482 formatArg t = formatString $ unpack t
@@ -612,6 +635,19 @@ init = coerce JSS.init
612 unstream (S.init (stream t)) = init t
635 unstream (S.init (stream t)) = init t
638+-- | /O(1)/ Returns all but the last character and the last character of a
639+-- 'Text', or 'Nothing' if empty.
642+unsnoc :: Text -> Maybe (Text, Char)
643+unsnoc (Text arr off len)
644+ | len <= 0 = Nothing
645+ | n < 0xDC00 || n > 0xDFFF = Just (text arr off (len-1), unsafeChr n)
646+ | otherwise = Just (text arr off (len-2), U16.chr2 n0 n)
647+ where n = A.unsafeIndex arr (off+len-1)
648+ n0 = A.unsafeIndex arr (off+len-2)
649+{-# INLINE [1] unsnoc #-}
615-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
651-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
616-- fusion.
652-- fusion.
617null :: Text -> Bool
653null :: Text -> Bool
@@ -693,8 +729,15 @@ compareLength t n = S.compareLengthI (stream t) n
693-- -----------------------------------------------------------------------------
729-- -----------------------------------------------------------------------------
694-- * Transformations
730-- * Transformations
695-- | /O(n)/ 'map' @f@ @t@ is the 'Text' obtained by applying @f@ to
731-- | /O(n)/ 'map' @f@ @t@ is the 'Text' obtained by applying @f@ to
732+-- each element of @t@.
736+-- >>> let message = pack "I am not angry. Not at all."
737+-- >>> T.map (\c -> if c == '.' then '!' else c) message
738+-- "I am not angry! Not at all!"
696−-- each element of @t@. Subject to fusion. Performs replacement on
740+-- Subject to fusion. Performs replacement on invalid scalar values.
697−-- invalid scalar values.
698map :: (Char -> Char) -> Text -> Text
741map :: (Char -> Char) -> Text -> Text
699map = coerce JSS.map
742map = coerce JSS.map
700-- map f t = unstream (S.map (safe . f) (stream t))
743-- map f t = unstream (S.map (safe . f) (stream t))
@@ -703,20 +746,38 @@ map = coerce JSS.map
703-- | /O(n)/ The 'intercalate' function takes a 'Text' and a list of
746-- | /O(n)/ The 'intercalate' function takes a 'Text' and a list of
704-- 'Text's and concatenates the list after interspersing the first
747-- 'Text's and concatenates the list after interspersing the first
705-- argument between each element of the list.
748-- argument between each element of the list.
752+-- >>> T.intercalate "NI!" ["We", "seek", "the", "Holy", "Grail"]
753+-- "WeNI!seekNI!theNI!HolyNI!Grail"
706intercalate :: Text -> [Text] -> Text
754intercalate :: Text -> [Text] -> Text
707intercalate = coerce JSS.intercalate
755intercalate = coerce JSS.intercalate
708-- intercalate t = concat . (F.intersperse t)
756-- intercalate t = concat . (F.intersperse t)
709{-# INLINE intercalate #-}
757{-# INLINE intercalate #-}
711-- | /O(n)/ The 'intersperse' function takes a character and places it
759-- | /O(n)/ The 'intersperse' function takes a character and places it
712−-- between the characters of a 'Text'. Subject to fusion. Performs
760+-- between the characters of a 'Text'.
764+-- >>> T.intersperse '.' "SHIELD"
713−-- replacement on invalid scalar values.
767+-- Subject to fusion. Performs replacement on invalid scalar values.
714intersperse :: Char -> Text -> Text
768intersperse :: Char -> Text -> Text
715intersperse = coerce JSS.intersperse
769intersperse = coerce JSS.intersperse
716-- intersperse c t = unstream (S.intersperse (safe c) (stream t))
770-- intersperse c t = unstream (S.intersperse (safe c) (stream t))
717{-# INLINE intersperse #-}
771{-# INLINE intersperse #-}
719−-- | /O(n)/ Reverse the characters of a string. Subject to fusion.
773+-- | /O(n)/ Reverse the characters of a string.
777+-- >>> T.reverse "desrever"
780+-- Subject to fusion.
720reverse :: Text -> Text
781reverse :: Text -> Text
721reverse = coerce JSS.reverse
782reverse = coerce JSS.reverse
722-- reverse t = S.reverse (stream t)
783-- reverse t = S.reverse (stream t)
@@ -736,12 +797,14 @@ reverse = coerce JSS.reverse
736-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
797-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
737-- be replaced recursively:
798-- be replaced recursively:
739−-- > replace "oo" "foo" "oo" == "foo"
800+-- >>> replace "oo" "foo" "oo"
741-- In cases where several instances of @needle@ overlap, only the
803-- In cases where several instances of @needle@ overlap, only the
742-- first one will be replaced:
804-- first one will be replaced:
744−-- > replace "ofo" "bar" "ofofo" == "barfo"
806+-- >>> replace "ofo" "bar" "ofofo"
746-- In (unlikely) bad cases, this function's time complexity degrades
809-- In (unlikely) bad cases, this function's time complexity degrades
747-- towards /O(n*m)/.
810-- towards /O(n*m)/.
@@ -859,6 +922,8 @@ toUpper = coerce JSS.toUpper
859-- guides disagree on whether the book name \"The Hill of the Red
922-- guides disagree on whether the book name \"The Hill of the Red
860-- Fox\" is correctly title cased—but this function will
923-- Fox\" is correctly title cased—but this function will
861-- capitalize /every/ word.
924-- capitalize /every/ word.
862toTitle :: Text -> Text
927toTitle :: Text -> Text
863toTitle = coerce JSS.toTitle
928toTitle = coerce JSS.toTitle
864-- toTitle t = unstream (S.toTitle (stream t))
929-- toTitle t = unstream (S.toTitle (stream t))
@@ -870,8 +935,11 @@ toTitle = coerce JSS.toTitle
871-- Examples:
936-- Examples:
873−-- > justifyLeft 7 'x' "foo" == "fooxxxx"
938+-- >>> justifyLeft 7 'x' "foo"
874−-- > justifyLeft 3 'x' "foobar" == "foobar"
941+-- >>> justifyLeft 3 'x' "foobar"
875justifyLeft :: Int -> Char -> Text -> Text
943justifyLeft :: Int -> Char -> Text -> Text
876justifyLeft = coerce JSS.justifyLeft
944justifyLeft = coerce JSS.justifyLeft
877-- justifyLeft k c t
945-- justifyLeft k c t
@@ -893,8 +961,11 @@ justifyLeft = coerce JSS.justifyLeft
894-- Examples:
962-- Examples:
896−-- > justifyRight 7 'x' "bar" == "xxxxbar"
964+-- >>> justifyRight 7 'x' "bar"
897−-- > justifyRight 3 'x' "foobar" == "foobar"
967+-- >>> justifyRight 3 'x' "foobar"
898justifyRight :: Int -> Char -> Text -> Text
969justifyRight :: Int -> Char -> Text -> Text
899justifyRight = coerce JSS.justifyRight
970justifyRight = coerce JSS.justifyRight
900-- justifyRight k c t
971-- justifyRight k c t
@@ -909,7 +980,8 @@ justifyRight = coerce JSS.justifyRight
910-- Examples:
981-- Examples:
912−-- > center 8 'x' "HS" = "xxxHSxxx"
983+-- >>> center 8 'x' "HS"
913center :: Int -> Char -> Text -> Text
985center :: Int -> Char -> Text -> Text
914center = coerce JSS.center
986center = coerce JSS.center
915-- center k c t
987-- center k c t
@@ -925,6 +997,14 @@ center = coerce JSS.center
925-- of its 'Text' argument. Note that this function uses 'pack',
997-- of its 'Text' argument. Note that this function uses 'pack',
926-- 'unpack', and the list version of transpose, and is thus not very
998-- 'unpack', and the list version of transpose, and is thus not very
927-- efficient.
999-- efficient.
1003+-- >>> transpose ["green","orange"]
1004+-- ["go","rr","ea","en","ng","e"]
1006+-- >>> transpose ["blue","red"]
1007+-- ["br","le","ud","e"]
928transpose :: [Text] -> [Text]
1008transpose :: [Text] -> [Text]
929transpose = coerce JSS.transpose
1009transpose = coerce JSS.transpose
930-- transpose ts = P.map pack (L.transpose (P.map unpack ts))
1010-- transpose ts = P.map pack (L.transpose (P.map unpack ts))
@@ -1207,7 +1287,10 @@ take = coerce JSS.take
1208-- Examples:
1288-- Examples:
1210−-- > takeEnd 3 "foobar" == "bar"
1290+-- >>> takeEnd 3 "foobar"
1211takeEnd :: Int -> Text -> Text
1294takeEnd :: Int -> Text -> Text
1212takeEnd = coerce JSS.takeEnd
1295takeEnd = coerce JSS.takeEnd
1213-- takeEnd n t@(Text arr off len)
1296-- takeEnd n t@(Text arr off len)
@@ -1248,7 +1331,10 @@ drop = coerce JSS.drop
1249-- Examples:
1332-- Examples:
1251−-- > dropEnd 3 "foobar" == "foo"
1334+-- >>> dropEnd 3 "foobar"
1252dropEnd :: Int -> Text -> Text
1338dropEnd :: Int -> Text -> Text
1253dropEnd = coerce JSS.dropEnd
1339dropEnd = coerce JSS.dropEnd
1254-- dropEnd n t@(Text arr off len)
1340-- dropEnd n t@(Text arr off len)
@@ -1280,7 +1366,10 @@ takeWhile = coerce JSS.takeWhile
1280-- satisfy @p@. Subject to fusion.
1366-- satisfy @p@. Subject to fusion.
1281-- Examples:
1367-- Examples:
1283−-- > takeWhileEnd (=='o') "foo" == "oo"
1369+-- >>> takeWhileEnd (=='o') "foo"
1284takeWhileEnd :: (Char -> Bool) -> Text -> Text
1373takeWhileEnd :: (Char -> Bool) -> Text -> Text
1285#ifndef __GHCJS__
1374#ifndef __GHCJS__
1286takeWhileEnd p t@(Text arr off len) = loop (len-1) len
1375takeWhileEnd p t@(Text arr off len) = loop (len-1) len
@@ -1329,7 +1418,8 @@ dropWhile = coerce JSS.dropWhile
1330-- Examples:
1419-- Examples:
1332−-- > dropWhileEnd (=='.') "foo..." == "foo"
1421+-- >>> dropWhileEnd (=='.') "foo..."
1333dropWhileEnd :: (Char -> Bool) -> Text -> Text
1423dropWhileEnd :: (Char -> Bool) -> Text -> Text
1334dropWhileEnd = coerce JSS.dropWhileEnd
1424dropWhileEnd = coerce JSS.dropWhileEnd
1335-- dropWhileEnd p t@(Text arr off len) = loop (len-1) len
1425-- dropWhileEnd p t@(Text arr off len) = loop (len-1) len
@@ -1454,9 +1544,14 @@ tails = coerce JSS.tails
1455-- Examples:
1545-- Examples:
1457−-- > splitOn "\r\n" "a\r\nb\r\nd\r\ne" == ["a","b","d","e"]
1547+-- >>> splitOn "\r\n" "a\r\nb\r\nd\r\ne"
1548+-- ["a","b","d","e"]
1458−-- > splitOn "aaa" "aaaXaaaXaaaXaaa" == ["","X","X","X",""]
1550+-- >>> splitOn "aaa" "aaaXaaaXaaaXaaa"
1551+-- ["","X","X","X",""]
1459−-- > splitOn "x" "x" == ["",""]
1553+-- >>> splitOn "x" "x"
@@ -1493,8 +1588,11 @@ splitOn = coerce JSS.splitOn
1493-- resulting components do not contain the separators. Two adjacent
1588-- resulting components do not contain the separators. Two adjacent
1494-- separators result in an empty component in the output. eg.
1589-- separators result in an empty component in the output. eg.
1496−-- > split (=='a') "aabbaca" == ["","","bb","c",""]
1591+-- >>> split (=='a') "aabbaca"
1592+-- ["","","bb","c",""]
1497−-- > split (=='a') "" == [""]
1594+-- >>> split (=='a') ""
1498split :: (Char -> Bool) -> Text -> [Text]
1596split :: (Char -> Bool) -> Text -> [Text]
1499split = coerce JSS.split
1597split = coerce JSS.split
1500-- split _ t@(Text _off _arr 0) = [t]
1598-- split _ t@(Text _off _arr 0) = [t]
@@ -1508,8 +1606,11 @@ split = coerce JSS.split
1508-- element may be shorter than the other chunks, depending on the
1606-- element may be shorter than the other chunks, depending on the
1509-- length of the input. Examples:
1607-- length of the input. Examples:
1511−-- > chunksOf 3 "foobarbaz" == ["foo","bar","baz"]
1609+-- >>> chunksOf 3 "foobarbaz"
1610+-- ["foo","bar","baz"]
1512−-- > chunksOf 4 "haskell.org" == ["hask","ell.","org"]
1612+-- >>> chunksOf 4 "haskell.org"
1613+-- ["hask","ell.","org"]
1513chunksOf :: Int -> Text -> [Text]
1614chunksOf :: Int -> Text -> [Text]
1514chunksOf = coerce JSS.chunksOf
1615chunksOf = coerce JSS.chunksOf
1515-- chunksOf k = go
1616-- chunksOf k = go
@@ -1558,8 +1659,11 @@ filter = coerce JSS.filter
1559-- Examples:
1660-- Examples:
1561−-- > breakOn "::" "a::b::c" ==> ("a", "::b::c")
1662+-- >>> breakOn "::" "a::b::c"
1562−-- > breakOn "/" "foobar" ==> ("foobar", "")
1665+-- >>> breakOn "/" "foobar"
@@ -1588,7 +1692,8 @@ breakOn = coerce JSS.breakOn
1588-- up to and including the last match of @needle@. The second is the
1692-- up to and including the last match of @needle@. The second is the
1589-- remainder of @haystack@, following the match.
1693-- remainder of @haystack@, following the match.
1591−-- > breakOnEnd "::" "a::b::c" ==> ("a::b::", "c")
1695+-- >>> breakOnEnd "::" "a::b::c"
1592breakOnEnd :: Text -> Text -> (Text, Text)
1697breakOnEnd :: Text -> Text -> (Text, Text)
1593breakOnEnd = coerce JSS.breakOnEnd
1698breakOnEnd = coerce JSS.breakOnEnd
1594-- breakOnEnd pat src = (reverse b, reverse a)
1699-- breakOnEnd pat src = (reverse b, reverse a)
@@ -1604,10 +1709,11 @@ breakOnEnd = coerce JSS.breakOnEnd
1605-- Examples:
1710-- Examples:
1607−-- > breakOnAll "::" ""
1712+-- >>> breakOnAll "::" ""
1608−-- > ==> []
1713+-- []
1609−-- > breakOnAll "/" "a/b/c/"
1715+-- >>> breakOnAll "/" "a/b/c/"
1610−-- > ==> [("a", "/b/c/"), ("a/b", "/c/"), ("a/b/c", "/")]
1716+-- [("a","/b/c/"),("a/b","/c/"),("a/b/c","/")]
1612-- In (unlikely) bad cases, this function's time complexity degrades
1718-- In (unlikely) bad cases, this function's time complexity degrades
1613-- towards /O(n*m)/.
1719-- towards /O(n*m)/.
@@ -1821,9 +1927,14 @@ isInfixOf = coerce JSS.isInfixOf
1822-- Examples:
1928-- Examples:
1824−-- > stripPrefix "foo" "foobar" == Just "bar"
1930+-- >>> stripPrefix "foo" "foobar"
1825−-- > stripPrefix "" "baz" == Just "baz"
1933+-- >>> stripPrefix "" "baz"
1826−-- > stripPrefix "foo" "quux" == Nothing
1936+-- >>> stripPrefix "foo" "quux"
1828-- This is particularly useful with the @ViewPatterns@ extension to
1939-- This is particularly useful with the @ViewPatterns@ extension to
1829-- GHC, as follows:
1940-- GHC, as follows:
@@ -1849,9 +1960,14 @@ stripPrefix = coerce JSS.stripPrefix
1850-- Examples:
1961-- Examples:
1852−-- > commonPrefixes "foobar" "fooquux" == Just ("foo","bar","quux")
1963+-- >>> commonPrefixes "foobar" "fooquux"
1964+-- Just ("foo","bar","quux")
1853−-- > commonPrefixes "veeble" "fetzer" == Nothing
1966+-- >>> commonPrefixes "veeble" "fetzer"
1854−-- > commonPrefixes "" "baz" == Nothing
1969+-- >>> commonPrefixes "" "baz"
1855commonPrefixes :: Text -> Text -> Maybe (Text,Text,Text)
1971commonPrefixes :: Text -> Text -> Maybe (Text,Text,Text)
1856commonPrefixes = coerce JSS.commonPrefixes
1972commonPrefixes = coerce JSS.commonPrefixes
1857-- commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
1973-- commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
@@ -1869,9 +1985,14 @@ commonPrefixes = coerce JSS.commonPrefixes
1870-- Examples:
1986-- Examples:
1872−-- > stripSuffix "bar" "foobar" == Just "foo"
1988+-- >>> stripSuffix "bar" "foobar"
1873−-- > stripSuffix "" "baz" == Just "baz"
1991+-- >>> stripSuffix "" "baz"
1874−-- > stripSuffix "foo" "quux" == Nothing
1994+-- >>> stripSuffix "foo" "quux"
1876-- This is particularly useful with the @ViewPatterns@ extension to
1997-- This is particularly useful with the @ViewPatterns@ extension to
1877-- GHC, as follows:
1998-- GHC, as follows:
@@ -1923,3 +2044,11 @@ foreign import javascript unsafe
1923 "h$jsstringReplicateChar" js_replicateChar :: Int -> Char -> JSString
2044 "h$jsstringReplicateChar" js_replicateChar :: Int -> Char -> JSString
1924foreign import javascript unsafe
2045foreign import javascript unsafe
1925 "$2.substr($1)" js_substr1 :: Int -> JSString -> JSString
2046 "$2.substr($1)" js_substr1 :: Int -> JSString -> JSString
2048+-------------------------------------------------
2049+-- NOTE: the named chunk below used by doctest;
2050+-- verify the doctests via `doctest -fobject-code Data/Text.hs`
2053+-- >>> :set -XOverloadedStrings
2054+-- >>> import qualified Data.Text as T