module Convert (style,annote) where import System.Exit (exitFailure) import System.IO (stderr,hPutStr,hPutStrLn) import Files (createDirectory,doesFileExist,doesDirectoryExist,baseName, newSuffix,isNewer) import Run (runCommand) import Strings (header,date,footer,sheet) import Regex (mkRegex,mkSub,doSub,isMatch) import GetOpt (isOption,getOption,getOptionOr) import Options (Flag(..),Options) import Split (Delims,split,joinDoc,joinCode) import Filter (doGeneric) import Haskell (doHaskell) page :: String -> String -> String -> String page day file body = if day == "" then top ++ body ++ footer else top ++ body ++ stamp ++ footer where title = doSub file $ mkSub (".hs$|.txt$", "") top = doSub header $ mkSub ("[{]TITLE[}]", title) stamp = doSub date $ mkSub ("[{]DATE[}]", day) style :: Options -> IO () style options = do let dir = getOption DocDir options css = dir ++ '/' : "annote.css" ok1 <- doesDirectoryExist dir if ok1 then return () else createDirectory dir ok2 <- doesFileExist css if not ok2 || isOption ForceStyle options then writeFile css sheet else return () getDelims :: Options -> Delims -> Delims getDelims options (start,end,xstart,xend) = let pad s = if null s then s else "^" ++ s ++ "[ \t]*$" in (pad $ getOptionOr DocStart options start, pad $ getOptionOr DocEnd options end, pad $ getOptionOr ExtStart options xstart, pad $ getOptionOr ExtEnd options xend) dispatch :: Options -> String -> String -> (IO String, String) dispatch options file text = f xs where xs = [ ("[.]hs$", doHaskell, ("[{]-", "-[}]", "[{]-[|]", "-[}]")) , ("[.](c|cp)$", doGeneric, ("/[*]", "[*]/", [], [])) , ("[.]py$", doGeneric, ("[ \t]*\"\"\"", "[ \t]*\"\"\"", [], [])) , ("[.]pl$", doGeneric, ("=pod", "=cut", [], [])) , ("[.]m2$", doGeneric, ("///[*]", "[*]///;", [], [])) , (".*", doGeneric, ("[{]-", "-[}]", [], [])) ] isCode = not $ isMatch file $ mkRegex "[.]txt" f [] = undefined f ((pat,doSrc,delims):xt) = if isMatch file $ mkRegex pat then let raw = split isCode (getDelims options delims) text in ((joinDoc . doSrc) raw, joinCode raw) else f xt timestamp :: String -> IO String timestamp format = do (time,ok) <- runCommand ("date +'" ++ format ++ "'") [] False return $ if ok then time else "???" checkFilter :: FilePath -> IO () checkFilter mark = do (_,ok) <- runCommand ("which " ++ mark) [] False if ok then return () else do hPutStrLn stderr $ mark ++ " not found" exitFailure annote :: Options -> FilePath -> IO () annote options file = do let dir = (getOption DocDir options) ++ "/" base = baseName file html = dir ++ newSuffix base "html" code = dir ++ base newer <- isNewer file html if not newer then return () else do day <- timestamp $ getOption DateFormat options let write doc src = do writeFile html $ page day file doc if isOption Code options then writeFile code src else return () text <- readFile file let (iodoc,src) = dispatch options file text doc <- iodoc if isOption NoFilter options then write doc src else do let mark = getOption Filter options checkFilter mark (out,ok) <- runCommand mark doc False if ok then write out src else hPutStr stderr out