@@ -0,0 +1,67 @@
1+module Main (main) where
4+import Control.Concurrent
7+import qualified Data.Text as T
8+import System.Environment
11+import System.Process.Typed
14+main = getArgs >>= runPrograms
16+runPrograms :: [String] -> IO ()
17+runPrograms progs = do
18+ exited <- newEmptyMVar
19+ processes <- forM (zip progs (prettifyProcesses progs)) $ \(prog, pretty) -> do
21+ startProcess . setStderr createPipe
22+ . setStdout createPipe
23+ . setStdin nullStream
27+ putMVar exited (pretty, e)
31+ isEmpty <- isEmptyMVar exited
33+ forM (zip colors processes) $ \(color, (prog, p)) -> do
35+ <$> writeOutput [color] prog (getStdout p)
36+ <*> writeOutput [color] prog (getStderr p)
43+ else threadDelay 100000
45+ (prog, exitCode) <- readMVar exited
46+ infoMessage $ T.pack prog <> " exited with " <> (T.pack . show) exitCode
47+ forM_ processes (stopProcess . snd)
51+colors = cycle [green, blue, magenta, cyan]
53+writeOutput :: [String] -> String -> Handle -> IO Bool
54+writeOutput color prog h = do
60+ putStrLn $ formatWith color (prog <> " | ") <> l
63+prettifyProcesses :: [String] -> [String]
64+prettifyProcesses ps' =
65+ let ps = take 50 <$> ps'
66+ maxLen = maximum . fmap length $ ps
67+ in ps <&> \p -> p <> replicate (maxLen - length p) ' '