From d5e433ecd3857ed0d5ed71c0769e4caf7b84aed8 Mon Sep 17 00:00:00 2001 From: Ranjeet Kumar Ranjan Date: Fri, 15 Jul 2022 17:20:45 +0530 Subject: [PATCH 1/2] Add Tail module --- src/Streamly/Coreutils/Tail.hs | 39 ++++++++++++++++++++++++++++++++++ streamly-coreutils.cabal | 2 ++ 2 files changed, 41 insertions(+) create mode 100644 src/Streamly/Coreutils/Tail.hs diff --git a/src/Streamly/Coreutils/Tail.hs b/src/Streamly/Coreutils/Tail.hs new file mode 100644 index 00000000..f8db98fe --- /dev/null +++ b/src/Streamly/Coreutils/Tail.hs @@ -0,0 +1,39 @@ +-- | +-- Module : Streamly.Coreutils.Tail +-- Copyright : (c) 2022 Composewell Technologies +-- License : Apache-2.0 +-- Maintainer : streamly@composewell.com +-- Stability : experimental +-- Portability : GHC +-- +-- Output the last part of files. + +module Streamly.Coreutils.Tail + (tail, tailN) +where + +import Control.Monad.IO.Class (MonadIO(liftIO)) +import Data.Function ((&)) +import Streamly.Prelude (SerialT) +import System.IO (IOMode(..), openFile) + +import qualified Streamly.FileSystem.Handle as File +import qualified Streamly.Internal.Data.Array as Array +import qualified Streamly.Internal.Data.Stream.IsStream as Stream +import qualified Streamly.Internal.Data.Fold as FL +import qualified Streamly.Internal.Unicode.Stream as Unicode + +import Prelude hiding (tail) + +tailN :: Int -> FilePath -> SerialT IO [Char] +tailN n fp = do + fh <- liftIO $ openFile fp ReadMode + Stream.unfold File.read fh + & Unicode.decodeUtf8 + & Unicode.lines FL.toList + & Stream.fold (Array.writeLastN n) + & Stream.map Array.toStream + & Stream.concat + +tail :: FilePath -> SerialT IO [Char] +tail = tailN 10 diff --git a/streamly-coreutils.cabal b/streamly-coreutils.cabal index fa31b395..06aadff5 100644 --- a/streamly-coreutils.cabal +++ b/streamly-coreutils.cabal @@ -92,6 +92,7 @@ library , unix >= 2.7.0 && < 2.8 , directory >= 1.2.2 && < 1.4 , data-default-class >= 0.1 && < 0.2 + , monad-control >= 1.0.3 && < 1.0.4 hs-source-dirs: src exposed-modules: Streamly.Coreutils @@ -99,6 +100,7 @@ library , Streamly.Coreutils.Cp , Streamly.Coreutils.FileTest , Streamly.Coreutils.ShellWords + , Streamly.Coreutils.Tail , Streamly.Coreutils.Uniq , Streamly.Coreutils.Which From be9bef5c530d83376963b6308c5d142955eb477c Mon Sep 17 00:00:00 2001 From: Ranjeet Kumar Ranjan Date: Fri, 15 Jul 2022 18:11:09 +0530 Subject: [PATCH 2/2] Add follow option --- src/Streamly/Coreutils/Tail.hs | 45 +++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/src/Streamly/Coreutils/Tail.hs b/src/Streamly/Coreutils/Tail.hs index f8db98fe..edcc8fee 100644 --- a/src/Streamly/Coreutils/Tail.hs +++ b/src/Streamly/Coreutils/Tail.hs @@ -9,7 +9,14 @@ -- Output the last part of files. module Streamly.Coreutils.Tail - (tail, tailN) + + ( tail + + -- * Options + , Tail + , follow + , tailN + ) where import Control.Monad.IO.Class (MonadIO(liftIO)) @@ -24,16 +31,42 @@ import qualified Streamly.Internal.Data.Fold as FL import qualified Streamly.Internal.Unicode.Stream as Unicode import Prelude hiding (tail) +import Streamly.Coreutils.Common (Switch(..)) + +newtype Tail = Tail{tailFollow :: Switch} + +defaultConfig :: Tail +defaultConfig = Tail Off -tailN :: Int -> FilePath -> SerialT IO [Char] -tailN n fp = do +follow :: Switch -> Tail -> Tail +follow opt cfg = cfg {tailFollow = opt} + +tailForEver :: Int -> FilePath -> SerialT IO [Char] +tailForEver n fp = do fh <- liftIO $ openFile fp ReadMode - Stream.unfold File.read fh + Stream.concatMap Stream.fromList + $ Stream.repeatM + $ Stream.toList + $ Stream.unfold File.read fh & Unicode.decodeUtf8 & Unicode.lines FL.toList & Stream.fold (Array.writeLastN n) & Stream.map Array.toStream & Stream.concat -tail :: FilePath -> SerialT IO [Char] -tail = tailN 10 +tailN :: (Tail -> Tail) -> Int -> FilePath -> SerialT IO [Char] +tailN f n fp = do + fh <- liftIO $ openFile fp ReadMode + let opt = f defaultConfig + case tailFollow opt of + On -> tailForEver n fp + Off -> + Stream.unfold File.read fh + & Unicode.decodeUtf8 + & Unicode.lines FL.toList + & Stream.fold (Array.writeLastN n) + & Stream.map Array.toStream + & Stream.concat + +tail :: (Tail -> Tail) -> FilePath -> SerialT IO [Char] +tail f = tailN f 10