diff --git a/Utils.hs b/Utils.hs index 2e19e5e33..c04bb97fb 100644 --- a/Utils.hs +++ b/Utils.hs @@ -11,23 +11,29 @@ import Control.Monad.Error import Data.Time.Clock import Ledger import Options (Opt,ledgerFilePathFromOpts,optsToIOArgs) +import System.Directory (doesFileExist) import System.IO import Text.ParserCombinators.Parsec import qualified Data.Map as Map (lookup) --- | parse the user's specified ledger file and run a hledger command on it, --- or report a parse error. This function makes the whole thing go. -withLedgerDo :: [Opt] -> [String] -> ([Opt] -> [String] -> Ledger -> IO ()) -> IO () -withLedgerDo opts args cmd = do +-- | Parse the user's specified ledger file and run a hledger command on +-- it, or report a parse error. This function makes the whole thing go. +withLedgerDo :: [Opt] -> [String] -> String -> ([Opt] -> [String] -> Ledger -> IO ()) -> IO () +withLedgerDo opts args cmdname cmd = do + -- We kludgily read the file before parsing to grab the full text, unless + -- it's stdin, or it doesn't exist and we are adding. We read it strictly + -- to let the add command work. f <- ledgerFilePathFromOpts opts - -- kludgily read the file a second time to get the full text. Only the ui command needs it. - -- kludgily try not to fail if it's stdin. - -- read it strictly to let the add command work - rawtext <- strictReadFile $ if f == "-" then "/dev/null" else f + let f' = if f == "-" then "/dev/null" else f + fileexists <- doesFileExist f + let creating = not fileexists && cmdname == "add" + rawtext <- if creating then return "" else strictReadFile f' t <- getCurrentLocalTime - let runcmd = cmd opts args . filterAndCacheLedgerWithOpts opts args t rawtext . (\rl -> rl{filepath=f}) - return f >>= runErrorT . parseLedgerFile t >>= either (hPutStrLn stderr) runcmd + let go = cmd opts args . filterAndCacheLedgerWithOpts opts args t rawtext . (\rl -> rl{filepath=f}) + case creating of + True -> return rawLedgerEmpty >>= go + False -> return f >>= runErrorT . parseLedgerFile t >>= either (hPutStrLn stderr) go -- | Get a Ledger from the given string and options, or raise an error. ledgerFromStringWithOpts :: [Opt] -> [String] -> LocalTime -> String -> IO Ledger diff --git a/hledger.hs b/hledger.hs index f69b1a82e..6fae6b4d5 100644 --- a/hledger.hs +++ b/hledger.hs @@ -84,17 +84,17 @@ main = do run cmd opts args | Help `elem` opts = putStr $ usage | Version `elem` opts = putStr versionmsg - | cmd `isPrefixOf` "balance" = withLedgerDo opts args balance - | cmd `isPrefixOf` "convert" = withLedgerDo opts args convert - | cmd `isPrefixOf` "print" = withLedgerDo opts args print' - | cmd `isPrefixOf` "register" = withLedgerDo opts args register - | cmd `isPrefixOf` "histogram" = withLedgerDo opts args histogram - | cmd `isPrefixOf` "add" = withLedgerDo opts args add + | cmd `isPrefixOf` "balance" = withLedgerDo opts args cmd balance + | cmd `isPrefixOf` "convert" = withLedgerDo opts args cmd convert + | cmd `isPrefixOf` "print" = withLedgerDo opts args cmd print' + | cmd `isPrefixOf` "register" = withLedgerDo opts args cmd register + | cmd `isPrefixOf` "histogram" = withLedgerDo opts args cmd histogram + | cmd `isPrefixOf` "add" = withLedgerDo opts args cmd add #ifdef VTY - | cmd `isPrefixOf` "ui" = withLedgerDo opts args ui + | cmd `isPrefixOf` "ui" = withLedgerDo opts args cmd ui #endif #ifdef HAPPS - | cmd `isPrefixOf` "web" = withLedgerDo opts args web + | cmd `isPrefixOf` "web" = withLedgerDo opts args cmd web #endif | cmd `isPrefixOf` "test" = runtests opts args >> return () | otherwise = putStr $ usage