diff --git a/hledger-lib/Hledger/Read.hs b/hledger-lib/Hledger/Read.hs index 4a2314f96..e970aef2d 100644 --- a/hledger-lib/Hledger/Read.hs +++ b/hledger-lib/Hledger/Read.hs @@ -124,7 +124,7 @@ tryReaders readers mrulesfile assrt path s = firstSuccessOrBestError [] readers -- A CSV conversion rules file may also be specified for use by the CSV reader. -- Also there is a flag specifying whether to check or ignore balance assertions in the journal. readJournal :: Maybe StorageFormat -> Maybe FilePath -> Bool -> Maybe FilePath -> String -> IO (Either String Journal) -readJournal mformat mrulesfile assrt path s = tryReaders (readersFor (mformat, path, s)) mrulesfile assrt path s +readJournal mformat mrulesfile assrt mpath s = tryReaders (readersFor (mformat, mpath, s)) mrulesfile assrt mpath s -- | Read a Journal from this file (or stdin if the filename is -) or give -- an error message, using the specified data format or trying all known @@ -132,20 +132,30 @@ readJournal mformat mrulesfile assrt path s = tryReaders (readersFor (mformat, p -- conversion of that format. Also there is a flag specifying whether -- to check or ignore balance assertions in the journal. readJournalFile :: Maybe StorageFormat -> Maybe FilePath -> Bool -> FilePath -> IO (Either String Journal) -readJournalFile format rulesfile assrt f = readJournalFiles format rulesfile assrt [f] +readJournalFile mformat mrulesfile assrt f = + readFileOrStdinAnyNewline f >>= readJournal mformat mrulesfile assrt (Just f) +-- | Read the given file, or standard input if the path is "-". +readFileOrStdinAnyNewline :: String -> IO String +readFileOrStdinAnyNewline f = do + requireJournalFileExists f + h <- fileHandle f + hSetNewlineMode h universalNewlineMode + hGetContents h + where + fileHandle "-" = return stdin + fileHandle f = openFile f ReadMode + +-- | Call readJournalFile on each specified file path, and combine the +-- resulting journals into one. If there are any errors, the first is +-- returned, otherwise they are combined per Journal's monoid instance +-- (concatenated, basically). Currently the parse state (eg directives +-- & aliases in effect) resets at the start of each file (though the +-- final parse states from all files are combined at the end). readJournalFiles :: Maybe StorageFormat -> Maybe FilePath -> Bool -> [FilePath] -> IO (Either String Journal) -readJournalFiles format rulesfile assrt fs = do - contents <- fmap concat $ mapM readFileAnyNewline fs - readJournal format rulesfile assrt (listToMaybe fs) contents - where - readFileAnyNewline f = do - requireJournalFileExists f - h <- fileHandle f - hSetNewlineMode h universalNewlineMode - hGetContents h - fileHandle "-" = return stdin - fileHandle f = openFile f ReadMode +readJournalFiles mformat mrulesfile assrt fs = do + (either Left (Right . mconcat) . sequence) + <$> mapM (readJournalFile mformat mrulesfile assrt) fs -- | If the specified journal file does not exist, give a helpful error and quit. requireJournalFileExists :: FilePath -> IO () diff --git a/hledger/doc/commands.m4.md b/hledger/doc/commands.m4.md index 60595ea67..9089057bf 100644 --- a/hledger/doc/commands.m4.md +++ b/hledger/doc/commands.m4.md @@ -108,7 +108,8 @@ Prompt for transactions and add them to the journal. Many hledger users edit their journals directly with a text editor, or generate them from CSV. For more interactive data entry, there is the `add` command, which prompts interactively on the console for new transactions, and appends -them to the journal file (existing transactions are not changed). +them to the journal file (if there are multiple `-f FILE` options, the first file is used.) +Existing transactions are not changed. This is the only hledger command that writes to the journal file. To use it, just run `hledger add` and follow the prompts. diff --git a/hledger/doc/options.m4.md b/hledger/doc/options.m4.md index fd91c79f1..86cb07e09 100644 --- a/hledger/doc/options.m4.md +++ b/hledger/doc/options.m4.md @@ -110,9 +110,11 @@ Both of these must be written after the command name. ## Multiple files -One may specify the `--file FILE` option multiple times. This is equivalent to -concatenating the files to standard input and passing `--file -`, except that -the add command functions normally and adds entries to the first specified file. +You can specify multiple `-f/--file FILE` options. This is like +combining all the files into one, except they can have different formats. +Also directives and aliases in one file do not affect subsequent files +(if you need that, use the [include directive](#including-other-files) +instead). ## Repeated options diff --git a/tests/cli/multiple-files.test b/tests/cli/multiple-files.test index b94e314c1..d53c73fbc 100644 --- a/tests/cli/multiple-files.test +++ b/tests/cli/multiple-files.test @@ -20,7 +20,7 @@ Total: >>>2 >>>=0 -# 2. aliases in files should only apply to later files +# 2. aliases etc. in files currently don't carry over to subsequent files hledger print -f personal.journal -f business.journal -f alias.journal -f personal.journal >>> 2014/01/01 @@ -32,8 +32,27 @@ hledger print -f personal.journal -f business.journal -f alias.journal -f person assets:cash $-1 2014/01/02 - equity:draw:personal:food $1 - assets:personal:cash $-1 + expenses:food $1 + assets:cash $-1 >>>2 >>>=0 +# 2014/01/02 +# equity:draw:personal:food $1 +# assets:personal:cash $-1 + + +# 3. files can be of different formats +hledger print -f personal.journal -f a.timeclock -f b.timedot +>>> +2014/01/02 + expenses:food $1 + assets:cash $-1 + +2016/01/01 * 12:00-16:00 + (a:aa) 4.00h + +2016/01/01 * + (b.bb) 1.00 + +>>>=0