packages feed

ideas-0.6: src/Documentation/LatexRules.hs

-----------------------------------------------------------------------------
-- Copyright 2010, Open Universiteit Nederland. This file is distributed 
-- under the terms of the GNU General Public License. For more information, 
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer  :  bastiaan.heeren@ou.nl
-- Stability   :  provisional
-- Portability :  portable (depends on ghc)
--
-----------------------------------------------------------------------------
module Documentation.LatexRules (makeLatexRules) where

import Common.Exercise
import Common.Rewriting
import Common.Transformation
import Common.Utils
import Control.Monad
import Data.Char
import Data.List
import Data.Maybe
import System.Directory
import System.Time

makeLatexRules :: String -> Exercise a -> IO ()
makeLatexRules dir ex = do
   let code = exerciseCode ex
       path = dir ++ "/" ++ domain code ++ "/" ++ filter (/= ' ') (identifier code)
   -- Exercise document
   let rules = concatMap getRewriteRules (ruleset ex)
   unless (null rules) $ do
      createDirectoryIfMissing True path
      doc <- makeDocument ex
      let filename = path ++ "/overview.lhs"
      putStrLn $ "Creating " ++ filename
      writeFile filename doc
   -- individual rules
   forM_ (ruleset ex) $ \r ->
       case makeSingleRule (domain code ++ "/" ++ domain code ++ ".fmt") r of
          Nothing  -> return ()
          Just txt -> do
             let filename = path ++ "/rule" ++ filter isAlphaNum (name r) ++ ".lhs"
             putStrLn $ "Creating " ++ filename
             writeFile filename txt

{- 
exerciseRulesToTeX :: Exercise a -> String
exerciseRulesToTeX ex = unlines . map ruleToTeX . concatMap getRewriteRules . ruleset $ ex
-}

ruleToTeX :: (Some RewriteRule, Bool) -> Maybe String
ruleToTeX (Some r, sound) = do
   txt <- showRewriteRule sound r
   return $ "RewriteRule " ++ withoutDigits (ruleName r) 
                           ++ " (" ++ txt ++ ")"

   
------------------------------------------------------

makeSingleRule :: String -> Rule a -> Maybe String
makeSingleRule dom r 
   | null (getRewriteRules r) = Nothing
   | otherwise = Just $ texHeader (Just dom) ++ texBody Nothing content
 where
   content = unlines $
      [ "\\pagestyle{empty}"
      , formatRuleName (name r)
      , "\\begin{code}"
      ] ++
      map (filter (/= '"') . fromMaybe "" . ruleToTeX) (getRewriteRules r) ++
      [ "\\end{code}"
      ]


makeDocument :: Exercise a -> IO String
makeDocument ex = do
   let code = exerciseCode ex
   time <- getClockTime
   return $ 
      texHeader (Just $ domain code ++ "/" ++ domain code ++ ".fmt") ++ 
      texBody (Just $ show time) (texSectionRules ex)

------------------------------------------------------

texHeader :: Maybe String -> String
texHeader fmt = unlines
   [ "\\documentclass{article}"
   , ""
   , "%include lhs2TeX.fmt"
   , "%format RewriteRule (a) (b) = \"\\rewriterule{\"a\"}{\"b\"}\""
   , "%format ~> = \"\\:\\leadsto\\:\""
   , "%format /~> = \"\\:\\not\\leadsto\\:\""
   , maybe "" ("%include "++) fmt
   , "" 
   , "\\newcommand{\\rewriterule}[2]{#1:\\quad #2}"
   , "\\newcommand{\\rulename}[1]{\\mbox{\\sc #1}}"
   ]
   
texBody :: Maybe String -> String -> String
texBody date content = unlines
   [ "\\begin{document}"
   , content
   , maybe "" (\s -> "\\par\\vspace*{5mm}\\noindent\\footnotesize{@(generated on " ++ s ++ ")@}") date
   , "\\end{document}"
   ]
   
texSectionRules :: Exercise a -> String
texSectionRules ex = unlines 
   [ "\\section{Rewrite rules}"
   , formats
   , makeGroup Nothing
   , unlines $ map (makeGroup . Just) groups
   ]
 where
   rules   = concatMap getRewriteRules (ruleset ex)
   groups  = nub (concatMap ruleGroups (ruleset ex))
   names   = let f (Some r, _) = ruleName r 
             in nub (map f rules)
   formats = unlines (map formatRuleName names)
   
   makeGroup :: Maybe String -> String
   makeGroup mgroup = unlines 
      [ maybe "" (\s -> "\\subsection{" ++ s ++ "}") mgroup
      , "\\begin{code}"
      , unlines $ map (filter (/= '"')) xs
      , "\\end{code}"
      ]
    where
      p x = maybe (null $ ruleGroups x) (`elem` ruleGroups x) mgroup
      xs  = mapMaybe ruleToTeX $ concatMap getRewriteRules $ filter p $ ruleset ex
      
formatRuleName :: String -> String
formatRuleName s = "%format " ++ withoutDigits s ++ " = \"\\rulename{" ++ s ++ "}\""

withoutDigits :: String -> String
withoutDigits = concatMap f 
 where
   f c | isAlpha c = [c]
       | isDigit c = "QX" ++ [chr (ord c + 49)]
       | otherwise = []