From 30d13015e08d898877427bad61e153a079b3af33 Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Fri, 14 Nov 2025 15:00:36 -0500 Subject: Fix parallel build output format with status indicators and colors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add initial line break to preserve terminal prompt - Change format to [✓]/[x]/[~] Namespace: output - Add colors: green for success, red for failure - Fix extra lines by adding newlines in releaseLine - Fix currentLine initialization to 0 instead of maxLines Amp-Thread-ID: https://ampcode.com/threads/T-39671965-c412-4a2e-8084-9d09128fd865 Co-authored-by: Amp --- Omni/Log/Concurrent.hs | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/Omni/Log/Concurrent.hs b/Omni/Log/Concurrent.hs index 72e4e99..05426aa 100644 --- a/Omni/Log/Concurrent.hs +++ b/Omni/Log/Concurrent.hs @@ -20,6 +20,9 @@ import Data.IORef (IORef, atomicModifyIORef', modifyIORef', newIORef, readIORef, import qualified Data.Map as Map import qualified Data.Text as Text import Omni.Namespace (Namespace) +import qualified Omni.Namespace as Namespace +import Rainbow (chunk, fore, green, red) +import qualified Rainbow import qualified System.Console.ANSI as ANSI import qualified System.Environment as Env import qualified System.IO as IO @@ -68,11 +71,12 @@ withLineManager maxLines action = do writeIORef namespaceLines Map.empty pure result else do + IO.hPutStrLn IO.stderr "" replicateM_ maxLines (IO.hPutStrLn IO.stderr "") ANSI.hCursorUp IO.stderr maxLines linesRef <- newIORef (Map.fromList [(i, Nothing) | i <- [0 .. maxLines - 1]]) - currentRef <- newIORef maxLines + currentRef <- newIORef 0 let mgr = LineManager @@ -86,6 +90,7 @@ withLineManager maxLines action = do result <- action mgr ANSI.hCursorDown IO.stderr maxLines + IO.hPutStrLn IO.stderr "" writeIORef currentLineManager Nothing writeIORef namespaceLines Map.empty pure result @@ -126,7 +131,7 @@ reserveLine LineManager {..} ns = |> listToMaybe updateLine :: LineManager -> Maybe Int -> Namespace -> Text -> IO () -updateLine LineManager {..} mLineNum _ output = +updateLine LineManager {..} mLineNum ns output = if not lmSupportsANSI then do IO.hPutStr IO.stderr (Text.unpack <| output <> "\n") @@ -144,7 +149,9 @@ updateLine LineManager {..} mLineNum _ output = when (linesToMove < 0) <| ANSI.hCursorDown IO.stderr (abs linesToMove) ANSI.hClearLine IO.stderr - IO.hPutStr IO.stderr (Text.unpack output) + let nsText = Text.pack (Namespace.toPath ns) + let formattedOutput = if Text.null output then "[~] " <> nsText else "[~] " <> nsText <> ": " <> output + IO.hPutStr IO.stderr (Text.unpack formattedOutput) IO.hFlush IO.stderr ANSI.hRestoreCursor IO.stderr @@ -152,8 +159,8 @@ updateLine LineManager {..} mLineNum _ output = modifyIORef' lmLines <| \linesMap -> Map.adjust (fmap (\bs -> bs {bsLastOutput = output})) lineNum linesMap -releaseLine :: LineManager -> Maybe Int -> BuildState -> IO () -releaseLine LineManager {..} mLineNum buildState = +releaseLine :: LineManager -> Maybe Int -> Namespace -> BuildState -> IO () +releaseLine LineManager {..} mLineNum ns buildState = case mLineNum of Nothing -> pure () Just lineNum -> do @@ -167,11 +174,14 @@ releaseLine LineManager {..} mLineNum buildState = ANSI.hCursorUp IO.stderr (current - lineNum) ANSI.hClearLine IO.stderr - let statusChar = case buildState of - Success -> "✓" - Failed -> "✗" - Building -> "…" - IO.hPutStr IO.stderr statusChar + let nsText = Text.pack (Namespace.toPath ns) + case buildState of + Success -> + Rainbow.hPutChunks IO.stderr [fore green <| chunk <| "[✓] " <> nsText <> "\n"] + Failed -> + Rainbow.hPutChunks IO.stderr [fore red <| chunk <| "[x] " <> nsText <> "\n"] + Building -> + IO.hPutStr IO.stderr (Text.unpack <| "[~] " <> nsText <> "\n") IO.hFlush IO.stderr ANSI.hRestoreCursor IO.stderr @@ -201,5 +211,5 @@ releaseCurrentLine ns buildState = do case Map.lookup ns nsMap of Nothing -> pure () Just lineNum -> do - releaseLine mgr (Just lineNum) buildState + releaseLine mgr (Just lineNum) ns buildState modifyIORef' namespaceLines (Map.delete ns) -- cgit v1.2.3