packages feed

hinstaller-2007.4.21: src/System/Installer/TH.hs

{-
    System.Installer : Installer wrapper for Haskell applications
    Copyright (C) 2007  Matthew Sackman

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA
-}

{-# LANGUAGE TemplateHaskell #-}

module System.Installer.TH
    (makeInstallFuncCase,
     makeDataDecls,
     makeInstallFunc)
where

import System.IO
import System.Directory
import System.FilePath
import Language.Haskell.TH
import Language.Haskell.TH.Syntax

makeInstallFuncCase :: String -> String -> FilePath -> String -> Q Clause
makeInstallFuncCase funcName name filepath contents
    = result
    where
      result = clause [conP dataName []]
               (normalB [| writeFileData filename $contentsQ |]) []
      contentsQ = liftString contents
      dataName = mkName $ "Installer_" ++ funcName ++ "_" ++ name
      filename = takeFileName filepath

makeInstallFunc :: String -> [Q Clause] -> Q Dec
makeInstallFunc funcName clauses
    = funD (mkName funcName) clauses

writeFileData :: String -> String -> FilePath -> IO ()
writeFileData origName content path
    = do { isDir <- doesDirectoryExist path
         ; let path' = if isDir then combine path origName else path
         ; h <- openFile path' WriteMode
         ; hPutStr h content
         ; hClose h
         }

liftString :: String -> Q Exp
liftString = return . LitE . StringL

makeDataDecls :: String -> [(String, FilePath)] -> Q [Dec]
makeDataDecls base names
    = do { dataDecl' <- dataDecl
         ; instanceDecl' <- instanceDecl
         ; return [dataDecl', instanceDecl']
         }
    where
      dataDecl = dataD (cxt []) dataDeclName []
                 constructors $ map mkName ["Eq", "Ord", "Enum"]
      instanceDecl = instanceD (cxt []) (appT (conT (mkName "Show"))
                                         (conT dataDeclName))
                     [showFuncs]
      showFuncs = funD (mkName "show") $ map makeShowFunc names
      dataDeclName = mkName $ "Installer_" ++ base
      constructors = map makeDataCons names
      makeDataCons :: (String, FilePath) -> Q Con
      makeDataCons (name, _)
          = normalC (mkName $ "Installer_" ++ base ++ "_" ++ name) []
      makeShowFunc :: (String, FilePath) -> Q Clause
      makeShowFunc (name, _)
          = clause [conP dataName []] (normalB . litE . stringL $ name) []
          where
            dataName = mkName $ "Installer_" ++ base ++ "_" ++ name