Skip to content

Instantly share code, notes, and snippets.

@Soft
Created February 13, 2014 19:27
Show Gist options
  • Save Soft/8982059 to your computer and use it in GitHub Desktop.
Save Soft/8982059 to your computer and use it in GitHub Desktop.
Combine inputs from multiple line-oriented sources. Useful for displaying things in status bars like dzen or bar.
import Control.Monad (liftM, mapM, forever)
import Control.Monad.Loops (untilM_)
import Control.Concurrent (forkIO, threadDelay)
import Control.Concurrent.STM (atomically)
import Control.Concurrent.STM.TMVar (TMVar, newTMVar, swapTMVar, readTMVar)
import System.IO (hGetLine, hIsEOF, hFlush, Handle, stdin, stdout)
import System.Process (createProcess, shell, CreateProcess(..), StdStream(..))
import System.Environment (getArgs)
import Data.Maybe (catMaybes)
import Data.List (nub)
hProducer :: Handle -> TMVar String -> IO ()
hProducer h var = untilM_ (hGetLine h >>= atomically . swapTMVar var) (hIsEOF h)
spawnHandle :: String -> IO (Maybe Handle)
spawnHandle cmd = do
(_, stdin, _, _) <- createProcess ((shell cmd) { std_in = CreatePipe, std_out = CreatePipe, std_err = CreatePipe })
return stdin
createProducer :: Handle -> IO (TMVar String)
createProducer h = do
v <- atomically $ newTMVar ""
forkIO $ hProducer h v
return v
printer :: [TMVar String] -> IO ()
printer vs = mapM (atomically . readTMVar) vs >>= putStrLn . concat >> hFlush stdout
argToHandle "-" = return . Just $ stdin
argToHandle cmd = spawnHandle cmd
main = do
handles <- liftM catMaybes $ getArgs >>= mapM argToHandle . nub
vs <- mapM createProducer handles
forever $ printer vs >> threadDelay 500000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment