auto-create missing journal files rather than giving an error
This commit is contained in:
		
							parent
							
								
									50aeb272b0
								
							
						
					
					
						commit
						eefb04abfe
					
				| @ -28,13 +28,14 @@ import qualified Data.Foldable as Foldable (find) | |||||||
| -- command has no effect. | -- command has no effect. | ||||||
| add :: [Opt] -> [String] -> Journal -> IO () | add :: [Opt] -> [String] -> Journal -> IO () | ||||||
| add opts args j | add opts args j | ||||||
|     | filepath j == "-" = return () |     | f == "-" = return () | ||||||
|     | otherwise = do |     | otherwise = do | ||||||
|   hPutStrLn stderr $ |   hPutStrLn stderr $ | ||||||
|     "Enter one or more transactions, which will be added to your journal file.\n" |     "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." |     ++"To complete a transaction, enter . as account name. To quit, press control-c." | ||||||
|   today <- getCurrentDay |   today <- getCurrentDay | ||||||
|   getAndAddTransactions j opts args today `catch` (\e -> unless (isEOFError e) $ ioError e) |   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, | -- | Read a number of transactions from the command line, prompting, | ||||||
| -- validating, displaying and appending them to the journal file, until | -- validating, displaying and appending them to the journal file, until | ||||||
|  | |||||||
| @ -23,7 +23,7 @@ import Hledger.Data | |||||||
| import Hledger.Read | import Hledger.Read | ||||||
| import Hledger.Cli.Options (Opt(..),journalFilePathFromOpts) -- ,optsToFilterSpec) | import Hledger.Cli.Options (Opt(..),journalFilePathFromOpts) -- ,optsToFilterSpec) | ||||||
| import Safe (readMay) | import Safe (readMay) | ||||||
| import System.Directory (doesFileExist, getModificationTime, getDirectoryContents, copyFile) | import System.Directory (getModificationTime, getDirectoryContents, copyFile) | ||||||
| import System.Exit | import System.Exit | ||||||
| import System.FilePath ((</>), splitFileName, takeDirectory) | import System.FilePath ((</>), splitFileName, takeDirectory) | ||||||
| import System.Info (os) | 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 | -- | Parse the user's specified journal file and run a hledger command on | ||||||
| -- it, or throw an error. | -- it, or throw an error. | ||||||
| withJournalDo :: [Opt] -> [String] -> String -> ([Opt] -> [String] -> Journal -> IO ()) -> IO () | 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 |   -- 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 |   -- it's stdin, or it doesn't exist and we are adding. We read it strictly | ||||||
|   -- to let the add command work. |   -- to let the add command work. | ||||||
|   f <- journalFilePathFromOpts opts |   journalFilePathFromOpts opts >>= readJournalFile Nothing >>= either error runcmd | ||||||
|   fileexists <- doesFileExist f |     where | ||||||
|   let creating = not fileexists && cmdname == "add" |  | ||||||
|       costify = (if CostBasis `elem` opts then journalConvertAmountsToCost else id) |       costify = (if CostBasis `elem` opts then journalConvertAmountsToCost else id) | ||||||
|       runcmd = cmd opts args . costify |       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. | -- | Get a journal from the given string and options, or throw an error. | ||||||
| readJournalWithOpts :: [Opt] -> String -> IO Journal | readJournalWithOpts :: [Opt] -> String -> IO Journal | ||||||
| readJournalWithOpts opts s = do | readJournalWithOpts opts s = do | ||||||
|     j <- readJournal Nothing s >>= either error return |   j <- readJournal Nothing s >>= either error return | ||||||
|     let cost = CostBasis `elem` opts |   return $ (if cost then journalConvertAmountsToCost else id) j | ||||||
|     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. | -- | Re-read a journal from its data file, or return an error string. | ||||||
| journalReload :: Journal -> IO (Either String Journal) | journalReload :: Journal -> IO (Either String Journal) | ||||||
|  | |||||||
| @ -16,16 +16,18 @@ module Hledger.Read ( | |||||||
|        myTimelog, |        myTimelog, | ||||||
| ) | ) | ||||||
| where | where | ||||||
|  | import Hledger.Data.Dates (getCurrentDay) | ||||||
| import Hledger.Data.Types (Journal(..)) | import Hledger.Data.Types (Journal(..)) | ||||||
| import Hledger.Data.Utils | import Hledger.Data.Utils | ||||||
| import Hledger.Read.Common | import Hledger.Read.Common | ||||||
| import Hledger.Read.Journal as Journal | import Hledger.Read.Journal as Journal | ||||||
| import Hledger.Read.Timelog as Timelog | import Hledger.Read.Timelog as Timelog | ||||||
|  | import Hledger.Cli.Version (version) | ||||||
| 
 | 
 | ||||||
| import Control.Monad.Error | import Control.Monad.Error | ||||||
| import Data.Either (partitionEithers) | import Data.Either (partitionEithers) | ||||||
| import Safe (headDef) | import Safe (headDef) | ||||||
| import System.Directory (getHomeDirectory) | import System.Directory (doesFileExist, getHomeDirectory) | ||||||
| import System.Environment (getEnv) | import System.Environment (getEnv) | ||||||
| import System.FilePath ((</>)) | import System.FilePath ((</>)) | ||||||
| import System.IO (IOMode(..), withFile, hGetContents, stderr) | import System.IO (IOMode(..), withFile, hGetContents, stderr) | ||||||
| @ -82,10 +84,28 @@ journalFromPathAndString format fp s = do | |||||||
|                 fmt fs = intercalate ", " (init fs) ++ " or " ++ last fs ++ " " |                 fmt fs = intercalate ", " (init fs) ++ " or " ++ last fs ++ " " | ||||||
| 
 | 
 | ||||||
| -- | Read a journal from this file, using the specified data format or | -- | 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 :: Maybe String -> FilePath -> IO (Either String Journal) | ||||||
| readJournalFile format "-" = getContents >>= journalFromPathAndString format "(stdin)" | 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 | -- | Read a Journal from this string, using the specified data format or | ||||||
| -- trying all known formats, or give an error string. | -- trying all known formats, or give an error string. | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user