diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2025-04-13 10:57:56 +0200 | 
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2025-04-15 19:51:22 +0200 | 
| commit | 30e91608555839e3cb0113cdbd670e76d2d35508 (patch) | |
| tree | 7d5050c075dd60534ccb381fbfaa406e7db23cfb /src/Output.hs | |
| parent | d0ade87f13dec39eb3b62cac34c3fe31135a14f8 (diff) | |
Output style options
Changelog: Added `--terminal-output` and `--log-output` options to set output style
Diffstat (limited to 'src/Output.hs')
| -rw-r--r-- | src/Output.hs | 99 | 
1 files changed, 99 insertions, 0 deletions
| diff --git a/src/Output.hs b/src/Output.hs new file mode 100644 index 0000000..54b434e --- /dev/null +++ b/src/Output.hs @@ -0,0 +1,99 @@ +module Output ( +    Output, +    OutputType(..), +    OutputEvent(..), +    OutputFootnote(..), + +    withOutput, +    outputTerminal, +    outputEvent, +    outputFootnote, +) where + +import Control.Monad +import Control.Monad.Catch + +import Data.Text (Text) +import Data.Text.IO qualified as T + +import System.IO + +import Job.Types +import Terminal + + +data Output = Output +    { outTerminal :: Maybe TerminalOutput +    , outLogs :: [ Handle ] +    , outTest :: [ Handle ] +    } + +data OutputType +    = TerminalOutput +    | LogOutput FilePath +    | TestOutput FilePath +    deriving (Eq, Ord) + +data OutputEvent +    = OutputMessage Text +    | JobStarted JobId +    | JobFinished JobId Text + +data OutputFootnote = OutputFootnote +    { footnoteText :: Text +    , footnoteTerminal :: Maybe TerminalFootnote +    } +    deriving (Eq) + + +withOutput :: [ OutputType ] -> (Output -> IO a) -> IO a +withOutput types inner = go types (Output Nothing [] []) +  where +    go (TerminalOutput : ts) out = do +        term <- initTerminalOutput +        go ts out { outTerminal = Just term } +    go (LogOutput path : ts) out = withOutputFile path $ \h -> do +        go ts out { outLogs = h : outLogs out } +    go (TestOutput path : ts) out = withOutputFile path $ \h -> do +        go ts out { outTest = h : outTest out } +    go [] out = inner out + +    withOutputFile "-" f = hSetBuffering stdout LineBuffering >> f stdout +    withOutputFile path f = bracket (openFile' path) hClose f +    openFile' path = do +        h <- openFile path WriteMode +        hSetBuffering h LineBuffering +        return h + + +outputTerminal :: Output -> Maybe TerminalOutput +outputTerminal = outTerminal + +outStrLn :: Output -> Handle -> Text -> IO () +outStrLn Output {..} h text +    | Just tout <- outTerminal, terminalHandle tout == h = do +        void $ newLine tout text +    | otherwise = do +        T.hPutStrLn h text + +outputEvent :: Output -> OutputEvent -> IO () +outputEvent out@Output {..} = \case +    OutputMessage msg -> do +        forM_ outTerminal $ \term -> void $ newLine term msg +        forM_ outLogs $ \h -> outStrLn out h msg +        forM_ outTest $ \h -> outStrLn out h ("msg " <> msg) + +    JobStarted jid -> do +        forM_ outLogs $ \h -> outStrLn out h ("Started " <> textJobId jid) +        forM_ outTest $ \h -> outStrLn out h ("job-start " <> textJobId jid) + +    JobFinished jid status -> do +        forM_ outLogs $ \h -> outStrLn out h ("Finished " <> textJobId jid <> " (" <> status <> ")") +        forM_ outTest $ \h -> outStrLn out h ("job-finish " <> textJobId jid <> " " <> status) + +outputFootnote :: Output -> Text -> IO OutputFootnote +outputFootnote out@Output {..} footnoteText = do +    footnoteTerminal <- forM outTerminal $ \term -> newFootnote term footnoteText +    forM_ outLogs $ \h -> outStrLn out h footnoteText +    forM_ outTest $ \h -> outStrLn out h ("note " <> footnoteText) +    return OutputFootnote {..} |