herringbone-0.1.0: Web/Herringbone/Preprocessor/StdIO.hs
module Web.Herringbone.Preprocessor.StdIO (
makeStdIOPP
) where
import Control.Monad.IO.Class
import Data.Monoid
import Data.Text (Text)
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as C8
import System.Exit (ExitCode(..))
import System.Process.ByteString (readProcessWithExitCode)
import Web.Herringbone
-- | Make a preprocessor which works over standard IO; reading input from
-- stdin, and writing output to stdout.
makeStdIOPP :: Text -- ^ Name (identifies the preprocessor)
-> Text -- ^ Source filename extension (eg "sass")
-> Text -- ^ Destination filename extension (eg "css")
-> String -- ^ Program name
-> [String] -- ^ Arguments
-> PP
makeStdIOPP name consumes produces progname args = PP
{ ppName = name
, ppConsumes = consumes
, ppProduces = produces
, ppAction = compile progname args
}
compile :: String
-> [String]
-> ByteString
-> PPM (Either CompileError ByteString)
compile progname args source =
liftIO $ readAllFromProcess progname args source
-- | Read from a process returning both std err and out.
readAllFromProcess :: String -- ^ Program
-> [String] -- ^ Args
-> ByteString -- ^ Stdin
-> IO (Either ByteString ByteString)
readAllFromProcess program args input = do
(code,out,err) <- readProcessWithExitCode program args input
return $ case code of
ExitFailure 127 -> Left $ "cannot find executable " <> C8.pack program
ExitFailure _ -> Left $ join (err, out)
ExitSuccess -> Right $ join (err, out)
where
join (err, out) = if B.null err
then out
else err <> "\n" <> out