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,10 +1520,11 @@ 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.
The print command also supports output destination and CSV output.
Here's an example of print's CSV output:
$ hledger print -Ocsv
@ -1540,20 +1541,20 @@ COMMANDS
"5","2008/12/31","","*","","pay off","","liabilities:debts","1","$","","1","",""
"5","2008/12/31","","*","","pay off","","assets:bank:checking","-1","$","1","","",""
o There is one CSV record per posting, with the parent transaction's
o There is one CSV record per posting, with the parent transaction's
fields repeated.
o The "txnidx" (transaction index) field shows which postings belong to
the same transaction. (This number might change if transactions are
reordered within the file, files are parsed/included in a different
the same transaction. (This number might change if transactions are
reordered within the file, files are parsed/included in a different
order, etc.)
o The amount is separated into "commodity" (the symbol) and "amount"
o The amount is separated into "commodity" (the symbol) and "amount"
(numeric quantity) fields.
o The numeric amount is repeated in either the "credit" or "debit" col-
umn, for convenience. (Those names are not accurate in the account-
ing sense; it just puts negative amounts under credit and zero or
umn, for convenience. (Those names are not accurate in the account-
ing sense; it just puts negative amounts under credit and zero or
greater amounts under debit.)
print-unique
@ -1566,7 +1567,7 @@ COMMANDS
show running total from report start date (default)
-H --historical
show historical running total/balance (includes postings before
show historical running total/balance (includes postings before
report start date)
-A --average
@ -1577,18 +1578,18 @@ COMMANDS
show postings' siblings instead
-w N --width=N
set output width (default: terminal width or COLUMNS. -wN,M
set output width (default: terminal width or COLUMNS. -wN,M
sets description width as well)
-O FMT --output-format=FMT
select the output format. Supported formats: txt, csv.
-o FILE --output-file=FILE
write output to FILE. A file extension matching one of the
write output to FILE. A file extension matching one of the
above formats selects that format.
The register command displays postings, one per line, and their running
total. This is typically used with a query selecting a particular
total. This is typically used with a query selecting a particular
account, to see that account's activity:
$ hledger register checking
@ -1597,8 +1598,8 @@ COMMANDS
2008/06/02 save assets:bank:checking $-1 $1
2008/12/31 pay off assets:bank:checking $-1 0
The --historical/-H flag adds the balance from any undisplayed prior
postings to the running total. This is useful when you want to see
The --historical/-H flag adds the balance from any undisplayed prior
postings to the running total. This is useful when you want to see
only recent activity, with a historically accurate running balance:
$ hledger register checking -b 2008/6 --historical
@ -1608,23 +1609,23 @@ COMMANDS
The --depth option limits the amount of sub-account detail displayed.
The --average/-A flag shows the running average posting amount instead
The --average/-A flag shows the running average posting amount instead
of the running total (so, the final number displayed is the average for
the whole report period). This flag implies --empty (see below). It
is affected by --historical. It works best when showing just one
the whole report period). This flag implies --empty (see below). It
is affected by --historical. It works best when showing just one
account and one commodity.
The --related/-r flag shows the other postings in the transactions of
The --related/-r flag shows the other postings in the transactions of
the postings which would normally be shown.
With a reporting interval, register shows summary postings, one per
With a reporting interval, register shows summary postings, one per
interval, aggregating the postings to each account:
$ hledger register --monthly income
2008/01 income:salary $-1 $-1
2008/06 income:gifts $-1 $-2
Periods with no activity, and summary postings with a zero amount, are
Periods with no activity, and summary postings with a zero amount, are
not shown by default; use the --empty/-E flag to see them:
$ hledger register --monthly income -E
@ -1641,7 +1642,7 @@ COMMANDS
2008/11 0 $-2
2008/12 0 $-2
Often, you'll want to see just one line per interval. The --depth
Often, you'll want to see just one line per interval. The --depth
option helps with this, causing subaccounts to be aggregated:
$ hledger register --monthly assets --depth 1h
@ -1649,19 +1650,19 @@ COMMANDS
2008/06 assets $-1 0
2008/12 assets $-1 $-1
Note when using report intervals, if you specify start/end dates these
will be adjusted outward if necessary to contain a whole number of
intervals. This ensures that the first and last intervals are full
Note when using report intervals, if you specify start/end dates these
will be adjusted outward if necessary to contain a whole number of
intervals. This ensures that the first and last intervals are full
length and comparable to the others in the report.
Custom register output
register uses the full terminal width by default, except on windows.
You can override this by setting the COLUMNS environment variable (not
register uses the full terminal width by default, except on windows.
You can override this by setting the COLUMNS environment variable (not
a bash shell variable) or by using the --width/-w option.
The description and account columns normally share the space equally
(about half of (width - 40) each). You can adjust this by adding a
description width as part of --width's argument, comma-separated:
The description and account columns normally share the space equally
(about half of (width - 40) each). You can adjust this by adding a
description width as part of --width's argument, comma-separated:
--width W,D . Here's a diagram:
<--------------------------------- width (W) ---------------------------------->
@ -1677,12 +1678,12 @@ COMMANDS
$ hledger reg -w 100,40 # set overall width 100, description width 40
$ hledger reg -w $COLUMNS,40 # use terminal width, and set description width
The register command also supports the -o/--output-file and -O/--out-
The register command also supports the -o/--output-file and -O/--out-
put-format options for controlling output destination and CSV output.
register-match
Print the one posting whose transaction description is closest to DESC,
in the style of the register command. Helps ledger-autosync detect
in the style of the register command. Helps ledger-autosync detect
already-seen transactions when importing.
rewrite
@ -1692,7 +1693,7 @@ COMMANDS
Show some journal statistics.
-o FILE --output-file=FILE
write output to FILE. A file extension matching one of the
write output to FILE. A file extension matching one of the
above formats selects that format.
$ hledger stats
@ -1707,8 +1708,8 @@ COMMANDS
Accounts : 8 (depth 3)
Commodities : 1 ($)
The stats command displays summary information for the whole journal,
or a matched part of it. With a reporting interval, it shows a report
The stats command displays summary information for the whole journal,
or a matched part of it. With a reporting interval, it shows a report
for each report period.
The stats command also supports -o/--output-file for controlling output
@ -1723,34 +1724,34 @@ COMMANDS
$ hledger test
Cases: 74 Tried: 74 Errors: 0 Failures: 0
This command runs hledger's built-in unit tests and displays a quick
This command runs hledger's built-in unit tests and displays a quick
report. With a regular expression argument, it selects only tests with
matching names. It's mainly used in development, but it's also nice to
be able to check your hledger executable for smoke at any time.
ADD-ON COMMANDS
hledger also searches for external add-on commands, and will include
hledger also searches for external add-on commands, and will include
these in the commands list. These are programs or scripts in your PATH
whose name starts with hledger- and ends with a recognised file exten-
whose name starts with hledger- and ends with a recognised file exten-
sion (currently: no extension, bat,com,exe, hs,lhs,pl,py,rb,rkt,sh).
Add-ons can be invoked like any hledger command, but there are a few
Add-ons can be invoked like any hledger command, but there are a few
things to be aware of. Eg if the hledger-web add-on is installed,
o hledger -h web shows hledger's help, while hledger web -h shows
hledger-web's help.
o Flags specific to the add-on must have a preceding -- to hide them
from hledger. So hledger web --serve --port 9000 will be rejected;
o Flags specific to the add-on must have a preceding -- to hide them
from hledger. So hledger web --serve --port 9000 will be rejected;
you must use hledger web -- --serve --port 9000.
o You can always run add-ons directly if preferred:
o You can always run add-ons directly if preferred:
hledger-web --serve --port 9000.
Add-ons are a relatively easy way to add local features or experiment
with new ideas. They can be written in any language, but haskell
scripts have a big advantage: they can use the same hledger (and
haskell) library functions that built-in commands do, for command-line
Add-ons are a relatively easy way to add local features or experiment
with new ideas. They can be written in any language, but haskell
scripts have a big advantage: they can use the same hledger (and
haskell) library functions that built-in commands do, for command-line
options, journal parsing, reporting, etc.
Here are some hledger add-ons available:
@ -1768,7 +1769,7 @@ ADD-ON COMMANDS
hledger-web provides a simple web interface.
Third party add-ons
These are maintained separately, and usually updated shortly after a
These are maintained separately, and usually updated shortly after a
hledger release.
diff
@ -1776,7 +1777,7 @@ ADD-ON COMMANDS
journal file and another.
iadd
hledger-iadd is a curses-style, more interactive replacement for the
hledger-iadd is a curses-style, more interactive replacement for the
add command.
interest
@ -1784,19 +1785,19 @@ ADD-ON COMMANDS
ing to various schemes.
irr
hledger-irr calculates the internal rate of return of an investment
hledger-irr calculates the internal rate of return of an investment
account.
Experimental add-ons
These are available in source form in the hledger repo's bin/ direc-
These are available in source form in the hledger repo's bin/ direc-
tory; installing them is pretty easy. They may be less mature and doc-
umented than built-in commands. Reading and tweaking these is a good
umented than built-in commands. Reading and tweaking these is a good
way to start making your own!
autosync
hledger-autosync is a symbolic link for easily running ledger-autosync,
if installed. ledger-autosync does deduplicating conversion of OFX
data and some CSV formats, and can also download the data if your bank
if installed. ledger-autosync does deduplicating conversion of OFX
data and some CSV formats, and can also download the data if your bank
offers OFX Direct Connect.
budget
@ -1809,21 +1810,21 @@ ADD-ON COMMANDS
hledger-check.hs checks more powerful account balance assertions.
ENVIRONMENT
COLUMNS The screen width used by the register command. Default: the
COLUMNS The screen width used by the register command. Default: the
full terminal width.
LEDGER_FILE The journal file path when not specified with -f. Default:
~/.hledger.journal (on windows, perhaps C:/Users/USER/.hledger.jour-
~/.hledger.journal (on windows, perhaps C:/Users/USER/.hledger.jour-
nal).
FILES
Reads data from one or more files in hledger journal, timeclock, time-
dot, or CSV format specified with -f, or $LEDGER_FILE, or
$HOME/.hledger.journal (on windows, perhaps
Reads data from one or more files in hledger journal, timeclock, time-
dot, or CSV format specified with -f, or $LEDGER_FILE, or
$HOME/.hledger.journal (on windows, perhaps
C:/Users/USER/.hledger.journal).
BUGS
The need to precede addon command options with -- when invoked from
The need to precede addon command options with -- when invoked from
hledger is awkward.
When input data contains non-ascii characters, a suitable system locale
@ -1836,33 +1837,33 @@ BUGS
In a Cygwin/MSYS/Mintty window, the tab key is not supported in hledger
add.
Not all of Ledger's journal file syntax is supported. See file format
Not all of Ledger's journal file syntax is supported. See file format
differences.
On large data files, hledger is slower and uses more memory than
On large data files, hledger is slower and uses more memory than
Ledger.
TROUBLESHOOTING
Here are some issues you might encounter when you run hledger (and
remember you can also seek help from the IRC channel, mail list or bug
Here are some issues you might encounter when you run hledger (and
remember you can also seek help from the IRC channel, mail list or bug
tracker):
Successfully installed, but "No command 'hledger' found"
stack and cabal install binaries into a special directory, which should
be added to your PATH environment variable. Eg on unix-like systems,
be added to your PATH environment variable. Eg on unix-like systems,
that is ~/.local/bin and ~/.cabal/bin respectively.
I set a custom LEDGER_FILE, but hledger is still using the default file
LEDGER_FILE should be a real environment variable, not just a shell
variable. The command env | grep LEDGER_FILE should show it. You may
LEDGER_FILE should be a real environment variable, not just a shell
variable. The command env | grep LEDGER_FILE should show it. You may
need to use export. Here's an explanation.
"Illegal byte sequence" or "Invalid or incomplete multibyte or wide
"Illegal byte sequence" or "Invalid or incomplete multibyte or wide
character" errors
In order to handle non-ascii letters and symbols (like ), hledger needs
an appropriate locale. This is usually configured system-wide; you can
also configure it temporarily. The locale may need to be one that sup-
ports UTF-8, if you built hledger with GHC < 7.2 (or possibly always,
ports UTF-8, if you built hledger with GHC < 7.2 (or possibly always,
I'm not sure yet).
Here's an example of setting the locale temporarily, on ubuntu
@ -1881,7 +1882,7 @@ TROUBLESHOOTING
$ echo "export LANG=en_US.UTF-8" >>~/.bash_profile
$ bash --login
If we preferred to use eg fr_FR.utf8, we might have to install that
If we preferred to use eg fr_FR.utf8, we might have to install that
first:
$ apt-get install language-pack-fr
@ -1902,7 +1903,7 @@ TROUBLESHOOTING
REPORTING BUGS
Report bugs at http://bugs.hledger.org (or on the #hledger IRC channel
Report bugs at http://bugs.hledger.org (or on the #hledger IRC channel
or hledger mail list)
@ -1916,7 +1917,7 @@ COPYRIGHT
SEE ALSO
hledger(1), hledger-ui(1), hledger-web(1), hledger-api(1),
hledger(1), hledger-ui(1), hledger-web(1), hledger-api(1),
hledger_csv(5), hledger_journal(5), hledger_timeclock(5), hledger_time-
dot(5), ledger(1)