packages feed

Hs2lib-0.4.8: WinDll/Utils/HaddockRead.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  WinDll.Utils.HaddockRead 
-- Copyright   :  (c) Tamar Christina 2009 - 2010
-- License     :  BSD3
-- 
-- Maintainer  :  tamar@zhox.com
-- Stability   :  experimental
-- Portability :  portable
--
-- A module to handle parsing and information querying of Haddock files
--
-----------------------------------------------------------------------------

module WinDll.Utils.HaddockRead where

import System.Environment
import System.Directory

import qualified Data.Map as M

import System.FilePath

import WinDll.Utils.Processes
import WinDll.Session
import WinDll.Utils.Feedback
import System.FilePath

import Data.List
import Data.Char

type FunctionName     = String
type Arg              = Int
type IndexedInterface = M.Map FunctionName FunctionSpec

data FunctionSpec = 
   FunctionSpec { description :: [String]
                , arguments :: [(Arg,String)]
                } deriving Show

-- | Read the function comments of the specified haddock file and create a simple datastructure to hold em.
getDocumentationInfo :: Exec IndexedInterface
getDocumentationInfo = 
 do session <- get
    let comment = pres_comment session
        build   = pipeline session
    case comment of
       False -> return M.empty
       True  -> do createProcess Nothing "haddock" createHoogle
                   specs <- liftIO $ fmap lines $ readFile ((addTrailingPathSeparator (dirPath build)) ++ "main.txt")
                   return $ parseHaddock specs M.empty
    
-- | Parse the haddock generated file and produce the map required
parseHaddock :: [String] -> IndexedInterface -> IndexedInterface
parseHaddock []    _map = _map
parseHaddock value _map 
  = let value'          = dropWhile (\x->not $ "-- |" `isPrefixOf` x) value
        (comments,rest) = span (\x->"-- " `isPrefixOf` x) value'
        (func:rest')    = rest
        isFunction x    = case x of
                            ':' -> True
                            _   -> False
        name            = takeWhile (\x-> not $ (isFunction x) || isSpace x) func
        isPart x        = case x of
                            '-' -> True
                            ' ' -> True
                            '|' -> True
                            _   -> False
        comment         = concatMap (reverse . dropWhile isSpace . reverse . dropWhile isPart) comments
        cmt'            = cleanupHaddock comment []
        specs           = FunctionSpec (([]:cmt')++[[]]) []
    in if null rest || null name then _map else parseHaddock rest' (M.insert name specs _map)
 
-- | Convert a long string into a haddock representation by splitting "." as newlines.
cleanupHaddock :: String -> String -> [String]
cleanupHaddock []              r = [reverse r]
cleanupHaddock (' ':'.':' ':x) r = reverse r : cleanupHaddock x []
cleanupHaddock ('<':'a':'>':x) r = cleanupHaddock x ('"':r)
cleanupHaddock ('<':'/':'a':'>':x) r = cleanupHaddock x ('"':r)
cleanupHaddock (c:x)           r = cleanupHaddock x (c:r)
 
-- | Generate hoogle documentation
createHoogle :: Exec (String, [String])
createHoogle = 
 do session <- get
    let dir  = addTrailingPathSeparator (baseDir session)
        deps  = (dependencies.workingset) session
        paths = (absPath session : map guessPath (drop 1 deps))
    return ("main.txt"
           , -- ["--optghc=\"-i" ++ if ' ' `elem` dir then show dir else dir ++ "\"" 
           ("--hoogle" : map (dir++) paths)
           )