How can I organize local haskell package documents?

160 Views Asked by At

I have many haskell packages and I have enabled some flag to allow them generate haddock documents. Now these documents are under directories like /usr/share/doc/{package-name}-{version}/html/.

Is there a tool to organize them? I want something like all packages by name page in hackage, so that local links to all these installed packages can be found in one page.

It'll be better if hoogle can be told to use these documents. By now my hoogle search resutls are all pointing to the corresponding pages in hackage.

1

There are 1 best solutions below

0
On

Since my question has not yet been answered, I wrote a quick and dirty program to answer my first question:

import System.Directory
import System.IO
import System.Environment
import System.Exit
import System.Path
import System.FilePath.Posix

import Control.Applicative
import Control.Monad
import Data.Maybe
import Data.List
import Text.Printf

-- | make markdown table row
makeTableRow :: String -> FilePath -> String
makeTableRow dirName htmlPath = intercalate "|" [ dirName
                                                , link "frames"
                                                , link "index"
                                                , link "doc-index"]
    where
        link s = printf "[%s](%s)" s $ htmlPath </> s ++ ".html"

scanAndMakeTable :: String -> IO [String]
scanAndMakeTable relDocPath = do
    (Just docPath) <- absNormPath' <$> getCurrentDirectory <*> pure relDocPath
    dirs <- getDirectoryContents docPath
    items <- liftM catMaybes
           . mapM (asHaskellPackage docPath)
           . sort $ dirs
    return $ headers1:headers2:map (uncurry makeTableRow) items
    where
        headers1 = "| " ++  intercalate " | " (words "Package Frames Contents Index") ++ " |"
        headers2 = intercalate " --- " $ replicate 5 "|"
        absNormPath' a p = addMissingRoot  <$> absNormPath a p
        -- sometimes the leading '/' is missing in absNormPath results
        addMissingRoot s@('/':_) = s
        addMissingRoot s = '/' : s
        asHaskellPackage :: String -> String -> IO (Maybe (String,FilePath))
        asHaskellPackage docPath dirName = do
            -- a valid haskell package has a "haddock dir"
            -- in which we can at least find a file with ".haddock" as extension name
            b1 <- doesDirectoryExist haddockFileDir
            if b1
               then do
                   b2 <- any ((== ".haddock") . takeExtension)
                             <$> getDirectoryContents haddockFileDir
                   return $ if b2 then Just (dirName,haddockFileDir) else Nothing
               else return Nothing
            where
                -- guess haddock dir
                haddockFileDir = docPath </> dirName </> "html"

main :: IO ()
main = do
    args <- getArgs
    case args of
      [docPath'] -> scanAndMakeTable docPath' >>= putStrLn . unlines
      _ -> help
    where
        help = hPutStrLn stderr "Usage: <program> <path-to-packages>"
            >> exitFailure

By observing the structure of these haddock directories, I recognize haddock directories by testing:

  • if there's a subdirectory called html.
  • if in the subdirectory html, there is a file with .haddock as extension name.

Run the program with runghc <source-file> /usr/share/doc/ >document-nav.md should generate a markdown file containing links to documents. Afterward just pipe it to pandoc or some other markdown2html converter and use the resulting HTML file in a browser to navigate through package documents.