hxbrief: Implement --tee to write copy of all output to file

master
Lennart Spitzner 2022-02-24 21:53:51 +00:00
parent 7e97c65716
commit 3cacc98227
2 changed files with 35 additions and 5 deletions

View File

@ -32,7 +32,8 @@ executable hxbrief
microlens >=0.4.12.0 && <0.5,
async >=2.2.3 && <2.3,
transformers >=0.5.6.2 &&<0.6,
clock >=0.8 &&<0.9
clock >=0.8 &&<0.9,
pretty >=1.1.3.6 && <1.2
hs-source-dirs: src-hxbrief
default-language: Haskell2010
ghc-options: -rtsopts -threaded -Wall

View File

@ -70,9 +70,12 @@ import qualified System.Environment
import System.Exit ( exitSuccess
, exitWith
)
import System.IO ( Handle )
import System.IO ( Handle
, IOMode(WriteMode)
)
import qualified System.IO
import qualified System.Process as P
import qualified Text.PrettyPrint.HughesPJ as PP
import Text.Printf ( printf )
import qualified UI.Butcher.Monadic as B
@ -421,6 +424,18 @@ main = B.mainFromCmdParser $ do
summarize <- B.addFlagStringParams "s" ["summarize"] "PATTERN" mempty
skip <- B.addFlagStringParams "x" ["skip"] "PATTERN" mempty
omitSummary <- B.addSimpleBoolFlag "" ["omit-summary"] mempty
tee <- B.addFlagStringParams
""
["tee"]
"BASENAMEBASEPATH"
( B.flagHelp
$ PP.text "Write copy of stdout/stderr to BASEPATH.{out/err}.txt"
)
teeBoth <- B.addFlagStringParams
""
["tee-both"]
"FILENAMEFILEPATH"
(B.flagHelp $ PP.text "Write copy of stdout and stderr to FILEPATH")
-- section <- B.addSimpleBoolFlag "" ["section"] mempty
B.reorderStop
rest <- B.addParamRestOfInputRaw "COMMAND" mempty <&> \case
@ -448,12 +463,24 @@ main = B.mainFromCmdParser $ do
System.IO.hSetEcho System.IO.stdin False
System.IO.hSetBuffering System.IO.stdin System.IO.LineBuffering
GHC.IO.Encoding.setLocaleEncoding GHC.IO.Encoding.utf8
pure ()
case (tee, teeBoth) of
([] , []) -> pure (Nothing, Nothing)
([teeName], []) -> do
h1 <- System.IO.openFile (teeName ++ ".out.txt") WriteMode
h2 <- System.IO.openFile (teeName ++ ".err.txt") WriteMode
pure (Just h1, Just h2)
([], [teeBothName]) -> do
h <- System.IO.openFile teeBothName WriteMode
pure (Just h, Just h)
_ -> error "too many/conflicting tee arguments!"
)
(\() -> do
(\teeHandles -> do
fst teeHandles `forM_` System.IO.hClose
snd teeHandles `forM_` System.IO.hClose
-- ^ may be closed already, this is not an error according to docs!
System.IO.hSetEcho System.IO.stdin True
)
withConcurrentOutput $ mainBracket $ \() -> mask $ \restore -> do
withConcurrentOutput $ mainBracket $ \teeHandles -> mask $ \restore -> do
-- restore $ GHC.IO.Encoding.setFileSystemEncoding GHC.IO.Encoding.utf8
-- restore $ System.IO.hSetEncoding System.IO.stdout GHC.IO.Encoding.utf8
-- restore $ System.IO.hSetEncoding System.IO.stderr GHC.IO.Encoding.utf8
@ -524,9 +551,11 @@ main = B.mainFromCmdParser $ do
in go
let outHandler out = forever $ do
x <- System.IO.hGetLine out
fst teeHandles `forM_` \h -> System.IO.hPutStrLn h x
modifyMVar_ stateVar (processLine (StdOut, x))
let errHandler err = forever $ do
x <- System.IO.hGetLine err
snd teeHandles `forM_` \h -> System.IO.hPutStrLn h x
modifyMVar_ stateVar (processLine (StdErr, x))
let tickHandler = forever $ do
threadDelay 333333