These now call error' and show errors in the standard style:
- reading a nonexistent data file
- reading an unsafe dotted file name on windows
- web: using --socket on windows
- demo: demo not found
- demo: error while running asciinema
- diff: bad arguments
- print --match: no match found
- register --match: no match found
- roi: no investment transactions found
`If blocks` and `If tables` now allow multiple matchers on the same line
separated by `&&` (AND) or `&& !` (AND NOT).
Example `if block` with two matchers on the same line:
if %description amazon && %date 2025-02-22
account2 expenses:books
Example `if table` with two matchers on the same line:
if,account2
%description amazon && %date 2025-02-22, expenses:books
Previously, hledger could read CSV files containing non-ascii
characters only if they are UTF8-encoded. Now there is a new CSV
rule, encoding ENCODING, which allows reading CSV files with other
encodings.
This adds a dependency on the encoding library, which supports fewer
encodings than text-icu but does not require a third-party C library.
To avoid build issues on various platforms, we require version 0.10+.
This adds some use of the ImplicitParams language extension, required
by encoding's API, but only in a small code region.
This also changes the type of Reader's rReadFn; it now takes
a `Handle` rather than a `Text`, allowing more flexibility.
Older ghc versions should also still build cleanly (tested with 9.8 so far).
I don't like enabling CPP in so many modules but it's easier that
figuring out how to do it with base-compat; hopefully no noticeable
compilation impact.
For brevity, and consistency with --conf.
--rules-file remains supported, as a hidden option.
hledger's main mode now supports the hidden legacy flags,
as the command modes do.
Adjust getEffectiveAssignment to compute an intermediary form of the
active assignments (with an additional Either wrapper to distinguish
top-level and conditional assignments) and move the remaining work to
its only caller, hledgerField.
Rework hledgerFieldValue. Instead of calling hledgerField, call
getEffectiveAssignment and--in the conditional block case--construct
a CsvRules scoped just to the active ConditionalBlock before calling
renderTemplate.
Adjust regexMatchValue to use rconditionalblocks to access conditional
blocks from the CsvRules, rather than rblocksassigning, since we haven't
narrowed the scope of that field.
The result is match group references are only expanded for match groups
that occur within the in-scope ConditionalBlock. Fixes: #2158.
Signed-off-by: Jonathan Dowland <jon@dow.land>
hledgerField is an alias to the function getEffectiveAssignment: both
names are used in various parts of RulesReader.
Treat hledgerField as the canonical name, and getEffectiveAssignment
as an implementation detail of hledgerField.
Replace all uses of getEffectiveAssignment with hledgerField (except the
one in hledgerField.)
Signed-off-by: Jonathan Dowland <jon@dow.land>
Note the headErr/tailErr calls will print stack traces if they fail
(small ones: five lines, one of which is the useful location info),
which may or may not be best UX.
In field assignment values we now parse %FIELD references, \MATCHGROUP references
and "\n" newline markers more carefully, so all can coexist.
Parsing these values might be slower than before, but hopefully not noticeably so.
Replace occurrences of '\N' (where N is a positive number) in field
templates with the corresponding regular expression match group, if it
exists.
E.g. Warp the date to the first of the month for the second posting
if %date (....-..)-..
comment2 date:\1-01
E.g. Strip a prefix from an imported account name
if %account1 liabilities:jon:(.*)
account1 \1
Fixes#2009.
Signed-off-by: Jonathan Dowland <jon@dow.land>
CSV rules files can now be read directly, eg you have the option of
writing `hledger -f foo.csv.rules CMD`. By default this will read data
from foo.csv in the same directory. But you can also specify a
different data file with a new `source FILE` rule. This has some
convenience features:
- If the data file does not exist, it is treated as empty, not an
error.
- If FILE is a relative path, it is relative to the rules file's
directory. If it is just a file name with no path, it is relative
to ~/Downloads/.
- If FILE is a glob pattern, the most recently modified matched file
is used.
This helps remove some of the busywork of managing CSV downloads.
Most of your financial institutions's default CSV filenames are
different and can be recognised by a glob pattern. So you can put a
rule like `source Checking1*.csv` in foo-checking.csv.rules,
periodically download CSV from Foo's website accepting your browser's
defaults, and then run `hledger import checking.csv.rules` to import
any new transactions. The next time, if you have done no cleanup, your
browser will probably save it as something like Checking1-2.csv, and
hledger will still see that because of the * wild card. You can choose
whether to delete CSVs after import, or keep them for a while as
temporary backups, or archive them somewhere.