From 858a1b2fad41f968d5d8d3470629c0cbb20562b8 Mon Sep 17 00:00:00 2001 From: Gwyneth Morgan Date: Wed, 6 Sep 2023 02:45:48 +0000 Subject: print: Align amounts even when account names are long When the account name is longer than the --account-width (default 36), the amounts stop aligning: 2023/01/01 Transaction with long account names Assets:Very:Long:Account:Name:That:Will:Push:The:Amount -10 ABC Assets:Another:Long:Account:Name:That:Will:Push:The:Amount -10 ABC Expenses:Short 20 ABC One can set a larger --account-width, but that is not a great solution for cases where you have only a few accounts with problematically long names. Instead, keep the current account width wherever possible, but when an account name is longer than the account width, account for that and still align the values: 2023/01/01 Transaction with short account names Assets:Short -10 ABC Assets:Short -10 ABC Expenses:Short 20 ABC 2023/01/01 Transaction with long account names Assets:Very:Long:Account:Name:That:Will:Push:The:Amount -10 ABC Assets:Another:Long:Account:Name:That:Will:Push:The:Amount -10 ABC Expenses:Short 20 ABC This is similar to hledger's behavior. --- src/print.cc | 70 ++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 30 deletions(-) (limited to 'src/print.cc') diff --git a/src/print.cc b/src/print.cc index bcc8cf9c..4febd871 100644 --- a/src/print.cc +++ b/src/print.cc @@ -100,6 +100,33 @@ namespace { } } + std::ostringstream format_account_name(xact_t& xact, post_t * post) + { + std::ostringstream pbuf; + + if (xact.state() == item_t::UNCLEARED) + pbuf << (post->state() == item_t::CLEARED ? "* " : + (post->state() == item_t::PENDING ? "! " : "")); + + if (post->has_flags(POST_VIRTUAL)) { + if (post->has_flags(POST_MUST_BALANCE)) + pbuf << '['; + else + pbuf << '('; + } + + pbuf << post->account->fullname(); + + if (post->has_flags(POST_VIRTUAL)) { + if (post->has_flags(POST_MUST_BALANCE)) + pbuf << ']'; + else + pbuf << ')'; + } + + return pbuf; + } + void print_xact(report_t& report, std::ostream& out, xact_t& xact) { format_type_t format_type = FMT_WRITTEN; @@ -158,6 +185,18 @@ namespace { std::size_t count = xact.posts.size(); std::size_t index = 0; + std::size_t account_width = + (report.HANDLED(account_width_) ? + lexical_cast(report.HANDLER(account_width_).str()) : 36); + + // Find the longest account name to line up all amounts when account names + // are long + foreach (post_t * post, xact.posts) { + unistring name = format_account_name(xact, post).str(); + if (account_width < name.length()) + account_width = name.length(); + } + foreach (post_t * post, xact.posts) { index++; @@ -168,37 +207,10 @@ namespace { out << " "; - std::ostringstream pbuf; - - if (xact.state() == item_t::UNCLEARED) - pbuf << (post->state() == item_t::CLEARED ? "* " : - (post->state() == item_t::PENDING ? "! " : "")); - - if (post->has_flags(POST_VIRTUAL)) { - if (post->has_flags(POST_MUST_BALANCE)) - pbuf << '['; - else - pbuf << '('; - } - - pbuf << post->account->fullname(); - - if (post->has_flags(POST_VIRTUAL)) { - if (post->has_flags(POST_MUST_BALANCE)) - pbuf << ']'; - else - pbuf << ')'; - } + std::ostringstream pbuf = format_account_name(xact, post); unistring name(pbuf.str()); - std::size_t account_width = - (report.HANDLED(account_width_) ? - lexical_cast(report.HANDLER(account_width_).str()) : 36); - - if (account_width < name.length()) - account_width = name.length(); - if (! post->has_flags(POST_CALCULATED) || report.HANDLED(generated)) { out << name.extract(); std::string::size_type slip = @@ -272,8 +284,6 @@ namespace { out << ' '; } out << trailer; - - account_width += unistring(trailer).length(); } } else { out << pbuf.str(); -- cgit v1.2.3