@@ -106,7 +106,7 @@ module Data.Text
106 -- ** Breaking into many substrings
106 -- ** Breaking into many substrings
108 , splitWith
108 , splitWith
109− -- , breakSubstring
109+ , breakSubstring
111 -- ** Breaking into lines and words
111 -- ** Breaking into lines and words
@@ -758,6 +758,45 @@ find :: (Char -> Bool) -> Text -> Maybe Char
758find p t = S.find p (stream t)
758find p t = S.find p (stream t)
759{-# INLINE find #-}
759{-# INLINE find #-}
761+-- | Break a string on a substring, returning a pair of the part of the
762+-- string prior to the match, and the rest of the string.
764+-- The following relationships hold:
766+-- > break (== c) l == breakSubstring (singleton c) l
770+-- > findSubstring s l ==
771+-- > if null s then Just 0
772+-- > else case breakSubstring s l of
773+-- > (x,y) | null y -> Nothing
774+-- > | otherwise -> Just (length x)
776+-- For example, to tokenise a string, dropping delimiters:
778+-- > tokenise x y = h : if null t then [] else tokenise x (drop (length x) t)
779+-- > where (h,t) = breakSubstring x y
781+-- To skip to the first occurence of a string:
783+-- > snd (breakSubstring x y)
785+-- To take the parts of a string before a delimiter:
787+-- > fst (breakSubstring x y)
789+breakSubstring :: Text -- ^ String to search for
790+ -> Text -- ^ String to search in
791+ -> (Text,Text) -- ^ Head and tail of string broken at substring
793+breakSubstring pat src = search 0 src
796+ | null s = (src,empty) -- not found
797+ | pat `isPrefixOf` s = (take n src,s)
798+ | otherwise = search (n+1) (tail s)
761-- | /O(n)/ 'filter', applied to a predicate and a 'Text',
800-- | /O(n)/ 'filter', applied to a predicate and a 'Text',
762-- returns a 'Text' containing those characters that satisfy the
801-- returns a 'Text' containing those characters that satisfy the
763-- predicate.
802-- predicate.