auto-create missing journal files rather than giving an error

This commit is contained in:
Simon Michael 2010-07-13 19:36:43 +00:00
parent 50aeb272b0
commit eefb04abfe
3 changed files with 32 additions and 15 deletions

View File

@ -28,13 +28,14 @@ import qualified Data.Foldable as Foldable (find)
-- command has no effect.
add :: [Opt] -> [String] -> Journal -> IO ()
add opts args j
| filepath j == "-" = return ()
| f == "-" = return ()
| otherwise = do
hPutStrLn stderr $
"Enter one or more transactions, which will be added to your journal file.\n"
++"To complete a transaction, enter . as account name. To quit, press control-c."
today <- getCurrentDay
getAndAddTransactions j opts args today `catch` (\e -> unless (isEOFError e) $ ioError e)
where f = filepath j
-- | Read a number of transactions from the command line, prompting,
-- validating, displaying and appending them to the journal file, until

View File

@ -23,7 +23,7 @@ import Hledger.Data
import Hledger.Read
import Hledger.Cli.Options (Opt(..),journalFilePathFromOpts) -- ,optsToFilterSpec)
import Safe (readMay)
import System.Directory (doesFileExist, getModificationTime, getDirectoryContents, copyFile)
import System.Directory (getModificationTime, getDirectoryContents, copyFile)
import System.Exit
import System.FilePath ((</>), splitFileName, takeDirectory)
import System.Info (os)
@ -34,25 +34,21 @@ import System.Time (ClockTime, getClockTime, diffClockTimes, TimeDiff(TimeDiff))
-- | Parse the user's specified journal file and run a hledger command on
-- it, or throw an error.
withJournalDo :: [Opt] -> [String] -> String -> ([Opt] -> [String] -> Journal -> IO ()) -> IO ()
withJournalDo opts args cmdname cmd = do
withJournalDo opts args _ 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 <- journalFilePathFromOpts opts
fileexists <- doesFileExist f
let creating = not fileexists && cmdname == "add"
journalFilePathFromOpts opts >>= readJournalFile Nothing >>= either error runcmd
where
costify = (if CostBasis `elem` opts then journalConvertAmountsToCost else id)
runcmd = cmd opts args . costify
if creating
then runcmd nulljournal
else readJournalFile Nothing f >>= either error runcmd
-- | Get a journal from the given string and options, or throw an error.
readJournalWithOpts :: [Opt] -> String -> IO Journal
readJournalWithOpts opts s = do
j <- readJournal Nothing s >>= either error return
let cost = CostBasis `elem` opts
return $ (if cost then journalConvertAmountsToCost else id) j
j <- readJournal Nothing s >>= either error return
return $ (if cost then journalConvertAmountsToCost else id) j
where cost = CostBasis `elem` opts
-- | Re-read a journal from its data file, or return an error string.
journalReload :: Journal -> IO (Either String Journal)

View File

@ -16,16 +16,18 @@ module Hledger.Read (
myTimelog,
)
where
import Hledger.Data.Dates (getCurrentDay)
import Hledger.Data.Types (Journal(..))
import Hledger.Data.Utils
import Hledger.Read.Common
import Hledger.Read.Journal as Journal
import Hledger.Read.Timelog as Timelog
import Hledger.Cli.Version (version)
import Control.Monad.Error
import Data.Either (partitionEithers)
import Safe (headDef)
import System.Directory (getHomeDirectory)
import System.Directory (doesFileExist, getHomeDirectory)
import System.Environment (getEnv)
import System.FilePath ((</>))
import System.IO (IOMode(..), withFile, hGetContents, stderr)
@ -82,10 +84,28 @@ journalFromPathAndString format fp s = do
fmt fs = intercalate ", " (init fs) ++ " or " ++ last fs ++ " "
-- | Read a journal from this file, using the specified data format or
-- trying all known formats, or give an error string.
-- trying all known formats, or give an error string; also create the file
-- if it doesn't exist.
readJournalFile :: Maybe String -> FilePath -> IO (Either String Journal)
readJournalFile format "-" = getContents >>= journalFromPathAndString format "(stdin)"
readJournalFile format f = withFile f ReadMode $ \h -> hGetContents h >>= journalFromPathAndString format f
readJournalFile format f = do
ensureJournalFile f
withFile f ReadMode $ \h -> hGetContents h >>= journalFromPathAndString format f
-- | Ensure there is a journal at the given file path, creating an empty one if needed.
ensureJournalFile :: FilePath -> IO ()
ensureJournalFile f = do
exists <- doesFileExist f
when (not exists) $ do
printf "No journal file at %s, creating...\n" f
printf "Edit this file or use hledger add or hledger web to add transactions.\n"
emptyJournal >>= writeFile f
-- | Give the content for a new auto-created journal file.
emptyJournal :: IO String
emptyJournal = do
d <- getCurrentDay
return $ printf "; journal created by hledger %s on %s\n; see http://hledger.org/MANUAL.html#file-format\n\n" version (show d)
-- | Read a Journal from this string, using the specified data format or
-- trying all known formats, or give an error string.