@@ -106,7 +106,7 @@ module Data.Text
106106 -- ** Breaking into many substrings
107107 , split
108108 , splitWith
109− -- , breakSubstring
109+ , breakSubstring
110110
111111 -- ** Breaking into lines and words
112112 , lines
@@ -758,6 +758,45 @@ find :: (Char -> Bool) -> Text -> Maybe Char
758758find p t = S.find p (stream t)
759759{-# INLINE find #-}
760760
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.
763+--
764+-- The following relationships hold:
765+--
766+-- > break (== c) l == breakSubstring (singleton c) l
767+--
768+-- and:
769+--
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)
775+--
776+-- For example, to tokenise a string, dropping delimiters:
777+--
778+-- > tokenise x y = h : if null t then [] else tokenise x (drop (length x) t)
779+-- > where (h,t) = breakSubstring x y
780+--
781+-- To skip to the first occurence of a string:
782+--
783+-- > snd (breakSubstring x y)
784+--
785+-- To take the parts of a string before a delimiter:
786+--
787+-- > fst (breakSubstring x y)
788+--
789+breakSubstring :: Text -- ^ String to search for
790+ -> Text -- ^ String to search in
791+ -> (Text,Text) -- ^ Head and tail of string broken at substring
792+
793+breakSubstring pat src = search 0 src
794+ where
795+ search !n !s
796+ | null s = (src,empty) -- not found
797+ | pat `isPrefixOf` s = (take n src,s)
798+ | otherwise = search (n+1) (tail s)
799+
761800-- | /O(n)/ 'filter', applied to a predicate and a 'Text',
762801-- returns a 'Text' containing those characters that satisfy the
763802-- predicate.