Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to print with normalized output width #1045

Open
alerque opened this issue Jun 11, 2019 · 15 comments
Open

Add option to print with normalized output width #1045

alerque opened this issue Jun 11, 2019 · 15 comments
Labels
A-WISH Some kind of improvement request, hare-brained proposal, or plea. print

Comments

@alerque
Copy link
Collaborator

alerque commented Jun 11, 2019

I use hledger itself to process and normalize all my ledgers whether imported from other sources or manually composed. The print command makes sure the values for every posting in a transaction are aligned.

2016/01/01 Example transaction
	Expense:Foo  $6
	Expense:Foo:Baz  $3
	Cash

Becomes the much nicer:

2016/01/01 Example transaction
    Expense:Foo                  $6
    Expense:Foo:Baz              $3
    Cash                        $-9

However the column at which this alignment happens varies from transaction to transaction. Consider this case:

2016/01/01 Example transaction
	Expense:Foo  $6
	Cash

2016/01/01 Another transaction
	Expense:Bar:Baz  $6
	Cash

Normalizing this using print -x will return each transaction aligned at a a different place:

2016/01/01 Example transaction
    Expense:Foo              $6
    Cash                    $-6

2016/01/01 Another transaction
    Expense:Bar:Baz              $6
    Cash                        $-6

In this case ledger print is superior in that all transactions are aligned together:

2016/01/01 Example transaction
    Expense:Foo                                   $6
    Cash

2016/01/01 Another transaction
    Expense:Bar:Baz                               $6
    Cash

I considered normalizing through ledger, but there are many other ways in which hledger print is preferable, such as alignment of postings with commodity costs:

# Source
2016/01/01 Unit prices
	Expense:Foo  56 @ $6.00
	Cash  $-336

# Output of hledger print
2016/01/01 Unit prices
    Expense:Foo      56 @ $6.00
    Cash                  $-336

# Output of ledger print
2016/01/01 Unit prices
    Expense:Foo                                   56 @ $6
    Cash                                       $-336

Personally I really like having the final cost of the posting right aligned as in the hledger output.

What I would like is some kind of format option that specifies the right edge to align to (if possible without truncation of course).

The reason this would be preferable to a fully automatic width guesser that spans multiple transactions is that I could standardize on a width such that future changes such as renaming an account or moving transactions from one ledger to another would not cause churn in my Git commit history just because the length of an account string changed. Right now running git blame on a Ledger file shows quite a bit of useless results as every posting in a transaction can change when just one posting is edited (because the column amounts are aligned to changes).

@alerque alerque added the A-WISH Some kind of improvement request, hare-brained proposal, or plea. label Jun 11, 2019
@alerque
Copy link
Collaborator Author

alerque commented Jun 11, 2019

Related: Automatically Sort and Align Ledger Transactions in VIM.

It looks like the vim-ledger plugin has some pattern matching based tools for this. They do help with my use case, but they are not a substitute for hledger supporting aligned output. For one thing it they do not handle multiple currency situations with different separators in the same file very well. Also without actually processing the numbers it doesn't understand how to make numbers match the commodity declaration (such as always adding the decimal separator and two digit precision). It's a stop-gap for me and I mention it here in case others are interested, but the wish still stands!

@simonmichael
Copy link
Owner

simonmichael commented Jun 12, 2019

Related code: https://github.com/simonmichael/hledger/blob/master/hledger-lib/Hledger/Data/Transaction.hs#L206

Thanks. I've wanted to do something about this for a long time. Here's a summary of current behaviour:

input

2000/01/01
    a  $6.0 @ A1000.00
    b  3 USD @ 10 B
    cccccccccccccccccccccccccccccccccccccccccccccccc50  $1
    dddddddddddddddddddddddddddddddddddddddddddddddd50  123456789012 USD
    d

hledger print

;-------------------------------------------------52
2000/01/01
    a                                                      $6.0 @ A1000.00
    b                                                         3 USD @ 10 B
    cccccccccccccccccccccccccccccccccccccccccccccccc50                $1.0
    dddddddddddddddddddddddddddddddddddddddddddddddd50    123456789012 USD
    d

  • starts accounts at column 4
  • uses the widest account width for all accounts
  • adds the minimum 2 spaces after account name area
  • uses the greater of the widest amount+price width, or 12, for all amounts
  • right-aligns posting amount+decimals+commodity+price

ledger print

;-------------------------------------------------52
2000/01/01 <Unspecified payee>
    a                                           $6.0 @ A1000
    b                                          3 USD @ B10
    cccccccccccccccccccccccccccccccccccccccccccccccc50        $1.0
    dddddddddddddddddddddddddddddddddddddddddddddddd50  123456789012 USD
    d
  • starts accounts at column 4
  • right-aligns posting amount+decimals+commodity (not price) at column 52
  • wide account names push individual amounts to the right if needed
  • adds the minimum 2 spaces after account name
  • uses a minimum of 10 width for amounts
  • wide amounts extend to the right if needed

ledger-mode C-tab (ledger-post-align-xact)

;-------------------------------------------------52
2000/01/01
    a                                           $6.0 @ A1000.00
    b                                              3 USD @ 10 B
    cccccccccccccccccccccccccccccccccccccccccccccccc50  $1
    dddddddddddddddddddddddddddddddddddddddddddddddd50  123456789012 USD
    d
  • starts accounts at ledger-post-account-alignment-column (default 4)
  • right aligns posting amount+decimals (not commodity or price) at ledger-post-amount-alignment-column (default 52, same as ledger)
  • adds the minimum 2 spaces after account name
  • amounts pushed to the right by wide account names are left aligned

Or, with ledger-post-amount-alignment-at set to :decimal instead of :end :

;-------------------------------------------------52
2000/01/01
    a                                             $6.0 @ A1000.00
    b                                              3 USD @ 10 B
    cccccccccccccccccccccccccccccccccccccccccccccccc50  $1
    dddddddddddddddddddddddddddddddddddddddddddddddd50  123456789012 USD
    d
  • right aligns posting amount's integral part/decimal point

@simonmichael
Copy link
Owner

Some impressions of pros and cons:

hledger

Pro

  • amounts within a transaction are always right aligned
  • right alignment is visually strong

Con

  • amount position often varies across transactions
  • amount, commodity, price are all part of alignment

ledger

Pro

  • amount position is often consistent within and across transactions
  • prices are not part of alignment

Con

  • wide/complex account names will often break the alignment within/across transactions; column 52 does not give much room
  • wide amounts will also break the alignment
  • commodity is part of alignment

ledger-mode (:end)

Pro

  • fairly close to ledger's output by default
  • commodity and prices are not part of alignment

Con

  • amounts after wide account names are not right aligned
  • decimals are part of alignment

ledger-mode (:decimal)

Pro

  • decimals, commodity, prices are not part of alignment (aligns decimal point)

Con

  • amounts after wide account names are not right aligned
  • decimal point alignment, while most correct, seems sometimes hard to read, eg when only some amounts have decimals

@simonmichael
Copy link
Owner

simonmichael commented Jun 12, 2019

What do y'all like about these ? My beancount is broken, do it or other ledgerlikes do anything interesting ? Here's a quick

hledger proposal A

  • right align amounts at column 52 by default (-> stay close to ledger/ledger-mode output, improve alignment across transactions)
  • align decimal point (or quantity ?) (-> improve readability)
  • always align amounts within a transaction; if one gets pushed right, they all do (-> preserve tidy appearance)
  • support -w/--width option, like register but less rigid. This would try to satisfy the preceding rules, but letting the amount alignment column move so that the rightmost content (eg the last character of a price or commodity symbol) reaches the specified width. Wide content would cause this width to be exceeded, since print may not elide content the way register does. (-> folks can allow more space for wide account names, or adjust to match their custom ledger-mode alignment column).

proposal B

  • I guess that --width idea won't work for cross-transaction alignment, maybe it needs to specify the amount alignment column instead.

Note these rules all try to produce mostly-tidy output while looking at just one transaction at a time; we could align perfectly by looking at the whole output, but presumably that's not good for efficiency.

@alerque
Copy link
Collaborator Author

alerque commented Jun 12, 2019

I won't mention what vim-ledger does with your example input because it's badly broken, but here is what I would like to see:

2000/01/01
    a                                                   $6.0 @ A1000.00
    b                                                     3 USD @ 10 B
    cccccccccccccccccccccccccccccccccccccccccccccccc50            $1.0
    dddddddddddddddddddddddddddddddddddddddddddddddd50  123456789012 USD
    d

This is very similar to your proposal A, but tweaked as follows

  • Align decimal place at column 50 by default (configurable to any number via -w/--width)
  • Always align on decimal place of final commodity amount no matter what the currency or decimal precision is (balances would run longer)
  • Yes maintain current per-transaction width adjustment in the event of long account names (here the decimal ended up at 68 because of the extra long account name and large USD value)

@simonmichael
Copy link
Owner

Ie, align the decimal place of the rightmost amount, whether it be the posting amount or a price amount ? That seems weird to me. Also if we're going to align around column 50 it might as well be 52 to minimise change when converting between ledger/ledger-mode/hledger.

@alerque
Copy link
Collaborator Author

alerque commented Jun 12, 2019

I didn't have a better idea how to align price amounts that do not have a total amount shown in the posting, so the price seemed like the right thing to match. Did you have a better idea?

I picked 50 out of a hat because for typical 2 digit precision currency that places the right edge of amounts at 52 to match ledger's default. I don't know about ledger-mode, but vim-ledger's defaults are wildly out of whack with that, but configurable (and I'm going to propose making it match by default, I'm trying to get maitainership on that because it needs help).

@simonmichael
Copy link
Owner

simonmichael commented Jun 12, 2019

ledger and ledger-mode align the main posting amount, allowing any unit/total price to hang off to the right.

I see. Showing two decimal places is fairly common, so if we align the decimal point at 50, it may often match ledger's output. Whereas if we align the right-most digit, 52 would work better.

Whether an amount-aligning option like --align=point|number|all[,COL] is worth the trouble I don't know.

You could also go all out and align each separate part for readability, at the cost of more screen space:

2000/01/01
    a                                                             $6.0     @ A1000.00
    b                                                              3   USD @    10    B
    cccccccccccccccccccccccccccccccccccccccccccccccc50            $1.0
    dddddddddddddddddddddddddddddddddddddddddddddddd50  123456789012   USD
    d

@alerque
Copy link
Collaborator Author

alerque commented Jun 12, 2019

Just be sure that last suggestion is behind an --ocd flag and we're golden. 🥇

For myself --align=point will likely be the only one to get any mileage but I'm sure opinions will differ on that. Sometimes matching ledger is good enough for me, fully matching is not the goal because it handles some other things less well (or else I'd be using that!), but having the chance of coinciding does make comparing output easier.

@simonmichael
Copy link
Owner

Ok, let's aim to align posting amount's decimal point at 50 for a start and see how that looks. Probably as a separate code path for now, to allow comparing old and new output for a while.

@alerque
Copy link
Collaborator Author

alerque commented Jun 12, 2019

ledger and ledger-mode align the main posting amount, allowing any unit/total price to hang off to the right.

Sure, but since when was the unit quantity EVER the most likely thing to be comparable to other posting amounts? The unit price may not match in amount, but at least it's more likely to be the same commodity (and hence more useful to align), while the total price is almost certainly going to correspond to something else in the transaction. Hence I don't think following ledger's lead of hanging the unit/total price out of the way here is a good idea. Those are specifically the numbers I think are most useful to align with other posting amounts.

@simonmichael
Copy link
Owner

You could be right. I more often have unit prices, not total prices, which are less comparable. And to me aligning two semantically different things feels weird. I think it will take some testing/real world use to know. We might even end up finding the simple right-align all behaviour is fastest and best after all. Are people really wanting to "sum up" amounts when reading print output ?

@simonmichael
Copy link
Owner

align posting amount's decimal point at 50 for a start

It's a bit tricky! I believe I see how to do it, but I probably won't do it this month. If @alerque or anyone wants to tackle it sooner I can share WIP and notes.

@alerque
Copy link
Collaborator Author

alerque commented Jun 13, 2019

I can't promise my Haskell will get anywhere substantial, but I'd be happy to poke at WIP if you put it in a branch somewhere. I'll be doing lots more accounting this month so I might get ants in my pants and try to make something work.

simonmichael added a commit that referenced this issue Jun 13, 2019
And use it. Plus some comments on decimal point aligning.
@simonmichael
Copy link
Owner

Great! Pushed as #1052.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-WISH Some kind of improvement request, hare-brained proposal, or plea. print
Projects
None yet
Development

No branches or pull requests

2 participants