diff options
Diffstat (limited to 'cli/Main.hs')
-rw-r--r-- | cli/Main.hs | 111 |
1 files changed, 2 insertions, 109 deletions
diff --git a/cli/Main.hs b/cli/Main.hs index 89b2d21..8e9426c 100644 --- a/cli/Main.hs +++ b/cli/Main.hs @@ -1,109 +1,2 @@ -{-# LANGUAGE OverloadedStrings #-} -module Main where - -import Control.Exception (catchJust) -import Control.Monad (filterM,foldM) -import System.Directory (doesFileExist,getHomeDirectory) -import System.Exit -import System.FilePath ((</>)) -import System.IO (hPutStrLn,stderr) -import System.IO.Error (isEOFError) -import Options.Applicative -import Data.Semigroup ((<>)) -import qualified Data.ByteString as B -import qualified Data.ByteString.Char8 as C -import qualified Data.Map.Strict as Map - -import Logstat.Types -import Logstat.Parse -import Logstat.Value -import Logstat.Eval - - --- Extract the final 'show' statement or provide a default expression to display. --- Returns an error if there is a non-last 'show' statement. -extractShow :: [Stmt] -> Either String ([Expr], [Stmt]) -extractShow proc = f [] ["msg"] proc - where - f l v [] = Right (map EField v, reverse l) - f l _ ((SShow e):[]) = Right (e, reverse l) - f _ _ ((SShow _):_) = Left $ "Error: 'show' must not be followed by other statements" -- TODO: CONTEXT! - f l _ (x@(SGroup v):xs) = f (x:l) v xs - f l v (x:xs) = f (x:l) v xs - - - -run :: [State] -> [Event -> Either EvalError Val] -> Step -> ([State] -> [Either EvalError Event]) -> IO () -run st sh stp fnl = loop st - where - loop state = do - r <- catchJust - (\e -> if isEOFError e then Just () else Nothing) - (Just <$> line state) - (const (Nothing <$ finalize state)) - case r of - Nothing -> return () - Just state' -> loop state' - - eval ev = - case mapM (\f -> f ev) sh of - Left e -> hPutStrLn stderr $ show e ++ " in show statement" - Right v -> C.putStrLn $ B.intercalate ", " $ map asBS v - - line state = do - l <- B.getLine - let event = Map.fromList [("msg", bs l)] - (state', r) = stp state event - case r of - Left Filtered -> return () - -- TODO: Add more error context, especially the file+line of the statement that triggered the error - Left e -> hPutStrLn stderr $ show e ++ " with input: " ++ show l - Right v -> eval v - return state' - - finalize state = mapM_ - (\r -> - case r of - Left e -> hPutStrLn stderr $ show e - Right l -> eval l) - (fnl state) - - - -data Options = Options - { optConfig :: [String] - , optEval :: [String] - , optNoRC :: Bool - } deriving(Show) - - -main :: IO () -main = do - o <- execParser opts - - home <- getHomeDirectory - c <- loadCfg - (if optNoRC o then [] else ["/etc/logstat.conf", home </> ".logstat.conf", "logstat.conf"]) - (optConfig o) - - stmts' <- concat <$> mapM (parseStmtsIO c "-e") (optEval o) - (sh, stmts) <- case extractShow stmts' of - Left e -> hPutStrLn stderr e >> exitFailure - Right r -> return r - - run (newState stmts) (map evalExpr sh) (stepL stmts) (finalL stmts) - - where - opts = info (optparse <**> helper) fullDesc - optparse = Options - <$> many (strOption (long "config" <> short 'c' <> metavar "FILE" <> help "Config file")) - <*> some (strOption (long "eval" <> short 'e' <> metavar "CODE" <> help "Code to evaluate")) - <*> switch (long "norc" <> short 'X' <> help "Don't load default config files") - - loadCfg :: [String] -> [String] -> IO Config - loadCfg def conf = do - def' <- filterM doesFileExist def - foldM - parseFileIO - (Config mempty mempty []) - (def' ++ conf) +module Main (main) where +import Logstat.Main |