summaryrefslogtreecommitdiff
path: root/Setup.hs
blob: 25960bcc414410d91b570578003d806bd1115a29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import Distribution.Simple
import Distribution.Simple.Setup
import Distribution.PackageDescription
import Distribution.Simple.LocalBuildInfo
import System.FilePath (combine, joinPath, takeFileName, takeExtension)
import System.Directory (getDirectoryContents, removeFile, copyFile)
import System.IO (readFile, writeFile)
import Control.Monad (foldM)
import Data.List (isPrefixOf)

main = defaultMainWithHooks myHooks

myHooks = defaultUserHooks { postConf = myPostConf, postClean = myPostClean }

pandocPath = combine "Text" "Pandoc"

-- Builds Text/Pandoc/ASCIIMathML.hs, Text/Pandoc/Writers/S5.hs, and
-- Text/Pandoc/Writers/DefaultHeaders.hs from templates and data.
myPostConf :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()
myPostConf _ configFlags pkgDescription buildInfo = do
  putStrLn "Generating source files from templates..."
  fillAsciiMathMLTemplate
  fillS5WriterTemplate
  fillDefaultHeadersTemplate
  let deps = packageDeps buildInfo
  let highlighting = any (\id -> pkgName id == "highlighting-kate") deps 
  let highlightingModule = if highlighting
                              then combine "templates" "Highlighting.yes.hs"
                              else combine "templates" "Highlighting.no.hs"
  copyFile highlightingModule $ joinPath ["Text", "Pandoc", "Highlighting.hs"] 
  putStrLn $ "  Text/Pandoc/Highlighting.hs [" ++ 
             (if highlighting then "with" else "without") ++ " syntax highlighting support]"

-- Fill templateFile with data in dataFiles and write to outputFile.
fillTemplate :: [FilePath] -> FilePath -> FilePath -> IO ()
fillTemplate dataFiles templateFile outputFile = do
  template <- readFile (combine "templates" templateFile)
  filled <- foldM processFile template $ map (combine "templates") dataFiles
  writeTemplate (combine pandocPath outputFile) filled 

fillAsciiMathMLTemplate :: IO ()
fillAsciiMathMLTemplate =
  fillTemplate ["ASCIIMathML.js.comment", "ASCIIMathML.js.packed"] "ASCIIMathML.hs" "ASCIIMathML.hs"

fillS5WriterTemplate :: IO ()
fillS5WriterTemplate = 
  let s5Path = joinPath ["ui", "default"]
      files = map (combine s5Path) ["slides.js.comment", "slides.js.packed", "s5-core.css", 
              "framing.css", "pretty.css", "opera.css", "outline.css", "print.css"]
  in  fillTemplate files "S5.hs" (combine "Writers" "S5.hs")

fillDefaultHeadersTemplate :: IO ()
fillDefaultHeadersTemplate = do
  files <- getDirectoryContents (combine "templates" "headers") >>= 
             return . map (combine "headers") . filter (\x -> takeExtension x == ".header")
  fillTemplate files "DefaultHeaders.hs" "DefaultHeaders.hs"

-- Post-clean: remove the files generated from templates.
myPostClean :: Args -> CleanFlags -> PackageDescription -> Maybe LocalBuildInfo -> IO ()
myPostClean _ _ _ _ = do
  putStrLn "Removing source files generated from templates:"
  removeGeneratedFile $ joinPath [pandocPath, "ASCIIMathML.hs"]
  removeGeneratedFile $ joinPath [pandocPath, "DefaultHeaders.hs"]
  removeGeneratedFile $ joinPath [pandocPath, "Highlighting.hs"]
  removeGeneratedFile $ joinPath [pandocPath, "Writers", "S5.hs"]

-- Remove file and print message.
removeGeneratedFile :: FilePath -> IO () 
removeGeneratedFile fpath = do
  putStrLn $ "  " ++ fpath
  removeFile fpath

-- Write the filled template file and print an explanatory message.
writeTemplate :: FilePath -> String -> IO ()
writeTemplate outfile contents = do
  putStrLn $ "  " ++ outfile
  let warning = "-- This file is generated from a template in the templates subdirectory.\n\
                \-- Modify that file, not this one.\n"
  writeFile outfile (warning ++ contents)

-- Read contents of fpath and insert in template replacing @fpath@.
processFile :: String -> FilePath -> IO String
processFile template fpath = do 
  contents <- readFile fpath >>= return . show
  return $ substitute ("@" ++ takeFileName fpath ++ "@") contents template

-- Replace each occurrence of one sublist in a list with another.
substitute :: (Eq a) => [a] -> [a] -> [a] -> [a]
substitute _ _ [] = []
substitute [] _ lst = lst
substitute target replacement lst = 
    if target `isPrefixOf` lst
       then replacement ++ (substitute target replacement $ drop (length target) lst)
       else (head lst):(substitute target replacement $ tail lst)