1
1
mirror of https://github.com/srid/rib.git synced 2024-11-30 03:45:00 +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,
warp >=3.2.28 && <3.3,
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(..)
, run
, runWith
, ribOutputDir
, ribInputDir
) where
import Control.Concurrent (threadDelay)
@ -24,6 +22,7 @@ import System.Console.CmdArgs
import System.FSNotify (watchTree, withManager)
import qualified Rib.Server as Server
import Rib.Shake (Dirs (..))
-- | Application modes
--
@ -35,34 +34,31 @@ data App
}
-- ^ Generate static files once.
| WatchAndGenerate
-- ^ Watch for changes in `ribInputDir` and run `Generate`
-- ^ Watch for changes in the input directory and run `Generate`
| Serve
{ port :: Int
-- ^ Port to bind the server
, dontWatch :: Bool
-- ^ 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)
-- | 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
:: 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
-> IO ()
run buildAction = runWith buildAction =<< cmdArgs ribCli
run src dst buildAction = runWith src dst buildAction =<< cmdArgs ribCli
where
ribCli = modes
[ Serve
@ -78,25 +74,26 @@ run buildAction = runWith buildAction =<< cmdArgs ribCli
]
-- | Like `run` but with an explicitly passed `App` mode
runWith :: Action () -> App -> IO ()
runWith buildAction = \case
runWith :: FilePath -> FilePath -> Action () -> App -> IO ()
runWith src dst buildAction = \case
WatchAndGenerate -> withManager $ \mgr -> do
-- 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
putStrLn $ "[Rib] Watching " <> ribInputDir
void $ watchTree mgr ribInputDir (const True) $ const $
runWith buildAction $ Generate False
putStrLn $ "[Rib] Watching " <> src
void $ watchTree mgr src (const True) $ const $
runWith src dst buildAction $ Generate False
-- Wait forever, effectively.
forever $ threadDelay maxBound
Serve p dw -> concurrently_
(unless dw $ runWith buildAction WatchAndGenerate)
(Server.serve p ribOutputDir)
(unless dw $ runWith src dst buildAction WatchAndGenerate)
(Server.serve p dst)
Generate forceGen ->
let opts = shakeOptions
{ shakeVerbosity = Chatty
, shakeRebuild = bool [] [(RebuildNow, "**")] forceGen
, shakeExtra = addShakeExtra (Dirs (src, dst)) (shakeExtra shakeOptions)
}
in shakeForward opts buildAction

View File

@ -6,8 +6,6 @@
-- | 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.
module Rib.Shake
(
@ -19,6 +17,7 @@ module Rib.Shake
, readPandocMulti
-- * Misc
, buildStaticFiles
, Dirs(..)
)
where
@ -39,20 +38,35 @@ import Development.Shake.FilePath
import Development.Shake.Forward (cacheAction)
import Lucid (Html)
import qualified Lucid
import System.Directory (createDirectoryIfMissing)
import Text.Pandoc (Pandoc (Pandoc), PandocIO, ReaderOptions)
import Rib.App (ribInputDir, ribOutputDir)
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
buildStaticFiles :: [FilePattern] -> Action [FilePath]
buildStaticFiles staticFilePatterns = do
files <- getDirectoryFiles ribInputDir staticFilePatterns
input <- ribInputDir
output <- ribOutputDir
files <- getDirectoryFiles input staticFilePatterns
void $ forP files $ \f ->
copyFileChanged (ribInputDir </> f) (ribOutputDir </> f)
copyFileChanged (input </> f) (output </> f)
pure files
-- | 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.
-> Action [(FilePath, Pandoc)]
readPandocMulti (pat, r) = do
fs <- getDirectoryFiles ribInputDir [pat]
input <- ribInputDir
fs <- getDirectoryFiles input [pat]
forP fs $ \f ->
jsonCacheAction f $ (f, ) <$> readPandoc r f
@ -91,7 +106,8 @@ readPandoc
-> FilePath
-> Action Pandoc
readPandoc r f = do
let inp = ribInputDir </> f
input <- ribInputDir
let inp = input </> f
need [inp]
content <- T.decodeUtf8 <$> liftIO (BS.readFile inp)
doc <- liftIO $ Rib.Pandoc.parse r content
@ -113,7 +129,8 @@ readPandoc r f = do
-- | Build a single HTML file with the given value
buildHtml :: FilePath -> Html () -> Action ()
buildHtml f html = do
let out = ribOutputDir </> f
output <- ribOutputDir
let out = output </> f
writeHtml out html
writeHtml :: MonadIO m => FilePath -> Html () -> m ()