hledger/Shake.hs

254 lines
8.6 KiB
Haskell
Raw Normal View History

#!/usr/bin/env stack
{- stack runghc --verbosity info
--package base-prelude
--package directory
--package extra
--package here
--package safe
--package shake
--package time
--package pandoc
-}
{-
Usage: see below.
Shake.hs is a more powerful Makefile, providing a number of commands
for performing useful tasks. Compiling this script is suggested, so that
it runs quicker and will not be affected eg when exploring old code versions.
More about Shake: http://shakebuild.com/manual
Requires: https://www.haskell.org/downloads#stack
Shake notes:
wishlist:
just one shake import
wildcards in phony rules
multiple individually accessible wildcards
not having to write :: Action ExitCode after a non-final cmd
-}
{-# LANGUAGE PackageImports, QuasiQuotes #-}
import Prelude ()
import "base-prelude" BasePrelude
-- import "base" System.Console.GetOpt
import "extra" Data.List.Extra
import "here" Data.String.Here
import "safe" Safe
import "shake" Development.Shake
import "shake" Development.Shake.FilePath
import "time" Data.Time
import "directory" System.Directory as S (getDirectoryContents)
usage = [i|Usage:
./Shake.hs compile # compile this script (optional)
./Shake --help # show options, eg --color
./Shake # show commands
./Shake all # generate everything
./Shake docs # generate general docs
./Shake site # generate the web site
./Shake manpages # generate nroff files for man
./Shake txtmanpages # generate text man pages for embedding
./Shake webmanpages # generate web man pages for hakyll
./Shake webmanual # generate combined web man page for hakyll
|]
pandoc =
-- "stack exec -- pandoc" -- use the pandoc required above
"pandoc" -- use pandoc in PATH (faster)
hakyllstd = "site/hakyll-std/hakyll-std"
nroff = "nroff"
main = do
pandocFilters <-
2016-04-06 01:46:44 +03:00
map ("doc" </>). nub . sort . map (-<.> "") . filter ("pandoc-" `isPrefixOf`)
<$> S.getDirectoryContents "doc"
shakeArgs
shakeOptions{
2016-04-13 06:32:01 +03:00
shakeVerbosity=Loud
-- ,shakeReport=[".shake.html"]
} $ do
want ["help"]
phony "help" $ liftIO $ putStrLn usage
phony "compile" $ need ["Shake"]
"Shake" %> \out -> do
need [out <.> "hs"]
cmd "stack ghc Shake.hs" :: Action ExitCode
putLoud "Compiled ./Shake, you can now use this instead of ./Shake.hs"
phony "all" $ need ["docs", "site"]
-- docs
let
manpageNames = [ -- in suggested reading order
"hledger.1"
,"hledger-ui.1"
,"hledger-web.1"
,"hledger-api.1"
,"hledger_journal.5"
,"hledger_csv.5"
2016-04-13 07:10:02 +03:00
,"hledger_timeclock.5"
,"hledger_timedot.5"
]
-- manuals m4 source, may include other files (hledger/doc/hledger.1.m4.md)
m4manpages = [manpageDir m </> m <.> "m4.md" | m <- manpageNames]
-- manuals rendered to markdown, ready for adjusting to web or man pages by pandoc (hledger/doc/hledger.1.md)
mdmanpages = [manpageDir m </> m <.> "md" | m <- manpageNames]
-- manuals rendered to nroff, ready for man (hledger/doc/hledger.1)
nroffmanpages = [manpageDir m </> m | m <- manpageNames]
-- manuals rendered to text, ready for embedding (hledger/doc/hledger.1.txt)
txtmanpages = [manpageDir m </> m <.> "txt" | m <- manpageNames]
-- manuals rendered to markdown, ready for web output by hakyll (site/hledger.md)
webmanpages = ["site" </> manpageNameToUri m <.>"md" | m <- manpageNames]
-- manuals rendered to markdown and combined, ready for web output by hakyll
webmanual = "site/manual.md"
-- hledger.1 -> hledger/doc, hledger_journal.5 -> hledger-lib/doc
manpageDir m
| '_' `elem` m = "hledger-lib" </> "doc"
| otherwise = dropExtension m </> "doc"
-- hledger.1 -> hledger, hledger_journal.5 -> journal
manpageNameToUri m | "hledger_" `isPrefixOf` m = dropExtension $ drop 8 m
| otherwise = dropExtension m
-- hledger -> hledger.1, journal -> hledger_journal.5
manpageUriToName u | "hledger" `isPrefixOf` u = u <.> "1"
| otherwise = "hledger_" ++ u <.> "5"
phony "docs" $ do
need $
nroffmanpages
++ txtmanpages
-- compile pandoc helpers
phony "pandocfilters" $ need pandocFilters
pandocFilters |%> \out -> do
need [out <.> "hs"]
cmd ("stack ghc") out
-- man pages
-- process m4 includes and macros to get markdown, ready for further processing by pandoc
mdmanpages |%> \out -> do -- hledger/doc/hledger.1.md
let dir = takeDirectory out
src = out -<.> "m4.md"
lib = "doc/lib.m4"
-- assume all other m4 files in dir are included by this one XXX not true in hledger-lib
deps <- liftIO $ filter (/= src) . filter (".m4.md" `isSuffixOf`) . map (dir </>)
<$> S.getDirectoryContents dir
need $ src : lib : deps
cmd Shell "m4 -P -DWEB -DMAN -I" dir lib src ">" out
-- adjust man page mds for man output and convert to nroff, with pandoc
phony "manpages" $ need nroffmanpages
nroffmanpages |%> \out -> do -- hledger/doc/hledger.1
let src = out <.> "md"
tmpl = "doc/manpage.nroff"
need $ src : tmpl : pandocFilters
cmd pandoc src "-s --template" tmpl
2016-04-06 18:20:27 +03:00
"--filter doc/pandoc-drop-web-blocks"
2016-04-06 01:46:44 +03:00
"--filter doc/pandoc-drop-html-blocks"
"--filter doc/pandoc-drop-html-inlines"
"--filter doc/pandoc-drop-links"
"--filter doc/pandoc-drop-notes"
"-o" out
-- render man page nroffs to fixed-width text for embedding in executables, with nroff
phony "txtmanpages" $ need txtmanpages
txtmanpages |%> \out -> do -- hledger/doc/hledger.1.txt
let src = dropExtension out
need [src]
cmd Shell nroff "-man" src ">" out
-- web site
phony "site" $ do
need $
webmanpages ++
[webmanual
,hakyllstd
]
cmd Shell (Cwd "site") "hakyll-std/hakyll-std" "build"
-- adjust man page mds for web output, with pandoc
phony "webmanpages" $ need webmanpages
webmanpages |%> \out -> do -- site/hledger.md
let m = manpageUriToName $ dropExtension $ takeFileName out -- hledger.1
src = manpageDir m </> m <.> "md" -- hledger/doc/hledger.1.md
2016-04-09 23:36:48 +03:00
heading = let h = dropExtension m
in if "hledger_" `isPrefixOf` h
then drop 8 h ++ " format"
else h
need $ src : pandocFilters
2016-04-09 23:36:48 +03:00
liftIO $ writeFile out $ "# " ++ heading ++ "\n\n"
cmd Shell pandoc src "-t markdown --atx-headers"
"--filter doc/pandoc-demote-headers"
-- "--filter doc/pandoc-add-toc"
-- "--filter doc/pandoc-drop-man-blocks"
2016-04-09 23:36:48 +03:00
">>" out
-- adjust and combine man page mds for single-page web output, using pandoc
phony "webmanual" $ need [ webmanual ]
webmanual %> \out -> do
need webmanpages
liftIO $ writeFile webmanual [i|
<style>
#toc > ol > li {
padding-top:1em;
font-weight:bold;
}
#toc > ol > li > ol {
font-weight:normal;
}
</style>
* toc
|]
forM_ webmanpages $ \f -> do -- site/hledger.md, site/journal.md
2016-04-09 23:36:48 +03:00
cmd Shell ("printf '\\n\\n' >>") webmanual :: Action ExitCode
cmd Shell "pandoc" f "-t markdown --atx-headers"
2016-04-09 23:36:48 +03:00
-- "--filter doc/pandoc-drop-man-blocks"
"--filter doc/pandoc-drop-toc"
-- "--filter doc/pandoc-capitalize-headers"
"--filter doc/pandoc-demote-headers"
">>" webmanual :: Action ExitCode
-- build standard hakyll script used for site rendering
hakyllstd %> \out -> do
let dir = takeDirectory out
need [out <.> "hs", dir </> "TableOfContents.hs"] -- XXX hard-coded dep
cmd (Cwd dir) "stack ghc hakyll-std"
2016-04-06 01:40:59 +03:00
-- cleanup
phony "clean" $ do
putNormal "Cleaning generated files"
removeFilesAfter "." ["hledger/doc/hledger.1.md"]
removeFilesAfter "." webmanpages
removeFilesAfter "." [webmanual]
phony "Clean" $ do
need ["clean"]
putNormal "Cleaning generated man page nroffs"
removeFilesAfter "." nroffmanpages
putNormal "Cleaning all hakyll generated files"
removeFilesAfter "site" ["_*"]
putNormal "Cleaning executables"
removeFilesAfter "." $ hakyllstd : pandocFilters
putNormal "Cleaning object files"
removeFilesAfter "doc" ["*.o","*.p_o","*.hi"] -- forces rebuild of exes ?
removeFilesAfter "site" ["*.o","*.p_o","*.hi"]
putNormal "Cleaning shake build files"
2016-04-13 06:32:01 +03:00
removeFilesAfter ".shake" ["//*"]