lib, print: rename --new's save files to .latest.*, easier to manage

This commit is contained in:
Simon Michael 2017-09-17 13:26:42 -07:00
parent c79c8b9883
commit 1edb828a75
5 changed files with 182 additions and 173 deletions

View File

@ -261,7 +261,7 @@ tryReaders readers mrulesfile assrt path t = firstSuccessOrFirstError [] readers
path' = fromMaybe "(string)" path path' = fromMaybe "(string)" path
--- New versions of readJournal* with easier arguments, and --new/last-seen handling. --- New versions of readJournal* with easier arguments, and support for --new.
readJournalFilesWithOpts :: InputOpts -> [FilePath] -> IO (Either String Journal) readJournalFilesWithOpts :: InputOpts -> [FilePath] -> IO (Either String Journal)
readJournalFilesWithOpts iopts = readJournalFilesWithOpts iopts =
@ -282,21 +282,60 @@ readJournalFileWithOpts iopts prefixedfile = do
case ej of case ej of
Left e -> return $ Left e Left e -> return $ Left e
Right j | new_ iopts -> do Right j | new_ iopts -> do
lastdates <- lastSeen f ds <- previousLatestDates f
let (newj, newlastdates) = journalFilterSinceLastDates lastdates j let (newj, newds) = journalFilterSinceLatestDates ds j
when (not $ null newlastdates) $ saveLastSeen newlastdates f when (not $ null newds) $ saveLatestDates newds f
return $ Right newj return $ Right newj
Right j -> return $ Right j Right j -> return $ Right j
-- | Given zero or more date values (all the same, representing the -- A "LatestDates" is zero or more copies of the same date,
-- representing the latest transaction date read from a file,
-- and how many transactions there were on that date.
type LatestDates = [Day]
-- | Get all instances of the latest date in an unsorted list of dates.
-- Ie, if the latest date appears once, return it in a one-element list,
-- if it appears three times (anywhere), return three of it.
latestDates :: [Day] -> LatestDates
latestDates = headDef [] . take 1 . group . reverse . sort
-- | Remember that these transaction dates were the latest seen when
-- reading this journal file.
saveLatestDates :: LatestDates -> FilePath -> IO ()
saveLatestDates dates f = writeFile (latestDatesFileFor f) $ unlines $ map showDate dates
-- | What were the latest transaction dates seen the last time this
-- journal file was read ? If there were multiple transactions on the
-- latest date, that number of dates is returned, otherwise just one.
-- Or none if no transactions were read, or if latest dates info is not
-- available for this file.
previousLatestDates :: FilePath -> IO LatestDates
previousLatestDates f = do
let latestfile = latestDatesFileFor f
exists <- doesFileExist latestfile
if exists
then map (parsedate . strip) . lines . strip . T.unpack <$> readFileStrictly latestfile
else return []
-- | Where to save latest transaction dates for the given file path.
-- (.latest.FILE)
latestDatesFileFor :: FilePath -> FilePath
latestDatesFileFor f = dir </> ".latest" <.> fname
where
(dir, fname) = splitFileName f
readFileStrictly :: FilePath -> IO Text
readFileStrictly f = readFile' f >>= \t -> C.evaluate (T.length t) >> return t
-- | Given zero or more latest dates (all the same, representing the
-- latest previously seen transaction date, and how many transactions -- latest previously seen transaction date, and how many transactions
-- were seen on that date), remove transactions with earlier dates -- were seen on that date), remove transactions with earlier dates
-- from the journal, and the same number of transactions on the -- from the journal, and the same number of transactions on the
-- latest date, if any, leaving only transactions that we can assume -- latest date, if any, leaving only transactions that we can assume
-- are newer. Also returns the new last dates of the new journal. -- are newer. Also returns the new latest dates of the new journal.
journalFilterSinceLastDates :: [Day] -> Journal -> (Journal, [Day]) journalFilterSinceLatestDates :: LatestDates -> Journal -> (Journal, LatestDates)
journalFilterSinceLastDates [] j = (j, latestDates $ map tdate $ jtxns j) journalFilterSinceLatestDates [] j = (j, latestDates $ map tdate $ jtxns j)
journalFilterSinceLastDates ds@(d:_) j = (j', ds') journalFilterSinceLatestDates ds@(d:_) j = (j', ds')
where where
samedateorlaterts = filter ((>= d).tdate) $ jtxns j samedateorlaterts = filter ((>= d).tdate) $ jtxns j
(samedatets, laterts) = span ((== d).tdate) $ sortBy (comparing tdate) samedateorlaterts (samedatets, laterts) = span ((== d).tdate) $ sortBy (comparing tdate) samedateorlaterts
@ -304,41 +343,6 @@ journalFilterSinceLastDates ds@(d:_) j = (j', ds')
j' = j{jtxns=newsamedatets++laterts} j' = j{jtxns=newsamedatets++laterts}
ds' = latestDates $ map tdate $ samedatets++laterts ds' = latestDates $ map tdate $ samedatets++laterts
-- | Get all instances of the latest date in an unsorted list of dates.
-- Ie, if the latest date appears once, return it in a one-element list,
-- if it appears three times (anywhere), return three of it.
latestDates :: [Day] -> [Day]
latestDates = headDef [] . take 1 . group . reverse . sort
-- | Where to save last-seen transactions info for the given file path
-- (.FILE.seen).
seenFileFor :: FilePath -> FilePath
seenFileFor f = dir </> fname' <.> "seen"
where
(dir, fname) = splitFileName f
fname' | "." `isPrefixOf` fname = fname
| otherwise = '.':fname
-- | What were the latest transaction dates seen the last time this
-- journal file was read ? If there were multiple transactions on the
-- latest date, that number of dates is returned, otherwise just one.
-- Or none if no transactions were seen.
lastSeen :: FilePath -> IO [Day]
lastSeen f = do
let seenfile = seenFileFor f
exists <- doesFileExist seenfile
if exists
then map (parsedate . strip) . lines . strip . T.unpack <$> readFileStrictly seenfile
else return []
readFileStrictly :: FilePath -> IO Text
readFileStrictly f = readFile' f >>= \t -> C.evaluate (T.length t) >> return t
-- | Remember that these transaction dates were the latest seen when
-- reading this journal file.
saveLastSeen :: [Day] -> FilePath -> IO ()
saveLastSeen dates f = writeFile (seenFileFor f) $ unlines $ map showDate dates
readJournalWithOpts :: InputOpts -> Maybe FilePath -> Text -> IO (Either String Journal) readJournalWithOpts :: InputOpts -> Maybe FilePath -> Text -> IO (Either String Journal)
readJournalWithOpts iopts mfile txt = readJournalWithOpts iopts mfile txt =
tryReadersWithOpts iopts mfile specifiedorallreaders txt tryReadersWithOpts iopts mfile specifiedorallreaders txt

View File

@ -524,16 +524,18 @@ With `-m`/`--match` and a STR argument, print will show at most one transaction:
one whose description is most similar to STR, and is most recent. STR should contain at one whose description is most similar to STR, and is most recent. STR should contain at
least two characters. If there is no similar-enough match, no transaction will be shown. least two characters. If there is no similar-enough match, no transaction will be shown.
With `--new`, for each FILE being read, hledger reads (and writes) a special .FILE.seen file in the same directory, With `--new`, for each FILE being read, hledger reads (and writes) a special
containing the latest transaction date(s) that were seen last time FILE was read. .latest.FILE file in the same directory, containing the latest transaction date(s)
When this file is found, only transactions with newer dates (and new transactions on the latest date) are printed. that were seen last time FILE was read. When this file is found, only transactions
with newer dates (and new transactions on the latest date) are printed.
This is useful for ignoring already-seen entries in import data, such as downloaded CSV files. This is useful for ignoring already-seen entries in import data, such as downloaded CSV files.
Eg: Eg:
```console ```console
$ hledger -f bank1.csv print --new $ hledger -f bank1.csv print --new
# shows transactions added since last print --new on this file # shows transactions added since last print --new on this file
``` ```
It assumes that only same-or-newer-dated transactions are added to FILE, and that the order of same-date transactions remains stable. This assumes that transactions added to FILE always have same or increasing dates,
and that transactions on the same day do not get reordered.
The print command also supports The print command also supports
[output destination](#output-destination) [output destination](#output-destination)

View File

@ -2140,8 +2140,8 @@ STR should contain at least two characters.
If there is no similar\-enough match, no transaction will be shown. If there is no similar\-enough match, no transaction will be shown.
.PP .PP
With \f[C]\-\-new\f[], for each FILE being read, hledger reads (and With \f[C]\-\-new\f[], for each FILE being read, hledger reads (and
writes) a special .FILE.seen file in the same directory, containing the writes) a special .latest.FILE file in the same directory, containing
latest transaction date(s) that were seen last time FILE was read. the latest transaction date(s) that were seen last time FILE was read.
When this file is found, only transactions with newer dates (and new When this file is found, only transactions with newer dates (and new
transactions on the latest date) are printed. transactions on the latest date) are printed.
This is useful for ignoring already\-seen entries in import data, such This is useful for ignoring already\-seen entries in import data, such
@ -2155,8 +2155,9 @@ $\ hledger\ \-f\ bank1.csv\ print\ \-\-new
\f[] \f[]
.fi .fi
.PP .PP
It assumes that only same\-or\-newer\-dated transactions are added to This assumes that transactions added to FILE always have same or
FILE, and that the order of same\-date transactions remains stable. increasing dates, and that transactions on the same day do not get
reordered.
.PP .PP
The print command also supports output destination and CSV output. The print command also supports output destination and CSV output.
Here\[aq]s an example of print\[aq]s CSV output: Here\[aq]s an example of print\[aq]s CSV output:

View File

@ -1713,7 +1713,7 @@ is most recent. STR should contain at least two characters. If there
is no similar-enough match, no transaction will be shown. is no similar-enough match, no transaction will be shown.
With '--new', for each FILE being read, hledger reads (and writes) a With '--new', for each FILE being read, hledger reads (and writes) a
special .FILE.seen file in the same directory, containing the latest special .latest.FILE file in the same directory, containing the latest
transaction date(s) that were seen last time FILE was read. When this transaction date(s) that were seen last time FILE was read. When this
file is found, only transactions with newer dates (and new transactions file is found, only transactions with newer dates (and new transactions
on the latest date) are printed. This is useful for ignoring on the latest date) are printed. This is useful for ignoring
@ -1722,8 +1722,9 @@ already-seen entries in import data, such as downloaded CSV files. Eg:
$ hledger -f bank1.csv print --new $ hledger -f bank1.csv print --new
# shows transactions added since last print --new on this file # shows transactions added since last print --new on this file
It assumes that only same-or-newer-dated transactions are added to This assumes that transactions added to FILE always have same or
FILE, and that the order of same-date transactions remains stable. increasing dates, and that transactions on the same day do not get
reordered.
The print command also supports output destination and CSV output. The print command also supports output destination and CSV output.
Here's an example of print's CSV output: Here's an example of print's CSV output:
@ -2233,51 +2234,51 @@ Node: prices52658
Ref: #prices52775 Ref: #prices52775
Node: print52818 Node: print52818
Ref: #print52930 Ref: #print52930
Node: print-unique57726 Node: print-unique57737
Ref: #print-unique57854 Ref: #print-unique57865
Node: register57922 Node: register57933
Ref: #register58051 Ref: #register58062
Node: Custom register output62552 Node: Custom register output62563
Ref: #custom-register-output62683 Ref: #custom-register-output62694
Node: register-match63980 Node: register-match63991
Ref: #register-match64116 Ref: #register-match64127
Node: rewrite64299 Node: rewrite64310
Ref: #rewrite64418 Ref: #rewrite64429
Node: stats64487 Node: stats64498
Ref: #stats64592 Ref: #stats64603
Node: tags65473 Node: tags65484
Ref: #tags65573 Ref: #tags65584
Node: test65605 Node: test65616
Ref: #test65691 Ref: #test65702
Node: ADD-ON COMMANDS66059 Node: ADD-ON COMMANDS66070
Ref: #add-on-commands66171 Ref: #add-on-commands66182
Node: Official add-ons67458 Node: Official add-ons67469
Ref: #official-add-ons67600 Ref: #official-add-ons67611
Node: api67687 Node: api67698
Ref: #api67778 Ref: #api67789
Node: ui67830 Node: ui67841
Ref: #ui67931 Ref: #ui67942
Node: web67989 Node: web68000
Ref: #web68080 Ref: #web68091
Node: Third party add-ons68126 Node: Third party add-ons68137
Ref: #third-party-add-ons68303 Ref: #third-party-add-ons68314
Node: diff68438 Node: diff68449
Ref: #diff68537 Ref: #diff68548
Node: iadd68636 Node: iadd68647
Ref: #iadd68752 Ref: #iadd68763
Node: interest68835 Node: interest68846
Ref: #interest68958 Ref: #interest68969
Node: irr69053 Node: irr69064
Ref: #irr69153 Ref: #irr69164
Node: Experimental add-ons69231 Node: Experimental add-ons69242
Ref: #experimental-add-ons69385 Ref: #experimental-add-ons69396
Node: autosync69676 Node: autosync69687
Ref: #autosync69790 Ref: #autosync69801
Node: budget70029 Node: budget70040
Ref: #budget70153 Ref: #budget70164
Node: chart70219 Node: chart70230
Ref: #chart70338 Ref: #chart70349
Node: check70409 Node: check70420
Ref: #check70513 Ref: #check70524
 
End Tag Table End Tag Table

View File

@ -1511,7 +1511,7 @@ COMMANDS
no similar-enough match, no transaction will be shown. no similar-enough match, no transaction will be shown.
With --new, for each FILE being read, hledger reads (and writes) a spe- With --new, for each FILE being read, hledger reads (and writes) a spe-
cial .FILE.seen file in the same directory, containing the latest cial .latest.FILE file in the same directory, containing the latest
transaction date(s) that were seen last time FILE was read. When this transaction date(s) that were seen last time FILE was read. When this
file is found, only transactions with newer dates (and new transactions file is found, only transactions with newer dates (and new transactions
on the latest date) are printed. This is useful for ignoring on the latest date) are printed. This is useful for ignoring
@ -1520,8 +1520,9 @@ COMMANDS
$ hledger -f bank1.csv print --new $ hledger -f bank1.csv print --new
# shows transactions added since last print --new on this file # shows transactions added since last print --new on this file
It assumes that only same-or-newer-dated transactions are added to This assumes that transactions added to FILE always have same or
FILE, and that the order of same-date transactions remains stable. increasing dates, and that transactions on the same day do not get
reordered.
The print command also supports output destination and CSV output. The print command also supports output destination and CSV output.
Here's an example of print's CSV output: Here's an example of print's CSV output: