packages feed

ztail-1.0: Tail.hs

module Tail (
    tailText
  ) where

import Data.Array (Array, array, (//), (!))
import Text.Regex
import qualified Data.Char
import qualified System.Exit
import qualified System.Cmd
import qualified Data.Time.Clock
import qualified Data.Time.LocalTime
import qualified Data.Time.Format
import qualified System.Locale

import Util
import Display
import TailTypes

type Substitutions = Array Char String
default_subst :: Substitutions
default_subst = array ('\0','\127') [('\\',"\\")]

timeFmt :: String -> IO String
timeFmt f = do
  t <- Data.Time.Clock.getCurrentTime
  z <- Data.Time.LocalTime.getCurrentTimeZone
  return $ Data.Time.Format.formatTime System.Locale.defaultTimeLocale f (Data.Time.LocalTime.utcToLocalTime z t)

shellEscape :: String -> String
shellEscape [] = []
shellEscape (c:l)
  | Data.Char.isAlphaNum c = c: shellEscape l
  | otherwise = '\\':c: shellEscape l

substText :: Substitutions -> (String -> String) -> String -> String
substText sub f str = go str
  where
    go ('\\':x:l) = f (sub!x) ++ go l
    go (x:l) = x : go l
    go [] = []

matchText :: Substitutions -> TailMatch -> String -> Maybe Substitutions
matchText sub MatchAll t = Just (sub // [('_',t)])
matchText sub (MatchRegex m) t =
  case matchRegexAll m t of
    Nothing -> Nothing
    Just (pre, mat, post, exps) ->
      Just (sub
	// [('_',t), ('`',pre), ('&',mat), ('\'',post)]
	// zip ['1'..'9'] exps)
matchText sub (MatchNotRegex m) t =
  case matchRegex m t of
    Nothing -> Just (sub // [('_',t)])
    Just _ -> Nothing

execute :: Tail -> String -> IO System.Exit.ExitCode
execute th e =
  tailErrMsg th ("execute: " ++ e) >>
  System.Cmd.system e

processText :: Tail -> String -> IO ()
processText t x = do
  now <- timeFmt $ tailTimeFmt t
  let init_sub = default_subst // [('0',tailName t),('@',now)] 
  case foldl mact (Just x, init_sub, [], []) (tailMatches t) of
    (Nothing, _, _, _) -> nop
    (Just out, _, color, exec) ->
      output color out >>
      mapM_ (execute t) exec
  where
    mact r@(Nothing, _, _, _) _ = r
    mact r@(Just s, sub, cl, el) (m, a) =
      case matchText sub m s of
	Nothing -> r
	Just sub -> case a of
	  ActionNone -> (Just s, sub, cl, el)
	  ActionHide -> (Nothing, sub, cl, el)
	  ActionColor c -> (Just s, sub, c ++ cl, el)
	  ActionSubst s' -> (Just (substText sub id s'), sub, cl, el)
	  ActionExecute e -> (Just s, sub, cl, (substText sub shellEscape e) : el)

tailText = processText