1
1
mirror of https://github.com/srid/rib.git synced 2024-12-02 10:23:46 +03:00

Merge pull request #38 from wagdav/configurable-input-output

Configurable input output directories
This commit is contained in:
Sridhar Ratnakumar 2019-10-26 11:37:30 -04:00 committed by GitHub
commit bdc55d6d10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 35 deletions

View File

@ -60,4 +60,5 @@ library
wai-extra >=3.0.26 && <3.1, wai-extra >=3.0.26 && <3.1,
warp >=3.2.28 && <3.3, warp >=3.2.28 && <3.3,
base >=4.7 && <5, base >=4.7 && <5,
pandoc >=2.7 && <3 pandoc >=2.7 && <3,
directory >= 1.0 && <2.0

View File

@ -9,8 +9,6 @@ module Rib.App
( App(..) ( App(..)
, run , run
, runWith , runWith
, ribOutputDir
, ribInputDir
) where ) where
import Control.Concurrent (threadDelay) import Control.Concurrent (threadDelay)
@ -24,6 +22,7 @@ import System.Console.CmdArgs
import System.FSNotify (watchTree, withManager) import System.FSNotify (watchTree, withManager)
import qualified Rib.Server as Server import qualified Rib.Server as Server
import Rib.Shake (Dirs (..))
-- | Application modes -- | Application modes
-- --
@ -35,34 +34,31 @@ data App
} }
-- ^ Generate static files once. -- ^ Generate static files once.
| WatchAndGenerate | WatchAndGenerate
-- ^ Watch for changes in `ribInputDir` and run `Generate` -- ^ Watch for changes in the input directory and run `Generate`
| Serve | Serve
{ port :: Int { port :: Int
-- ^ Port to bind the server -- ^ Port to bind the server
, dontWatch :: Bool , dontWatch :: Bool
-- ^ Unless set run `WatchAndGenerate` automatically -- ^ Unless set run `WatchAndGenerate` automatically
} }
-- ^ Run a HTTP server serving `ribOutputDir` -- ^ Run a HTTP server serving content from the output directory
deriving (Data,Typeable,Show,Eq) deriving (Data,Typeable,Show,Eq)
-- | The path where static files will be generated.
--
-- Rib's server uses this directory when serving files.
ribOutputDir :: FilePath
ribOutputDir = "b"
-- | Directory from which source content will be read.
ribInputDir :: FilePath
ribInputDir = "a"
-- NOTE: ^ This should ideally *not* be `"."` as our use of watchTree (of
-- `runWith`) can interfere with Shake's file scaning.
-- | Run Rib using arguments passed in the command line. -- | Run Rib using arguments passed in the command line.
run run
:: Action () :: FilePath
-- ^ Directory from which source content will be read.
--
-- NOTE: This should ideally *not* be `"."` as our use of watchTree (of
-- `runWith`) can interfere with Shake's file scaning.
-> FilePath
-- ^ The path where static files will be generated. Rib's server uses this
-- directory when serving files.
-> Action ()
-- ^ Shake build rules for building the static site -- ^ Shake build rules for building the static site
-> IO () -> IO ()
run buildAction = runWith buildAction =<< cmdArgs ribCli run src dst buildAction = runWith src dst buildAction =<< cmdArgs ribCli
where where
ribCli = modes ribCli = modes
[ Serve [ Serve
@ -78,25 +74,26 @@ run buildAction = runWith buildAction =<< cmdArgs ribCli
] ]
-- | Like `run` but with an explicitly passed `App` mode -- | Like `run` but with an explicitly passed `App` mode
runWith :: Action () -> App -> IO () runWith :: FilePath -> FilePath -> Action () -> App -> IO ()
runWith buildAction = \case runWith src dst buildAction = \case
WatchAndGenerate -> withManager $ \mgr -> do WatchAndGenerate -> withManager $ \mgr -> do
-- Begin with a *full* generation as the HTML layout may have been changed. -- Begin with a *full* generation as the HTML layout may have been changed.
runWith buildAction $ Generate True runWith src dst buildAction $ Generate True
-- And then every time a file changes under the current directory -- And then every time a file changes under the current directory
putStrLn $ "[Rib] Watching " <> ribInputDir putStrLn $ "[Rib] Watching " <> src
void $ watchTree mgr ribInputDir (const True) $ const $ void $ watchTree mgr src (const True) $ const $
runWith buildAction $ Generate False runWith src dst buildAction $ Generate False
-- Wait forever, effectively. -- Wait forever, effectively.
forever $ threadDelay maxBound forever $ threadDelay maxBound
Serve p dw -> concurrently_ Serve p dw -> concurrently_
(unless dw $ runWith buildAction WatchAndGenerate) (unless dw $ runWith src dst buildAction WatchAndGenerate)
(Server.serve p ribOutputDir) (Server.serve p dst)
Generate forceGen -> Generate forceGen ->
let opts = shakeOptions let opts = shakeOptions
{ shakeVerbosity = Chatty { shakeVerbosity = Chatty
, shakeRebuild = bool [] [(RebuildNow, "**")] forceGen , shakeRebuild = bool [] [(RebuildNow, "**")] forceGen
, shakeExtra = addShakeExtra (Dirs (src, dst)) (shakeExtra shakeOptions)
} }
in shakeForward opts buildAction in shakeForward opts buildAction

View File

@ -6,8 +6,6 @@
-- | Combinators for working with Shake. -- | Combinators for working with Shake.
-- --
-- The functions in this module work with `ribInputDir` and `ribOutputDir`.
--
-- See the source of `Rib.Simple.buildAction` for example usage. -- See the source of `Rib.Simple.buildAction` for example usage.
module Rib.Shake module Rib.Shake
( (
@ -19,6 +17,7 @@ module Rib.Shake
, readPandocMulti , readPandocMulti
-- * Misc -- * Misc
, buildStaticFiles , buildStaticFiles
, Dirs(..)
) )
where where
@ -39,20 +38,35 @@ import Development.Shake.FilePath
import Development.Shake.Forward (cacheAction) import Development.Shake.Forward (cacheAction)
import Lucid (Html) import Lucid (Html)
import qualified Lucid import qualified Lucid
import System.Directory (createDirectoryIfMissing)
import Text.Pandoc (Pandoc (Pandoc), PandocIO, ReaderOptions) import Text.Pandoc (Pandoc (Pandoc), PandocIO, ReaderOptions)
import Rib.App (ribInputDir, ribOutputDir)
import qualified Rib.Pandoc import qualified Rib.Pandoc
-- FIXME: Auto create ./b directory newtype Dirs = Dirs (FilePath, FilePath)
getDirs :: Action (FilePath, FilePath)
getDirs = getShakeExtra >>= \case
Just (Dirs d) -> return d
Nothing -> fail "Input output directories are not initialized"
ribInputDir :: Action FilePath
ribInputDir = fst <$> getDirs
ribOutputDir :: Action FilePath
ribOutputDir = do
output <- snd <$> getDirs
liftIO $ createDirectoryIfMissing True output
return output
-- | Shake action to copy static files as is -- | Shake action to copy static files as is
buildStaticFiles :: [FilePattern] -> Action [FilePath] buildStaticFiles :: [FilePattern] -> Action [FilePath]
buildStaticFiles staticFilePatterns = do buildStaticFiles staticFilePatterns = do
files <- getDirectoryFiles ribInputDir staticFilePatterns input <- ribInputDir
output <- ribOutputDir
files <- getDirectoryFiles input staticFilePatterns
void $ forP files $ \f -> void $ forP files $ \f ->
copyFileChanged (ribInputDir </> f) (ribOutputDir </> f) copyFileChanged (input </> f) (output </> f)
pure files pure files
-- | Convert the given pattern of source files into their HTML. -- | Convert the given pattern of source files into their HTML.
@ -77,7 +91,8 @@ readPandocMulti
-- ^ Tuple of pattern of files to work on and document format. -- ^ Tuple of pattern of files to work on and document format.
-> Action [(FilePath, Pandoc)] -> Action [(FilePath, Pandoc)]
readPandocMulti (pat, r) = do readPandocMulti (pat, r) = do
fs <- getDirectoryFiles ribInputDir [pat] input <- ribInputDir
fs <- getDirectoryFiles input [pat]
forP fs $ \f -> forP fs $ \f ->
jsonCacheAction f $ (f, ) <$> readPandoc r f jsonCacheAction f $ (f, ) <$> readPandoc r f
@ -91,7 +106,8 @@ readPandoc
-> FilePath -> FilePath
-> Action Pandoc -> Action Pandoc
readPandoc r f = do readPandoc r f = do
let inp = ribInputDir </> f input <- ribInputDir
let inp = input </> f
need [inp] need [inp]
content <- T.decodeUtf8 <$> liftIO (BS.readFile inp) content <- T.decodeUtf8 <$> liftIO (BS.readFile inp)
doc <- liftIO $ Rib.Pandoc.parse r content doc <- liftIO $ Rib.Pandoc.parse r content
@ -113,7 +129,8 @@ readPandoc r f = do
-- | Build a single HTML file with the given value -- | Build a single HTML file with the given value
buildHtml :: FilePath -> Html () -> Action () buildHtml :: FilePath -> Html () -> Action ()
buildHtml f html = do buildHtml f html = do
let out = ribOutputDir </> f output <- ribOutputDir
let out = output </> f
writeHtml out html writeHtml out html
writeHtml :: MonadIO m => FilePath -> Html () -> m () writeHtml :: MonadIO m => FilePath -> Html () -> m ()