----------------------------------------------------------------------------- -- -- Module : Main -- Copyright : (c) Ingolf Wagner -- License : BSD3 -- -- Maintainer : Ingolf Wagner -- Stability : unstable -- Portability : -- ----------------------------------------------------------------------------- module Main ( main ) where import Data.List.Split import Data.Maybe import System.Console.GetOpt import System.Environment import System.Exit import System.IO import Parser import Qifer import QifOptions -- | the famous main method main = do args <- getArgs -- Parse options, getting a list of option actions let (actions, nonOptions, errors) = getOpt RequireOrder options args -- Here we thread startOptions through all supplied option actions opts <- foldl (>>=) (return startOptions) actions let Options {optInput = input, optOutput = output} = opts checkArguments opts let rules = rule opts parseResult <- parseCSVFromFile (optSkip opts) (optInput opts) (optSeparator opts) case parseResult of Left error -> do hPutStrLn stderr $ error exitFailure Right csv -> do let actions = toTransactions rules csv updatedActions <- case (optUpdater opts) of Nothing -> return $ actions Just file -> do updaterConfig <- readUpdaterFile file return $ update updaterConfig actions let qif = transToQif updatedActions withFile (optOutput opts) WriteMode (\h -> mapM_ (hPutStrLn h) qif) -- | reads updater file readUpdaterFile :: String -> IO [(String, String)] readUpdaterFile fileName = do content <- readFile fileName return $ tupler . onlyTuple . splitter . lines $ content where tupler = map (\(x:(y:[])) -> (x, y)) onlyTuple = filter (\l -> length l == 2) splitter = map (\l -> splitOn "<->" l) -- | this function is unsafe call it after checkArguments -- @todo : make me safer rule :: Options -> Rule rule opts = Rule { dateField = fromJust $ optDate opts , balanceField = fromJust $ optBalance opts , textField = optLongText opts , descField = optText opts } -- | checks input arguments for minimum of configuration checkArguments :: Options -> IO () checkArguments opts = do case errors of [] -> return () _ -> do mapM_ putStrLn errors exitFailure return () where errors = catMaybes list list = [ (check optDate "need date column") , (check optBalance "need balance column") , (checkL optText "need text columns") , (checkL optLongText "need long text columns") , (checkL optInput "need input file") ] check getter text = case (getter opts) of Nothing -> Just text Just _ -> Nothing checkL getter text = case (getter opts) of [] -> Just text _ -> Nothing