packages feed

zre-0.1.1.0: app/Cat.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Main where

import Control.Monad
import Control.Monad.IO.Class
import Control.Concurrent
import Control.Concurrent.Async.Lifted

import qualified Data.ByteString.Char8 as B

import System.IO
import System.Environment

import Network.ZRE
import Options.Applicative

data CatOpts = CatOpts {
    shutdown     :: Bool  -- ^ Close connection after EOF on the input
  , lineBuffered :: Bool
  , bufferSize   :: Int
  , catGroup     :: Group
  } deriving (Eq, Show, Ord)

parseCatOptions = CatOpts
  <$> switch (long "shutdown" <> short 'N')
  <*> switch (long "bufbyline" <> short 'l')
  <*> option auto (long "bufsize" <> short 'O' <> value (1024*128))
  <*> (mkGroup <$> strArgument (metavar "GROUP"))

main :: IO ()
main = do
  runZreParse parseCatOptions $ groupCat

groupCat :: CatOpts -> ZRE ()
groupCat CatOpts{..} = do
  zjoin catGroup
  void $ async $ catln
  -- wait a sec so join is received by peers before sending stuff
  void $ async $ (liftIO $ threadDelay 1000000) >> (stdin' catGroup)
  cat

catln :: ZRE ()
catln = forever $ do
  e <- readZ
  case e of
    Shout _uuid _group content _time  -> liftIO $ B.putStrLn $ B.concat content
    Whisper _uuid content _time -> liftIO $ B.putStrLn $ B.concat content
    _ -> return ()

cat :: ZRE ()
cat = forever $ do
  e <- readZ
  case e of
    Shout _uuid _group content _time  -> liftIO $ B.putStr $ B.concat content
    Whisper _uuid content _time -> liftIO $ B.putStr $ B.concat content
    _ -> return ()

stdinln :: Group -> ZRE ()
stdinln group = forever $ do
  l <- fmap B.pack $ liftIO getLine
  zshout group l

bufsize :: Int
bufsize = 1024*128

stdin' :: Group -> ZRE ()
stdin' group = do
  liftIO $ hSetBuffering stdin $ BlockBuffering (Just bufsize)
  forever $ do
    eof <- liftIO $ hIsEOF stdin
    case eof of
      True -> zquit
      False -> do
        buf <- liftIO $ B.hGetSome stdin bufsize
        zshout group buf