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
--- 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 iopts =
@ -282,21 +282,60 @@ readJournalFileWithOpts iopts prefixedfile = do
case ej of
Left e -> return $ Left e
Right j | new_ iopts -> do
lastdates <- lastSeen f
let (newj, newlastdates) = journalFilterSinceLastDates lastdates j
when (not $ null newlastdates) $ saveLastSeen newlastdates f
ds <- previousLatestDates f
let (newj, newds) = journalFilterSinceLatestDates ds j
when (not $ null newds) $ saveLatestDates newds f
return $ Right newj
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
-- were seen on that date), remove transactions with earlier dates
-- from the journal, and the same number of transactions on the
-- latest date, if any, leaving only transactions that we can assume
-- are newer. Also returns the new last dates of the new journal.
journalFilterSinceLastDates :: [Day] -> Journal -> (Journal, [Day])
journalFilterSinceLastDates [] j = (j, latestDates $ map tdate $ jtxns j)
journalFilterSinceLastDates ds@(d:_) j = (j', ds')
-- are newer. Also returns the new latest dates of the new journal.
journalFilterSinceLatestDates :: LatestDates -> Journal -> (Journal, LatestDates)
journalFilterSinceLatestDates [] j = (j, latestDates $ map tdate $ jtxns j)
journalFilterSinceLatestDates ds@(d:_) j = (j', ds')
where
samedateorlaterts = filter ((>= d).tdate) $ jtxns j
(samedatets, laterts) = span ((== d).tdate) $ sortBy (comparing tdate) samedateorlaterts
@ -304,41 +343,6 @@ journalFilterSinceLastDates ds@(d:_) j = (j', ds')
j' = j{jtxns=newsamedatets++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 iopts mfile 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
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,
containing 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 transactions on the latest date) are printed.
With `--new`, for each FILE being read, hledger reads (and writes) a special
.latest.FILE file in the same directory, containing 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 transactions on the latest date) are printed.
This is useful for ignoring already-seen entries in import data, such as downloaded CSV files.
Eg:
```console
$ hledger -f bank1.csv print --new
# 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
[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.
.PP
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
latest transaction date(s) that were seen last time FILE was read.
writes) a special .latest.FILE file in the same directory, containing
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
transactions on the latest date) are printed.
This is useful for ignoring already\-seen entries in import data, such
@ -2155,8 +2155,9 @@ $\ hledger\ \-f\ bank1.csv\ print\ \-\-new
\f[]
.fi
.PP
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.
.PP
The print command also supports output destination and 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.
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
file is found, only transactions with newer dates (and new transactions
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
# 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 output destination and CSV output.
Here's an example of print's CSV output:
@ -2233,51 +2234,51 @@ Node: prices52658
Ref: #prices52775
Node: print52818
Ref: #print52930
Node: print-unique57726
Ref: #print-unique57854
Node: register57922
Ref: #register58051
Node: Custom register output62552
Ref: #custom-register-output62683
Node: register-match63980
Ref: #register-match64116
Node: rewrite64299
Ref: #rewrite64418
Node: stats64487
Ref: #stats64592
Node: tags65473
Ref: #tags65573
Node: test65605
Ref: #test65691
Node: ADD-ON COMMANDS66059
Ref: #add-on-commands66171
Node: Official add-ons67458
Ref: #official-add-ons67600
Node: api67687
Ref: #api67778
Node: ui67830
Ref: #ui67931
Node: web67989
Ref: #web68080
Node: Third party add-ons68126
Ref: #third-party-add-ons68303
Node: diff68438
Ref: #diff68537
Node: iadd68636
Ref: #iadd68752
Node: interest68835
Ref: #interest68958
Node: irr69053
Ref: #irr69153
Node: Experimental add-ons69231
Ref: #experimental-add-ons69385
Node: autosync69676
Ref: #autosync69790
Node: budget70029
Ref: #budget70153
Node: chart70219
Ref: #chart70338
Node: check70409
Ref: #check70513
Node: print-unique57737
Ref: #print-unique57865
Node: register57933
Ref: #register58062
Node: Custom register output62563
Ref: #custom-register-output62694
Node: register-match63991
Ref: #register-match64127
Node: rewrite64310
Ref: #rewrite64429
Node: stats64498
Ref: #stats64603
Node: tags65484
Ref: #tags65584
Node: test65616
Ref: #test65702
Node: ADD-ON COMMANDS66070
Ref: #add-on-commands66182
Node: Official add-ons67469
Ref: #official-add-ons67611
Node: api67698
Ref: #api67789
Node: ui67841
Ref: #ui67942
Node: web68000
Ref: #web68091
Node: Third party add-ons68137
Ref: #third-party-add-ons68314
Node: diff68449
Ref: #diff68548
Node: iadd68647
Ref: #iadd68763
Node: interest68846
Ref: #interest68969
Node: irr69064
Ref: #irr69164
Node: Experimental add-ons69242
Ref: #experimental-add-ons69396
Node: autosync69687
Ref: #autosync69801
Node: budget70040
Ref: #budget70164
Node: chart70230
Ref: #chart70349
Node: check70420
Ref: #check70524

End Tag Table

View File

@ -1511,7 +1511,7 @@ COMMANDS
no similar-enough match, no transaction will be shown.
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
file is found, only transactions with newer dates (and new transactions
on the latest date) are printed. This is useful for ignoring
@ -1520,8 +1520,9 @@ COMMANDS
$ hledger -f bank1.csv print --new
# 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 output destination and CSV output.
Here's an example of print's CSV output: