    --------------------------------------------------------------------------------
    -- | Exports a datastructure for the top-level hakyll configuration
    module Hakyll.Core.Configuration
        ( Configuration (..)
        , shouldIgnoreFile
        , defaultConfiguration
        ) where

    --------------------------------------------------------------------------------
    import           Data.Default     (Default (..))
    import           Data.List        (isPrefixOf, isSuffixOf)
    import           System.Directory (canonicalizePath)
    import           System.Exit      (ExitCode)
    import           System.FilePath  (isAbsolute, normalise, takeFileName)
    import           System.IO.Error  (catchIOError)
    import           System.Process   (system)

    --------------------------------------------------------------------------------
    data Configuration = Configuration
        { -- | Directory in which the output written
          Configuration -> FilePath
    destinationDirectory :: FilePath
        , -- | Directory where hakyll's internal store is kept
          Configuration -> FilePath
    storeDirectory       :: FilePath
        , -- | Directory in which some temporary files will be kept
          Configuration -> FilePath
    tmpDirectory         :: FilePath
        , -- | Directory where hakyll finds the files to compile. This is @.@ by
          -- default.
          Configuration -> FilePath
    providerDirectory    :: FilePath
        , -- | Function to determine ignored files
          --
          -- In 'defaultConfiguration', the following files are ignored:
          --
          -- * files starting with a @.@
          --
          -- * files starting with a @#@
          --
          -- * files ending with a @~@
          --
          -- * files ending with @.swp@
          --
          -- Note that the files in 'destinationDirectory' and 'storeDirectory' will
          -- also be ignored. Note that this is the configuration parameter, if you
          -- want to use the test, you should use 'shouldIgnoreFile'.
          --
          Configuration -> FilePath -> Bool
    ignoreFile           :: FilePath -> Bool
        , -- | Here, you can plug in a system command to upload/deploy your site.
          --
          -- Example:
          --
          -- > rsync -ave 'ssh -p 2217' _site jaspervdj@jaspervdj.be:hakyll
          --
          -- You can execute this by using
          --
          -- > ./site deploy
          --
          Configuration -> FilePath
    deployCommand        :: String
        , -- | Function to deploy the site from Haskell.
          --
          -- By default, this command executes the shell command stored in
          -- 'deployCommand'. If you override it, 'deployCommand' will not
          -- be used implicitely.
          --
          -- The 'Configuration' object is passed as a parameter to this
          -- function.
          --
          Configuration -> Configuration -> IO ExitCode
    deploySite           :: Configuration -> IO ExitCode
        , -- | Use an in-memory cache for items. This is faster but uses more
          -- memory.
          Configuration -> Bool
    inMemoryCache        :: Bool
        , -- | Override default host for preview server. Default is "127.0.0.1",
          -- which binds only on the loopback address.
          -- One can also override the host as a command line argument:
          -- ./site preview -h "0.0.0.0"
          Configuration -> FilePath
    previewHost          :: String
        , -- | Override default port for preview server. Default is 8000.
          -- One can also override the port as a command line argument:
          -- ./site preview -p 1234
          Configuration -> Int
    previewPort          :: Int
        }

    --------------------------------------------------------------------------------
    instance Default Configuration where
        def :: Configuration
    def = Configuration
    defaultConfiguration

    --------------------------------------------------------------------------------
    -- | Default configuration for a hakyll application
    defaultConfiguration :: Configuration
    defaultConfiguration :: Configuration
    defaultConfiguration = Configuration :: FilePath
    -> FilePath
    -> FilePath
    -> FilePath
    -> (FilePath -> Bool)
    -> FilePath
    -> (Configuration -> IO ExitCode)
    -> Bool
    -> FilePath
    -> Int
    -> Configuration
    Configuration
        { destinationDirectory :: FilePath
    destinationDirectory = "_site"
        , storeDirectory :: FilePath
    storeDirectory       = "_cache"
        , tmpDirectory :: FilePath
    tmpDirectory         = "_cache/tmp"
        , providerDirectory :: FilePath
    providerDirectory    = "."
        , ignoreFile :: FilePath -> Bool
    ignoreFile           = FilePath -> Bool
    ignoreFile'
        , deployCommand :: FilePath
    deployCommand        = "echo 'No deploy command specified' && exit 1"
        , deploySite :: Configuration -> IO ExitCode
    deploySite           = FilePath -> IO ExitCode
    system (FilePath -> IO ExitCode)
    -> (Configuration -> FilePath) -> Configuration -> IO ExitCode
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Configuration -> FilePath
    deployCommand
        , inMemoryCache :: Bool
    inMemoryCache        = Bool
    True
        , previewHost :: FilePath
    previewHost          = "127.0.0.1"
        , previewPort :: Int
    previewPort          = 8000
        }
      where
        ignoreFile' :: FilePath -> Bool
    ignoreFile' path :: FilePath
    path
            | "."    FilePath -> FilePath -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    `isPrefixOf` FilePath
    fileName = Bool
    True
            | "#"    FilePath -> FilePath -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    `isPrefixOf` FilePath
    fileName = Bool
    True
            | "~"    FilePath -> FilePath -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    `isSuffixOf` FilePath
    fileName = Bool
    True
            | ".swp" FilePath -> FilePath -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    `isSuffixOf` FilePath
    fileName = Bool
    True
            | Bool
    otherwise                    = Bool
    False
          where
            fileName :: FilePath
    fileName = FilePath -> FilePath
    takeFileName FilePath
    path

    --------------------------------------------------------------------------------
    -- | Check if a file should be ignored
    shouldIgnoreFile :: Configuration -> FilePath -> IO Bool
    shouldIgnoreFile :: Configuration -> FilePath -> IO Bool
    shouldIgnoreFile conf :: Configuration
    conf path :: FilePath
    path = [IO Bool] -> IO Bool
    orM
        [ FilePath -> IO Bool
    inDir (Configuration -> FilePath
    destinationDirectory Configuration
    conf)
        , FilePath -> IO Bool
    inDir (Configuration -> FilePath
    storeDirectory Configuration
    conf)
        , FilePath -> IO Bool
    inDir (Configuration -> FilePath
    tmpDirectory Configuration
    conf)
        , Bool -> IO Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Configuration -> FilePath -> Bool
    ignoreFile Configuration
    conf FilePath
    path')
        ]
      where
        path' :: FilePath
    path'    = FilePath -> FilePath
    normalise FilePath
    path
        absolute :: Bool
    absolute = FilePath -> Bool
    isAbsolute FilePath
    path

        inDir :: FilePath -> IO Bool
    inDir dir :: FilePath
    dir
            | Bool
    absolute  = do
                FilePath
    dir' <- IO FilePath -> (IOError -> IO FilePath) -> IO FilePath
    forall a. IO a -> (IOError -> IO a) -> IO a
    catchIOError (FilePath -> IO FilePath
    canonicalizePath FilePath
    dir) (IO FilePath -> IOError -> IO FilePath
    forall a b. a -> b -> a
    const (IO FilePath -> IOError -> IO FilePath)
    -> IO FilePath -> IOError -> IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath -> IO FilePath
    forall (m :: * -> *) a. Monad m => a -> m a
    return FilePath
    dir)
                Bool -> IO Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Bool -> IO Bool) -> Bool -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ FilePath
    dir' FilePath -> FilePath -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    `isPrefixOf` FilePath
    path'
            | Bool
    otherwise = Bool -> IO Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Bool -> IO Bool) -> Bool -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ FilePath
    dir FilePath -> FilePath -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    `isPrefixOf` FilePath
    path'

        orM :: [IO Bool] -> IO Bool
        orM :: [IO Bool] -> IO Bool
    orM []       = Bool -> IO Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    False
        orM (x :: IO Bool
    x : xs :: [IO Bool]
    xs) = IO Bool
    x IO Bool -> (Bool -> IO Bool) -> IO Bool
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \b :: Bool
    b -> if Bool
    b then Bool -> IO Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    True else [IO Bool] -> IO Bool
    orM [IO Bool]
    xs