refactor add command, more validation

This commit is contained in:
Simon Michael 2009-04-10 08:31:43 +00:00
parent 90cf39cc09
commit 7c155b7d1d

View File

@ -28,42 +28,52 @@ add opts args l
hPutStrLn stderr $ printf "\nAdded %d transactions to %s ." (length ts) (filepath $ rawledger l) hPutStrLn stderr $ printf "\nAdded %d transactions to %s ." (length ts) (filepath $ rawledger l)
-- | Read a number of ledger transactions from the command line, -- | Read a number of ledger transactions from the command line,
-- prompting, validating, displaying and appending them to the ledger file. -- prompting, validating, displaying and appending them to the ledger
-- file, until EOF.
getAndAddTransactions :: Ledger -> IO [LedgerTransaction] getAndAddTransactions :: Ledger -> IO [LedgerTransaction]
getAndAddTransactions l = (do getAndAddTransactions l = (do
t <- getTransaction l >>= addTransaction l
liftM (t:) (getAndAddTransactions l)
) `catch` (\e -> if isEOFError e then return [] else ioError e)
-- | Read a transaction from the command line.
getTransaction :: Ledger -> IO LedgerTransaction
getTransaction l = do
today <- getCurrentDay today <- getCurrentDay
datestr <- askFor "date" (Just $ showDate today) datestr <- askFor "date" (Just $ showDate today)
(Just $ \s -> null s || (Just $ \s -> null s ||
(isRight $ parse (smartdate >> many spacenonewline >> eof) "" $ lowercase s)) (isRight $ parse (smartdate >> many spacenonewline >> eof) "" $ lowercase s))
let date = fixSmartDate today $ fromparse $ parseSmartDate datestr let date = fixSmartDate today $ fromparse $ (parse smartdate "" . lowercase) datestr
description <- askFor "description" Nothing (Just $ not . null) description <- askFor "description" Nothing (Just $ not . null)
ps <- getPostings [] let getpostingsandvalidate = do
ps <- getPostings []
let t = nullledgertxn{ltdate=date
,ltstatus=False
,ltdescription=description
,ltpostings=ps
}
either (const retry) (return) $ balanceLedgerTransaction t
retry = do
hPutStrLn stderr $ nonzerobalanceerror ++ ". Re-enter:"
getpostingsandvalidate
getpostingsandvalidate
let t = nullledgertxn{ltdate=date -- | Read two or more postings from the command line.
,ltstatus=False
,ltdescription=description
,ltpostings=ps
}
-- a final validation, will raise an error if not parseable and balanced
putStrLn =<< registerFromString (show t)
appendToLedgerFile l $ show t
liftM (t:) (getAndAddTransactions l)
) `catch` (\e -> if isEOFError e then return [] else ioError e)
where parseSmartDate = parse smartdate "" . lowercase
-- | Read two or more postings interactively.
getPostings :: [Posting] -> IO [Posting] getPostings :: [Posting] -> IO [Posting]
getPostings prevps = do getPostings prevps = do
account <- askFor "account" Nothing (Just $ \s -> not $ null s && (length prevps < 2)) account <- askFor (printf "account %d" n) Nothing (Just $ \s -> not $ null s && (length prevps < 2))
if null account if null account
then return prevps then return prevps
else do else do
amount <- liftM (fromparse . parse (someamount <|> return missingamt) "") amount <- liftM (fromparse . parse (someamount <|> return missingamt) "")
$ askFor "amount" Nothing (Just $ \s -> not $ null s && null prevps) $ askFor (printf "amount %d" n) Nothing
(Just $ \s -> (null s && (not $ null prevps)) ||
(isRight $ parse (someamount>>many spacenonewline>>eof) "" s))
let p = nullrawposting{paccount=account,pamount=amount} let p = nullrawposting{paccount=account,pamount=amount}
if amount == missingamt if amount == missingamt
then return $ prevps ++ [p] then return $ prevps ++ [p]
else getPostings $ prevps ++ [p] else getPostings $ prevps ++ [p]
where n = length prevps + 1
-- | Prompt and read a string value, possibly with a default and a validator. -- | Prompt and read a string value, possibly with a default and a validator.
-- A validator will cause the prompt to repeat until the input is valid. -- A validator will cause the prompt to repeat until the input is valid.
@ -78,9 +88,15 @@ askFor prompt def validator = do
Nothing -> return input Nothing -> return input
where showdef s = " [" ++ s ++ "]" where showdef s = " [" ++ s ++ "]"
-- | Append a string of transactions to the ledger's file, ensuring proper -- | Append this transaction to the ledger's file.
-- separation from the existing data; or if the file is "-", print them addTransaction :: Ledger -> LedgerTransaction -> IO LedgerTransaction
-- to stdout. addTransaction l t = do
putStrLn =<< registerFromString (show t)
appendToLedgerFile l $ show t
return t
-- | Append data to the ledger's file, ensuring proper separation from any
-- existing data; or if the file is "-", dump it to stdout.
appendToLedgerFile :: Ledger -> String -> IO () appendToLedgerFile :: Ledger -> String -> IO ()
appendToLedgerFile l s = appendToLedgerFile l s =
if f == "-" if f == "-"