1 {-| 2 3 Utilities for top-level modules and ghci. See also "Ledger.IO" and 4 "Ledger.Utils". 5 6 -} 7 8 module Utils 9 where 10 import Control.Monad.Error 11 import Data.Time.Clock 12 import Ledger 13 import Options (Opt,ledgerFilePathFromOpts,optsToIOArgs) 14 import System.Directory (doesFileExist) 15 import System.IO 16 import Text.ParserCombinators.Parsec 17 import qualified Data.Map as Map (lookup) 18 19 20 -- | Parse the user's specified ledger file and run a hledger command on 21 -- it, or report a parse error. This function makes the whole thing go. 22 withLedgerDo :: [Opt] -> [String] -> String -> ([Opt] -> [String] -> Ledger -> IO ()) -> IO () 23 withLedgerDo opts args cmdname cmd = do 24 -- We kludgily read the file before parsing to grab the full text, unless 25 -- it's stdin, or it doesn't exist and we are adding. We read it strictly 26 -- to let the add command work. 27 f <- ledgerFilePathFromOpts opts 28 let f' = if f == "-" then "/dev/null" else f 29 fileexists <- doesFileExist f 30 let creating = not fileexists && cmdname == "add" 31 rawtext <- if creating then return "" else strictReadFile f' 32 t <- getCurrentLocalTime 33 let go = cmd opts args . filterAndCacheLedgerWithOpts opts args t rawtext . (\rl -> rl{filepath=f}) 34 case creating of 35 True -> return rawLedgerEmpty >>= go 36 False -> return f >>= runErrorT . parseLedgerFile t >>= either (hPutStrLn stderr) go 37 38 -- | Get a Ledger from the given string and options, or raise an error. 39 ledgerFromStringWithOpts :: [Opt] -> [String] -> LocalTime -> String -> IO Ledger 40 ledgerFromStringWithOpts opts args reftime s = 41 liftM (filterAndCacheLedgerWithOpts opts args reftime s) $ rawLedgerFromString s 42 43 -- | Read a Ledger from the given file, filtering according to the 44 -- options, or give an error. 45 readLedgerWithOpts :: [Opt] -> [String] -> FilePath -> IO Ledger 46 readLedgerWithOpts opts args f = do 47 t <- getCurrentLocalTime 48 readLedgerWithIOArgs (optsToIOArgs opts args t) f 49 50 -- | Convert a RawLedger to a canonicalised, cached and filtered Ledger 51 -- based on the command-line options/arguments and a reference time. 52 filterAndCacheLedgerWithOpts :: [Opt] -> [String] -> LocalTime -> String -> RawLedger -> Ledger 53 filterAndCacheLedgerWithOpts opts args t = filterAndCacheLedger (optsToIOArgs opts args t) 54