1 import Control.Applicative( (<$>) )
2 import Control.Monad( unless )
3 import qualified Data.Map as Map
4 import Data.Time.Clock( UTCTime(..) )
5 import Diddo( DiddoEntry(..), LogEntry(..), parseDiddoLogline, formatDiddoEntry, timestamp, logToDiddoEntry )
6 import System.Console.GetOpt
7 import System.Environment( getArgs )
8 import System.Exit( exitSuccess, exitFailure )
9 import System.IO( stderr, hPutStr )
15 , optInputFiles :: [String]
16 , optOutputFile :: String
17 , optInputFormat :: String
18 , optOutputFormat :: String
19 , optStartDate :: String
20 , optEndDate :: String
30 , optInputFormat = "%FT%T%z"
31 , optOutputFormat = "%FT%T%z"
36 availableOptions :: [OptDescr (Opt -> IO Opt)]
38 [ Option ['h'] ["help"]
39 (NoArg (\_ -> putStrLn (usageInfo "Usage: diddohs [OPTION...]" availableOptions) >> exitSuccess))
40 "Display program help"
41 , Option ['v'] ["verbose"]
42 (NoArg (\opts -> return opts { optVerbose = True }))
43 "More detailed output"
44 , Option ['V'] ["version"]
45 (NoArg (\opts -> return opts { optVersion = True }))
46 "Display program version"
47 , Option ['f'] ["file"]
48 (ReqArg (\arg opts -> return opts { optInputFiles = optInputFiles opts ++ [arg]}) "FILE" )
50 , Option ['w'] ["output"]
51 (ReqArg (\arg opts -> return opts { optOutputFile = arg }) "FILE")
53 , Option ['i'] ["informat"]
54 (ReqArg (\arg opts -> return opts { optInputFormat = arg }) "FORMAT")
55 "Timeformat used in input"
56 , Option ['o'] ["outformat"]
57 (ReqArg (\arg opts -> return opts { optOutputFormat = arg }) "FORMAT")
58 "Timeformat used in output"
59 , Option ['s'] ["start"]
60 (ReqArg (\arg opts -> return opts { optStartDate = arg }) "DATE")
61 "Start of reporting period"
62 , Option ['e'] ["end"]
63 (ReqArg (\arg opts -> return opts { optEndDate = arg }) "DATE")
64 "End of reporting period"
67 -- SECTION: Map of logentries to Map of DiddoEntries
68 mapToDiddoEntries :: Map.Map UTCTime Diddo.LogEntry -> Map.Map UTCTime Diddo.DiddoEntry
69 mapToDiddoEntries logmap = Map.mapWithKey toDddEntry logmap
71 toDddEntry key value = Diddo.logToDiddoEntry (preceedingTimestamp key) value
72 preceedingTimestamp x = case Map.lookupLT x logmap of
74 Nothing -> fst $ Map.findMin logmap
75 -- SECTION: Map of logentries to Map of DiddoEntries
79 -- SECTION: option processing
80 (givenOptions,args,errs) <- getArgs >>= return . getOpt Permute availableOptions
82 unless (null errs) $ do
83 mapM_ (hPutStr stderr) errs
86 effectiveOptions <- foldl (>>=) (return defaultOpts) givenOptions
87 -- SECTION: option processing
90 map Diddo.parseDiddoLogline <$> case optInputFiles effectiveOptions of
91 files@(_:_) -> lines . concat <$> mapM readFile files
92 [] -> lines <$> getContents
95 dddLogEntryMap = Map.fromList $ map (\diddo -> (Diddo.timestamp diddo, diddo)) dddLogEntries
96 diddoEntriesMap = mapToDiddoEntries dddLogEntryMap
97 inDateFmt = optInputFormat effectiveOptions
98 outDateFmt = optOutputFormat effectiveOptions
104 mapM_ (putStrLn . snd) $ Map.toAscList $ Map.map (Diddo.formatDiddoEntry outDateFmt) diddoEntriesMap