on master help sign in
cmdargs isn't pretty but it's the best we have...
ed03544Jasper Van der Jeugt
hakyll.cabal+3
@@ -102,6 +102,7 @@ Library
102 mtl >= 1 && < 2.2,
102 mtl >= 1 && < 2.2,
103 old-locale >= 1.0 && < 1.1,
103 old-locale >= 1.0 && < 1.1,
104 old-time >= 1.0 && < 1.2,
104 old-time >= 1.0 && < 1.2,
105+ cmdargs >= 0.10 && < 0.11,
105 pandoc >= 1.9.3 && < 1.10,
106 pandoc >= 1.9.3 && < 1.10,
106 parsec >= 3.0 && < 3.2,
107 parsec >= 3.0 && < 3.2,
107 process >= 1.0 && < 1.2,
108 process >= 1.0 && < 1.2,
@@ -141,6 +142,7 @@ Library
141
142
142 Other-Modules:
143 Other-Modules:
143 Hakyll.Check
144 Hakyll.Check
145+ Hakyll.Commands
144 Hakyll.Core.Compiler.Internal
146 Hakyll.Core.Compiler.Internal
145 Hakyll.Core.Compiler.Require
147 Hakyll.Core.Compiler.Require
146 Hakyll.Core.Item.SomeItem
148 Hakyll.Core.Item.SomeItem
@@ -205,6 +207,7 @@ Test-suite hakyll-tests
205 mtl >= 1 && < 2.2,
207 mtl >= 1 && < 2.2,
206 old-locale >= 1.0 && < 1.1,
208 old-locale >= 1.0 && < 1.1,
207 old-time >= 1.0 && < 1.2,
209 old-time >= 1.0 && < 1.2,
210+ cmdargs >= 0.10 && < 0.11,
208 pandoc >= 1.9.3 && < 1.10,
211 pandoc >= 1.9.3 && < 1.10,
209 parsec >= 3.0 && < 3.2,
212 parsec >= 3.0 && < 3.2,
210 process >= 1.0 && < 1.2,
213 process >= 1.0 && < 1.2,
src/Hakyll/Commands.hsnew file+128
@@ -0,0 +1,128 @@
1+--------------------------------------------------------------------------------
2+-- | Implementation of Hakyll commands: build, preview...
3+{-# LANGUAGE CPP #-}
4+module Hakyll.Commands
5+ ( build
6+ , check
7+ , clean
8+ , preview
9+ , rebuild
10+ , server
11+ , deploy
12+ ) where
13+
14+
15+--------------------------------------------------------------------------------
16+import Control.Monad (when)
17+import System.Directory (doesDirectoryExist,
18+ removeDirectoryRecursive)
19+import System.Exit (exitWith)
20+import System.Process (system)
21+
22+
23+--------------------------------------------------------------------------------
24+import qualified Hakyll.Check as Check
25+import Hakyll.Core.Configuration
26+import Hakyll.Core.Rules
27+import Hakyll.Core.Runtime
28+
29+
30+--------------------------------------------------------------------------------
31+#ifdef PREVIEW_SERVER
32+import Control.Applicative ((<$>))
33+import Control.Concurrent (forkIO)
34+import qualified Data.Set as S
35+import Hakyll.Core.Identifier
36+import Hakyll.Core.Rules.Internal
37+import Hakyll.Preview.Poll
38+import Hakyll.Preview.Server
39+#endif
40+
41+
42+--------------------------------------------------------------------------------
43+-- | Build the site
44+build :: Configuration -> Rules a -> IO ()
45+build conf rules = do
46+ _ <- run conf rules
47+ return ()
48+
49+
50+--------------------------------------------------------------------------------
51+-- | Run the checker and exit
52+check :: Configuration -> IO ()
53+check config = Check.check config >>= exitWith
54+
55+
56+--------------------------------------------------------------------------------
57+-- | Remove the output directories
58+clean :: Configuration -> IO ()
59+clean conf = do
60+ remove $ destinationDirectory conf
61+ remove $ storeDirectory conf
62+ where
63+ remove dir = do
64+ putStrLn $ "Removing " ++ dir ++ "..."
65+ exists <- doesDirectoryExist dir
66+ when exists $ removeDirectoryRecursive dir
67+
68+
69+--------------------------------------------------------------------------------
70+-- | Preview the site
71+preview :: Configuration -> Rules a -> Int -> IO ()
72+#ifdef PREVIEW_SERVER
73+preview conf rules port = do
74+ -- Fork a thread polling for changes
75+ _ <- forkIO $ previewPoll conf update
76+
77+ -- Run the server in the main thread
78+ server conf port
79+ where
80+ update = map toFilePath . S.toList . rulesResources <$> run conf rules
81+#else
82+preview _ _ _ = previewServerDisabled
83+#endif
84+
85+
86+--------------------------------------------------------------------------------
87+-- | Rebuild the site
88+rebuild :: Configuration -> Rules a -> IO ()
89+rebuild conf rules = do
90+ clean conf
91+ build conf rules
92+
93+
94+--------------------------------------------------------------------------------
95+-- | Start a server
96+server :: Configuration -> Int -> IO ()
97+#ifdef PREVIEW_SERVER
98+server conf port = do
99+ let destination = destinationDirectory conf
100+ staticServer destination preServeHook port
101+ where
102+ preServeHook _ = return ()
103+#else
104+server _ _ = previewServerDisabled
105+#endif
106+
107+
108+--------------------------------------------------------------------------------
109+-- | Upload the site
110+deploy :: Configuration -> IO ()
111+deploy conf = do
112+ _ <- system $ deployCommand conf
113+ return ()
114+
115+
116+--------------------------------------------------------------------------------
117+-- | Print a warning message about the preview serving not being enabled
118+#ifndef PREVIEW_SERVER
119+previewServerDisabled :: IO ()
120+previewServerDisabled =
121+ mapM_ putStrLn
122+ [ "PREVIEW SERVER"
123+ , ""
124+ , "The preview server is not enabled in the version of Hakyll. To"
125+ , "enable it, set the flag to True and recompile Hakyll."
126+ , "Alternatively, use an external tool to serve your site directory."
127+ ]
128+#endif
src/Hakyll/Core/Configuration.hs+1−1
@@ -57,7 +57,7 @@ data Configuration = Configuration
57 , -- | Use an in-memory cache for items. This is faster but uses more
57 , -- | Use an in-memory cache for items. This is faster but uses more
58 -- memory.
58 -- memory.
59 inMemoryCache :: Bool
59 inMemoryCache :: Bool
60− -- | Verbosity for the logger
60+ -- | Verbosity for the logger. Can be overwritten by the command-line.
61 , verbosity :: Verbosity
61 , verbosity :: Verbosity
62 }
62 }
63
63
src/Hakyll/Main.hs+61−133
@@ -1,6 +1,7 @@
1--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
2-- | Module providing the main hakyll function and command-line argument parsing
2-- | Module providing the main hakyll function and command-line argument parsing
3−{-# LANGUAGE CPP #-}
3+{-# LANGUAGE CPP #-}
4+{-# LANGUAGE DeriveDataTypeable #-}
4module Hakyll.Main
5module Hakyll.Main
5 ( hakyll
6 ( hakyll
6 , hakyllWith
7 , hakyllWith
@@ -8,171 +9,98 @@ module Hakyll.Main
8
9
9
10
10--------------------------------------------------------------------------------
11--------------------------------------------------------------------------------
11−import Control.Monad (when)
12+import System.Console.CmdArgs
12−import System.Directory (doesDirectoryExist,
13+import qualified System.Console.CmdArgs.Explicit as CA
13− removeDirectoryRecursive)
14+import System.Environment (getProgName)
14−import System.Environment (getArgs, getProgName)
15−import System.Exit (exitWith)
15+import System.IO.Unsafe (unsafePerformIO)
16−import System.Process (system)
17
16
18
17
19--------------------------------------------------------------------------------
18--------------------------------------------------------------------------------
20−import qualified Hakyll.Check as Check
19+import qualified Hakyll.Commands as Commands
21−import Hakyll.Core.Configuration
20+import qualified Hakyll.Core.Configuration as Config
21+import qualified Hakyll.Core.Logger as Logger
22import Hakyll.Core.Rules
22import Hakyll.Core.Rules
23−import Hakyll.Core.Runtime
24−
25−
26−--------------------------------------------------------------------------------
27−#ifdef PREVIEW_SERVER
28−import Control.Applicative ((<$>))
29−import Control.Concurrent (forkIO)
30−import qualified Data.Set as S
31−import Hakyll.Core.Identifier
32−import Hakyll.Core.Rules.Internal
33−import Hakyll.Preview.Poll
34−import Hakyll.Preview.Server
35−#endif
36
23
37
24
38--------------------------------------------------------------------------------
25--------------------------------------------------------------------------------
39-- | This usualy is the function with which the user runs the hakyll compiler
26-- | This usualy is the function with which the user runs the hakyll compiler
40hakyll :: Rules a -> IO ()
27hakyll :: Rules a -> IO ()
41−hakyll = hakyllWith defaultConfiguration
28+hakyll = hakyllWith Config.defaultConfiguration
42
29
43
30
44--------------------------------------------------------------------------------
31--------------------------------------------------------------------------------
45-- | A variant of 'hakyll' which allows the user to specify a custom
32-- | A variant of 'hakyll' which allows the user to specify a custom
46-- configuration
33-- configuration
47−hakyllWith :: Configuration -> Rules a -> IO ()
34+hakyllWith :: Config.Configuration -> Rules a -> IO ()
48hakyllWith conf rules = do
35hakyllWith conf rules = do
49− args <- getArgs
36+ args' <- cmdArgs hakyllArgs
50− case args of
51− ["build"] -> build conf rules
52− ["check"] -> check conf
53− ["clean"] -> clean conf
54− ["help"] -> help
55− ["preview"] -> preview conf rules 8000
56− ["preview", p] -> preview conf rules (read p)
57− ["rebuild"] -> rebuild conf rules
58− ["server"] -> server conf 8000
59− ["server", p] -> server conf (read p)
60− ["deploy"] -> deploy conf
61− _ -> help
62−
63−
64−--------------------------------------------------------------------------------
65−-- | Build the site
66−build :: Configuration -> Rules a -> IO ()
67−build conf rules = do
68− _ <- run conf rules
69− return ()
70−
71
37
72−--------------------------------------------------------------------------------
38+ -- Overwrite conf based on args
73−-- | Run the checker and exit
39+ let conf' = conf
74−check :: Configuration -> IO ()
40+ { Config.verbosity =
75−check config = Check.check config >>= exitWith
41+ if verbose args' then Logger.Debug else Config.verbosity conf
42+ }
76
43
77−
44+ case args' of
78−--------------------------------------------------------------------------------
45+ Build _ -> Commands.build conf' rules
79−-- | Remove the output directories
46+ Check _ -> Commands.check conf'
80−clean :: Configuration -> IO ()
47+ Clean _ -> Commands.clean conf'
81−clean conf = do
48+ Deploy _ -> Commands.deploy conf'
82− remove $ destinationDirectory conf
49+ Help _ -> showHelp
83− remove $ storeDirectory conf
50+ Preview _ p -> Commands.preview conf' rules p
84− where
51+ Rebuild _ -> Commands.rebuild conf' rules
85− remove dir = do
52+ Server _ _ -> Commands.server conf' (port args')
86− putStrLn $ "Removing " ++ dir ++ "..."
87− exists <- doesDirectoryExist dir
88− when exists $ removeDirectoryRecursive dir
89
53
90
54
91--------------------------------------------------------------------------------
55--------------------------------------------------------------------------------
92-- | Show usage information.
56-- | Show usage information.
93−help :: IO ()
57+showHelp :: IO ()
94−help = do
58+showHelp = print $ CA.helpText [] CA.HelpFormatOne $ cmdArgsMode hakyllArgs
95− name <- getProgName
96− mapM_ putStrLn
97− [ "ABOUT"
98− , ""
99− , "This is a Hakyll site generator program. You should always"
100− , "run it from the project root directory."
101− , ""
102− , "USAGE"
103− , ""
104− , name ++ " build Generate the site"
105− , name ++ " clean Clean up and remove cache"
106− , name ++ " help Show this message"
107− , name ++ " preview [port] Run a server and autocompile"
108− , name ++ " rebuild Clean up and build again"
109− , name ++ " server [port] Run a local test server"
110− , name ++ " deploy Upload/deploy your site"
111− , ""
112− ]
113−
114−#ifndef PREVIEW_SERVER
115− previewServerDisabled
116−#endif
117
59
118
60
119--------------------------------------------------------------------------------
61--------------------------------------------------------------------------------
120−-- | Preview the site
62+data HakyllArgs
121−preview :: Configuration -> Rules a -> Int -> IO ()
63+ = Build {verbose :: Bool}
122−#ifdef PREVIEW_SERVER
64+ | Check {verbose :: Bool}
123−preview conf rules port = do
65+ | Clean {verbose :: Bool}
124− -- Fork a thread polling for changes
66+ | Deploy {verbose :: Bool}
125− _ <- forkIO $ previewPoll conf update
67+ | Help {verbose :: Bool}
126−
68+ | Preview {verbose :: Bool, port :: Int}
127− -- Run the server in the main thread
69+ | Rebuild {verbose :: Bool}
128− server conf port
70+ | Server {verbose :: Bool, port :: Int}
129− where
71+ deriving (Data, Typeable, Show)
130− update = map toFilePath . S.toList . rulesResources <$> run conf rules
131−#else
132−preview _ _ _ = previewServerDisabled
133−#endif
134
72
135
73
136--------------------------------------------------------------------------------
74--------------------------------------------------------------------------------
137−-- | Rebuild the site
75+hakyllArgs :: HakyllArgs
138−rebuild :: Configuration -> Rules a -> IO ()
76+hakyllArgs = modes
139−rebuild conf rules = do
77+ [ (Build $ verboseFlag def) &= help "Generate the site"
140− clean conf
78+ , (Check $ verboseFlag def) &= help "Validate the site output"
141− build conf rules
79+ , (Clean $ verboseFlag def) &= help "Clean up and remove cache"
80+ , (Deploy $ verboseFlag def) &= help "Upload/deploy your site"
81+ , (Help $ verboseFlag def) &= help "Show this message" &= auto
82+ , (Preview (verboseFlag def) (portFlag 8000)) &=
83+ help "Start a preview server and autocompile on changes"
84+ , (Rebuild $ verboseFlag def) &= help "Clean and build again"
85+ , (Server (verboseFlag def) (portFlag 8000)) &=
86+ help "Start a preview server"
87+ ] &= help "Hakyll static site compiler" &= program progName
142
88
143
89
144--------------------------------------------------------------------------------
90--------------------------------------------------------------------------------
145−-- | Start a server
91+verboseFlag :: Data a => a -> a
146−server :: Configuration -> Int -> IO ()
92+verboseFlag x = x &= help "Run in verbose mode"
147−#ifdef PREVIEW_SERVER
93+{-# INLINE verboseFlag #-}
148−server conf port = do
149− let destination = destinationDirectory conf
150− staticServer destination preServeHook port
151− where
152− preServeHook _ = return ()
153−#else
154−server _ _ = previewServerDisabled
155−#endif
156
94
157
95
158--------------------------------------------------------------------------------
96--------------------------------------------------------------------------------
159−-- | Upload the site
97+portFlag :: Data a => a -> a
160−deploy :: Configuration -> IO ()
98+portFlag x = x &= help "Port to listen on"
161−deploy conf = do
99+{-# INLINE portFlag #-}
162− _ <- system $ deployCommand conf
163− return ()
164
100
165
101
166--------------------------------------------------------------------------------
102--------------------------------------------------------------------------------
167−-- | Print a warning message about the preview serving not being enabled
103+-- | This is necessary because not everyone calls their program the same...
168−#ifndef PREVIEW_SERVER
104+progName :: String
169−previewServerDisabled :: IO ()
105+progName = unsafePerformIO getProgName
170−previewServerDisabled =
106+{-# NOINLINE progName #-}
171− mapM_ putStrLn
172− [ "PREVIEW SERVER"
173− , ""
174− , "The preview server is not enabled in the version of Hakyll. To"
175− , "enable it, set the flag to True and recompile Hakyll."
176− , "Alternatively, use an external tool to serve your site directory."
177− ]
178−#endif