packages feed

wembley (empty) → 0.1.0.0

raw patch · 7 files changed

+364/−0 lines, 7 filesdep +basedep +bytestringdep +filemanipsetup-changed

Dependencies added: base, bytestring, filemanip, filepath, optparse-applicative, split

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Daniel Lovasko (c) 2016++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Daniel Lovasko nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Latex.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE OverloadedStrings #-}++module Latex+( render+) where++import Data.Monoid+import qualified Data.ByteString.Char8 as C+import qualified System.FilePath as F++-- | Translate an extension into a  Minted language name. Note that+-- extensions that are not recognized will be rendered without any+-- syntax highlighting.+translateExt :: String       -- ^ file extension+             -> C.ByteString -- ^ Minted language+translateExt ext+  | ext == "c" || ext == "h" = "c"+  | ext == "sh"              = "bash"+  | ext == "hs"              = "haskell"+  | ext == "pl"              = "perl"+  | ext == "py"              = "python"+  | ext == "rb"              = "ruby"+  | ext == "java"            = "java"+  | otherwise                = "text"++-- | Append newline as the last character of a string if it does not end+-- with one.+ensureNewline :: C.ByteString -- ^ old string+              -> C.ByteString -- ^ new string+ensureNewline str+  | C.null str         = str+  | C.last str == '\n' = str+  | otherwise          = str <> "\n"++-- | All underscores must be escaped in order to prevent the subscript+-- redenring.+escapeUnderscore :: String -- ^ old string+                 -> String -- ^ new string+escapeUnderscore [] = []+escapeUnderscore (x:xs)+  | x == '_'  = '\\':x:escapeUnderscore xs+  | otherwise = x:escapeUnderscore xs++-- | Apply decoration to a single file and its contents.+decorateFile :: (String, C.ByteString) -- ^ file name & content+             -> C.ByteString           -- ^ decorated file+decorateFile (name, content) = C.unlines+  [ "\\section*{" <> name' <> "}"+  , "\\addcontentsline{toc}{subsection}{" <> name' <> "}"+  , "\\begin{minted}{" <> translateExt (tail $ F.takeExtensions name) <> "}"+  , ensureNewline content <> "\\end{minted}"+  , "\n" ]+  where name' = C.pack $ escapeUnderscore name++-- | Wrap the document in a standard envelope.+envelope :: String       -- ^ project name+         -> C.ByteString -- ^ content+         -> C.ByteString -- ^ finished document+envelope name content = C.unlines+  [ "\\documentclass{article}"+  , "\\usepackage{minted}"+  , "\\usepackage{fullpage}"+  , "\\begin{document}"+  , "\\centerline{\\bf{\\Huge{" <> name' <> "}}}"+  , "\\bigskip"+  , "\\tableofcontents"+  , "\\bigskip"+  , content+  , "\\end{document}" ]+  where name' = C.pack $ escapeUnderscore name++-- | Apply decoration to a whole codebase in order to create a document.+render :: String                   -- ^ project name+       -> [(String, C.ByteString)] -- ^ file names & contents+       -> C.ByteString             -- ^ final document+render name entries = envelope name (C.unlines $ map decorateFile entries)
+ src/Main.hs view
@@ -0,0 +1,65 @@+import Data.List+import Data.List.Split (splitOn)+import Options.Applicative (execParser)+import qualified System.FilePath as F+import qualified System.FilePath.Find as F+import qualified Data.ByteString.Char8 as C++import Latex+import Markdown+import Options+++-- | Convert paths to be relative to the project root.+relativePaths :: Options    -- ^ command-line options+              -> [FilePath] -- ^ absolute file paths+              -> [FilePath] -- ^ relative file paths+relativePaths options = map (F.makeRelative (getRootDir options))++-- | Generate the contents of the resuling document.+generateOutput :: Options                  -- ^ command-line options+               -> [(String, C.ByteString)] -- ^ file names & contents+               -> C.ByteString             -- ^ final document+generateOutput options entries = run (getOutputFormat options)+  where+    run FmtLatex    = Latex.render name entries+    run FmtMarkdown = Markdown.render name entries+    name            = getProjectName options++-- | Sort the file names alphabetically and by the number of path+-- components.+sortNames :: [FilePath] -- ^ file names+          -> [FilePath] -- ^ sorted file names+sortNames names = sortBy compSort (sort names)+  where+    compSort a b = compare (compCount a) (compCount b)+    compCount    = length . F.splitPath++-- | Filter predicate to determine relevant file extensions.+acceptExtensions :: Options           -- ^ command-line options+                 -> F.FindClause Bool -- ^ filter predicate+acceptExtensions options+  | null exts = return False+  | otherwise = foldr (F.||?) (return False) clauses+  where+    clauses  = map (F.extension F.==?) withDots+    withDots = map ('.' :) $ filter (not . null) (splitOn "," exts)+    exts     = getExtensions options++-- | Find all files that are relevant to the provided options.+findFiles :: Options       -- ^ options+          -> IO [FilePath] -- ^ file names+findFiles options = do+  let recurse = acceptExtensions options+  files <- F.find F.always recurse (getRootDir options)+  return $ sortNames files++-- | Pretty-printing of a whole codebase into a document.+main :: IO ()+main = do+  options  <- execParser Options.parser+  names    <- findFiles options+  contents <- mapM C.readFile names+  let entries = zip (relativePaths options names) contents+  C.writeFile (getOutputFile options) (generateOutput options entries)+
+ src/Markdown.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedStrings #-}++module Markdown+( render+) where++import Data.Char+import Data.Monoid+import qualified Data.ByteString.Char8 as C+import qualified System.FilePath as F+++-- | Translate an extension into a GitHub markdown language name. Note+-- that extensions that are not recognized will be rendered without any+-- syntax highlighting.+translateExt :: String       -- ^ file extension+             -> C.ByteString -- ^ Markdown language+translateExt ext+  | ext == "c" || ext == "h" = "c"+  | ext == "sh"              = "sh"+  | ext == "hs"              = "haskell"+  | ext == "pl"              = "perl"+  | ext == "py"              = "python"+  | ext == "rb"              = "ruby"+  | ext == "java"            = "java"+  | otherwise                = ""++-- | Append newline as the last character of a string if it does not end+-- with one.+ensureNewline :: C.ByteString -- ^ old string+              -> C.ByteString -- ^ new string+ensureNewline str+  | C.null str         = str+  | C.last str == '\n' = str+  | otherwise          = str <> "\n"++-- | Apply decoration to a single file and its contents.+decorateFile :: (String, C.ByteString) -- ^ file name & content+             -> C.ByteString           -- ^ decorated file+decorateFile (name, content) = C.unlines+  [ "## " <> C.pack name+  , "```" <> translateExt (tail $ F.takeExtensions name)+  , ensureNewline content <> "```" ]++-- | Generate the "table of contents" section+generateTOC :: [String]     -- ^ file names+            -> C.ByteString -- ^ section content+generateTOC names = C.unlines (header : map (convert . C.pack) names)+  where+    header       = "### Files"+    convert name = "* [" <> name <> "](#" <> linkify name <> ")"+    linkify      = C.map toLower . C.filter (\c -> isAlpha c || c == '_')++-- | Apply decoration to a whole codebase in order to create a document.+render :: String                   -- ^ project name+       -> [(String, C.ByteString)] -- ^ file names & contents+       -> C.ByteString             -- ^ final document+render name entries = C.unlines+  ["# " <> C.pack name+  , generateTOC $ map fst entries+  , C.unlines $ map decorateFile entries ]
+ src/Options.hs view
@@ -0,0 +1,97 @@+module Options+( Format(..)+, Options(..)+, parser+) where++import Data.Monoid+import Options.Applicative++-- | Output formats.+data Format = FmtLatex    -- ^ LaTeX+            | FmtMarkdown -- ^ GitHub Flavoured Markdown++-- | Command-line options.+data Options = Options { getExtensions   :: String+                       , getProjectName  :: String+                       , getOutputFormat :: Format+                       , getOutputFile   :: String+                       , getRootDir      :: String }++-- | Textual representation of the Format type.+instance Show Format where+  show FmtLatex    = "latex"+  show FmtMarkdown = "markdown"++-- | Parse a output format name.+formatReader :: String               -- ^ input+             -> Either String Format -- ^ error message | format+formatReader "latex"    = Right FmtLatex+formatReader "markdown" = Right FmtMarkdown+formatReader _          = Left "Format not supported"++-- | Relevant file extensions options.+optionExtensions :: Parser String -- ^ parser+optionExtensions = strOption+   $ short   'e'+  <> long    "extensions"+  <> value   "hs"+  <> metavar "EXTS"+  <> help    "Comma-separated list of relevant file extensions"+  <> showDefault++-- | Project name option.+optionProjectName :: Parser String -- ^ parser+optionProjectName = strOption+   $ short   'n'+  <> long    "name"+  <> metavar "NAME"+  <> help    "Name of the codebase. Appears in footers and as a title"++-- | Output file location option.+optionOutputFile :: Parser String -- ^ parser+optionOutputFile = strOption+   $ short   'o'+  <> long    "output"+  <> metavar "PATH"+  <> help    "Location of the resulting document"++-- | Output format option.+optionOutputFormat :: Parser Format -- ^ parser+optionOutputFormat = option (eitherReader formatReader)+   $ short   'f'+  <> long    "format"+  <> value   FmtLatex+  <> metavar "FORMAT"+  <> help    "Format of the resulting document, supported: latex, markdown"+  <> showDefault++-- | Root source directory option.+optionRootDir :: Parser String -- ^ parser+optionRootDir = strOption+   $ short   'd'+  <> long    "root-dir"+  <> value   "."+  <> metavar "PATH"+  <> help    "Root source directory path"+  <> showDefault++-- | Command-line user interface.+optionsParser :: Parser Options -- ^ parser+optionsParser = Options+  <$> optionExtensions+  <*> optionProjectName+  <*> optionOutputFormat+  <*> optionOutputFile+  <*> optionRootDir++-- | Description of the utility.+optionsDescription :: InfoMod Options -- ^ parser description+optionsDescription =+     header "wembley - pretty-print a whole codebase into a document"+  <> fullDesc++-- | Parser of the command-line options.+parser :: ParserInfo Options -- ^ parser+parser = info (helper <*> optionsParser) optionsDescription+
+ wembley.cabal view
@@ -0,0 +1,33 @@+name:                wembley+version:             0.1.0.0+synopsis:            Pretty-printing of codebases+description:         Pretty-printing of codebases for the purposes of code+                     review on paper or publication of a whole codebase+                     in a document form.+homepage:            https://github.com/lovasko/wembley+license:             BSD3+license-file:        LICENSE+author:              Daniel Lovasko <daniel.lovasko@gmail.com>+maintainer:          Daniel Lovasko <daniel.lovasko@gmail.com>+copyright:           2016 Daniel Lovasko+category:            Pretty-printing+build-type:          Simple+cabal-version:       >=1.10++executable wembley+  hs-source-dirs:      src+  main-is:             Main.hs+  other-modules:       Latex+                     , Markdown+                     , Options+  build-depends:       base >= 4.7 && < 5+                     , bytestring+                     , filepath+                     , filemanip+                     , optparse-applicative+                     , split+  default-language:    Haskell2010++source-repository head+  type:     git+  location: https://github.com/lovasko/wembley