module Coreutils.Cat where

-- cat
--
  read files from the command line or echo stdin

import           Control.Exception
import           Control.Monad
import qualified Streaming.ByteString as Q
import           System.Exit
import           System.Info
import           System.IO

import           Coreutils.Util

data Cat = Cat

instance Util Cat where
    run _ = runner

runner :: [String] -> IO ()
-- attempt to write each input file to stdout, continues on intermediary failures
runner args
        | null files = piper cat
        | otherwise  = do
            failures <- mapM switch files
            when (or failures) exitFailure
    where
        switch "-" = wrap (piper cat)
        switch fn  = wrap (withFile fn ReadMode cat)

        cat = Q.stdout . Q.fromHandle

        files = filter (/= "--") args
        wrap f = catch (f >> pure False) (\e -> pError e >> pure True)

        pError :: SomeException -> IO ()
        pError = hPrint stderr

piper :: (Handle -> IO ()) -> IO ()
  this allows us to read from stdin multiple times ; used by some build scripts
piper f
    | os == "mingw32" = f stdin
    | otherwise       = withFile "/dev/tty" ReadMode f

 cat

 attempt to write each input file to stdout, continues on intermediary failures
module Coreutils.Cat where

  read files from the command line or echo stdin

import           Control.Exception
import           Control.Monad
import qualified Streaming.ByteString as Q
import           System.Exit
import           System.Info
import           System.IO

import           Coreutils.Util

data Cat = Cat

instance Util Cat where
    run _ = runner

runner :: [String] -> IO ()
runner args
        | null files = piper cat
        | otherwise  = do
            failures <- mapM switch files
            when (or failures) exitFailure
    where
        switch "-" = wrap (piper cat)
        switch fn  = wrap (withFile fn ReadMode cat)

        cat = Q.stdout . Q.fromHandle

        files = filter (/= "--") args
        wrap f = catch (f >> pure False) (\e -> pError e >> pure True)

        pError :: SomeException -> IO ()
        pError = hPrint stderr

piper :: (Handle -> IO ()) -> IO ()
  this allows us to read from stdin multiple times ; used by some build scripts
piper f
    | os == "mingw32" = f stdin
    | otherwise       = withFile "/dev/tty" ReadMode f
