summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ledger.texi17
-rw-r--r--walk.cc46
-rw-r--r--walk.h37
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
diff --git a/walk.cc b/walk.cc
index 4469ac67..02f7050d 100644
--- a/walk.cc
+++ b/walk.cc
@@ -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();
diff --git a/walk.h b/walk.h
index 42c4ff44..78322ffd 100644
--- a/walk.h
+++ b/walk.h
@@ -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;