-
Notifications
You must be signed in to change notification settings - Fork 4
/
ShakeExampleMain.hs
executable file
·93 lines (71 loc) · 2.57 KB
/
ShakeExampleMain.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
{-# LANGUAGE QuasiQuotes #-}
module Main where
import MultilineRe (multilineRe)
import Development.Shake
import Development.Shake.FilePath
import Text.Regex.PCRE.Heavy (Regex, scan)
import Data.Maybe (listToMaybe)
import Text.Printf (printf)
import Control.Monad (zipWithM)
shakeDir :: FilePath
shakeDir = "_build"
-- | File, sorted by day, containing a line for each Markdown source of a post.
daysSources :: FilePath
daysSources = shakeDir </> "days-sources"
-- | File, sorted by day, containing a line for each generated Day of Hackage post.
daysUrls :: FilePath
daysUrls = shakeDir </> "days-urls"
tocFile :: FilePath
tocFile = shakeDir </> "TOC.md"
-- | Base directory of blog source.
blogDir :: FilePath
blogDir = "/Users/chen/Sync/ConscientiousProgrammer"
-- | Base directory of generated blog.
publicDir :: FilePath
publicDir = "/Users/chen/ConscientiousProgrammer-public"
-- | Generated HTML directory for each post.
urlsGlob :: FilePattern
urlsGlob = "blog/2015/1*/*/*hackage-2015-day-*"
-- | Location of Markdown blog posts.
postDir :: FilePath
postDir = blogDir </> "content/post"
-- | Rely on naming convention here.
postGlob :: FilePattern
postGlob = "*hackage-2015-day-*"
main :: IO ()
main = shakeArgs shakeOptions{shakeFiles=shakeDir} $ do
want [tocFile]
tocFile %> \out -> do
sourcePaths <- readFileLines daysSources
urls <- readFileLines daysUrls
toc <- zipWithM extractTOCEntry sourcePaths urls
writeFileChanged out $ unlines $ map formatTOCEntry toc
-- Run Hugo to generate a directory for each post.
daysUrls %> \out -> do
need [daysSources]
unit $ cmd (Cwd blogDir) "hugo"
Stdout stdout <- cmd Shell (Cwd publicDir) "echo" urlsGlob
writeFileChanged out $ unlines $ words stdout
daysSources %> \out -> do
daysFiles <- getDirectoryFiles postDir [postGlob]
writeFileChanged out $ unlines $ map (postDir </>) daysFiles
-- | A day's entry in the TOC.
data TOCEntry =
TOCEntry { _day :: Int
, _title :: String
, _url :: String
}
deriving (Eq, Ord)
dayTitleRegex :: Regex
dayTitleRegex = [multilineRe|^title:.*day\s+(\d+):\s*([^"]+)|]
extractTOCEntry :: FilePath -> String -> Action TOCEntry
extractTOCEntry sourcePath url = do
text <- readFile' sourcePath
case listToMaybe (scan dayTitleRegex text) of
Just (_, [dayString, title]) ->
return $ TOCEntry (read dayString) title url
_ ->
error $ printf "failed to extract day and title from %s" sourcePath
formatTOCEntry :: TOCEntry -> String
formatTOCEntry entry =
printf "- Day %d: [%s](/%s/)" (_day entry) (_title entry) (_url entry)