{- Code generator for function documentation tables (Function / Return Type / Description / Example / Result). Usage: runghc doc-to-sgml.hs < documentation > out -} import Control.Applicative import Data.Char import Data.List import Data.Maybe trim :: String -> String trim = f . f where f = reverse . dropWhile isSpace list_find :: (Eq a) => [a] -> [a] -> Maybe Int list_find [] _ = error "list_find: Empty search string" list_find needle@(x:xs) haystack = f 0 haystack where len = length needle - 1 f i [] = Nothing f i (y:ys) = if x == y && (xs == take len ys) then Just i else f (i+1) ys explode :: (Eq a) => [a] -> [a] -> [[a]] explode delim str = f str where len = length delim f str = fromMaybe [str] $ do pos <- list_find delim str let (a,b) = splitAt pos str return (a : f (drop len b)) data Line = Line Int Int String deriving (Show) subLine :: Line -> String -> Line subLine (Line number indent text) newtext = Line number indent newtext line_no :: Line -> Int line_no (Line n _ _) = n line_indent :: Line -> Int line_indent (Line _ n _) = n line_str :: Line -> String line_str (Line _ _ str) = str line_error :: String -> Line -> a line_error info line = error (info ++ ": error at line " ++ show (line_no line)) line_split :: Line -> [String] -> [String] line_split line splitters = f (line_str line) splitters where f str [] = [str] f str (x:xs) = a : f (drop (length x) b) xs where (a,b) = splitAt (fromMaybe err $ list_find x str) str err = line_error ("line_split " ++ show (line_str line) ++ " " ++ show splitters) line lines' :: String -> [Line] lines' str = filter noblank $ zipWith mkLine [1..] (lines str) where noblank line = trim (line_str line) /= "" mkLine num line = Line num (indentOf line) (trim line) indentOf line = length $ takeWhile (== '\t') line data DocEntry = DocEntry { function :: String, returns :: Type, description :: String, examples :: [(String, Result)] } deriving (Show) data Type = Type String | Enum String [String] deriving (Show) data Result = Result String | ResultSet [String] deriving (Show) entriesToSgml :: String -> String -> [DocEntry] -> String entriesToSgml table_id title entries = "