module Split (Split(..),Delims,split,unsplit,joinDoc,joinCode,joinDebug) where import Regex (mkRegex,isMatch) data Split = Code String | Delim String | Doc String | Blank String | Ext String | Shell (IO String) type Delims = (String,String,String,String) split :: Bool -> Delims -> String -> [Split] split isCode (start,end,xstart,xend) text = startFilt $ lines text where startFilt = if isCode then inCode else inDoc startDoc, endDoc, startExt, endExt :: String -> Bool startDoc x = isMatch x $ mkRegex start endDoc x = isMatch x $ mkRegex end endExt x = isMatch x $ mkRegex xend startExt x = if null xstart then False else isMatch x $ mkRegex xstart isBlank :: String -> Bool isBlank x = all (`elem` " \t") x inCode, inDoc, inExt :: [String] -> [Split] inCode [] = [] inCode (x:xt) | startDoc x = Delim x : inDoc xt | startExt x = Ext x : inExt xt | isBlank x = Blank x : inCode xt | otherwise = Code x : inCode xt inDoc [] = [] inDoc (x:xt) | endDoc x = Delim x : inCode xt | isBlank x = Blank x : inDoc xt | otherwise = Doc x : inDoc xt inExt [] = [] inExt (x:xt) | endExt x = Ext x : inCode xt | otherwise = Ext x : inExt xt unsplit :: [Split] -> IO String unsplit xs = let f :: Split -> IO ShowS f x = let ln s = s ++ "\n" io s = return (ln s ++) in case x of Code s -> io s Delim s -> io s Doc s -> io s Blank s -> io s Ext s -> io s Shell y -> do { s <- y; io s } g :: IO ShowS -> IO ShowS -> IO ShowS g x y = do { s <- x; t <- y; return (s . t) } in do s <- foldr1 g $ map f xs return (s []) joinDoc :: [Split] -> IO String joinDoc text = (unsplit . preCode) text where startCode, endCode, blank :: Split startCode = Doc "\n
"
    endCode   = Doc "
\n" blank = Doc "" preCode, preDoc, inCode, inDoc, skipCode, skipDoc :: [Split] -> [Split] preCode [] = [blank] preCode (x:xt) = case x of Code _ -> startCode : x : inCode xt Delim _ -> preDoc xt Doc _ -> x : inDoc xt Shell _ -> x : inDoc xt _ -> preCode xt preDoc [] = [blank] preDoc (x:xt) = case x of Code _ -> startCode : x : inCode xt Delim _ -> preCode xt Doc _ -> x : inDoc xt Shell _ -> x : inDoc xt _ -> preDoc xt inCode [] = [endCode] inCode (x:xt) = case x of Code _ -> x : inCode xt Delim _ -> endCode : preDoc xt Doc _ -> endCode : x : inDoc xt Shell _ -> endCode : x : inDoc xt Blank _ -> skipCode xt Ext _ -> inCode xt inDoc [] = [blank] inDoc (x:xt) = case x of Code _ -> startCode : x : inCode xt Delim _ -> preCode xt Doc _ -> x : inDoc xt Shell _ -> x : inDoc xt Blank _ -> skipDoc xt Ext _ -> inDoc xt skipCode [] = [endCode] skipCode (x:xt) = case x of Code _ -> blank : x : inCode xt Delim _ -> endCode : preDoc xt Doc _ -> endCode : x : inDoc xt Shell _ -> endCode : x : inDoc xt _ -> skipCode xt skipDoc [] = [blank] skipDoc (x:xt) = case x of Code _ -> startCode : x : inCode xt Delim _ -> preCode xt Doc _ -> blank : x : inDoc xt Shell _ -> blank : x : inDoc xt _ -> skipDoc xt joinCode :: [Split] -> String joinCode text = (unlines . inCode) text where inCode, inDoc :: [Split] -> [String] inCode [] = [] inCode (x:xt) = case x of Code s -> s : inCode xt Blank s -> s : inCode xt _ -> inDoc xt inDoc [] = [] inDoc (x:xt) = case x of Code s -> s : inCode xt Delim _ -> inCode xt _ -> inDoc xt joinDebug :: [Split] -> String joinDebug text = (unlines . tag) text where tag :: [Split] -> [String] tag [] = [] tag (x:xt) = t : tag xt where t = case x of Code s -> "C " ++ s Delim s -> "= " ++ s Doc s -> "D " ++ s Blank s -> "B " ++ s Ext s -> "E " ++ s Shell _ -> "S"