packages feed

hgom-0.5.1: Gom/FileGen.hs

-------------------------------------------------------------------
-- |
-- Module      : Gom.FileGen
-- Copyright   : (c) Paul Brauner 2009
--               (c) Emilie Balland 2009
--               (c) INRIA 2009
-- Licence     : GPL (see COPYING)
--
-- Maintainer  : paul.brauner@inria.fr
-- Stability   : provisional
-- Portability : non-portable (requires generalized newtype deriving)
--
-- Exposes 'FileHierarchy', a datatype representing a file hierarchy made of
-- packages, java files and tom files as well as an impure function for
-- actually generating the hierarchy.
--------------------------------------------------------------------

module Gom.FileGen (
  FileHierarchy(..),
  generateFileHierarchy
) where

import Text.PrettyPrint.Leijen
import Data.List(intercalate)
import System.FilePath hiding ((</>))
import System.Directory
import System.IO

-- | Represents a hierarchy of Java packages, Java classes and .tom files.
-- Constructors and field names speak for themselves.
data FileHierarchy
  = Package { 
    packageName    :: String,
    packageContent :: [FileHierarchy]
  }
  | Class {
    className    :: String,
    classContent :: Doc -- ^ without @package ...@ at the begining
  }
  | Tom {
    fileName    :: String, -- ^ without the extension
    fileContent :: Doc 
  }

-- | Actually generates files on disk. If the first argument is
-- true, generates compact code.
generateFileHierarchy :: Bool -> FileHierarchy -> IO ()
generateFileHierarchy c h = do cur <- getCurrentDirectory
                               generateHierarchyIn c cur [] h

-- | @generateHierarchyIn compact dir [pack]@ generates the files in
-- directory @dir@ in package @pack@. Adds proper @package ...@ on top of java
-- files. If @compatc@ is true, the generated code is more compact.
--
-- GenMonad usage : @generateFileHierarchyIn compact dir []@
generateHierarchyIn :: Bool -> FilePath -> [String] -> FileHierarchy -> IO ()
generateHierarchyIn cp dir pac h = go h
  where go (Package n hs) = let ndir = dir `combine` n
                                npac = pac ++ [n]       
                            in do createDirectoryIfMissing False ndir
                                  mapM_ (generateHierarchyIn cp ndir npac) hs
        go (Class n b)    = let fn = dir `combine` (n `addExtension` "java")
                                fb = rFullClass pac b
                            in renderInFile fn fb
        go (Tom n b)      = let fn = dir `combine` (n `addExtension` "tom")
                            in renderInFile fn b
        renderInFile n b  = do hdl <- openFile n WriteMode
                               displayIO hdl (rdr b) 
                               hClose hdl
        rdr = if cp then renderCompact else renderPretty 0.6 80 

-- | Adds package name at the top of a class declaration.
rFullClass
  :: [String] -- ^ package
  -> Doc      -- ^ class content
  -> Doc
rFullClass [] bd = bd
rFullClass pk bd = text "package" <+> text (intercalate "." pk) <>
                   semi <> linebreak <$> bd