{-# LANGUAGE CPP #-}
module Hakyll.Main
(
hakyll
, hakyllWith
, hakyllWithArgs
, hakyllWithExitCode
, hakyllWithExitCodeAndArgs
, Options(..)
, Command(..)
, optionParser
, commandParser
, defaultParser
, defaultParserPure
, defaultParserPrefs
, defaultParserInfo
) where
import System.Environment (getProgName)
import System.Exit (ExitCode (ExitSuccess), exitWith)
import System.IO.Unsafe (unsafePerformIO)
import Data.Monoid ((<>))
import qualified Options.Applicative as OA
import qualified Hakyll.Check as Check
import qualified Hakyll.Commands as Commands
import qualified Hakyll.Core.Configuration as Config
import qualified Hakyll.Core.Logger as Logger
import Hakyll.Core.Rules
hakyll :: Rules a -> IO ()
hakyll = hakyllWith Config.defaultConfiguration
hakyllWith :: Config.Configuration -> Rules a -> IO ()
hakyllWith conf rules = hakyllWithExitCode conf rules >>= exitWith
hakyllWithExitCode :: Config.Configuration -> Rules a -> IO ExitCode
hakyllWithExitCode conf rules = do
args <- defaultParser conf
hakyllWithExitCodeAndArgs conf args rules
hakyllWithArgs :: Config.Configuration -> Options -> Rules a -> IO ()
hakyllWithArgs conf args rules =
hakyllWithExitCodeAndArgs conf args rules >>= exitWith
hakyllWithExitCodeAndArgs :: Config.Configuration ->
Options -> Rules a -> IO ExitCode
hakyllWithExitCodeAndArgs conf args rules = do
let args' = optCommand args
verbosity' = if verbosity args then Logger.Debug else Logger.Message
check =
if internal_links args' then Check.InternalLinks else Check.All
logger <- Logger.new verbosity'
invokeCommands args' conf check logger rules
defaultParser :: Config.Configuration -> IO Options
defaultParser conf =
OA.customExecParser defaultParserPrefs (defaultParserInfo conf)
defaultParserPure :: Config.Configuration -> [String] -> OA.ParserResult Options
defaultParserPure conf =
OA.execParserPure defaultParserPrefs (defaultParserInfo conf)
defaultParserPrefs :: OA.ParserPrefs
defaultParserPrefs = OA.prefs OA.showHelpOnError
defaultParserInfo :: Config.Configuration -> OA.ParserInfo Options
defaultParserInfo conf =
OA.info (OA.helper <*> optionParser conf) (OA.fullDesc <> OA.progDesc (
progName ++ " - Static site compiler created with Hakyll"))
invokeCommands :: Command -> Config.Configuration ->
Check.Check -> Logger.Logger -> Rules a -> IO ExitCode
invokeCommands args conf check logger rules =
case args of
Build -> Commands.build conf logger rules
Check _ -> Commands.check conf logger check
Clean -> Commands.clean conf logger >> ok
Deploy -> Commands.deploy conf
Preview p -> Commands.preview conf logger rules p >> ok
Rebuild -> Commands.rebuild conf logger rules
Server _ _ -> Commands.server conf logger (host args) (port args) >> ok
Watch _ p s -> Commands.watch conf logger (host args) p (not s) rules >> ok
where
ok = return ExitSuccess
data Options = Options {verbosity :: Bool, optCommand :: Command}
deriving (Show)
data Command
= Build
| Check {internal_links :: Bool}
| Clean
| Deploy
| Preview {port :: Int}
| Rebuild
| Server {host :: String, port :: Int}
| Watch {host :: String, port :: Int, no_server :: Bool }
deriving (Show)
{-# DEPRECATED Preview "Use Watch instead." #-}
optionParser :: Config.Configuration -> OA.Parser Options
optionParser conf = Options <$> verboseParser <*> commandParser conf
where
verboseParser = OA.switch (OA.long "verbose" <> OA.short 'v' <> OA.help "Run in verbose mode")
commandParser :: Config.Configuration -> OA.Parser Command
commandParser conf = OA.subparser $ foldr ((<>) . produceCommand) mempty commands
where
portParser = OA.option OA.auto (OA.long "port" <> OA.help "Port to listen on" <> OA.value (Config.previewPort conf))
hostParser = OA.strOption (OA.long "host" <> OA.help "Host to bind on" <> OA.value (Config.previewHost conf))
produceCommand (c,a,b) = OA.command c (OA.info (OA.helper <*> a) (b))
commands =
[ ( "build"
, pure Build
, OA.fullDesc <> OA.progDesc "Generate the site"
)
, ( "check"
, pure Check <*> OA.switch (OA.long "internal-links" <> OA.help "Check internal links only")
, OA.fullDesc <> OA.progDesc "Validate the site output"
)
, ( "clean"
, pure Clean
, OA.fullDesc <> OA.progDesc "Clean up and remove cache"
)
, ( "deploy"
, pure Deploy
, OA.fullDesc <> OA.progDesc "Upload/deploy your site"
)
, ( "preview"
, pure Preview <*> portParser
, OA.fullDesc <> OA.progDesc "[DEPRECATED] Please use the watch command"
)
, ( "rebuild"
, pure Rebuild
, OA.fullDesc <> OA.progDesc "Clean and build again"
)
, ( "server"
, pure Server <*> hostParser <*> portParser
, OA.fullDesc <> OA.progDesc "Start a preview server"
)
, ( "watch"
, pure Watch <*> hostParser <*> portParser <*> OA.switch (OA.long "no-server" <> OA.help "Disable the built-in web server")
, OA.fullDesc <> OA.progDesc "Autocompile on changes and start a preview server. You can watch and recompile without running a server with --no-server."
)
]
progName :: String
progName = unsafePerformIO getProgName
{-# NOINLINE progName #-}