Open nobodyinperson opened 3 years ago
I don't use pivoting, so I can't comment on the proposed implementation, but it sounds pretty cool to me.
Apparently, IIUC, part of this proposal was silently implemented in #2050 by @glguy. Would you be interested in taking a look at the other ideas to eventually collect the bounty? 🙂
Hi everyone,
Tags in combination with pivoting add an incredible amount of depth to an
hledger
journal. They effectively enable looking at the transactions in an arbitrary amount of different layers of categorization.I have an idea to push this even further while maintaining backwards-compatibility.
👀 Current
--pivot
behaviourAs far as I understand (and the docs state it),
--pivot=TAG
causes each account name to be replaced by the (possibly non-existant) value of the givenTAG
. So basically pivoting is actually just a string manipulation action at a time where all tags attached to the transaction are known.Currently, this string manipulation action can only do one thing: replacing the existing account name with the value of a single tag.
✨ Proposed new
--pivot
behaviourI propose to make pivoting much more powerful by adding new simple string manipulations. A tag name looks like
[[:word:]-]+
, so pretty much all special characters are free to have a special meaning in--pivot
, for example:⤵
--pivot=TAG1|TAG2|TAG3
- OR - fallback to other tag valueReplace the account name with value of
TAG1
, but if this one is empty or doesn't exist, replace it withTAG2
's value. IfTAG2
is equally empty, tryTAG3
.This is useful to fill empty space when pivoting in
hledger register
over a description/notes tag (be it the built-indesc
or another tag one uses for additional info likemynotes
):hledger register checking --pivot='mynotes|desc'
. A CSV import for example can only really set thedesc
-tag, which for real-world-accounts will be something like the gibberish transaction details, but I find myself to often add additional info in human-readable form to the transactions for nice presentation inhledger register
. This ”or” operator could be used to fall back to certain tag values.This operator would have the lowest priority, i.e. it would be evaluated last.
➕
--pivot=TAG1:TAG2
- concatenation with colonReplace the account name with the given tags' values concatenated with a colon
:
.This adds the possibility to create nested account structures on-the-fly. Especially if there were an auto-generated tag containing the original account name (is there already?) like
acct
, you could append/prepend additional nesting levels contained in tags. For example if you tag specific expenses with aconcerns: Bob
orconcerns: Alice
tag depending on whom it concerns, you could then quickly get an overview over everyone's concerning balances with a single commandhledger balance --pivot=acct:concerns
(orhledger balance --pivot=concerns:acct
, depending on how you'd want to see it). Currently, you'd have to issue one command per concerned person to get the same information (hledger balance tag:concerns=Alice
,hledger balance tag:concerns=Bob
, ...).➕
--pivot=TAG1+TAG2+TAG3
- basic concatenationLike the above, but the (non-empty) tag values concatenated with a different character. I guess a space would be fine, but I can imagine people wanting to use a custom concatenation string (like
,
or-
or;
, etc...), though I am not yet sure what syntax to use for that (maybe--pivot=TAG1(, )TAG2(, )TAG3
?). A custom concatenation string would then also include the concatenation with colon.This is useful like the fallback “or” above, but if you want to see all of the tags values in
hledger register
.This is just a couple of examples, I see a lot of possibilities (like regex substitution, mapping values, etc...).
✏ Syntax
Maybe the simple syntax proposed above is a little too limited for future improvements. It is concise and simple to read though and rather probably simple™️ to implement (should be ”just” string parsing and manipulation). As parentheses are also not allowed in tag names, I could also imagine a ”functional”-style
--pivot
syntax:--pivot=or(TAG1,TAG2,TAG3)
fallback--pivot=concat(':',TAG1,TAG2,TAG3)
colon concatenation--pivot=concat(', ',TAG1,TAG2,TAG3)
custom concatenation--pivot=sub(TAG1,/bob/alice/)
regex replacement--pivot=or(TAG1,concat(', ',TAG2,TAG3))
nesting callsThis syntax is admittedly more involved but much more future-proof as adding an arbitrary amount of new features will be possible.
⏪ Backwards-Compatibility
As tag names are only allowed to contain something like
[a-zA-Z0-9-]
and no special characters, I can't imagine someone relying on special characters in--pivot
. So, any new syntax with special characters we introduce to--pivot
won't break backwards-compatibility.What do you think? I bet people will come up with amazing ideas to use this new functionality. I for sure would love to use it.
Cheers,
Yann