diff options
-rw-r--r-- | ledger.texi | 17 | ||||
-rw-r--r-- | walk.cc | 46 | ||||
-rw-r--r-- | walk.h | 37 |
3 files changed, 82 insertions, 18 deletions
diff --git a/ledger.texi b/ledger.texi index db20cdab..a73aee1d 100644 --- a/ledger.texi +++ b/ledger.texi @@ -1050,14 +1050,14 @@ beginning of the ledger. For food spending just this month (September), use: @example -ledger -d sep balance expenses:food +ledger -p sep balance expenses:food @end example Or maybe I want to see all of my assets, in which case the -s (show sub-accounts) option comes in handy: @example -ledger balance -s +ledger -s balance @end example To exclude a particular account, use a regular expression with a @@ -1068,13 +1068,20 @@ food spending: ledger balance expenses -food @end example -If you want to show all accounts but for one account, remember to use -``--'' to separate the exclusion pattern from the options list: +A query like the following will show the largest expense categories +since a given date: @example -ledger balance -- -equity +ledger -b 2003/10 -s -S -AT -d "T>1000" bal ^expenses -internet @end example +From left to right the options used mean: Show entries since October, +2003; showa all sub-accounts; sort in verse order by the absolute +value of the total; display only accounts with a total value greater +than 1000 units (of whichever commodities the account contains); and +report the balance for all expenses, except for those matching +``internet''. + @node File format, , Typical queries, Running Ledger @section File format @@ -9,6 +9,28 @@ std::list<void **> transactions_xdata_ptrs; std::list<account_xdata_t> accounts_xdata; std::list<void **> accounts_xdata_ptrs; +template <> +bool compare_items<transaction_t>::operator()(const transaction_t * left, + const transaction_t * right) +{ + assert(left); + assert(right); + + transaction_xdata_t& lxdata(transaction_xdata(*left)); + if (! (lxdata.dflags & TRANSACTION_SORT_CALC)) { + sort_order->compute(lxdata.sort_value, details_t(*left)); + lxdata.dflags |= TRANSACTION_SORT_CALC; + } + + transaction_xdata_t& rxdata(transaction_xdata(*right)); + if (! (rxdata.dflags & TRANSACTION_SORT_CALC)) { + sort_order->compute(rxdata.sort_value, details_t(*right)); + rxdata.dflags |= TRANSACTION_SORT_CALC; + } + + return lxdata.sort_value < rxdata.sort_value; +} + void sort_transactions::flush() { std::stable_sort(transactions.begin(), transactions.end(), @@ -123,7 +145,7 @@ static void handle_value(const value_t& value, } } -void determine_amount(value_t& result, balance_pair_t& bal_pair) +static inline void determine_amount(value_t& result, balance_pair_t& bal_pair) { account_xdata_t xdata; xdata.value = bal_pair; @@ -319,6 +341,28 @@ void clear_transactions_xdata() **i = NULL; } +template <> +bool compare_items<account_t>::operator()(const account_t * left, + const account_t * right) +{ + assert(left); + assert(right); + + account_xdata_t& lxdata(account_xdata(*left)); + if (! (lxdata.dflags & ACCOUNT_SORT_CALC)) { + sort_order->compute(lxdata.sort_value, details_t(*left)); + lxdata.dflags |= ACCOUNT_SORT_CALC; + } + + account_xdata_t& rxdata(account_xdata(*right)); + if (! (rxdata.dflags & ACCOUNT_SORT_CALC)) { + sort_order->compute(rxdata.sort_value, details_t(*right)); + rxdata.dflags |= ACCOUNT_SORT_CALC; + } + + return lxdata.sort_value < rxdata.sort_value; +} + void sum_accounts(account_t& account) { for (accounts_map::iterator i = account.accounts.begin(); @@ -38,27 +38,36 @@ struct item_handler { template <typename T> class compare_items { - value_t left_result; - value_t right_result; - const value_expr_t * sort_order; - public: compare_items(const value_expr_t * _sort_order) : sort_order(_sort_order) { assert(sort_order); } + bool operator()(const T * left, const T * right); +}; + +template <typename T> +bool compare_items<T>::operator()(const T * left, const T * right) +{ + assert(left); + assert(right); - bool operator()(const T * left, const T * right) { - assert(left); - assert(right); + value_t left_result; + value_t right_result; + sort_order->compute(left_result, details_t(*left)); + sort_order->compute(right_result, details_t(*right)); - sort_order->compute(left_result, details_t(*left)); - sort_order->compute(right_result, details_t(*right)); + return left_result < right_result; +} - return left_result < right_result; - } -}; +template <> +bool compare_items<transaction_t>::operator()(const transaction_t * left, + const transaction_t * right); + +template <> +bool compare_items<account_t>::operator()(const account_t * left, + const account_t * right); ////////////////////////////////////////////////////////////////////// // @@ -69,10 +78,12 @@ class compare_items { #define TRANSACTION_TO_DISPLAY 0x0002 #define TRANSACTION_DISPLAYED 0x0004 #define TRANSACTION_NO_TOTAL 0x0008 +#define TRANSACTION_SORT_CALC 0x0010 struct transaction_xdata_t { value_t total; + value_t sort_value; unsigned int index; unsigned short dflags; @@ -400,11 +411,13 @@ class related_transactions : public item_handler<transaction_t> #define ACCOUNT_TO_DISPLAY 0x1 #define ACCOUNT_DISPLAYED 0x2 +#define ACCOUNT_SORT_CALC 0x4 struct account_xdata_t { value_t value; value_t total; + value_t sort_value; unsigned int count; // transactions counted toward total unsigned int subcount; unsigned short dflags; |