packages feed

hyakko 0.2.1 → 0.3.0

raw patch · 3 files changed

+58/−35 lines, 3 filesdep +bytestring

Dependencies added: bytestring

Files

hyakko.cabal view
@@ -1,5 +1,5 @@ name:             hyakko-version:          0.2.1+version:          0.3.0 cabal-version:    >= 1.6 build-type:       Simple license:          MIT@@ -39,7 +39,8 @@                   regex-pcre >= 0.9,                   containers >= 0.4,                   directory >= 1,-                  pandoc >= 1.8.2+                  pandoc >= 1.8.2,+                  bytestring >= 0.9   hs-source-dirs: src   ghc-options:    -O2 -Wall   main-is:        Hyakko.hs
src/Hyakko.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE OverloadedStrings #-} -- **Hyakko** is a Haskell port of [docco](http://jashkenas.github.com/docco/): -- the original quick-and-dirty, hundred-line-line, literate-programming-style -- documentation generator. It produces HTML that displays your comments@@ -19,12 +20,19 @@ --     git clone git://github.com/sourrust/hyakko.git --     cd hyakko --     cabal install+--+--  or+--+--     cabal update+--     cabal install hyakko module Main where  import Text.Markdown  import Data.Map (Map) import qualified Data.Map as M+import Data.ByteString.Lazy.Char8 (ByteString)+import qualified Data.ByteString.Lazy.Char8 as L import Data.List (sort, groupBy) import Data.Maybe (fromJust) import Control.Monad (filterM)@@ -41,15 +49,19 @@  -- Make type signature more readable with these two `Callback` types. type Callback  = IO ()-type Callback' = [Map String String] -> IO ()+type Callback' = [Map String ByteString] -> IO () +(><) :: ByteString -> ByteString -> ByteString+(><) = L.append+{-# INLINE (><) #-}+ -- Generate the documentation for a source file by reading it in, splitting it -- up into comment/code sections, highlighting them for the appropriate language, -- and merging them into an HTML template. generateDocumentation :: [FilePath] -> IO () generateDocumentation [] = return () generateDocumentation (x:xs) = do-  code <- readFile x+  code <- L.readFile x   let sections = parse (getLanguage x) code   if null sections then     putStrLn $ "hyakko doesn't support the language extension " ++ takeExtension x@@ -69,17 +81,19 @@ --       ("codeHtml", ...) --     ] ---inSections :: [String] -> String -> [Map String String]+inSections :: [ByteString] -> ByteString -> [Map String ByteString] inSections xs r =   let mkRegex' = mkRegex . (=~ r)       -- Generalized function used to section off code and comments       groupBy' t t1 = groupBy $ \x y -> and $ map (t1 . (=~ r)) [t x, t y]       -- Replace the beggining comment symbol with nothing-      replace = unlines . map (\y -> subRegex (mkRegex' y) y "")+      replace = L.unlines . map (\y ->+        let y' = L.unpack y+        in L.pack $ subRegex (mkRegex' y') y' "")       -- Clump sectioned off lines into doc and code text.       clump [] = []       clump [x] = clump $ ensurePair [x]-      clump (x:y:ys) = [("docsText", replace x),("codeText", unlines y)] : clump ys+      clump (x:y:ys) = [("docsText", replace x),("codeText", L.unlines y)] : clump ys       -- Make sure the result is in the right pairing order       ensurePair ys = if even $ length ys then ys else         if (head . head) ys =~ r then ys ++ [[""]] else [""]:ys@@ -93,10 +107,10 @@       s3 = ensurePair $ map concat s2   in [M.fromList l | l <- clump s3] -parse :: Maybe (Map String String) -> String -> [Map String String]+parse :: Maybe (Map String ByteString) -> ByteString -> [Map String ByteString] parse Nothing _ = [] parse (Just src) code =-  let line = filter ((/=) "#!" . take 2) $ lines code+  let line = filter ((/=) "#!" . L.take 2) $ L.lines code   in inSections line $ src M.! "comment"  -- Highlights a single chunk of Haskell code, using **Pygments** over stdio,@@ -106,26 +120,30 @@ -- We process the entire file in a single call to Pygments by inserting little -- marker comments between each section and then splitting the result string -- wherever our markers occur.-highlight :: FilePath -> [Map String String] -> Callback' -> IO ()+highlight :: FilePath -> [Map String ByteString] -> Callback' -> IO () highlight src section cb = do   let language = fromJust $ getLanguage src-      options  = ["-l", language M.! "name", "-f", "html", "-O", "encoding=utf-8"]-      input = concatMap (\x -> x M.! "codeText"++(language M.! "dividerText")) section+      options  = ["-l", L.unpack $ language M.! "name", "-f",+                  "html", "-O", "encoding=utf-8"]+      input = concatMap (\x ->+        let codeText = L.unpack $ x M.! "codeText"+            divider  = L.unpack $ language M.! "dividerText"+        in codeText ++ divider) section    output <- readProcess "pygmentize" options input    let output'   = subRegex (mkRegex highlightReplace) output ""-      fragments = splitRegex (mkRegex $ language M.! "dividerHtml") output'+      fragments = splitRegex (mkRegex . L.unpack $ language M.! "dividerHtml") output'    cb $ map (\x -> let s = section !! x-    in M.insert "docsHtml" (toHTML $ s M.! "docsText") $-       M.insert "codeHtml" (highlightStart ++ (fragments !! x) +++    in M.insert "docsHtml" (toHTML . L.unpack $ s M.! "docsText") $+       M.insert "codeHtml" (highlightStart >< (L.pack $ fragments !! x) ><          highlightEnd) s) [0..(length section) - 1]  -- Once all of the code is finished highlighting, we can generate the HTML file -- and write out the documentation. Pass the completed sections into the template -- found in `resources/hyakko.html`-generateHTML :: FilePath -> [Map String String] -> IO ()+generateHTML :: FilePath -> [Map String ByteString] -> IO () generateHTML src section = do   let title = takeFileName src       dest  = destination src@@ -142,22 +160,22 @@       "    <div class='pilwrap'>",       "      <a class='pilcrow' href='#section-"++show (x + 1)++"'>&#955;</a>",       "    </div>",-      (section !! x) M.! "docsHtml",+      L.unpack $ (section !! x) M.! "docsHtml",       "  </td>",       "  <td class='code'>",-      (section !! x) M.! "codeHtml",+      L.unpack $ (section !! x) M.! "codeHtml",       "  </td>",       "</tr>" ])) [0..(length section) - 1]     ]   putStrLn $ "hyakko: " ++ src ++ " -> " ++ dest-  writeFile dest html+  L.writeFile dest html  -- ### Helpers & Setup  -- A list of the languages that Hyakko supports, mapping the file extension to -- the name of the Pygments lexer and the symbol that indicates a comment. To -- add another language to Hyakko's repertoire, add it here.-languages :: Map String (Map String String)+languages :: Map String (Map String ByteString) languages =   let hashSymbol = ("symbol", "#")       l = M.fromList [@@ -175,17 +193,17 @@   -- Build out the appropriate matchers and delimiters for each language.   in M.map (\x -> let s = x M.! "symbol"     -- Does the line begin with a comment?-    in M.insert "comment" ("^\\s*"++s++"\\s?") $+    in M.insert "comment" ("^\\s*"><s><"\\s?") $        -- The dividing token we feed into Pygments, to delimit the boundaries        -- between sections.-       M.insert "dividerText" ("\n"++s++"DIVIDER\n") $+       M.insert "dividerText" ("\n"><s><"DIVIDER\n") $        -- The mirror of `divider_text` that we expect Pygments to return. We can        -- split on this to recover the original sections.        -- Note: the class is "c" for Python and "c1" for the other languages-       M.insert "dividerHtml" ("\n*<span class=\"c1?\">"++s++"DIVIDER</span>\n") x) l+       M.insert "dividerHtml" ("\n*<span class=\"c1?\">"><s><"DIVIDER</span>\n") x) l  -- Get the current language we're documenting, based on the extension.-getLanguage :: FilePath -> Maybe (Map String String)+getLanguage :: FilePath -> Maybe (Map String ByteString) getLanguage src = M.lookup (takeExtension src) languages  -- Compute the destination HTML path for an input source file path. If the source@@ -198,23 +216,25 @@ ensureDirectory cb = system "mkdir -p docs" >> cb  -- Create the template that we will use to generate the Hyakko HTML page.-hyakkoTemplate :: [(String, String)] -> IO String+hyakkoTemplate :: [(String, String)] -> IO ByteString hyakkoTemplate var = readDataFile "resources/hyakko.html" >>=-  return . renderTemplate var+  return . renderTemplate var . L.unpack  -- The CSS styles we'd like to apply to the documentation.-hyakkoStyles :: IO String+hyakkoStyles :: IO ByteString hyakkoStyles = readDataFile "resources/hyakko.css"  -- The start and end of each Pygments highlight block.-highlightStart, highlightEnd, highlightReplace :: String+highlightStart, highlightEnd :: ByteString highlightStart   = "<div class=\"highlight\"><pre>" highlightEnd     = "</pre></div>"-highlightReplace = highlightStart ++ "|" ++ highlightEnd +highlightReplace :: String+highlightReplace = L.unpack highlightStart ++ "|" ++ L.unpack highlightEnd+ -- Reads from resource path given in cabal package-readDataFile :: FilePath -> IO String-readDataFile f = getDataFileName f >>= readFile+readDataFile :: FilePath -> IO ByteString+readDataFile f = getDataFileName f >>= L.readFile  -- For each source file passed in as an argument, generate the documentation. sources :: IO [FilePath]@@ -228,7 +248,8 @@ -- in sub-directories. unpackDirectories :: FilePath -> IO [FilePath] unpackDirectories d = do-  content <- getDirectoryContents d >>= return . filter (=~ "[^\\.{1,2}]")+  let reg = "[^(^\\.{1,2}$)]" :: ByteString+  content <- getDirectoryContents d >>= return . filter (=~ reg)   let content' = map (d </>) content   files <- filterM doesFileExist content'   subdir <- filterM doesDirectoryExist content'@@ -241,5 +262,5 @@   style <- hyakkoStyles   source <- sources   ensureDirectory $ do-    writeFile "docs/hyakko.css" style+    L.writeFile "docs/hyakko.css" style     generateDocumentation source
src/Text/Markdown.hs view
@@ -6,10 +6,11 @@   , defaultParserState   , defaultWriterOptions   )+import Data.ByteString.Lazy.Char8 (ByteString, pack)  -- Function for translating Markdown to HTML since `Pandoc` has several -- different generators for other markup languages.-toHTML :: String -> String-toHTML = writeHtmlString defaultWriterOptions . parse+toHTML :: String -> ByteString+toHTML = pack . writeHtmlString defaultWriterOptions . parse   where parse = readMarkdown defaultParserState {-# INLINE toHTML #-}