@@ -2,14 +2,20 @@
22--
33module Hakyll.Core.UnixFilter
44 ( unixFilter
5+ , unixFilterLBS
56 ) where
67
78import Control.Concurrent (forkIO)
8−import System.IO (hPutStr, hClose, hGetContents)
99import System.Posix.Process (executeFile, forkProcess)
1010import System.Posix.IO ( dupTo, createPipe, stdInput
1111 , stdOutput, closeFd, fdToHandle
1212 )
13+import System.IO ( Handle, hPutStr, hClose, hGetContents
14+ , hSetEncoding, localeEncoding
15+ )
16+
17+import Data.ByteString.Lazy (ByteString)
18+import qualified Data.ByteString.Lazy as LB
1319
1420import Hakyll.Core.Compiler
1521
@@ -26,25 +32,54 @@ import Hakyll.Core.Compiler
2632--
2733-- The code is fairly straightforward, given that we use @.scss@ for sass:
2834--
29−-- > route "style.scss" $ setExtension "css"
30−-- > compile "style.scss" $
31−-- > getResourceString >>> unixFilter "sass" ["-s", "--scss"]
32−-- > >>> arr compressCss
35+-- > match "style.scss" $ do
36+-- > route $ setExtension "css"
37+-- > compile $ getResourceString >>> unixFilter "sass" ["-s", "--scss"]
38+-- > >>> arr compressCss
3339--
3440unixFilter :: String -- ^ Program name
3541 -> [String] -- ^ Program args
3642 -> Compiler String String -- ^ Resulting compiler
37−unixFilter programName args =
43+unixFilter = unixFilterWith writer reader
44+ where
45+ writer handle input = do
46+ hSetEncoding handle localeEncoding
47+ hPutStr handle input
48+ reader handle = do
49+ hSetEncoding handle localeEncoding
50+ hGetContents handle
51+
52+-- | Variant of 'unixFilter' that should be used for binary files
53+--
54+-- > match "music.wav" $ do
55+-- > route $ setExtension "ogg"
56+-- > compile $ getResourceLBS >>> unixFilter "oggenc" ["-"]
57+--
58+unixFilterLBS :: String -- ^ Program name
59+ -> [String] -- ^ Program args
60+ -> Compiler ByteString ByteString -- ^ Resulting compiler
61+unixFilterLBS = unixFilterWith LB.hPutStr LB.hGetContents
62+
63+-- | Overloaded compiler
64+--
65+unixFilterWith :: (Handle -> i -> IO ()) -- ^ Writer
66+ -> (Handle -> IO o) -- ^ Reader
67+ -> String -- ^ Program name
68+ -> [String] -- ^ Program args
69+ -> Compiler i o -- ^ Resulting compiler
70+unixFilterWith writer reader programName args =
3871 timedCompiler ("Executing external program " ++ programName) $
39− unsafeCompiler $ \input -> unixFilterIO programName args input
72+ unsafeCompiler $ unixFilterIO writer reader programName args
4073
4174-- | Internally used function
4275--
43−unixFilterIO :: String
44− -> [String]
76+unixFilterIO :: (Handle -> i -> IO ())
77+ -> (Handle -> IO o)
4578 -> String
46− -> IO String
47−unixFilterIO programName args input = do
79+ -> [String]
80+ -> i
81+ -> IO o
82+unixFilterIO writer reader programName args input = do
4883 -- Create pipes
4984 (stdinRead, stdinWrite) <- createPipe
5085 (stdoutRead, stdoutWrite) <- createPipe
@@ -68,9 +103,9 @@ unixFilterIO programName args input = do
68103 -- Write the input to the child pipe
69104 _ <- forkIO $ do
70105 stdinWriteHandle <- fdToHandle stdinWrite
71− hPutStr stdinWriteHandle input
106+ writer stdinWriteHandle input
72107 hClose stdinWriteHandle
73108
74109 -- Receive the output from the child
75110 stdoutReadHandle <- fdToHandle stdoutRead
76− hGetContents stdoutReadHandle
111+ reader stdoutReadHandle