module Hakyll.Process
(
newExtension
, newExtOutFilePath
, execName
, execCompiler
, execCompilerWith
, unsafeExecCompiler
, CompilerOut(..)
, ExecutableArg(..)
, ExecutableArgs
, ExecutableName
, OutFilePath(..)
) where
import qualified Data.ByteString.Lazy.Char8 as B
import GHC.Conc (atomically)
import Hakyll.Core.Item
import Hakyll.Core.Compiler
import System.Process.Typed
data CompilerOut =
CStdOut
| COutFile OutFilePath
data ExecutableArg =
HakFilePath
| ProcArg String deriving (ReadPrec [ExecutableArg]
ReadPrec ExecutableArg
Int -> ReadS ExecutableArg
ReadS [ExecutableArg]
(Int -> ReadS ExecutableArg)
-> ReadS [ExecutableArg]
-> ReadPrec ExecutableArg
-> ReadPrec [ExecutableArg]
-> Read ExecutableArg
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [ExecutableArg]
$creadListPrec :: ReadPrec [ExecutableArg]
readPrec :: ReadPrec ExecutableArg
$creadPrec :: ReadPrec ExecutableArg
readList :: ReadS [ExecutableArg]
$creadList :: ReadS [ExecutableArg]
readsPrec :: Int -> ReadS ExecutableArg
$creadsPrec :: Int -> ReadS ExecutableArg
Read, Int -> ExecutableArg -> ShowS
[ExecutableArg] -> ShowS
ExecutableArg -> String
(Int -> ExecutableArg -> ShowS)
-> (ExecutableArg -> String)
-> ([ExecutableArg] -> ShowS)
-> Show ExecutableArg
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExecutableArg] -> ShowS
$cshowList :: [ExecutableArg] -> ShowS
show :: ExecutableArg -> String
$cshow :: ExecutableArg -> String
showsPrec :: Int -> ExecutableArg -> ShowS
$cshowsPrec :: Int -> ExecutableArg -> ShowS
Show)
data OutFilePath =
SpecificPath FilePath
| RelativePath (FilePath -> FilePath)
newtype ExecutableName = ExecutableName String deriving (ReadPrec [ExecutableName]
ReadPrec ExecutableName
Int -> ReadS ExecutableName
ReadS [ExecutableName]
(Int -> ReadS ExecutableName)
-> ReadS [ExecutableName]
-> ReadPrec ExecutableName
-> ReadPrec [ExecutableName]
-> Read ExecutableName
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [ExecutableName]
$creadListPrec :: ReadPrec [ExecutableName]
readPrec :: ReadPrec ExecutableName
$creadPrec :: ReadPrec ExecutableName
readList :: ReadS [ExecutableName]
$creadList :: ReadS [ExecutableName]
readsPrec :: Int -> ReadS ExecutableName
$creadsPrec :: Int -> ReadS ExecutableName
Read, Int -> ExecutableName -> ShowS
[ExecutableName] -> ShowS
ExecutableName -> String
(Int -> ExecutableName -> ShowS)
-> (ExecutableName -> String)
-> ([ExecutableName] -> ShowS)
-> Show ExecutableName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExecutableName] -> ShowS
$cshowList :: [ExecutableName] -> ShowS
show :: ExecutableName -> String
$cshow :: ExecutableName -> String
showsPrec :: Int -> ExecutableName -> ShowS
$cshowsPrec :: Int -> ExecutableName -> ShowS
Show)
type ExecutableArgs = [ExecutableArg]
newExtension ::
String
-> FilePath
-> FilePath
newExtension :: String -> ShowS
newExtension String
ext String
f = (ShowS
forall a. [a] -> [a]
reverse ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.') ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
reverse ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ String
f) String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
ext
newExtOutFilePath :: String -> CompilerOut
newExtOutFilePath :: String -> CompilerOut
newExtOutFilePath String
ext = OutFilePath -> CompilerOut
COutFile (OutFilePath -> CompilerOut) -> OutFilePath -> CompilerOut
forall a b. (a -> b) -> a -> b
$ ShowS -> OutFilePath
RelativePath (String -> ShowS
newExtension String
ext)
execName :: String -> ExecutableName
execName :: String -> ExecutableName
execName = String -> ExecutableName
ExecutableName
execCompiler :: ExecutableName -> CompilerOut -> Compiler (Item B.ByteString)
execCompiler :: ExecutableName -> CompilerOut -> Compiler (Item ByteString)
execCompiler ExecutableName
name CompilerOut
out = ExecutableName
-> [ExecutableArg] -> CompilerOut -> Compiler (Item ByteString)
execCompilerWith ExecutableName
name [] CompilerOut
out
execCompilerWith :: ExecutableName -> ExecutableArgs -> CompilerOut -> Compiler (Item B.ByteString)
execCompilerWith :: ExecutableName
-> [ExecutableArg] -> CompilerOut -> Compiler (Item ByteString)
execCompilerWith ExecutableName
name [ExecutableArg]
exArgs CompilerOut
out = do
String
input <- Compiler String
getResourceFilePath
let args :: [String]
args = (ExecutableArg -> String) -> [ExecutableArg] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> ExecutableArg -> String
hargToArg String
input) [ExecutableArg]
exArgs
let outputReader :: ByteString -> IO ByteString
outputReader = String -> CompilerOut -> ByteString -> IO ByteString
cOutToFileContents String
input CompilerOut
out
ExecutableName
-> [String]
-> (ByteString -> IO ByteString)
-> Compiler (Item ByteString)
unsafeExecCompiler ExecutableName
name [String]
args ByteString -> IO ByteString
outputReader
unsafeExecCompiler ::
ExecutableName
-> [String]
-> (B.ByteString -> IO B.ByteString)
-> Compiler (Item B.ByteString)
unsafeExecCompiler :: ExecutableName
-> [String]
-> (ByteString -> IO ByteString)
-> Compiler (Item ByteString)
unsafeExecCompiler (ExecutableName String
exName) [String]
args ByteString -> IO ByteString
outputReader =
do
ByteString
results <- IO ByteString -> Compiler ByteString
forall a. IO a -> Compiler a
unsafeCompiler (IO ByteString -> Compiler ByteString)
-> IO ByteString -> Compiler ByteString
forall a b. (a -> b) -> a -> b
$ IO ByteString
procResults
Item String
oldBody <- Compiler (Item String)
getResourceString
Item ByteString -> Compiler (Item ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Item ByteString -> Compiler (Item ByteString))
-> Item ByteString -> Compiler (Item ByteString)
forall a b. (a -> b) -> a -> b
$ ByteString -> Item String -> Item ByteString
forall a b. a -> Item b -> Item a
itemSetBody ByteString
results Item String
oldBody
where
procResults :: IO ByteString
procResults = ProcessConfig () (STM ByteString) ()
-> (Process () (STM ByteString) () -> IO ByteString)
-> IO ByteString
forall (m :: * -> *) stdin stdout stderr a.
MonadUnliftIO m =>
ProcessConfig stdin stdout stderr
-> (Process stdin stdout stderr -> m a) -> m a
withProcessWait ProcessConfig () (STM ByteString) ()
procConf Process () (STM ByteString) () -> IO ByteString
forall stdin stderr.
Process stdin (STM ByteString) stderr -> IO ByteString
waitOutput
procConf :: ProcessConfig () (STM ByteString) ()
procConf = StreamSpec 'STOutput (STM ByteString)
-> ProcessConfig () () () -> ProcessConfig () (STM ByteString) ()
forall stdout stdin stdout0 stderr.
StreamSpec 'STOutput stdout
-> ProcessConfig stdin stdout0 stderr
-> ProcessConfig stdin stdout stderr
setStdout StreamSpec 'STOutput (STM ByteString)
byteStringOutput (ProcessConfig () () () -> ProcessConfig () (STM ByteString) ())
-> ([String] -> ProcessConfig () () ())
-> [String]
-> ProcessConfig () (STM ByteString) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String] -> ProcessConfig () () ()
proc String
exName ([String] -> ProcessConfig () (STM ByteString) ())
-> [String] -> ProcessConfig () (STM ByteString) ()
forall a b. (a -> b) -> a -> b
$ [String]
args
waitOutput :: Process stdin (STM ByteString) stderr -> IO ByteString
waitOutput Process stdin (STM ByteString) stderr
process = do
let stmProc :: STM ByteString
stmProc = Process stdin (STM ByteString) stderr -> STM ByteString
forall stdin stdout stderr. Process stdin stdout stderr -> stdout
getStdout Process stdin (STM ByteString) stderr
process
ByteString
out <- STM ByteString -> IO ByteString
forall a. STM a -> IO a
atomically STM ByteString
stmProc
Process stdin (STM ByteString) stderr -> IO ()
forall (m :: * -> *) stdin stdout stderr.
MonadIO m =>
Process stdin stdout stderr -> m ()
checkExitCode Process stdin (STM ByteString) stderr
process
ByteString -> IO ByteString
outputReader ByteString
out
cOutToFileContents :: FilePath -> CompilerOut -> B.ByteString -> IO B.ByteString
cOutToFileContents :: String -> CompilerOut -> ByteString -> IO ByteString
cOutToFileContents String
_ CompilerOut
CStdOut ByteString
out = ByteString -> IO ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure ByteString
out
cOutToFileContents String
_ (COutFile (SpecificPath String
f)) ByteString
_ = String -> IO ByteString
B.readFile String
f
cOutToFileContents String
input (COutFile (RelativePath ShowS
f)) ByteString
_ = String -> IO ByteString
B.readFile (ShowS
f String
input)
hargToArg :: FilePath -> ExecutableArg -> String
hargToArg :: String -> ExecutableArg -> String
hargToArg String
_ (ProcArg String
s) = String
s
hargToArg String
f ExecutableArg
HakFilePath = String
f