wembley-0.1.0.0: src/Main.hs
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)