-- ** Breaking into lines and words
import Prelude (Char, Bool(..), Functor(..), Int, Maybe(..), String,
(&&), (||), (+), (-), (<), (>), (<=), (>=), (.), ($),
-- | /O(n)/ Breaks a 'Text' up into a list of 'Text's at
-- newline 'Char's. The resulting strings do not contain newlines.
+ | otherwise = h : if null t
+ else lines (unsafeTail t)
+ where (h,t) = span (/= '\n') ps
+-- | /O(n)/ Portably breaks a 'Text' up into a list of 'Text's at line
- | otherwise = case search ps of
- Just n -> take n ps : lines (drop (n+1) ps)
- where search = elemIndex '\n'
+-- A line boundary is considered to be either a line feed, a carriage
+-- return immediately followed by a line feed, or a carriage return.
+-- This accounts for both Unix and Windows line ending conventions,
+-- and for the old convention used on Mac OS 9 and earlier.
+lines' :: Text -> [Text]
+lines' ps | null ps = 
+ | otherwise = h : case uncons t of
+ | c == '\n' -> lines t'
+ | c == '\r' -> case uncons t' of
+ Just ('\n',t'') -> lines t''
+ where (h,t) = span notEOL ps
+ notEOL c = c /= '\n' && c /= '\r'
-- | /O(n)/ Joins lines, after appending a terminating newline to