1
- {-# LANGUAGE OverloadedStrings #-}
2
- {-# LANGUAGE QuasiQuotes #-}
1
+ {-# LANGUAGE OverloadedStrings #-}
2
+ {-# LANGUAGE QuasiQuotes #-}
3
+ {-# LANGUAGE ScopedTypeVariables #-}
3
4
4
5
module Main where
5
6
@@ -9,15 +10,16 @@ import Control.Concurrent.MVar
9
10
import Control.Concurrent.STM
10
11
import Control.Exception (finally )
11
12
import Control.Exception.Enclosed (handleAny )
12
- import Control.Monad (MonadPlus (.. ))
13
13
import Data.ByteString (ByteString )
14
14
import qualified Data.ByteString as B
15
+ import qualified Data.ByteString.Char8 as BSC8
15
16
import Data.Foldable
16
17
import qualified Data.List as L
17
18
import qualified Data.List.NonEmpty as NL
18
19
import Data.String.Class (toStrictByteString )
19
20
import Options.Applicative
20
21
import Prelude hiding (mapM , mapM_ )
22
+ import Safe
21
23
import SlaveThread (fork )
22
24
import System.Exit
23
25
import System.IO
@@ -69,8 +71,8 @@ runSingle outQ errQ cmdBig = do
69
71
(_, Just hout, Just herr, ph) <-
70
72
createProcess (shell cmd){ std_out = CreatePipe
71
73
, std_err = CreatePipe }
72
- (_, w1) <- forkW (forwardHandler hout outQ ( \ s -> [toBs cmdPrefix <> s]) )
73
- (_, w2) <- forkW (forwardHandler herr errQ ( \ s -> [toBs cmdPrefix <> s]) )
74
+ (_, w1) <- forkW (forwardHandler hout outQ prefixer )
75
+ (_, w2) <- forkW (forwardHandler herr errQ prefixer )
74
76
res <- waitForProcess ph
75
77
waitSignal w1 >> waitSignal w2
76
78
return res
@@ -82,18 +84,28 @@ runSingle outQ errQ cmdBig = do
82
84
else (cmdBig, " " )
83
85
parprefix = " PARPREFIX="
84
86
toBs = toStrictByteString
87
+ prefixer chunk isNewline = if isNewline
88
+ then [toBs cmdPrefix <> chunk]
89
+ else [chunk]
85
90
86
- forwardHandler :: (MonadPlus mp , Foldable mp )
87
- => Handle -> TBQueue (Maybe ByteString ) -> (ByteString -> mp ByteString ) -> IO ()
88
- forwardHandler from to f = fin (hndl go)
91
+ forwardHandler :: Handle
92
+ -> TBQueue (Maybe ByteString )
93
+ -> (ByteString -> Bool -> [ByteString ])
94
+ -> IO ()
95
+ forwardHandler from to f = fin (hndl (go True ))
89
96
where
90
- go = do
97
+ go endedNewline = do
91
98
eof <- hIsEOF from
92
99
if eof then return ()
93
100
else do
94
- l <- B. hGetSome from (1024 * 1024 )
95
- mapM_ (\ s -> atomically (writeTBQueue to (Just s))) (f l)
96
- go
101
+ chunk <- B. hGetSome from (1024 * 1024 )
102
+ let ls = BSC8. split ' \n ' chunk
103
+ let fl = f (headDef " " ls) endedNewline
104
+ rest = msum (map (\ l -> f l True ) (tailDef [] ls))
105
+ lastEmpty = last ls == " "
106
+ rest' = if lastEmpty then init rest else rest
107
+ mapM_ (\ l -> atomically (writeTBQueue to (Just (l <> " \n " )))) (fl <> rest')
108
+ go lastEmpty
97
109
hndl = handleAny (const (return () ))
98
110
fin f' = finally f' (atomically (writeTBQueue to Nothing ))
99
111
0 commit comments