{-# LANGUAGE CPP, Rank2Types #-} module TailTypes ( Interval, fromInterval, TailTarget(..), TailRuntime(..), TailMatch(..), TailAction(..), TailMatches, Tail(..), tailName, tailErrMsg ) where import qualified System.Posix.Types import qualified System.Posix.IO import qualified Text.Regex #ifdef INOTIFY import qualified System.INotify as INotify #endif import Display newtype Interval = Interval { fromInterval :: Int } deriving (Eq, Ord) instance Show Interval where show (Interval x) | x `mod` 1000000 == 0 = show (x `div` 1000000) | otherwise = show (fromIntegral x / 1000000.0) instance Read Interval where readsPrec n s = map (\(x,s) -> (Interval $ floor (1000000.0 * x), s)) $ readsPrec n s instance Num Interval where Interval x + Interval y = Interval (x + y) Interval x * Interval y = Interval (x * y) Interval x - Interval y = Interval (x - y) negate (Interval x) = Interval (negate x) abs (Interval x) = Interval (abs x) signum (Interval x) = Interval (signum x) fromInteger n = Interval (fromInteger $ 1000000 * n) data TailTarget = TailPath !FilePath | TailFd !System.Posix.Types.Fd instance Show TailTarget where show (TailFd 0) = "-" show (TailFd x) = '&':(show x) show (TailPath path) = path instance Read TailTarget where readsPrec _ "-" = [(TailFd System.Posix.IO.stdInput, "")] readsPrec n ('&':s) = map (\(f,s) -> (TailFd f, s)) $ readsPrec n s readsPrec _ s = [(TailPath s, "")] data TailMatch = MatchAll | MatchRegex !Text.Regex.Regex | MatchNotRegex !Text.Regex.Regex data TailAction = ActionNone | ActionHide | ActionColor !TermColor | ActionSubst !String | ActionExecute !String type TailMatches = [(TailMatch, TailAction)] data Tail = Tail { tailTarg :: TailTarget , tailPollInterval :: !Interval , tailReopenInterval :: !Interval #ifdef INOTIFY , tailPollINotify :: !Bool , tailReopenINotify :: !Bool #endif , tailBegin :: !Bool -- start at beginning of file , tailFileTail :: !Bool -- enable this tail for non-directories (almost always True) , tailDirTail :: !Bool -- tail immediate children , tailDirList :: !Bool -- enable this tail for directory content , tailDirRecursive :: !Bool -- tail children recursively , tailTimeFmt :: !String , tailMatches :: !TailMatches } tailName :: Tail -> String tailName = show . tailTarg tailErrMsg :: Tail -> String -> IO () tailErrMsg t msg = errMsg ("ztail " ++ tailName t ++ ": " ++ msg) data TailRuntime = TailRuntime { trUnlock :: forall a. IO a -> IO a , trAddTail :: Tail -> IO () , trText :: Tail -> String -> IO () #ifdef INOTIFY , trINotify :: Maybe INotify.INotify #endif }