{-# LANGUAGE ViewPatterns #-} module Main where -- Static site generator for failing tests import Data.Algorithm.Diff (getDiff) import Data.Algorithm.DiffOutput (ppDiff) import System.Directory import System.FilePath import Control.Monad import Debug.Trace import Data.List import System.Environment import Data.Maybe import Text.Read main :: IO () main = do n <- getArgs case readMaybe =<< listToMaybe n of Nothing -> site 100 Just k -> site k site :: Int -> IO () site n = do putStrLn $ "Generating site for first: " ++ show n failPaths <- filterM doesFileExist =<< (map ("tests/roundtrip" ) . take n <$> getDirectoryContents "tests/roundtrip") traceShowM failPaths fails <- mapM parseFail failPaths writeFile "origfailures.txt" (intercalate "\n" (map getfname fails)) writeFile "failures/failures.html" (makeIndex failPaths) let padded = "failures.html" : (map makeFailLink failPaths ++ ["failures.html"]) let resolved = zipWith (\x (y,z) -> (x, y, z)) padded (zip (tail padded) (tail (tail padded))) mapM_ (uncurry page) (zip resolved fails) makeFailLink :: FilePath -> String makeFailLink fp = takeFileName fp <.> "html" makeIndex :: [FilePath] -> String makeIndex files = intercalate "
" (map mkIndexLink files) where mkIndexLink f = mkLink (takeFileName f <.> "html") f page :: (FilePath, FilePath, FilePath) -> Failure -> IO () page (prev, out, next) (Failure res fname) = do -- traceM out original <- readFile fname let diff = getDiff (tokenize original) (tokenize res) let l = length (lines res) if (l > 50000) then putStrLn ("Skipping: " ++ fname) >> print l else writeFile ("failures" out) (mkPage (ppDiff diff) prev next original res) where tokenize :: String -> [[String]] tokenize s = map (:[]) . lines $ s mkPage :: String -> String -> String -> String -> String -> String mkPage diff prev next original printed = intercalate "
" [mkLink prev "prev" , mkLink "failures.html" "home" , mkLink next "next" , "" , "
" ++ diff ++ "
" , "

original

" , "
" ++ original ++ "
" , "

printed

" , "
" ++ printed ++ "
" ] mkLink :: String -> String -> String mkLink s label = "" ++ label ++ "" data Failure = Failure String FilePath getfname (Failure _ fp) = fp parseFail :: FilePath -> IO Failure parseFail fp = do res <- lines <$> readFile fp let (finalres, head . tail -> fname) = break (=="==============") res return (Failure (unlines finalres) fname)