summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xacprep2
-rw-r--r--src/account.cc24
-rw-r--r--src/account.h7
-rw-r--r--src/amount.cc6
-rw-r--r--src/annotate.cc4
-rw-r--r--src/annotate.h9
-rw-r--r--src/archive.cc2
-rw-r--r--src/balance.h35
-rw-r--r--src/chain.cc11
-rw-r--r--src/commodity.cc54
-rw-r--r--src/commodity.h167
-rw-r--r--src/filters.cc60
-rw-r--r--src/filters.h3
-rw-r--r--src/item.cc2
-rw-r--r--src/item.h3
-rw-r--r--src/iterators.cc4
-rw-r--r--src/op.h4
-rw-r--r--src/pool.cc28
-rw-r--r--src/pool.h3
-rw-r--r--src/post.cc17
-rw-r--r--src/post.h2
-rw-r--r--src/precmd.cc10
-rw-r--r--src/predicate.cc36
-rw-r--r--src/py_amount.cc148
-rw-r--r--src/py_balance.cc280
-rw-r--r--src/pyinterp.cc2
-rw-r--r--src/report.cc2
-rw-r--r--src/report.h6
-rw-r--r--src/session.cc3
-rw-r--r--src/session.h6
-rw-r--r--src/temps.cc10
-rw-r--r--src/temps.h2
-rw-r--r--src/times.cc40
-rw-r--r--src/xact.cc4
-rw-r--r--src/xact.h1
-rwxr-xr-xtest/ConfirmTests.py2
-rwxr-xr-xtest/GenerateTests.py6
-rwxr-xr-xtest/LedgerHarness.py31
-rwxr-xr-xtest/RegressTests.py10
-rw-r--r--test/baseline/opt-add-budget.test144
-rw-r--r--test/baseline/opt-anon.test4
-rw-r--r--test/baseline/opt-budget.test96
-rw-r--r--test/manual/transaction-codes-1.test22
-rw-r--r--test/manual/transaction-codes-2.test24
-rw-r--r--test/manual/transaction-notes-1.test24
-rw-r--r--test/manual/transaction-notes-2.test23
-rw-r--r--test/manual/transaction-notes-3.test23
-rw-r--r--test/manual/transaction-notes-4.test27
-rw-r--r--test/manual/transaction-status-1.test19
-rw-r--r--test/manual/transaction-status-2.test17
-rw-r--r--test/manual/transaction-status-3.test18
-rw-r--r--test/manual/transaction-status-4.test17
-rw-r--r--test/regress/25A099C9.test19
-rw-r--r--test/regress/373540CC.test9
-rw-r--r--test/regress/5F1BAF17.test130
-rw-r--r--test/regress/7F3650FD.test50
-rw-r--r--test/regress/8254755E.test20
-rw-r--r--test/regress/D060256A.test16
-rw-r--r--test/regress/E627C594.test18
-rw-r--r--test/regress/F559EC12.test8
-rw-r--r--tools/Makefile.am20
-rwxr-xr-xtools/proof2
62 files changed, 1227 insertions, 569 deletions
diff --git a/acprep b/acprep
index 3ee47026..915d3dca 100755
--- a/acprep
+++ b/acprep
@@ -1337,8 +1337,6 @@ class PrepareBuild(CommandLineApp):
def phase_proof(self, *args):
self.log.info('Executing phase: proof')
- self.phase_makeall(reset=False, *args)
-
self.log.info('=== Copying source tree ===')
self.phase_rsync()
self.phase_makeall(reset=True, *args)
diff --git a/src/account.cc b/src/account.cc
index 52a6b436..23761049 100644
--- a/src/account.cc
+++ b/src/account.cc
@@ -42,10 +42,9 @@ account_t::~account_t()
{
TRACE_DTOR(account_t);
- foreach (accounts_map::value_type& pair, accounts) {
- assert(! pair.second->has_flags(ACCOUNT_TEMP));
- checked_delete(pair.second);
- }
+ foreach (accounts_map::value_type& pair, accounts)
+ if (! pair.second->has_flags(ACCOUNT_TEMP))
+ checked_delete(pair.second);
}
account_t * account_t::find_account(const string& name,
@@ -55,7 +54,7 @@ account_t * account_t::find_account(const string& name,
if (i != accounts.end())
return (*i).second;
- char buf[256];
+ char buf[8192];
string::size_type sep = name.find(':');
assert(sep < 256|| sep == string::npos);
@@ -398,6 +397,21 @@ value_t account_t::amount(const optional<expr_t&>& expr) const
xdata_->self_details.last_post = i;
}
+ if (xdata_->self_details.last_reported_post)
+ i = *xdata_->self_details.last_reported_post;
+ else
+ i = xdata_->reported_posts.begin();
+
+ for (; i != xdata_->reported_posts.end(); i++) {
+ if ((*i)->xdata().has_flags(POST_EXT_VISITED)) {
+ if (! (*i)->xdata().has_flags(POST_EXT_CONSIDERED)) {
+ (*i)->add_to_value(xdata_->self_details.total, expr);
+ (*i)->xdata().add_flags(POST_EXT_CONSIDERED);
+ }
+ }
+ xdata_->self_details.last_reported_post = i;
+ }
+
return xdata_->self_details.total;
} else {
return NULL_VALUE;
diff --git a/src/account.h b/src/account.h
index ce0a7a66..4ac69532 100644
--- a/src/account.h
+++ b/src/account.h
@@ -159,6 +159,7 @@ public:
std::set<string> payees_referenced;
optional<posts_list::const_iterator> last_post;
+ optional<posts_list::const_iterator> last_reported_post;
details_t()
: calculated(false),
@@ -176,8 +177,9 @@ public:
void update(post_t& post, bool gather_all = false);
};
- details_t self_details;
- details_t family_details;
+ details_t self_details;
+ details_t family_details;
+ posts_list reported_posts;
std::list<sort_value_t> sort_values;
@@ -193,7 +195,6 @@ public:
{
TRACE_CTOR(account_t::xdata_t, "copy");
}
-
~xdata_t() throw() {
TRACE_DTOR(account_t::xdata_t);
}
diff --git a/src/amount.cc b/src/amount.cc
index 3ac47c59..435cdea4 100644
--- a/src/amount.cc
+++ b/src/amount.cc
@@ -783,7 +783,7 @@ void amount_t::annotate(const annotation_t& details)
else if (! has_commodity())
return; // ignore attempt to annotate a "bare commodity
- if (commodity().annotated) {
+ if (commodity().is_annotated()) {
this_ann = &as_annotated_commodity(commodity());
this_base = &this_ann->referent();
} else {
@@ -811,9 +811,9 @@ bool amount_t::is_annotated() const
throw_(amount_error,
_("Cannot determine if an uninitialized amount's commodity is annotated"));
- assert(! has_commodity() || ! commodity().annotated ||
+ assert(! has_commodity() || ! commodity().is_annotated() ||
as_annotated_commodity(commodity()).details);
- return has_commodity() && commodity().annotated;
+ return has_commodity() && commodity().is_annotated();
}
annotation_t& amount_t::annotation()
diff --git a/src/annotate.cc b/src/annotate.cc
index c6084f7f..9c676086 100644
--- a/src/annotate.cc
+++ b/src/annotate.cc
@@ -135,13 +135,13 @@ void annotation_t::print(std::ostream& out, bool keep_base) const
bool keep_details_t::keep_all(const commodity_t& comm) const
{
- return (! comm.annotated ||
+ return (! comm.is_annotated() ||
(keep_price && keep_date && keep_tag && ! only_actuals));
}
bool keep_details_t::keep_any(const commodity_t& comm) const
{
- return comm.annotated && (keep_price || keep_date || keep_tag);
+ return comm.is_annotated() && (keep_price || keep_date || keep_tag);
}
bool annotated_commodity_t::operator==(const commodity_t& comm) const
diff --git a/src/annotate.h b/src/annotate.h
index 77dd9372..cb2a1161 100644
--- a/src/annotate.h
+++ b/src/annotate.h
@@ -185,9 +185,10 @@ class annotated_commodity_t
equality_comparable2<annotated_commodity_t, commodity_t,
noncopyable> >
{
-public:
+protected:
+ friend class commodity_pool_t;
+
commodity_t * ptr;
- annotation_t details;
explicit annotated_commodity_t(commodity_t * _ptr,
const annotation_t& _details)
@@ -195,6 +196,10 @@ public:
TRACE_CTOR(annotated_commodity_t, "commodity_t *, annotation_t");
annotated = true;
}
+
+public:
+ annotation_t details;
+
virtual ~annotated_commodity_t() {
TRACE_DTOR(annotated_commodity_t);
}
diff --git a/src/archive.cc b/src/archive.cc
index b3aff7d7..d54b1179 100644
--- a/src/archive.cc
+++ b/src/archive.cc
@@ -43,7 +43,7 @@
#include "xact.h"
#define LEDGER_MAGIC 0x4c454447
-#define ARCHIVE_VERSION 0x03000002
+#define ARCHIVE_VERSION 0x03000003
//BOOST_IS_ABSTRACT(ledger::scope_t)
BOOST_CLASS_EXPORT(ledger::scope_t)
diff --git a/src/balance.h b/src/balance.h
index 5452510b..ad340aa5 100644
--- a/src/balance.h
+++ b/src/balance.h
@@ -207,7 +207,7 @@ public:
template <typename T>
bool operator==(const T& val) const {
- return *this == balance_t(val);
+ return *this == amount_t(val);
}
/**
@@ -217,11 +217,29 @@ public:
*/
balance_t& operator+=(const balance_t& bal);
balance_t& operator+=(const amount_t& amt);
+ balance_t& operator+=(const double val) {
+ return *this += amount_t(val);
+ }
+ balance_t& operator+=(const unsigned long val) {
+ return *this += amount_t(val);
+ }
+ balance_t& operator+=(const long val) {
+ return *this += amount_t(val);
+ }
+
balance_t& operator-=(const balance_t& bal);
balance_t& operator-=(const amount_t& amt);
+ balance_t& operator-=(const double val) {
+ return *this -= amount_t(val);
+ }
+ balance_t& operator-=(const unsigned long val) {
+ return *this -= amount_t(val);
+ }
+ balance_t& operator-=(const long val) {
+ return *this -= amount_t(val);
+ }
balance_t& operator*=(const amount_t& amt);
-
balance_t& operator*=(const double val) {
return *this *= amount_t(val);
}
@@ -233,7 +251,6 @@ public:
}
balance_t& operator/=(const amount_t& amt);
-
balance_t& operator/=(const double val) {
return *this /= amount_t(val);
}
@@ -278,7 +295,7 @@ public:
* in_place_reduce()
* in_place_unreduce()
*/
- balance_t negate() const {
+ balance_t negated() const {
balance_t temp(*this);
temp.in_place_negate();
return temp;
@@ -288,7 +305,7 @@ public:
pair.second.in_place_negate();
}
balance_t operator-() const {
- return negate();
+ return negated();
}
balance_t abs() const {
@@ -388,6 +405,13 @@ public:
* it.
*/
operator bool() const {
+ return is_nonzero();
+ }
+
+ bool is_nonzero() const {
+ if (is_empty())
+ return false;
+
foreach (const amounts_map::value_type& pair, amounts)
if (pair.second.is_nonzero())
return true;
@@ -433,6 +457,7 @@ public:
else
throw_(balance_error,
_("Cannot convert a balance with multiple commodities to an amount"));
+ return amount_t();
}
/**
diff --git a/src/chain.cc b/src/chain.cc
index db52269c..defa2e97 100644
--- a/src/chain.cc
+++ b/src/chain.cc
@@ -159,6 +159,17 @@ post_handler_ptr chain_post_handlers(report_t& report,
handler.reset(new sort_posts(handler, "date"));
}
+ if (report.HANDLED(set_reported_account_))
+ handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
+ report.session.journal->master,
+ report.HANDLER(set_reported_account_).str(),
+ report));
+ else if (report.HANDLED(set_reported_payee_))
+ handler.reset(new transfer_details(handler, transfer_details::SET_PAYEE,
+ report.session.journal->master,
+ report.HANDLER(set_reported_payee_).str(),
+ report));
+
// related_posts will pass along all posts related to the post received. If
// the `related_all' handler is on, then all the xact's posts are passed;
// meaning that if one post of an xact is to be printed, all the post for
diff --git a/src/commodity.cc b/src/commodity.cc
index de529ac4..d896572f 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -38,10 +38,12 @@
namespace ledger {
-void commodity_t::base_t::history_t::add_price(commodity_t& source,
- const datetime_t& date,
- const amount_t& price,
- const bool reflexive)
+bool commodity_t::european_by_default = false;
+
+void commodity_t::history_t::add_price(commodity_t& source,
+ const datetime_t& date,
+ const amount_t& price,
+ const bool reflexive)
{
DEBUG("commodity.prices.add", "add_price to " << source
<< (reflexive ? " (secondary)" : " (primary)")
@@ -67,7 +69,7 @@ void commodity_t::base_t::history_t::add_price(commodity_t& source,
}
}
-bool commodity_t::base_t::history_t::remove_price(const datetime_t& date)
+bool commodity_t::history_t::remove_price(const datetime_t& date)
{
DEBUG("commodity.prices.add", "remove_price: " << date);
@@ -77,7 +79,7 @@ bool commodity_t::base_t::history_t::remove_price(const datetime_t& date)
return false;
}
-void commodity_t::base_t::varied_history_t::
+void commodity_t::varied_history_t::
add_price(commodity_t& source,
const datetime_t& date,
const amount_t& price,
@@ -97,9 +99,8 @@ void commodity_t::base_t::varied_history_t::
hist->add_price(source, date, price, reflexive);
}
-bool commodity_t::base_t::varied_history_t::
- remove_price(const datetime_t& date,
- commodity_t& comm)
+bool commodity_t::varied_history_t::remove_price(const datetime_t& date,
+ commodity_t& comm)
{
DEBUG("commodity.prices.add", "varied_remove_price: " << date << ", " << comm);
@@ -109,13 +110,12 @@ bool commodity_t::base_t::varied_history_t::
}
optional<price_point_t>
- commodity_t::base_t::history_t::
- find_price(const optional<datetime_t>& moment,
- const optional<datetime_t>& oldest
+commodity_t::history_t::find_price(const optional<datetime_t>& moment,
+ const optional<datetime_t>& oldest
#if defined(DEBUG_ON)
- , const int indent
+ , const int indent
#endif
- ) const
+ ) const
{
price_point_t point;
bool found = false;
@@ -220,15 +220,14 @@ optional<price_point_t>
}
optional<price_point_t>
- commodity_t::base_t::varied_history_t::
- find_price(const commodity_t& source,
- const optional<commodity_t&>& commodity,
- const optional<datetime_t>& moment,
- const optional<datetime_t>& oldest
+commodity_t::varied_history_t::find_price(const commodity_t& source,
+ const optional<commodity_t&>& commodity,
+ const optional<datetime_t>& moment,
+ const optional<datetime_t>& oldest
#if defined(DEBUG_ON)
- , const int indent
+ , const int indent
#endif
- ) const
+ ) const
{
optional<price_point_t> point;
optional<datetime_t> limit = oldest;
@@ -352,9 +351,8 @@ optional<price_point_t>
return none;
}
-optional<commodity_t::base_t::history_t&>
- commodity_t::base_t::varied_history_t::
- history(const optional<commodity_t&>& commodity)
+optional<commodity_t::history_t&>
+commodity_t::varied_history_t::history(const optional<commodity_t&>& commodity)
{
commodity_t * comm = NULL;
if (! commodity) {
@@ -602,11 +600,11 @@ bool compare_amount_commodities::operator()(const amount_t * left,
if (cmp != 0)
return cmp < 0;
- if (! leftcomm.annotated) {
- return rightcomm.annotated;
+ if (! leftcomm.is_annotated()) {
+ return rightcomm.is_annotated();
}
- else if (! rightcomm.annotated) {
- return ! leftcomm.annotated;
+ else if (! rightcomm.is_annotated()) {
+ return ! leftcomm.is_annotated();
}
else {
annotated_commodity_t& aleftcomm(static_cast<annotated_commodity_t&>(leftcomm));
diff --git a/src/commodity.h b/src/commodity.h
index 1df1ab18..25397131 100644
--- a/src/commodity.h
+++ b/src/commodity.h
@@ -86,87 +86,85 @@ class commodity_t
: public delegates_flags<uint_least16_t>,
public equality_comparable1<commodity_t, noncopyable>
{
- friend class commodity_pool_t;
-
public:
- class base_t : public noncopyable, public supports_flags<uint_least16_t>
- {
- base_t() {
- TRACE_CTOR(base_t, "");
- }
-
- public:
- typedef std::map<const datetime_t, amount_t> history_map;
+ typedef std::map<const datetime_t, amount_t> history_map;
- struct history_t
- {
- history_map prices;
+ struct history_t
+ {
+ history_map prices;
- void add_price(commodity_t& source,
- const datetime_t& date,
- const amount_t& price,
- const bool reflexive = true);
- bool remove_price(const datetime_t& date);
+ void add_price(commodity_t& source,
+ const datetime_t& date,
+ const amount_t& price,
+ const bool reflexive = true);
+ bool remove_price(const datetime_t& date);
- optional<price_point_t>
- find_price(const optional<datetime_t>& moment = none,
- const optional<datetime_t>& oldest = none
+ optional<price_point_t>
+ find_price(const optional<datetime_t>& moment = none,
+ const optional<datetime_t>& oldest = none
#if defined(DEBUG_ON)
- , const int indent = 0
+ , const int indent = 0
#endif
- ) const;
+ ) const;
#if defined(HAVE_BOOST_SERIALIZATION)
- private:
- /** Serialization. */
+ private:
+ /** Serialization. */
- friend class boost::serialization::access;
+ friend class boost::serialization::access;
- template<class Archive>
- void serialize(Archive & ar, const unsigned int /* version */) {
- ar & prices;
- }
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* version */) {
+ ar & prices;
+ }
#endif // HAVE_BOOST_SERIALIZATION
- };
-
- typedef std::map<commodity_t *, history_t> history_by_commodity_map;
-
- struct varied_history_t
- {
- history_by_commodity_map histories;
+ };
- void add_price(commodity_t& source,
- const datetime_t& date,
- const amount_t& price,
- const bool reflexive = true);
- bool remove_price(const datetime_t& date, commodity_t& commodity);
+ typedef std::map<commodity_t *, history_t> history_by_commodity_map;
- optional<price_point_t>
- find_price(const commodity_t& source,
- const optional<commodity_t&>& commodity = none,
- const optional<datetime_t>& moment = none,
- const optional<datetime_t>& oldest = none
+ struct varied_history_t
+ {
+ history_by_commodity_map histories;
+
+ void add_price(commodity_t& source,
+ const datetime_t& date,
+ const amount_t& price,
+ const bool reflexive = true);
+ bool remove_price(const datetime_t& date, commodity_t& commodity);
+
+ optional<price_point_t>
+ find_price(const commodity_t& source,
+ const optional<commodity_t&>& commodity = none,
+ const optional<datetime_t>& moment = none,
+ const optional<datetime_t>& oldest = none
#if defined(DEBUG_ON)
- , const int indent = 0
+ , const int indent = 0
#endif
- ) const;
+ ) const;
- optional<history_t&>
- history(const optional<commodity_t&>& commodity = none);
+ optional<history_t&>
+ history(const optional<commodity_t&>& commodity = none);
#if defined(HAVE_BOOST_SERIALIZATION)
- private:
- /** Serialization. */
+ private:
+ /** Serialization. */
- friend class boost::serialization::access;
+ friend class boost::serialization::access;
- template<class Archive>
- void serialize(Archive & ar, const unsigned int /* version */) {
- ar & histories;
- }
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* version */) {
+ ar & histories;
+ }
#endif // HAVE_BOOST_SERIALIZATION
- };
+ };
+
+protected:
+ friend class commodity_pool_t;
+ friend class annotated_commodity_t;
+ class base_t : public noncopyable, public supports_flags<uint_least16_t>
+ {
+ public:
#define COMMODITY_STYLE_DEFAULTS 0x000
#define COMMODITY_STYLE_SUFFIXED 0x001
#define COMMODITY_STYLE_SEPARATED 0x002
@@ -190,7 +188,9 @@ public:
public:
explicit base_t(const string& _symbol)
- : supports_flags<uint_least16_t>(COMMODITY_STYLE_DEFAULTS),
+ : supports_flags<uint_least16_t>(commodity_t::european_by_default ?
+ COMMODITY_STYLE_EUROPEAN :
+ COMMODITY_STYLE_DEFAULTS),
symbol(_symbol), precision(0), searched(false) {
TRACE_CTOR(base_t, "const string&");
}
@@ -199,33 +199,31 @@ public:
}
#if defined(HAVE_BOOST_SERIALIZATION)
- private:
- /** Serialization. */
-
- friend class boost::serialization::access;
-
- template<class Archive>
- void serialize(Archive & ar, const unsigned int /* version */) {
- ar & boost::serialization::base_object<supports_flags<uint_least16_t> >(*this);
- ar & symbol;
- ar & precision;
- ar & name;
- ar & note;
- ar & varied_history;
- ar & smaller;
- ar & larger;
- }
+ private:
+ base_t() {
+ TRACE_CTOR(base_t, "");
+ }
+
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<supports_flags<uint_least16_t> >(*this);
+ ar & symbol;
+ ar & precision;
+ ar & name;
+ ar & note;
+ ar & varied_history;
+ ar & smaller;
+ ar & larger;
+ }
#endif // HAVE_BOOST_SERIALIZATION
};
-public:
static bool symbol_needs_quotes(const string& symbol);
- typedef base_t::history_t history_t;
- typedef base_t::history_map history_map;
- typedef base_t::varied_history_t varied_history_t;
- typedef base_t::history_by_commodity_map history_by_commodity_map;
-
shared_ptr<base_t> base;
commodity_pool_t * parent_;
@@ -233,13 +231,16 @@ public:
optional<string> mapping_key_;
bool annotated;
-public:
explicit commodity_t(commodity_pool_t * _parent,
const shared_ptr<base_t>& _base)
: delegates_flags<uint_least16_t>(*_base.get()), base(_base),
parent_(_parent), annotated(false) {
TRACE_CTOR(commodity_t, "commodity_pool_t *, shared_ptr<base_t>");
}
+
+public:
+ static bool european_by_default;
+
virtual ~commodity_t() {
TRACE_DTOR(commodity_t);
}
diff --git a/src/filters.cc b/src/filters.cc
index da9e39ae..00e495dd 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -133,6 +133,40 @@ void sort_posts::post_accumulated_posts()
posts.clear();
}
+namespace {
+ void split_string(const string& str, const char ch,
+ std::list<string>& strings)
+ {
+ const char * b = str.c_str();
+ for (const char * p = b; *p; p++) {
+ if (*p == ch) {
+ strings.push_back(string(b, p - b));
+ b = p + 1;
+ }
+ }
+ strings.push_back(string(b));
+ }
+
+ account_t * create_temp_account_from_path(std::list<string>& account_names,
+ temporaries_t& temps,
+ account_t * master)
+ {
+ account_t * new_account = NULL;
+ foreach (const string& name, account_names) {
+ if (new_account) {
+ new_account = new_account->find_account(name);
+ } else {
+ new_account = master->find_account(name, false);
+ if (! new_account)
+ new_account = &temps.create_account(name, master);
+ }
+ }
+
+ assert(new_account != NULL);
+ return new_account;
+ }
+}
+
void anonymize_posts::operator()(post_t& post)
{
SHA1 sha;
@@ -158,27 +192,19 @@ void anonymize_posts::operator()(post_t& post)
}
std::list<string> account_names;
- account_t * new_account = NULL;
for (account_t * acct = post.account;
acct;
acct = acct->parent) {
- if (! acct->parent) {
- new_account = acct;
- break;
- }
-
sha.Reset();
sha << acct->name.c_str();
sha.Result(message_digest);
account_names.push_front(to_hex(message_digest));
}
- assert(new_account);
-
- foreach (const string& name, account_names)
- new_account = new_account->find_account(name);
+ account_t * new_account =
+ create_temp_account_from_path(account_names, temps, xact.journal->master);
post_t& temp = temps.copy_post(post, xact, new_account);
temp.note = none;
@@ -685,11 +711,15 @@ void transfer_details::operator()(post_t& post)
case SET_PAYEE:
xact.payee = expr.calc(bound_scope).to_string();
break;
- case SET_ACCOUNT:
+ case SET_ACCOUNT: {
+ std::list<string> account_names;
temp.account->remove_post(&temp);
- temp.account = master->find_account(expr.calc(bound_scope).to_string());
+ split_string(expr.calc(bound_scope).to_string(), ':', account_names);
+ temp.account = create_temp_account_from_path(account_names, temps,
+ xact.journal->master);
temp.account->add_post(&temp);
break;
+ }
default:
assert(false);
break;
@@ -739,11 +769,11 @@ void budget_posts::report_budget_items(const date_t& date)
}
assert(begin);
- if (*begin < date &&
+ if (*begin <= date &&
(! pair.first.end || *begin < *pair.first.end)) {
post_t& post = *pair.second;
- DEBUG("ledger.walk.budget", "Reporting budget for "
+ DEBUG("budget.generate", "Reporting budget for "
<< post.reported_account()->fullname());
xact_t& xact = temps.create_xact();
@@ -785,7 +815,7 @@ void budget_posts::operator()(post_t& post)
post_in_budget = true;
// Report the post as if it had occurred in the parent account.
if (post.reported_account() != acct)
- post.xdata().account = acct;
+ post.set_reported_account(acct);
goto handle;
}
}
diff --git a/src/filters.h b/src/filters.h
index 7c1f169c..0dcf5e41 100644
--- a/src/filters.h
+++ b/src/filters.h
@@ -288,8 +288,7 @@ public:
class anonymize_posts : public item_handler<post_t>
{
temporaries_t temps;
-
- xact_t * last_xact;
+ xact_t * last_xact;
anonymize_posts();
diff --git a/src/item.cc b/src/item.cc
index debda7a3..37e19a82 100644
--- a/src/item.cc
+++ b/src/item.cc
@@ -237,7 +237,7 @@ namespace {
in_context_t<item_t> env(scope, "s");
if (optional<string> value = env->get_tag(env.get<string>(0)))
return string_value(*value);
- return false;
+ return string_value(empty_string);
}
value_t get_pathname(item_t& item) {
diff --git a/src/item.h b/src/item.h
index 28eb3f80..b65d482a 100644
--- a/src/item.h
+++ b/src/item.h
@@ -143,6 +143,7 @@ public:
_date_eff = item._date_eff;
note = item.note;
pos = item.pos;
+ metadata = item.metadata;
}
virtual bool operator==(const item_t& xact) {
@@ -206,8 +207,8 @@ private:
ar & _date;
ar & _date_eff;
ar & note;
- ar & metadata;
ar & pos;
+ ar & metadata;
}
#endif // HAVE_BOOST_SERIALIZATION
};
diff --git a/src/iterators.cc b/src/iterators.cc
index 50c67ade..540ba8ae 100644
--- a/src/iterators.cc
+++ b/src/iterators.cc
@@ -94,9 +94,9 @@ void posts_commodities_iterator::reset(journal_t& journal)
comm->varied_history()) {
account_t * account = journal.master->find_account(comm->symbol());
- foreach (commodity_t::base_t::history_by_commodity_map::value_type pair,
+ foreach (commodity_t::history_by_commodity_map::value_type pair,
history->histories) {
- foreach (commodity_t::base_t::history_map::value_type hpair,
+ foreach (commodity_t::history_map::value_type hpair,
pair.second.prices) {
xact_t * xact;
string symbol = hpair.second.commodity().symbol();
diff --git a/src/op.h b/src/op.h
index 8d474b80..b27384ec 100644
--- a/src/op.h
+++ b/src/op.h
@@ -232,13 +232,13 @@ public:
private:
void acquire() const {
- DEBUG("ledger.xpath.memory",
+ DEBUG("op.memory",
"Acquiring " << this << ", refc now " << refc + 1);
assert(refc >= 0);
refc++;
}
void release() const {
- DEBUG("ledger.xpath.memory",
+ DEBUG("op.memory",
"Releasing " << this << ", refc now " << refc - 1);
assert(refc > 0);
if (--refc == 0)
diff --git a/src/pool.cc b/src/pool.cc
index 68ba3ed7..06a4706c 100644
--- a/src/pool.cc
+++ b/src/pool.cc
@@ -108,25 +108,23 @@ commodity_pool_t::create(const string& symbol, const annotation_t& details)
return new_comm;
}
-namespace {
- string make_qualified_name(const commodity_t& comm,
- const annotation_t& details)
- {
- assert(details);
+string commodity_pool_t::make_qualified_name(const commodity_t& comm,
+ const annotation_t& details)
+{
+ assert(details);
- if (details.price && details.price->sign() < 0)
- throw_(amount_error, _("A commodity's price may not be negative"));
+ if (details.price && details.price->sign() < 0)
+ throw_(amount_error, _("A commodity's price may not be negative"));
- std::ostringstream name;
- comm.print(name);
- details.print(name, comm.parent().keep_base);
+ std::ostringstream name;
+ comm.print(name);
+ details.print(name, comm.parent().keep_base);
- DEBUG("amounts.commodities", "make_qualified_name for "
- << *comm.qualified_symbol << std::endl << details);
- DEBUG("amounts.commodities", "qualified_name is " << name.str());
+ DEBUG("amounts.commodities", "make_qualified_name for "
+ << *comm.qualified_symbol << std::endl << details);
+ DEBUG("amounts.commodities", "qualified_name is " << name.str());
- return name.str();
- }
+ return name.str();
}
commodity_t *
diff --git a/src/pool.h b/src/pool.h
index 6fce0c59..7e54e595 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -98,6 +98,9 @@ public:
checked_delete(pair.second);
}
+ string make_qualified_name(const commodity_t& comm,
+ const annotation_t& details);
+
commodity_t * create(const string& symbol);
commodity_t * find(const string& name);
commodity_t * find_or_create(const string& symbol);
diff --git a/src/post.cc b/src/post.cc
index 7b5e5325..2a1663cb 100644
--- a/src/post.cc
+++ b/src/post.cc
@@ -141,6 +141,12 @@ namespace {
return string_value(post.xact->payee);
}
+ value_t get_note(post_t& post) {
+ string note = post.note ? *post.note : empty_string;
+ note += post.xact->note ? *post.xact->note : empty_string;
+ return string_value(note);
+ }
+
value_t get_magnitude(post_t& post) {
return post.xact->magnitude();
}
@@ -318,6 +324,11 @@ expr_t::ptr_op_t post_t::lookup(const string& name)
return WRAP_FUNCTOR(get_wrapper<&get_magnitude>);
break;
+ case 'n':
+ if (name == "note")
+ return WRAP_FUNCTOR(get_wrapper<&get_note>);
+ break;
+
case 'p':
if (name == "post")
return WRAP_FUNCTOR(get_wrapper<&get_this>);
@@ -425,4 +436,10 @@ void post_t::add_to_value(value_t& value, const optional<expr_t&>& expr) const
}
}
+void post_t::set_reported_account(account_t * account)
+{
+ xdata().account = account;
+ account->xdata().reported_posts.push_back(this);
+}
+
} // namespace ledger
diff --git a/src/post.h b/src/post.h
index a89ce3bc..5fdee968 100644
--- a/src/post.h
+++ b/src/post.h
@@ -193,6 +193,8 @@ public:
void add_to_value(value_t& value,
const optional<expr_t&>& expr = none) const;
+ void set_reported_account(account_t * account);
+
account_t * reported_account() {
if (xdata_)
if (account_t * acct = xdata_->account)
diff --git a/src/precmd.cc b/src/precmd.cc
index 590d2553..a08fd2d6 100644
--- a/src/precmd.cc
+++ b/src/precmd.cc
@@ -42,7 +42,7 @@
namespace ledger {
namespace {
- post_t * get_sample_post(report_t& report)
+ post_t * get_sample_xact(report_t& report)
{
{
string str;
@@ -50,7 +50,11 @@ namespace {
std::ostringstream buf;
buf << "2004/05/27 Book Store\n"
+ << " ; This note applies to all postings. :SecondTag:\n"
<< " Expenses:Books 20 BOOK @ $10\n"
+ << " ; Metadata: Some Value\n"
+ << " ; :ExampleTag:\n"
+ << " ; Here follows a note describing the posting.\n"
<< " Liabilities:MasterCard $-200.00\n";
str = buf.str();
@@ -82,7 +86,7 @@ value_t parse_command(call_scope_t& args)
report_t& report(find_scope<report_t>(args));
std::ostream& out(report.output_stream);
- post_t * post = get_sample_post(report);
+ post_t * post = get_sample_xact(report);
out << _("--- Input expression ---") << std::endl;
out << arg << std::endl;
@@ -131,7 +135,7 @@ value_t format_command(call_scope_t& args)
report_t& report(find_scope<report_t>(args));
std::ostream& out(report.output_stream);
- post_t * post = get_sample_post(report);
+ post_t * post = get_sample_xact(report);
out << _("--- Input format string ---") << std::endl;
out << arg << std::endl << std::endl;
diff --git a/src/predicate.cc b/src/predicate.cc
index b3926116..d5b41362 100644
--- a/src/predicate.cc
+++ b/src/predicate.cc
@@ -156,7 +156,7 @@ query_lexer_t::token_t query_lexer_t::next_token()
else if (ident == "code")
return token_t(token_t::TOK_CODE);
else if (ident == "note")
- return token_t(token_t::TOK_NOT);
+ return token_t(token_t::TOK_NOTE);
else if (ident == "tag")
return token_t(token_t::TOK_META);
else if (ident == "meta")
@@ -242,7 +242,39 @@ query_parser_t::parse_query_term(query_lexer_t::token_t::kind_t tok_context)
case query_lexer_t::token_t::TERM:
assert(tok.value);
if (tok_context == query_lexer_t::token_t::TOK_META) {
- assert(0);
+ node = new expr_t::op_t(expr_t::op_t::O_CALL);
+
+ expr_t::ptr_op_t ident;
+ ident = new expr_t::op_t(expr_t::op_t::IDENT);
+ ident->set_ident("has_tag");
+ node->set_left(ident);
+
+ expr_t::ptr_op_t arg1;
+ arg1 = new expr_t::op_t(expr_t::op_t::VALUE);
+ arg1->set_value(mask_t(*tok.value));
+
+ tok = lexer.peek_token();
+ if (tok.kind == query_lexer_t::token_t::TOK_EQ) {
+ tok = lexer.next_token();
+ tok = lexer.next_token();
+ if (tok.kind != query_lexer_t::token_t::TERM)
+ throw_(parse_error,
+ _("Metadata equality operator not followed by term"));
+
+ expr_t::ptr_op_t cons;
+ cons = new expr_t::op_t(expr_t::op_t::O_CONS);
+
+ expr_t::ptr_op_t arg2;
+ arg2 = new expr_t::op_t(expr_t::op_t::VALUE);
+ assert(tok.value);
+ arg2->set_value(mask_t(*tok.value));
+
+ cons->set_left(arg1);
+ cons->set_right(arg2);
+ node->set_right(cons);
+ } else {
+ node->set_right(arg1);
+ }
} else {
node = new expr_t::op_t(expr_t::op_t::O_MATCH);
diff --git a/src/py_amount.cc b/src/py_amount.cc
index 7fe12674..efae7514 100644
--- a/src/py_amount.cc
+++ b/src/py_amount.cc
@@ -42,59 +42,66 @@ namespace ledger {
using namespace boost::python;
-boost::optional<amount_t> py_value_0(const amount_t& amount) {
- return amount.value();
-}
-boost::optional<amount_t> py_value_1(const amount_t& amount,
- const bool primary_only) {
- return amount.value(primary_only);
-}
-boost::optional<amount_t> py_value_2(const amount_t& amount,
- const bool primary_only,
- const boost::optional<datetime_t>& moment) {
- return amount.value(primary_only, moment);
-}
-boost::optional<amount_t> py_value_3(const amount_t& amount,
- const bool primary_only,
- const boost::optional<datetime_t>& moment,
- const boost::optional<commodity_t&>& in_terms_of) {
- return amount.value(primary_only, moment, in_terms_of);
-}
+namespace {
-void py_parse_2(amount_t& amount, object in, unsigned char flags) {
- if (PyFile_Check(in.ptr())) {
- pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr()));
- amount.parse(instr, flags);
- } else {
- PyErr_SetString(PyExc_IOError,
- _("Argument to amount.parse(file) is not a file object"));
+ boost::optional<amount_t> py_value_0(const amount_t& amount) {
+ return amount.value();
+ }
+ boost::optional<amount_t> py_value_1(const amount_t& amount,
+ const bool primary_only) {
+ return amount.value(primary_only);
}
-}
-void py_parse_1(amount_t& amount, object in) {
- py_parse_2(amount, in, 0);
-}
-void py_parse_str_1(amount_t& amount, const string& str) {
- amount.parse(str);
-}
-void py_parse_str_2(amount_t& amount, const string& str, unsigned char flags) {
- amount.parse(str, flags);
-}
+ boost::optional<amount_t>
+ py_value_2(const amount_t& amount,
+ const bool primary_only,
+ const boost::optional<datetime_t>& moment) {
+ return amount.value(primary_only, moment);
+ }
-void py_print(amount_t& amount, object out)
-{
- if (PyFile_Check(out.ptr())) {
- pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr()));
- amount.print(outstr);
- } else {
- PyErr_SetString(PyExc_IOError,
- _("Argument to amount.print_(file) is not a file object"));
+ boost::optional<amount_t>
+ py_value_3(const amount_t& amount,
+ const bool primary_only,
+ const boost::optional<datetime_t>& moment,
+ const boost::optional<commodity_t&>& in_terms_of) {
+ return amount.value(primary_only, moment, in_terms_of);
}
-}
-void py_amount_initialize() {
- amount_t::initialize();
-}
+ void py_parse_2(amount_t& amount, object in, unsigned char flags) {
+ if (PyFile_Check(in.ptr())) {
+ pyifstream instr(reinterpret_cast<PyFileObject *>(in.ptr()));
+ amount.parse(instr, flags);
+ } else {
+ PyErr_SetString(PyExc_IOError,
+ _("Argument to amount.parse(file) is not a file object"));
+ }
+ }
+ void py_parse_1(amount_t& amount, object in) {
+ py_parse_2(amount, in, 0);
+ }
+
+ void py_parse_str_1(amount_t& amount, const string& str) {
+ amount.parse(str);
+ }
+ void py_parse_str_2(amount_t& amount, const string& str, unsigned char flags) {
+ amount.parse(str, flags);
+ }
+
+ void py_print(amount_t& amount, object out) {
+ if (PyFile_Check(out.ptr())) {
+ pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr()));
+ amount.print(outstr);
+ } else {
+ PyErr_SetString(PyExc_IOError,
+ _("Argument to amount.print_(file) is not a file object"));
+ }
+ }
+
+ void py_amount_initialize() {
+ amount_t::initialize();
+ }
+
+} // unnamed namespace
#define EXC_TRANSLATOR(type) \
void exc_translate_ ## type(const type& err) { \
@@ -106,15 +113,18 @@ EXC_TRANSLATOR(amount_error)
void export_amount()
{
class_< amount_t > ("Amount")
+ .add_static_property("current_pool",
+ make_getter(&amount_t::current_pool,
+ return_value_policy<reference_existing_object>()))
+
.def("initialize", py_amount_initialize) // only for the PyUnitTests
.staticmethod("initialize")
.def("shutdown", &amount_t::shutdown)
.staticmethod("shutdown")
- .add_static_property("current_pool",
- make_getter(&amount_t::current_pool,
- return_value_policy<reference_existing_object>()))
-
+ .add_static_property("is_initialized",
+ make_getter(&amount_t::is_initialized),
+ make_setter(&amount_t::is_initialized))
.add_static_property("stream_fullstrings",
make_getter(&amount_t::stream_fullstrings),
make_setter(&amount_t::stream_fullstrings))
@@ -129,7 +139,8 @@ internal precision."))
.def(init<amount_t>())
- .def("compare", &amount_t::compare)
+ .def("compare", &amount_t::compare, args("amount"),
+ _("Compare two amounts for equality, returning <0, 0 or >0."))
.def(self == self)
.def(self == long())
@@ -186,6 +197,10 @@ internal precision."))
.def(long() / self)
.def("precision", &amount_t::precision)
+ .def("keep_precision", &amount_t::keep_precision)
+ .def("set_keep_precision", &amount_t::set_keep_precision, args("keep"),
+ _("Set whether an amount should always display at full precision."))
+ .def("display_precision", &amount_t::display_precision)
.def("negated", &amount_t::negated)
.def("in_place_negate", &amount_t::in_place_negate,
@@ -195,8 +210,19 @@ internal precision."))
.def("abs", &amount_t::abs)
.def("__abs__", &amount_t::abs)
+ .def("inverted", &amount_t::inverted)
+
.def("rounded", &amount_t::rounded)
+ .def("in_place_round", &amount_t::in_place_round,
+ return_value_policy<reference_existing_object>())
+
+ .def("truncated", &amount_t::truncated)
+ .def("in_place_truncate", &amount_t::in_place_truncate,
+ return_value_policy<reference_existing_object>())
+
.def("unrounded", &amount_t::unrounded)
+ .def("in_place_unround", &amount_t::in_place_unround,
+ return_value_policy<reference_existing_object>())
.def("reduced", &amount_t::reduced)
.def("in_place_reduce", &amount_t::in_place_reduce,
@@ -207,9 +233,11 @@ internal precision."))
return_value_policy<reference_existing_object>())
.def("value", py_value_0)
- .def("value", py_value_1)
- .def("value", py_value_2)
- .def("value", py_value_3)
+ .def("value", py_value_1, args("primary_only"))
+ .def("value", py_value_2, args("primary_only", "moment"))
+ .def("value", py_value_3, args("primary_only", "moment", "in_terms_of"))
+
+ .def("price", &amount_t::price)
.def("sign", &amount_t::sign)
.def("__nonzero__", &amount_t::is_nonzero)
@@ -222,22 +250,21 @@ internal precision."))
.def("__float__", &amount_t::to_double)
.def("to_long", &amount_t::to_long)
.def("__int__", &amount_t::to_long)
+ .def("fits_in_long", &amount_t::fits_in_long)
+
.def("to_string", &amount_t::to_string)
.def("__str__", &amount_t::to_string)
.def("to_fullstring", &amount_t::to_fullstring)
.def("__repr__", &amount_t::to_fullstring)
-
- .def("fits_in_long", &amount_t::fits_in_long)
-
.def("quantity_string", &amount_t::quantity_string)
.def("commodity", &amount_t::commodity,
return_value_policy<reference_existing_object>())
+ .def("has_commodity", &amount_t::has_commodity)
.def("set_commodity", &amount_t::set_commodity,
with_custodian_and_ward<1, 2>())
-
- .def("has_commodity", &amount_t::has_commodity)
.def("clear_commodity", &amount_t::clear_commodity)
+
.def("number", &amount_t::number)
.def("annotate", &amount_t::annotate)
@@ -256,7 +283,6 @@ internal precision."))
.staticmethod("parse_conversion")
.def("print_", py_print)
-
.def("dump", &amount_t::dump)
.def("valid", &amount_t::valid)
diff --git a/src/py_balance.cc b/src/py_balance.cc
index 086b7b12..2d940876 100644
--- a/src/py_balance.cc
+++ b/src/py_balance.cc
@@ -32,69 +32,90 @@
#include <system.hh>
#include "pyinterp.h"
+#include "pyutils.h"
+#include "pyfstream.h"
+#include "commodity.h"
+#include "annotate.h"
+#include "balance.h"
namespace ledger {
using namespace boost::python;
-#define EXC_TRANSLATOR(type) \
- void exc_translate_ ## type(const type& err) { \
- PyErr_SetString(PyExc_ArithmeticError, err.what()); \
+namespace {
+
+ boost::optional<balance_t> py_value_0(const balance_t& balance) {
+ return balance.value();
+ }
+ boost::optional<balance_t> py_value_1(const balance_t& balance,
+ const bool primary_only) {
+ return balance.value(primary_only);
}
-EXC_TRANSLATOR(balance_error)
+ boost::optional<balance_t>
+ py_value_2(const balance_t& balance,
+ const bool primary_only,
+ const boost::optional<datetime_t>& moment) {
+ return balance.value(primary_only, moment);
+ }
-void export_balance()
-{
-#if 0
- class_< balance_t > ("Balance")
- ;
-#endif
+ boost::optional<balance_t>
+ py_value_3(const balance_t& balance,
+ const bool primary_only,
+ const boost::optional<datetime_t>& moment,
+ const boost::optional<commodity_t&>& in_terms_of) {
+ return balance.value(primary_only, moment, in_terms_of);
+ }
- //register_optional_to_python<amount_t>();
+ boost::optional<amount_t>
+ py_commodity_amount_0(const balance_t& balance) {
+ return balance.commodity_amount();
+ }
- //implicitly_convertible<string, amount_t>();
+ boost::optional<amount_t>
+ py_commodity_amount_1(const balance_t& balance,
+ const boost::optional<const commodity_t&>& commodity) {
+ return balance.commodity_amount(commodity);
+ }
-#define EXC_TRANSLATE(type) \
- register_exception_translator<type>(&exc_translate_ ## type);
+ void py_print(balance_t& balance, object out) {
+ if (PyFile_Check(out.ptr())) {
+ pyofstream outstr(reinterpret_cast<PyFileObject *>(out.ptr()));
+ balance.print(outstr);
+ } else {
+ PyErr_SetString(PyExc_IOError,
+ _("Argument to balance.print_(file) is not a file object"));
+ }
+ }
- //EXC_TRANSLATE(balance_error);
-}
+ long balance_len(balance_t& bal) {
+ return bal.amounts.size();
+ }
-} // namespace ledger
+ amount_t balance_getitem(balance_t& bal, long i) {
+ long len = bal.amounts.size();
-#if 0
-unsigned int balance_len(balance_t& bal)
-{
- return bal.amounts.size();
-}
+ if (labs(i) >= len) {
+ PyErr_SetString(PyExc_IndexError, _("Index out of range"));
+ throw_error_already_set();
+ }
-amount_t balance_getitem(balance_t& bal, int i)
-{
- std::size_t len = bal.amounts.size();
+ long x = i < 0 ? len + i : i;
+ balance_t::amounts_map::iterator elem = bal.amounts.begin();
+ while (--x >= 0)
+ elem++;
- if (abs(i) >= len) {
- PyErr_SetString(PyExc_IndexError, _("Index out of range"));
- throw_error_already_set();
+ return (*elem).second;
}
- int x = i < 0 ? len + i : i;
- balance_t::amounts_map::iterator elem = bal.amounts.begin();
- while (--x >= 0)
- elem++;
+} // unnamed namespace
- return (*elem).second;
-}
-
-unsigned int balance_pair_len(balance_pair_t& bal_pair)
-{
- return balance_len(bal_pair.quantity);
-}
+#define EXC_TRANSLATOR(type) \
+ void exc_translate_ ## type(const type& err) { \
+ PyErr_SetString(PyExc_ArithmeticError, err.what()); \
+ }
-amount_t balance_pair_getitem(balance_pair_t& bal_pair, int i)
-{
- return balance_getitem(bal_pair.quantity, i);
-}
+EXC_TRANSLATOR(balance_error)
void export_balance()
{
@@ -102,8 +123,7 @@ void export_balance()
.def(init<balance_t>())
.def(init<amount_t>())
.def(init<long>())
- .def(init<unsigned long>())
- .def(init<double>())
+ .def(init<string>())
.def(self += self)
.def(self += other<amount_t>())
@@ -117,32 +137,16 @@ void export_balance()
.def(self - self)
.def(self - other<amount_t>())
.def(self - long())
- .def(self *= self)
.def(self *= other<amount_t>())
.def(self *= long())
- .def(self * self)
.def(self * other<amount_t>())
.def(self * long())
- .def(self /= self)
.def(self /= other<amount_t>())
.def(self /= long())
- .def(self / self)
.def(self / other<amount_t>())
.def(self / long())
.def(- self)
- .def(self < self)
- .def(self < other<amount_t>())
- .def(self < long())
- .def(self <= self)
- .def(self <= other<amount_t>())
- .def(self <= long())
- .def(self > self)
- .def(self > other<amount_t>())
- .def(self > long())
- .def(self >= self)
- .def(self >= other<amount_t>())
- .def(self >= long())
.def(self == self)
.def(self == other<amount_t>())
.def(self == long())
@@ -153,114 +157,70 @@ void export_balance()
.def(self_ns::str(self))
+ .def("negated", &balance_t::negated)
+ .def("in_place_negate", &balance_t::in_place_negate,
+ return_value_policy<reference_existing_object>())
+ .def(- self)
+
+ .def("abs", &balance_t::abs)
.def("__abs__", &balance_t::abs)
+
.def("__len__", balance_len)
.def("__getitem__", balance_getitem)
- .def("valid", &balance_t::valid)
+ .def("rounded", &balance_t::rounded)
+ .def("in_place_round", &balance_t::in_place_round,
+ return_value_policy<reference_existing_object>())
- .def("realzero", &balance_t::realzero)
- .def("amount", &balance_t::amount)
- .def("value", &balance_t::value)
- .def("price", &balance_t::price)
- .def("date", &balance_t::date)
- .def("strip_annotations", &balance_t::strip_annotations)
- .def("write", &balance_t::write)
- .def("round", &balance_t::round)
- .def("negate", &balance_t::negate)
- .def("negated", &balance_t::negated)
- ;
+ .def("truncated", &balance_t::truncated)
+ .def("in_place_truncate", &balance_t::in_place_truncate,
+ return_value_policy<reference_existing_object>())
- class_< balance_pair_t > ("BalancePair")
- .def(init<balance_pair_t>())
- .def(init<balance_t>())
- .def(init<amount_t>())
- .def(init<long>())
- .def(init<unsigned long>())
- .def(init<double>())
+ .def("unrounded", &balance_t::unrounded)
+ .def("in_place_unround", &balance_t::in_place_unround,
+ return_value_policy<reference_existing_object>())
- .def(self += self)
- .def(self += other<balance_t>())
- .def(self += other<amount_t>())
- .def(self += long())
- .def(self + self)
- .def(self + other<balance_t>())
- .def(self + other<amount_t>())
- .def(self + long())
- .def(self -= self)
- .def(self -= other<balance_t>())
- .def(self -= other<amount_t>())
- .def(self -= long())
- .def(self - self)
- .def(self - other<balance_t>())
- .def(self - other<amount_t>())
- .def(self - long())
- .def(self *= self)
- .def(self *= other<balance_t>())
- .def(self *= other<amount_t>())
- .def(self *= long())
- .def(self * self)
- .def(self * other<balance_t>())
- .def(self * other<amount_t>())
- .def(self * long())
- .def(self /= self)
- .def(self /= other<balance_t>())
- .def(self /= other<amount_t>())
- .def(self /= long())
- .def(self / self)
- .def(self / other<balance_t>())
- .def(self / other<amount_t>())
- .def(self / long())
- .def(- self)
+ .def("reduced", &balance_t::reduced)
+ .def("in_place_reduce", &balance_t::in_place_reduce,
+ return_value_policy<reference_existing_object>())
- .def(self < self)
- .def(self < other<balance_t>())
- .def(self < other<amount_t>())
- .def(self < long())
- .def(self <= self)
- .def(self <= other<balance_t>())
- .def(self <= other<amount_t>())
- .def(self <= long())
- .def(self > self)
- .def(self > other<balance_t>())
- .def(self > other<amount_t>())
- .def(self > long())
- .def(self >= self)
- .def(self >= other<balance_t>())
- .def(self >= other<amount_t>())
- .def(self >= long())
- .def(self == self)
- .def(self == other<balance_t>())
- .def(self == other<amount_t>())
- .def(self == long())
- .def(self != self)
- .def(self != other<balance_t>())
- .def(self != other<amount_t>())
- .def(self != long())
- .def(! self)
+ .def("unreduced", &balance_t::unreduced)
+ .def("in_place_unreduce", &balance_t::in_place_unreduce,
+ return_value_policy<reference_existing_object>())
- .def(self_ns::str(self))
+ .def("value", py_value_0)
+ .def("value", py_value_1, args("primary_only"))
+ .def("value", py_value_2, args("primary_only", "moment"))
+ .def("value", py_value_3, args("primary_only", "moment", "in_terms_of"))
+
+ .def("price", &balance_t::price)
+
+ .def("__nonzero__", &balance_t::is_nonzero)
+ .def("is_nonzero", &balance_t::is_nonzero)
+ .def("is_zero", &balance_t::is_zero)
+ .def("is_realzero", &balance_t::is_realzero)
+
+ .def("is_empty", &balance_t::is_empty)
+ .def("single_amount", &balance_t::single_amount)
+
+ .def("to_amount", &balance_t::to_amount)
- .def("__abs__", &balance_pair_t::abs)
- .def("__len__", balance_pair_len)
- .def("__getitem__", balance_pair_getitem)
-
- .def("valid", &balance_pair_t::valid)
-
- .def("realzero", &balance_pair_t::realzero)
- .def("amount", &balance_pair_t::amount)
- .def("value", &balance_pair_t::value)
- .def("price", &balance_pair_t::price)
- .def("date", &balance_pair_t::date)
- .def("strip_annotations", &balance_pair_t::strip_annotations)
- .def("write", &balance_pair_t::write)
- .def("round", &balance_pair_t::round)
- .def("negate", &balance_pair_t::negate)
- .def("negated", &balance_pair_t::negated)
-
- .add_property("cost",
- make_getter(&balance_pair_t::cost,
- return_value_policy<reference_existing_object>()))
+ .def("commodity_count", &balance_t::commodity_count)
+ .def("commodity_amount", py_commodity_amount_0)
+ .def("commodity_amount", py_commodity_amount_1)
+
+ .def("strip_annotations", &balance_t::strip_annotations)
+
+ .def("print_", py_print)
+ .def("dump", &balance_t::dump)
+
+ .def("valid", &balance_t::valid)
;
+
+#define EXC_TRANSLATE(type) \
+ register_exception_translator<type>(&exc_translate_ ## type);
+
+ EXC_TRANSLATE(balance_error);
}
-#endif
+
+} // namespace ledger
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
index f5b1a543..9ad9a906 100644
--- a/src/pyinterp.cc
+++ b/src/pyinterp.cc
@@ -83,7 +83,7 @@ void initialize_for_python()
export_value();
export_xact();
- scope().attr("session") = python_session;
+ scope().attr("current_session") = python_session;
}
struct python_run
diff --git a/src/report.cc b/src/report.cc
index 9f15a2d5..60f6955c 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -664,6 +664,8 @@ option_t<report_t> * report_t::lookup_option(const char * p)
case 's':
OPT(set_account_);
else OPT(set_payee_);
+ else OPT(set_reported_account_);
+ else OPT(set_reported_payee_);
else OPT(sort_);
else OPT(sort_all_);
else OPT(sort_xacts_);
diff --git a/src/report.h b/src/report.h
index 0fe7d05b..e00c6460 100644
--- a/src/report.h
+++ b/src/report.h
@@ -284,6 +284,8 @@ public:
HANDLER(seed_).report(out);
HANDLER(set_account_).report(out);
HANDLER(set_payee_).report(out);
+ HANDLER(set_reported_account_).report(out);
+ HANDLER(set_reported_payee_).report(out);
HANDLER(sort_).report(out);
HANDLER(sort_all_).report(out);
HANDLER(sort_xacts_).report(out);
@@ -652,7 +654,7 @@ public:
if (have_less) {
on(none, "less");
- setenv("LESS", "--quit-if-one-screen -R", 0);
+ setenv("LESS", "-FRSX", 0); // don't overwrite
}
}
}
@@ -805,6 +807,8 @@ public:
OPTION(report_t, seed_);
OPTION(report_t, set_account_);
OPTION(report_t, set_payee_);
+ OPTION(report_t, set_reported_account_);
+ OPTION(report_t, set_reported_payee_);
OPTION_(report_t, sort_, DO_(args) { // -S
on_with(args[0].as_string(), args[1]);
diff --git a/src/session.cc b/src/session.cc
index 3f29716d..33c27165 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -264,6 +264,9 @@ option_t<session_t> * session_t::lookup_option(const char * p)
case 'd':
OPT(download); // -Q
break;
+ case 'e':
+ OPT(european);
+ break;
case 'f':
OPT_(file_); // -f
break;
diff --git a/src/session.h b/src/session.h
index c1e0243b..58e33f6b 100644
--- a/src/session.h
+++ b/src/session.h
@@ -50,6 +50,7 @@
#include "account.h"
#include "journal.h"
#include "option.h"
+#include "commodity.h"
namespace ledger {
@@ -105,6 +106,7 @@ public:
HANDLER(account_).report(out);
HANDLER(cache_).report(out);
HANDLER(download).report(out);
+ HANDLER(european).report(out);
HANDLER(file_).report(out);
HANDLER(input_date_format_).report(out);
HANDLER(price_db_).report(out);
@@ -124,6 +126,10 @@ public:
OPTION(session_t, cache_);
OPTION(session_t, download); // -Q
+ OPTION_(session_t, european, DO() {
+ commodity_t::european_by_default = true;
+ });
+
OPTION__
(session_t, price_exp_, // -Z
CTOR(session_t, price_exp_) { value = 24L * 3600L; }
diff --git a/src/temps.cc b/src/temps.cc
index f2dee159..012a573b 100644
--- a/src/temps.cc
+++ b/src/temps.cc
@@ -49,6 +49,13 @@ temporaries_t::~temporaries_t()
post.account->remove_post(&post);
}
}
+
+ if (acct_temps) {
+ foreach (account_t& acct, *acct_temps) {
+ if (acct.parent && ! acct.parent->has_flags(ACCOUNT_TEMP))
+ acct.parent->remove_account(&acct);
+ }
+ }
}
xact_t& temporaries_t::copy_xact(xact_t& origin)
@@ -120,6 +127,9 @@ account_t& temporaries_t::create_account(const string& name,
acct_temps->push_back(account_t(parent, name));
account_t& temp(acct_temps->back());
+ if (parent)
+ parent->add_account(&temp);
+
temp.add_flags(ACCOUNT_TEMP);
return temp;
}
diff --git a/src/temps.h b/src/temps.h
index 646f4dcd..34494ba8 100644
--- a/src/temps.h
+++ b/src/temps.h
@@ -68,7 +68,7 @@ public:
post_t& last_post() {
return post_temps->back();
}
- account_t& create_account(const string& name,
+ account_t& create_account(const string& name = "",
account_t * parent = NULL);
account_t& last_account() {
return acct_temps->back();
diff --git a/src/times.cc b/src/times.cc
index 667f65a3..b737b2a0 100644
--- a/src/times.cc
+++ b/src/times.cc
@@ -55,12 +55,13 @@ namespace {
#endif // USE_BOOST_FACETS
public:
- bool has_year;
- bool input;
+ bool has_year;
+ bool has_day;
+ bool input;
temporal_io_t(const char * _fmt_str, bool _input)
: fmt_str(_fmt_str), has_year(icontains(fmt_str, "%y")),
- input(_input) {
+ has_day(icontains(fmt_str, "%d")), input(_input) {
#if defined(USE_BOOST_FACETS)
if (input) {
input_facet = new InputFacetType(fmt_str);
@@ -75,6 +76,7 @@ namespace {
void set_format(const char * fmt) {
fmt_str = fmt;
has_year = icontains(fmt_str, "%y");
+ has_day = icontains(fmt_str, "%d");
#if defined(USE_BOOST_FACETS)
if (input)
@@ -190,7 +192,7 @@ namespace {
date_t parse_date_mask_routine(const char * date_str, date_io_t& io,
optional<date_t::year_type> year,
- bool& saw_year)
+ bool& saw_year, bool& saw_day)
{
date_t when;
@@ -220,26 +222,30 @@ namespace {
if (when.month() > CURRENT_DATE().month())
when -= gregorian::years(1);
- } else {
+ }
+ else {
saw_year = true;
}
+
+ saw_day = io.has_day;
}
return when;
}
date_t parse_date_mask(const char * date_str,
- optional<date_t::year_type> year, bool& saw_year)
+ optional<date_t::year_type> year,
+ bool& saw_year, bool& saw_day)
{
if (input_date_io.get()) {
date_t when = parse_date_mask_routine(date_str, *input_date_io.get(),
- year, saw_year);
+ year, saw_year, saw_day);
if (! when.is_not_a_date())
return when;
}
foreach (shared_ptr<date_io_t>& reader, readers) {
date_t when = parse_date_mask_routine(date_str, *reader.get(),
- year, saw_year);
+ year, saw_year, saw_day);
if (! when.is_not_a_date())
return when;
}
@@ -311,7 +317,8 @@ datetime_t parse_datetime(const char * str, optional<date_t::year_type>)
date_t parse_date(const char * str, optional<date_t::year_type> current_year)
{
bool saw_year;
- return parse_date_mask(str, current_year, saw_year);
+ bool saw_day;
+ return parse_date_mask(str, current_year, saw_year, saw_day);
}
std::ostream& operator<<(std::ostream& out,
@@ -549,7 +556,8 @@ namespace {
date_t * end)
{
bool saw_year = true;
- date_t when = parse_date_mask(word.c_str(), none, saw_year);
+ bool saw_day = true;
+ date_t when = parse_date_mask(word.c_str(), none, saw_year, saw_day);
if (when.is_not_a_date())
throw_(date_error, _("Could not parse date mask: %1") << word);
@@ -558,8 +566,8 @@ namespace {
*begin = when;
if (end) {
- if (saw_year)
- *end = *begin + gregorian::years(1);
+ if (saw_day)
+ *end = *begin + gregorian::days(1);
else
*end = *begin + gregorian::months(1);
}
@@ -728,17 +736,17 @@ void date_interval_t::parse(std::istream& in)
if (wday) {
while (start->day_of_week() != *wday)
- *start = duration_t(duration_t::DAYS, 1).subtract(*start);
+ *start -= gregorian::days(1);
if (! end)
- end = duration_t(duration_t::DAYS, 1).add(*start);
+ end = *start + gregorian::days(1);
} else {
bool overwrite_end = false;
if (year) {
start = date_t(*year, 1, 1);
if (! end) {
- end = duration_t(duration_t::YEARS, 1).add(*start);
+ end = *start + gregorian::years(1);
overwrite_end = true;
}
}
@@ -746,7 +754,7 @@ void date_interval_t::parse(std::istream& in)
if (mon) {
start = date_t(start->year(), *mon, 1);
if (! end || overwrite_end)
- end = duration_t(duration_t::MONTHS, 1).add(*start);
+ end = *start + gregorian::months(1);
}
}
}
diff --git a/src/xact.cc b/src/xact.cc
index 3670cb94..3291c5be 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -39,8 +39,8 @@
namespace ledger {
-xact_base_t::xact_base_t(const xact_base_t&)
- : item_t(), journal(NULL)
+xact_base_t::xact_base_t(const xact_base_t& xact_base)
+ : item_t(xact_base), journal(xact_base.journal)
{
TRACE_CTOR(xact_base_t, "copy");
}
diff --git a/src/xact.h b/src/xact.h
index 59ddd1bc..7de30ee8 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -65,7 +65,6 @@ class xact_base_t : public item_t
{
public:
journal_t * journal;
-
posts_list posts;
xact_base_t() : item_t(), journal(NULL) {
diff --git a/test/ConfirmTests.py b/test/ConfirmTests.py
index 0b3d4897..901ae7cd 100755
--- a/test/ConfirmTests.py
+++ b/test/ConfirmTests.py
@@ -10,7 +10,7 @@ import re
from LedgerHarness import LedgerHarness
harness = LedgerHarness(sys.argv)
-tests = sys.argv[2]
+tests = sys.argv[3]
if not os.path.isdir(tests) and not os.path.isfile(tests):
sys.exit(1)
diff --git a/test/GenerateTests.py b/test/GenerateTests.py
index aa36737d..d60e0581 100755
--- a/test/GenerateTests.py
+++ b/test/GenerateTests.py
@@ -104,9 +104,9 @@ def generation_test(seed):
beg_range = 1
end_range = 20
-if len(sys.argv) > 3:
- beg_range = int(sys.argv[2])
- end_range = int(sys.argv[3])
+if len(sys.argv) > 4:
+ beg_range = int(sys.argv[3])
+ end_range = int(sys.argv[4])
for i in range(beg_range, end_range):
if generation_test(i):
diff --git a/test/LedgerHarness.py b/test/LedgerHarness.py
index cf65f590..8a5af123 100755
--- a/test/LedgerHarness.py
+++ b/test/LedgerHarness.py
@@ -7,22 +7,27 @@ import re
from subprocess import Popen, PIPE
class LedgerHarness:
- ledger = None
- succeeded = 0
- failed = 0
- verify = False
- gmalloc = False
+ ledger = None
+ sourcepath = None
+ succeeded = 0
+ failed = 0
+ verify = False
+ gmalloc = False
def __init__(self, argv):
if not os.path.isfile(argv[1]):
print "Cannot find ledger at '%s'" % argv[1]
sys.exit(1)
+ if not os.path.isdir(argv[2]):
+ print "Cannot find source path at '%s'" % argv[2]
+ sys.exit(1)
- self.ledger = argv[1]
- self.succeeded = 0
- self.failed = 0
- self.verify = '--verify' in argv
- self.gmalloc = '--gmalloc' in argv
+ self.ledger = argv[1]
+ self.sourcepath = argv[2]
+ self.succeeded = 0
+ self.failed = 0
+ self.verify = '--verify' in argv
+ self.gmalloc = '--gmalloc' in argv
def run(self, command, verify=None, gmalloc=None, columns=True):
env = os.environ.copy()
@@ -48,10 +53,8 @@ class LedgerHarness:
if columns:
insert += ' --columns=80'
- command = re.sub('\$ledger', '%s%s %s %s %s %s' % \
- (self.ledger, insert, '--args-only',
- '--no-color', '--pager=none',
- '--date-format=%y-%b-%d'), command)
+ command = re.sub('\$ledger', '%s%s %s' % \
+ (self.ledger, insert, '--args-only'), command)
return Popen(command, shell=True, close_fds=True, env=env,
stdin=PIPE, stdout=PIPE, stderr=PIPE)
diff --git a/test/RegressTests.py b/test/RegressTests.py
index 4d23f6b5..13a0a113 100755
--- a/test/RegressTests.py
+++ b/test/RegressTests.py
@@ -11,7 +11,7 @@ from difflib import unified_diff
from LedgerHarness import LedgerHarness
harness = LedgerHarness(sys.argv)
-tests = sys.argv[2]
+tests = sys.argv[3]
if not os.path.isdir(tests) and not os.path.isfile(tests):
sys.exit(1)
@@ -27,11 +27,15 @@ class RegressFile:
line == ">>>2\n" or \
line.startswith("===")
+ def transform_line(self, line):
+ line = re.sub('\$sourcepath', harness.sourcepath, line)
+ return line
+
def read_section(self):
lines = []
line = self.fd.readline()
while not self.is_directive(line):
- lines.append(line)
+ lines.append(self.transform_line(line))
line = self.fd.readline()
return (lines, line)
@@ -60,7 +64,7 @@ class RegressFile:
test['exitcode'] = int(match.group(1))
return test
else:
- test['command'] = line
+ test['command'] = self.transform_line(line)
line = self.fd.readline()
return None
diff --git a/test/baseline/opt-add-budget.test b/test/baseline/opt-add-budget.test
index 20dfd320..535335d3 100644
--- a/test/baseline/opt-add-budget.test
+++ b/test/baseline/opt-add-budget.test
@@ -244,124 +244,124 @@ reg --add-budget books cards
Liabilities:Cards $120.00
Assets:Cash
>>>1
-08-Jan-01 January Expenses:Books $10.00 $10.00
- Liabilities:Cards $10.00 $20.00
-08-Jan-01 Budget transaction Expenses:Books $-10.00 $10.00
+08-Jan-01 Budget transaction Expenses:Books $-10.00 $-10.00
+08-Jan-01 January Expenses:Books $10.00 0
+ Liabilities:Cards $10.00 $10.00
08-Jan-31 End of January Expenses:Books $10.00 $20.00
Liabilities:Cards $10.00 $30.00
-08-Feb-01 February Expenses:Books $20.00 $50.00
- Liabilities:Cards $20.00 $70.00
-08-Feb-01 Budget transaction Expenses:Books $-10.00 $60.00
+08-Feb-01 Budget transaction Expenses:Books $-10.00 $20.00
+08-Feb-01 February Expenses:Books $20.00 $40.00
+ Liabilities:Cards $20.00 $60.00
08-Feb-28 End of February Expenses:Books $20.00 $80.00
Liabilities:Cards $20.00 $100.00
-08-Mar-01 March Expenses:Books $30.00 $130.00
- Liabilities:Cards $30.00 $160.00
-08-Mar-01 Budget transaction Expenses:Books $-10.00 $150.00
+08-Mar-01 Budget transaction Expenses:Books $-10.00 $90.00
+08-Mar-01 March Expenses:Books $30.00 $120.00
+ Liabilities:Cards $30.00 $150.00
08-Mar-31 End of March Expenses:Books $30.00 $180.00
Liabilities:Cards $30.00 $210.00
-08-Apr-01 April Expenses:Books $40.00 $250.00
- Liabilities:Cards $40.00 $290.00
-08-Apr-01 Budget transaction Expenses:Books $-10.00 $280.00
+08-Apr-01 Budget transaction Expenses:Books $-10.00 $200.00
+08-Apr-01 April Expenses:Books $40.00 $240.00
+ Liabilities:Cards $40.00 $280.00
08-Apr-30 End of April Expenses:Books $40.00 $320.00
Liabilities:Cards $40.00 $360.00
-08-May-01 May Expenses:Books $50.00 $410.00
- Liabilities:Cards $50.00 $460.00
-08-May-01 Budget transaction Expenses:Books $-10.00 $450.00
+08-May-01 Budget transaction Expenses:Books $-10.00 $350.00
+08-May-01 May Expenses:Books $50.00 $400.00
+ Liabilities:Cards $50.00 $450.00
08-May-31 End of May Expenses:Books $50.00 $500.00
Liabilities:Cards $50.00 $550.00
-08-Jun-01 June Expenses:Books $60.00 $610.00
- Liabilities:Cards $60.00 $670.00
-08-Jun-01 Budget transaction Expenses:Books $-10.00 $660.00
+08-Jun-01 Budget transaction Expenses:Books $-10.00 $540.00
+08-Jun-01 June Expenses:Books $60.00 $600.00
+ Liabilities:Cards $60.00 $660.00
08-Jun-30 End of June Expenses:Books $60.00 $720.00
Liabilities:Cards $60.00 $780.00
-08-Jul-01 July Expenses:Books $70.00 $850.00
- Liabilities:Cards $70.00 $920.00
-08-Jul-01 Budget transaction Expenses:Books $-10.00 $910.00
+08-Jul-01 Budget transaction Expenses:Books $-10.00 $770.00
+08-Jul-01 July Expenses:Books $70.00 $840.00
+ Liabilities:Cards $70.00 $910.00
08-Jul-31 End of July Expenses:Books $70.00 $980.00
Liabilities:Cards $70.00 $1050.00
-08-Aug-01 August Expenses:Books $80.00 $1130.00
- Liabilities:Cards $80.00 $1210.00
-08-Aug-01 Budget transaction Expenses:Books $-10.00 $1200.00
+08-Aug-01 Budget transaction Expenses:Books $-10.00 $1040.00
+08-Aug-01 August Expenses:Books $80.00 $1120.00
+ Liabilities:Cards $80.00 $1200.00
08-Aug-31 End of August Expenses:Books $80.00 $1280.00
Liabilities:Cards $80.00 $1360.00
-08-Sep-01 September Expenses:Books $90.00 $1450.00
- Liabilities:Cards $90.00 $1540.00
-08-Sep-01 Budget transaction Expenses:Books $-10.00 $1530.00
+08-Sep-01 Budget transaction Expenses:Books $-10.00 $1350.00
+08-Sep-01 September Expenses:Books $90.00 $1440.00
+ Liabilities:Cards $90.00 $1530.00
08-Sep-30 End of September Expenses:Books $90.00 $1620.00
Liabilities:Cards $90.00 $1710.00
-08-Oct-01 October Expenses:Books $100.00 $1810.00
- Liabilities:Cards $100.00 $1910.00
-08-Oct-01 Budget transaction Expenses:Books $-10.00 $1900.00
+08-Oct-01 Budget transaction Expenses:Books $-10.00 $1700.00
+08-Oct-01 October Expenses:Books $100.00 $1800.00
+ Liabilities:Cards $100.00 $1900.00
08-Oct-31 End of October Expenses:Books $100.00 $2000.00
Liabilities:Cards $100.00 $2100.00
-08-Nov-01 November Expenses:Books $110.00 $2210.00
- Liabilities:Cards $110.00 $2320.00
-08-Nov-01 Budget transaction Expenses:Books $-10.00 $2310.00
+08-Nov-01 Budget transaction Expenses:Books $-10.00 $2090.00
+08-Nov-01 November Expenses:Books $110.00 $2200.00
+ Liabilities:Cards $110.00 $2310.00
08-Nov-30 End of November Expenses:Books $110.00 $2420.00
Liabilities:Cards $110.00 $2530.00
-08-Dec-01 December Expenses:Books $120.00 $2650.00
- Liabilities:Cards $120.00 $2770.00
-08-Dec-01 Budget transaction Expenses:Books $-10.00 $2760.00
+08-Dec-01 Budget transaction Expenses:Books $-10.00 $2520.00
+08-Dec-01 December Expenses:Books $120.00 $2640.00
+ Liabilities:Cards $120.00 $2760.00
08-Dec-31 End of December Expenses:Books $120.00 $2880.00
Liabilities:Cards $120.00 $3000.00
-09-Jan-01 January Expenses:Books $10.00 $3010.00
- Liabilities:Cards $10.00 $3020.00
-09-Jan-01 Budget transaction Expenses:Books $-10.00 $3010.00
+09-Jan-01 Budget transaction Expenses:Books $-10.00 $2990.00
+09-Jan-01 January Expenses:Books $10.00 $3000.00
+ Liabilities:Cards $10.00 $3010.00
09-Jan-31 End of January Expenses:Books $10.00 $3020.00
Liabilities:Cards $10.00 $3030.00
-09-Feb-01 February Expenses:Books $20.00 $3050.00
- Liabilities:Cards $20.00 $3070.00
-09-Feb-01 Budget transaction Expenses:Books $-10.00 $3060.00
+09-Feb-01 Budget transaction Expenses:Books $-10.00 $3020.00
+09-Feb-01 February Expenses:Books $20.00 $3040.00
+ Liabilities:Cards $20.00 $3060.00
09-Feb-28 End of February Expenses:Books $20.00 $3080.00
Liabilities:Cards $20.00 $3100.00
-09-Mar-01 March Expenses:Books $30.00 $3130.00
- Liabilities:Cards $30.00 $3160.00
-09-Mar-01 Budget transaction Expenses:Books $-10.00 $3150.00
+09-Mar-01 Budget transaction Expenses:Books $-10.00 $3090.00
+09-Mar-01 March Expenses:Books $30.00 $3120.00
+ Liabilities:Cards $30.00 $3150.00
09-Mar-31 End of March Expenses:Books $30.00 $3180.00
Liabilities:Cards $30.00 $3210.00
-09-Apr-01 April Expenses:Books $40.00 $3250.00
- Liabilities:Cards $40.00 $3290.00
-09-Apr-01 Budget transaction Expenses:Books $-10.00 $3280.00
+09-Apr-01 Budget transaction Expenses:Books $-10.00 $3200.00
+09-Apr-01 April Expenses:Books $40.00 $3240.00
+ Liabilities:Cards $40.00 $3280.00
09-Apr-30 End of April Expenses:Books $40.00 $3320.00
Liabilities:Cards $40.00 $3360.00
-09-May-01 May Expenses:Books $50.00 $3410.00
- Liabilities:Cards $50.00 $3460.00
-09-May-01 Budget transaction Expenses:Books $-10.00 $3450.00
+09-May-01 Budget transaction Expenses:Books $-10.00 $3350.00
+09-May-01 May Expenses:Books $50.00 $3400.00
+ Liabilities:Cards $50.00 $3450.00
09-May-31 End of May Expenses:Books $50.00 $3500.00
Liabilities:Cards $50.00 $3550.00
-09-Jun-01 June Expenses:Books $60.00 $3610.00
- Liabilities:Cards $60.00 $3670.00
-09-Jun-01 Budget transaction Expenses:Books $-10.00 $3660.00
+09-Jun-01 Budget transaction Expenses:Books $-10.00 $3540.00
+09-Jun-01 June Expenses:Books $60.00 $3600.00
+ Liabilities:Cards $60.00 $3660.00
09-Jun-30 End of June Expenses:Books $60.00 $3720.00
Liabilities:Cards $60.00 $3780.00
-09-Jul-01 July Expenses:Books $70.00 $3850.00
- Liabilities:Cards $70.00 $3920.00
-09-Jul-01 Budget transaction Expenses:Books $-10.00 $3910.00
+09-Jul-01 Budget transaction Expenses:Books $-10.00 $3770.00
+09-Jul-01 July Expenses:Books $70.00 $3840.00
+ Liabilities:Cards $70.00 $3910.00
09-Jul-31 End of July Expenses:Books $70.00 $3980.00
Liabilities:Cards $70.00 $4050.00
-09-Aug-01 August Expenses:Books $80.00 $4130.00
- Liabilities:Cards $80.00 $4210.00
-09-Aug-01 Budget transaction Expenses:Books $-10.00 $4200.00
+09-Aug-01 Budget transaction Expenses:Books $-10.00 $4040.00
+09-Aug-01 August Expenses:Books $80.00 $4120.00
+ Liabilities:Cards $80.00 $4200.00
09-Aug-31 End of August Expenses:Books $80.00 $4280.00
Liabilities:Cards $80.00 $4360.00
-09-Sep-01 September Expenses:Books $90.00 $4450.00
- Liabilities:Cards $90.00 $4540.00
-09-Sep-01 Budget transaction Expenses:Books $-10.00 $4530.00
+09-Sep-01 Budget transaction Expenses:Books $-10.00 $4350.00
+09-Sep-01 September Expenses:Books $90.00 $4440.00
+ Liabilities:Cards $90.00 $4530.00
09-Sep-30 End of September Expenses:Books $90.00 $4620.00
Liabilities:Cards $90.00 $4710.00
-09-Oct-01 October Expenses:Books $100.00 $4810.00
- Liabilities:Cards $100.00 $4910.00
-09-Oct-01 Budget transaction Expenses:Books $-10.00 $4900.00
+09-Oct-01 Budget transaction Expenses:Books $-10.00 $4700.00
+09-Oct-01 October Expenses:Books $100.00 $4800.00
+ Liabilities:Cards $100.00 $4900.00
09-Oct-31 End of October Expenses:Books $100.00 $5000.00
Liabilities:Cards $100.00 $5100.00
-09-Nov-01 November Expenses:Books $110.00 $5210.00
- Liabilities:Cards $110.00 $5320.00
-09-Nov-01 Budget transaction Expenses:Books $-10.00 $5310.00
+09-Nov-01 Budget transaction Expenses:Books $-10.00 $5090.00
+09-Nov-01 November Expenses:Books $110.00 $5200.00
+ Liabilities:Cards $110.00 $5310.00
09-Nov-30 End of November Expenses:Books $110.00 $5420.00
Liabilities:Cards $110.00 $5530.00
-09-Dec-01 December Expenses:Books $120.00 $5650.00
- Liabilities:Cards $120.00 $5770.00
-09-Dec-01 Budget transaction Expenses:Books $-10.00 $5760.00
+09-Dec-01 Budget transaction Expenses:Books $-10.00 $5520.00
+09-Dec-01 December Expenses:Books $120.00 $5640.00
+ Liabilities:Cards $120.00 $5760.00
09-Dec-31 End of December Expenses:Books $120.00 $5880.00
Liabilities:Cards $120.00 $6000.00
>>>2
diff --git a/test/baseline/opt-anon.test b/test/baseline/opt-anon.test
index f9244451..6fe6b75f 100644
--- a/test/baseline/opt-anon.test
+++ b/test/baseline/opt-anon.test
@@ -4,8 +4,8 @@ reg --anon
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
Income:Dividends:Vanguard:VMMXX $-0.35
>>>1
-07-Feb-02 6a93dcb3 20:5d:27:988a9c3a 0.350 VMMXX 0.350 VMMXX
- 1c:b6:27:988a9c3a $-0.35 $-0.35
+07-Feb-02 6a93dcb3 da:20:5d:27:988a9c3a 0.350 VMMXX 0.350 VMMXX
+ da:1c:b6:27:988a9c3a $-0.35 $-0.35
0.350 VMMXX
>>>2
=== 0
diff --git a/test/baseline/opt-budget.test b/test/baseline/opt-budget.test
index 097d19d8..eb2ade9d 100644
--- a/test/baseline/opt-budget.test
+++ b/test/baseline/opt-budget.test
@@ -245,77 +245,77 @@ reg --budget books
Liabilities:Cards $120.00
Assets:Cash
>>>1
-08-Jan-01 January Expenses:Books $10.00 $10.00
-08-Jan-01 Budget transaction Expenses:Books $-10.00 0
+08-Jan-01 Budget transaction Expenses:Books $-10.00 $-10.00
+08-Jan-01 January Expenses:Books $10.00 0
08-Jan-31 End of January Expenses:Books $10.00 $10.00
-08-Feb-01 February Expenses:Books $20.00 $30.00
-08-Feb-01 Budget transaction Expenses:Books $-10.00 $20.00
+08-Feb-01 Budget transaction Expenses:Books $-10.00 0
+08-Feb-01 February Expenses:Books $20.00 $20.00
08-Feb-28 End of February Expenses:Books $20.00 $40.00
-08-Mar-01 March Expenses:Books $30.00 $70.00
-08-Mar-01 Budget transaction Expenses:Books $-10.00 $60.00
+08-Mar-01 Budget transaction Expenses:Books $-10.00 $30.00
+08-Mar-01 March Expenses:Books $30.00 $60.00
08-Mar-31 End of March Expenses:Books $30.00 $90.00
-08-Apr-01 April Expenses:Books $40.00 $130.00
-08-Apr-01 Budget transaction Expenses:Books $-10.00 $120.00
+08-Apr-01 Budget transaction Expenses:Books $-10.00 $80.00
+08-Apr-01 April Expenses:Books $40.00 $120.00
08-Apr-30 End of April Expenses:Books $40.00 $160.00
-08-May-01 May Expenses:Books $50.00 $210.00
-08-May-01 Budget transaction Expenses:Books $-10.00 $200.00
+08-May-01 Budget transaction Expenses:Books $-10.00 $150.00
+08-May-01 May Expenses:Books $50.00 $200.00
08-May-31 End of May Expenses:Books $50.00 $250.00
-08-Jun-01 June Expenses:Books $60.00 $310.00
-08-Jun-01 Budget transaction Expenses:Books $-10.00 $300.00
+08-Jun-01 Budget transaction Expenses:Books $-10.00 $240.00
+08-Jun-01 June Expenses:Books $60.00 $300.00
08-Jun-30 End of June Expenses:Books $60.00 $360.00
-08-Jul-01 July Expenses:Books $70.00 $430.00
-08-Jul-01 Budget transaction Expenses:Books $-10.00 $420.00
+08-Jul-01 Budget transaction Expenses:Books $-10.00 $350.00
+08-Jul-01 July Expenses:Books $70.00 $420.00
08-Jul-31 End of July Expenses:Books $70.00 $490.00
-08-Aug-01 August Expenses:Books $80.00 $570.00
-08-Aug-01 Budget transaction Expenses:Books $-10.00 $560.00
+08-Aug-01 Budget transaction Expenses:Books $-10.00 $480.00
+08-Aug-01 August Expenses:Books $80.00 $560.00
08-Aug-31 End of August Expenses:Books $80.00 $640.00
-08-Sep-01 September Expenses:Books $90.00 $730.00
-08-Sep-01 Budget transaction Expenses:Books $-10.00 $720.00
+08-Sep-01 Budget transaction Expenses:Books $-10.00 $630.00
+08-Sep-01 September Expenses:Books $90.00 $720.00
08-Sep-30 End of September Expenses:Books $90.00 $810.00
-08-Oct-01 October Expenses:Books $100.00 $910.00
-08-Oct-01 Budget transaction Expenses:Books $-10.00 $900.00
+08-Oct-01 Budget transaction Expenses:Books $-10.00 $800.00
+08-Oct-01 October Expenses:Books $100.00 $900.00
08-Oct-31 End of October Expenses:Books $100.00 $1000.00
-08-Nov-01 November Expenses:Books $110.00 $1110.00
-08-Nov-01 Budget transaction Expenses:Books $-10.00 $1100.00
+08-Nov-01 Budget transaction Expenses:Books $-10.00 $990.00
+08-Nov-01 November Expenses:Books $110.00 $1100.00
08-Nov-30 End of November Expenses:Books $110.00 $1210.00
-08-Dec-01 December Expenses:Books $120.00 $1330.00
-08-Dec-01 Budget transaction Expenses:Books $-10.00 $1320.00
+08-Dec-01 Budget transaction Expenses:Books $-10.00 $1200.00
+08-Dec-01 December Expenses:Books $120.00 $1320.00
08-Dec-31 End of December Expenses:Books $120.00 $1440.00
-09-Jan-01 January Expenses:Books $10.00 $1450.00
-09-Jan-01 Budget transaction Expenses:Books $-10.00 $1440.00
+09-Jan-01 Budget transaction Expenses:Books $-10.00 $1430.00
+09-Jan-01 January Expenses:Books $10.00 $1440.00
09-Jan-31 End of January Expenses:Books $10.00 $1450.00
-09-Feb-01 February Expenses:Books $20.00 $1470.00
-09-Feb-01 Budget transaction Expenses:Books $-10.00 $1460.00
+09-Feb-01 Budget transaction Expenses:Books $-10.00 $1440.00
+09-Feb-01 February Expenses:Books $20.00 $1460.00
09-Feb-28 End of February Expenses:Books $20.00 $1480.00
-09-Mar-01 March Expenses:Books $30.00 $1510.00
-09-Mar-01 Budget transaction Expenses:Books $-10.00 $1500.00
+09-Mar-01 Budget transaction Expenses:Books $-10.00 $1470.00
+09-Mar-01 March Expenses:Books $30.00 $1500.00
09-Mar-31 End of March Expenses:Books $30.00 $1530.00
-09-Apr-01 April Expenses:Books $40.00 $1570.00
-09-Apr-01 Budget transaction Expenses:Books $-10.00 $1560.00
+09-Apr-01 Budget transaction Expenses:Books $-10.00 $1520.00
+09-Apr-01 April Expenses:Books $40.00 $1560.00
09-Apr-30 End of April Expenses:Books $40.00 $1600.00
-09-May-01 May Expenses:Books $50.00 $1650.00
-09-May-01 Budget transaction Expenses:Books $-10.00 $1640.00
+09-May-01 Budget transaction Expenses:Books $-10.00 $1590.00
+09-May-01 May Expenses:Books $50.00 $1640.00
09-May-31 End of May Expenses:Books $50.00 $1690.00
-09-Jun-01 June Expenses:Books $60.00 $1750.00
-09-Jun-01 Budget transaction Expenses:Books $-10.00 $1740.00
+09-Jun-01 Budget transaction Expenses:Books $-10.00 $1680.00
+09-Jun-01 June Expenses:Books $60.00 $1740.00
09-Jun-30 End of June Expenses:Books $60.00 $1800.00
-09-Jul-01 July Expenses:Books $70.00 $1870.00
-09-Jul-01 Budget transaction Expenses:Books $-10.00 $1860.00
+09-Jul-01 Budget transaction Expenses:Books $-10.00 $1790.00
+09-Jul-01 July Expenses:Books $70.00 $1860.00
09-Jul-31 End of July Expenses:Books $70.00 $1930.00
-09-Aug-01 August Expenses:Books $80.00 $2010.00
-09-Aug-01 Budget transaction Expenses:Books $-10.00 $2000.00
+09-Aug-01 Budget transaction Expenses:Books $-10.00 $1920.00
+09-Aug-01 August Expenses:Books $80.00 $2000.00
09-Aug-31 End of August Expenses:Books $80.00 $2080.00
-09-Sep-01 September Expenses:Books $90.00 $2170.00
-09-Sep-01 Budget transaction Expenses:Books $-10.00 $2160.00
+09-Sep-01 Budget transaction Expenses:Books $-10.00 $2070.00
+09-Sep-01 September Expenses:Books $90.00 $2160.00
09-Sep-30 End of September Expenses:Books $90.00 $2250.00
-09-Oct-01 October Expenses:Books $100.00 $2350.00
-09-Oct-01 Budget transaction Expenses:Books $-10.00 $2340.00
+09-Oct-01 Budget transaction Expenses:Books $-10.00 $2240.00
+09-Oct-01 October Expenses:Books $100.00 $2340.00
09-Oct-31 End of October Expenses:Books $100.00 $2440.00
-09-Nov-01 November Expenses:Books $110.00 $2550.00
-09-Nov-01 Budget transaction Expenses:Books $-10.00 $2540.00
+09-Nov-01 Budget transaction Expenses:Books $-10.00 $2430.00
+09-Nov-01 November Expenses:Books $110.00 $2540.00
09-Nov-30 End of November Expenses:Books $110.00 $2650.00
-09-Dec-01 December Expenses:Books $120.00 $2770.00
-09-Dec-01 Budget transaction Expenses:Books $-10.00 $2760.00
+09-Dec-01 Budget transaction Expenses:Books $-10.00 $2640.00
+09-Dec-01 December Expenses:Books $120.00 $2760.00
09-Dec-31 End of December Expenses:Books $120.00 $2880.00
>>>2
=== 0
diff --git a/test/manual/transaction-codes-1.test b/test/manual/transaction-codes-1.test
new file mode 100644
index 00000000..878c5cac
--- /dev/null
+++ b/test/manual/transaction-codes-1.test
@@ -0,0 +1,22 @@
+reg --columns=60 food and code xfer
+<<<
+2009/10/29 (XFER) Panera Bread
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/10/30 (DEP) Pay day!
+ Assets:Checking $20.00
+ Income
+
+2009/10/30 (XFER) Panera Bread
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/10/31 (559385768438A8D7) Panera Bread
+ Expenses:Food $4.50
+ Liabilities:Credit Card
+>>>1
+09-Oct-29 Panera Bread Expenses:Food $4.50 $4.50
+09-Oct-30 Panera Bread Expenses:Food $4.50 $9.00
+>>>2
+=== 0
diff --git a/test/manual/transaction-codes-2.test b/test/manual/transaction-codes-2.test
new file mode 100644
index 00000000..4e4c76cf
--- /dev/null
+++ b/test/manual/transaction-codes-2.test
@@ -0,0 +1,24 @@
+bal checking --set-reported-account=code
+<<<
+2009/10/29 (XFER) Panera Bread
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/10/30 (DEP) Pay day!
+ Assets:Checking $20.00
+ Income
+
+2009/10/30 (XFER) Panera Bread
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/10/31 (559385768438A8D7) Panera Bread
+ Expenses:Food $4.50
+ Liabilities:Credit Card
+>>>1
+ $20.00 DEP
+ $-9.00 XFER
+--------------------
+ $11.00
+>>>2
+=== 0
diff --git a/test/manual/transaction-notes-1.test b/test/manual/transaction-notes-1.test
new file mode 100644
index 00000000..d3fab3b6
--- /dev/null
+++ b/test/manual/transaction-notes-1.test
@@ -0,0 +1,24 @@
+reg --columns=60 food and note eat
+<<<
+2009/11/01 Panera Bread ; Got something to eat
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Coffee
+ ; Let’s see, I ate a whole bunch of stuff, drank some coffee,
+ ; pondered a bagel, then decided against the donut.
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Dining
+ ; :Eating:
+ ; This is another long note, after the metadata.
+ Expenses:Food $4.50
+ Assets:Checking
+>>>1
+09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50
+09-Nov-01 Panera Bread Expenses:Food $4.50 $9.00
+>>>2
+=== 0
diff --git a/test/manual/transaction-notes-2.test b/test/manual/transaction-notes-2.test
new file mode 100644
index 00000000..b7a258e0
--- /dev/null
+++ b/test/manual/transaction-notes-2.test
@@ -0,0 +1,23 @@
+reg --columns=60 food and tag eating
+<<<
+2009/11/01 Panera Bread ; Got something to eat
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Coffee
+ ; Let’s see, I ate a whole bunch of stuff, drank some coffee,
+ ; pondered a bagel, then decided against the donut.
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Dining
+ ; :Eating:
+ ; This is another long note, after the metadata.
+ Expenses:Food $4.50
+ Assets:Checking
+>>>1
+09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50
+>>>2
+=== 0
diff --git a/test/manual/transaction-notes-3.test b/test/manual/transaction-notes-3.test
new file mode 100644
index 00000000..9d532d5f
--- /dev/null
+++ b/test/manual/transaction-notes-3.test
@@ -0,0 +1,23 @@
+reg --columns=60 food and tag type=dining
+<<<
+2009/11/01 Panera Bread ; Got something to eat
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Coffee
+ ; Let’s see, I ate a whole bunch of stuff, drank some coffee,
+ ; pondered a bagel, then decided against the donut.
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Dining
+ ; :Eating:
+ ; This is another long note, after the metadata.
+ Expenses:Food $4.50
+ Assets:Checking
+>>>1
+09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50
+>>>2
+=== 0
diff --git a/test/manual/transaction-notes-4.test b/test/manual/transaction-notes-4.test
new file mode 100644
index 00000000..516094c7
--- /dev/null
+++ b/test/manual/transaction-notes-4.test
@@ -0,0 +1,27 @@
+bal food and tag type --set-reported-account='"Tags:" + tag("Type")'
+<<<
+2009/11/01 Panera Bread ; Got something to eat
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Coffee
+ ; Let’s see, I ate a whole bunch of stuff, drank some coffee,
+ ; pondered a bagel, then decided against the donut.
+ Expenses:Food $4.50
+ Assets:Checking
+
+2009/11/01 Panera Bread
+ ; Type: Dining
+ ; :Eating:
+ ; This is another long note, after the metadata.
+ Expenses:Food $4.50
+ Assets:Checking
+>>>1
+ $9.00 Tags
+ $4.50 Coffee
+ $4.50 Dining
+--------------------
+ $9.00
+>>>2
+=== 0
diff --git a/test/manual/transaction-status-1.test b/test/manual/transaction-status-1.test
new file mode 100644
index 00000000..4bdf893a
--- /dev/null
+++ b/test/manual/transaction-status-1.test
@@ -0,0 +1,19 @@
+reg --columns=60 food
+<<<
+2009/10/31 * Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/01 ! Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/02 Panera Bread
+ Expenses:Food $4.50
+ Assets
+>>>1
+09-Oct-31 Panera Bread Expenses:Food $4.50 $4.50
+09-Nov-01 Panera Bread Expenses:Food $4.50 $9.00
+09-Nov-02 Panera Bread Expenses:Food $4.50 $13.50
+>>>2
+=== 0
diff --git a/test/manual/transaction-status-2.test b/test/manual/transaction-status-2.test
new file mode 100644
index 00000000..dbbb04ae
--- /dev/null
+++ b/test/manual/transaction-status-2.test
@@ -0,0 +1,17 @@
+reg --columns=60 food --cleared
+<<<
+2009/10/31 * Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/01 ! Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/02 Panera Bread
+ Expenses:Food $4.50
+ Assets
+>>>1
+09-Oct-31 Panera Bread Expenses:Food $4.50 $4.50
+>>>2
+=== 0
diff --git a/test/manual/transaction-status-3.test b/test/manual/transaction-status-3.test
new file mode 100644
index 00000000..1e6467ef
--- /dev/null
+++ b/test/manual/transaction-status-3.test
@@ -0,0 +1,18 @@
+reg --columns=60 food --uncleared
+<<<
+2009/10/31 * Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/01 ! Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/02 Panera Bread
+ Expenses:Food $4.50
+ Assets
+>>>1
+09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50
+09-Nov-02 Panera Bread Expenses:Food $4.50 $9.00
+>>>2
+=== 0
diff --git a/test/manual/transaction-status-4.test b/test/manual/transaction-status-4.test
new file mode 100644
index 00000000..5275eec3
--- /dev/null
+++ b/test/manual/transaction-status-4.test
@@ -0,0 +1,17 @@
+reg --columns=60 food --pending
+<<<
+2009/10/31 * Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/01 ! Panera Bread
+ Expenses:Food $4.50
+ Assets
+
+2009/11/02 Panera Bread
+ Expenses:Food $4.50
+ Assets
+>>>1
+09-Nov-01 Panera Bread Expenses:Food $4.50 $4.50
+>>>2
+=== 0
diff --git a/test/regress/25A099C9.test b/test/regress/25A099C9.test
new file mode 100644
index 00000000..fb5613e2
--- /dev/null
+++ b/test/regress/25A099C9.test
@@ -0,0 +1,19 @@
+-f $sourcepath/src/amount.h reg
+<<<
+>>>1
+>>>2
+While parsing file "$sourcepath/src/amount.h", line 67:
+Error: No quantity specified for amount
+While parsing file "$sourcepath/src/amount.h", line 707:
+Error: Invalid date/time: line amount_t amoun
+While parsing file "$sourcepath/src/amount.h", line 713:
+Error: Invalid date/time: line string amount_
+While parsing file "$sourcepath/src/amount.h", line 719:
+Error: Invalid date/time: line string amount_
+While parsing file "$sourcepath/src/amount.h", line 725:
+Error: Invalid date/time: line string amount_
+While parsing file "$sourcepath/src/amount.h", line 731:
+Error: Invalid date/time: line std::ostream&
+While parsing file "$sourcepath/src/amount.h", line 738:
+Error: Invalid date/time: line std::istream&
+=== 7
diff --git a/test/regress/373540CC.test b/test/regress/373540CC.test
new file mode 100644
index 00000000..5c589ec9
--- /dev/null
+++ b/test/regress/373540CC.test
@@ -0,0 +1,9 @@
+bal --sort total --flat -X '$' not '(Income|Liabilities)'
+<<<
+2004/05/27 Book Store
+ Expenses:Books 20 BOOK @ $10
+ Liabilities:MasterCard $-200.00
+>>>1
+ $200.00 Expenses:Books
+>>>2
+=== 0
diff --git a/test/regress/5F1BAF17.test b/test/regress/5F1BAF17.test
new file mode 100644
index 00000000..f52ffb86
--- /dev/null
+++ b/test/regress/5F1BAF17.test
@@ -0,0 +1,130 @@
+bal da39 --flat --sort amount --display-total amount
+<<<
+2006/02/16 b5f40e96
+ da39a3ee:8d437dbf:ee2bf9bd:f61e33bf $713.35
+ Assets
+
+2006/03/27 c7ab1f2d
+ da39a3ee:8d437dbf:ee2bf9bd:9b69a35a $139.62
+ Assets
+
+2006/03/30 f32ea1dc
+ da39a3ee:8d437dbf:ee2bf9bd:d219c681 $1,600.00
+ Assets
+
+2006/04/21 d449d51e
+ da39a3ee:8d437dbf:ee2bf9bd:75b04b88 $698.10
+ Assets
+
+2006/05/02 b02f8323
+ da39a3ee:8d437dbf:ee2bf9bd $42.22
+ Assets
+
+2006/05/05 2a6f6850
+ da39a3ee:8d437dbf:ee2bf9bd:75b04b88:b3850e04 $2,468.00
+ Assets
+
+2006/05/09 59f92263
+ da39a3ee:8d437dbf:ee2bf9bd:071c929a $132.82
+ Assets
+
+2006/05/18 f78a7a51
+ da39a3ee:8d437dbf:ee2bf9bd:e97de844 $368.05
+ Assets
+
+2006/05/19 f35c594c
+ da39a3ee:8d437dbf:ee2bf9bd:d4e7d7d3 $386.62
+ Assets
+
+2006/05/22 0233a991
+ da39a3ee:8d437dbf:ee2bf9bd:9c6e5a3f $141.98
+ Assets
+
+2006/05/23 56ccae7f
+ da39a3ee:8d437dbf:ee2bf9bd:d31d367b $81.78
+ Assets
+
+2006/05/24 d449d51e
+ da39a3ee:8d437dbf:ee2bf9bd:75b04b88 $65.00
+ Assets
+
+2006/05/25 dc833c91
+ da39a3ee:8d437dbf:ee2bf9bd:d31d367b $34.37
+ Assets
+
+2006/05/31 6822b496
+ da39a3ee:8d437dbf:ee2bf9bd:e97de844 $41.78
+ Assets
+
+2006/06/02 dff8ccb2
+ da39a3ee:8d437dbf:ee2bf9bd:14e351e1 $67.36
+ Assets
+
+2006/06/02 e1eb3f4b
+ da39a3ee:8d437dbf:ee2bf9bd:2c7a078f $14.00
+ Assets
+
+2006/06/04 feec73ea
+ da39a3ee:8d437dbf:ee2bf9bd:131260cb $144.99
+ Assets
+
+2006/06/04 e8f65e0a
+ da39a3ee:8d437dbf:ee2bf9bd:d219c681 $75.00
+ Assets
+
+2006/06/04 3fd43f7b
+ da39a3ee:8d437dbf:ee2bf9bd:9c4ba7d0 $239.59
+ Assets
+
+2006/06/06 754be754
+ da39a3ee:8d437dbf:ee2bf9bd:35b25929 $1,160.14
+ Assets
+
+2006/06/06 00c16d44
+ da39a3ee:8d437dbf:ee2bf9bd:e97de844 $78.45
+ Assets
+
+2006/06/08 e7b0b317
+ da39a3ee:8d437dbf:ee2bf9bd $443.00
+ Assets
+
+2006/07/17 a30c4c31
+ da39a3ee:8d437dbf:ee2bf9bd $880.80
+ Assets
+
+2006/08/08 e31a0cf9
+ da39a3ee:8d437dbf:ee2bf9bd $104.53
+ Assets
+
+2006/08/10 f0c0c688
+ da39a3ee:8d437dbf:ee2bf9bd $196.70
+ Assets
+
+2006/09/12 1bc59c63
+ da39a3ee:8d437dbf:ee2bf9bd $217.79
+ Assets
+
+2007/07/16 557e3a00
+ da39a3ee:8d437dbf:ee2bf9bd:f61e33bf $117.80
+ Assets
+>>>1
+ $14.00 da39a3ee:8d437dbf:ee2bf9bd:2c7a078f
+ $67.36 da39a3ee:8d437dbf:ee2bf9bd:14e351e1
+ $116.15 da39a3ee:8d437dbf:ee2bf9bd:d31d367b
+ $132.82 da39a3ee:8d437dbf:ee2bf9bd:071c929a
+ $139.62 da39a3ee:8d437dbf:ee2bf9bd:9b69a35a
+ $141.98 da39a3ee:8d437dbf:ee2bf9bd:9c6e5a3f
+ $144.99 da39a3ee:8d437dbf:ee2bf9bd:131260cb
+ $239.59 da39a3ee:8d437dbf:ee2bf9bd:9c4ba7d0
+ $386.62 da39a3ee:8d437dbf:ee2bf9bd:d4e7d7d3
+ $488.28 da39a3ee:8d437dbf:ee2bf9bd:e97de844
+ $763.10 da39a3ee:8d437dbf:ee2bf9bd:75b04b88
+ $831.15 da39a3ee:8d437dbf:ee2bf9bd:f61e33bf
+ $1,160.14 da39a3ee:8d437dbf:ee2bf9bd:35b25929
+ $1,675.00 da39a3ee:8d437dbf:ee2bf9bd:d219c681
+ $1,885.04 da39a3ee:8d437dbf:ee2bf9bd
+ $2,468.00 da39a3ee:8d437dbf:ee2bf9bd:75b04b88:b3850e04
+--------------------
+ 0
+>>>2
+=== 0
diff --git a/test/regress/7F3650FD.test b/test/regress/7F3650FD.test
new file mode 100644
index 00000000..0eb3a96f
--- /dev/null
+++ b/test/regress/7F3650FD.test
@@ -0,0 +1,50 @@
+period --now=2010/11/01 12/01
+<<<
+>>>1
+global details =>
+
+ start: 09-Dec-01
+ end: 09-Dec-02
+ factor: 1
+>>>2
+=== 0
+period --now=2010/11/01 10/01
+<<<
+>>>1
+global details =>
+
+ start: 10-Oct-01
+ end: 10-Oct-02
+ factor: 1
+>>>2
+=== 0
+period --now=2010/11/01 2009/10
+<<<
+>>>1
+global details =>
+
+ start: 09-Oct-01
+ end: 09-Nov-01
+ factor: 1
+>>>2
+=== 0
+period --now=2010/11/01 2009/10/01
+<<<
+>>>1
+global details =>
+
+ start: 09-Oct-01
+ end: 09-Oct-02
+ factor: 1
+>>>2
+=== 0
+period --now=2010/11/01 2009
+<<<
+>>>1
+global details =>
+
+ start: 09-Jan-01
+ end: 10-Jan-01
+ factor: 1
+>>>2
+=== 0
diff --git a/test/regress/8254755E.test b/test/regress/8254755E.test
new file mode 100644
index 00000000..26baf52d
--- /dev/null
+++ b/test/regress/8254755E.test
@@ -0,0 +1,20 @@
+bal --flat food:out
+<<<
+~ Monthly
+ Expenses:Auto:Fuel $120.00
+ Expenses:Food:Out $100.00
+ Expenses:Food:Groceries $350.00
+ Assets
+
+2009/11/01
+ Expenses:Food:Out $50.00
+ Assets
+>>>1
+ $50.00 Expenses:Food:Out
+>>>2
+=== 0
+bal --flat --budget food:out
+>>>1
+ $-50.00 Expenses:Food:Out
+>>>2
+=== 0
diff --git a/test/regress/D060256A.test b/test/regress/D060256A.test
new file mode 100644
index 00000000..26c30351
--- /dev/null
+++ b/test/regress/D060256A.test
@@ -0,0 +1,16 @@
+budget --now=2009/11/01 --end=2009/11/30
+<<<
+~ Monthly
+ Expenses:Food $500.00
+ Assets
+
+2009/11/01 Sample
+ Expenses:Food:Dining $20.00
+ Assets
+>>>1
+ $-20.00 $-500.00 $480.00 4% Assets
+ $20.00 $500.00 $-480.00 4% Expenses:Food
+------------ ------------ ------------ -----
+ 0 0 0 0
+>>>2
+=== 0
diff --git a/test/regress/E627C594.test b/test/regress/E627C594.test
new file mode 100644
index 00000000..0dfbf778
--- /dev/null
+++ b/test/regress/E627C594.test
@@ -0,0 +1,18 @@
+reg --forecast-while="d<[2010/03/01]" --now=2009/11/01
+<<<
+~ Monthly
+ Expenses:Food $500.00
+ Assets
+
+2009/11/01 Sample
+ Expenses:Food:Dining $20.00
+ Assets
+>>>1
+09-Nov-01 Sample Expenses:Food:Dining $20.00 $20.00
+ Assets $-20.00 0
+10-Jan-01 Forecast transaction Expenses:Food $500.00 $500.00
+10-Jan-01 Forecast transaction Assets $-500.00 0
+10-Feb-01 Forecast transaction Expenses:Food $500.00 $500.00
+10-Feb-01 Forecast transaction Assets $-500.00 0
+>>>2
+=== 0
diff --git a/test/regress/F559EC12.test b/test/regress/F559EC12.test
index 7900b60d..c8b686db 100644
--- a/test/regress/F559EC12.test
+++ b/test/regress/F559EC12.test
@@ -3,7 +3,11 @@ format "%-12(scrub(amount))"
>>>1
--- Context is first posting of the following transaction ---
2004/05/27 Book Store
+ ; This note applies to all postings. :SecondTag:
Expenses:Books 20 BOOK @ $10
+ ; Metadata: Some Value
+ ; :ExampleTag:
+ ; Here follows a note describing the posting.
Liabilities:MasterCard $-200.00
--- Input format string ---
@@ -20,7 +24,11 @@ format "%12(scrub(amount))"
>>>1
--- Context is first posting of the following transaction ---
2004/05/27 Book Store
+ ; This note applies to all postings. :SecondTag:
Expenses:Books 20 BOOK @ $10
+ ; Metadata: Some Value
+ ; :ExampleTag:
+ ; Here follows a note describing the posting.
Liabilities:MasterCard $-200.00
--- Input format string ---
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 13ea4e7f..4dd4a871 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -247,7 +247,7 @@ endif
TESTS =
if HAVE_PYTHON
-TESTS += RegressTests BaselineTests ConfirmTests GenerateTests
+TESTS += RegressTests BaselineTests ManualTests ConfirmTests GenerateTests
endif
if HAVE_CPPUNIT
@@ -370,7 +370,7 @@ RegressTests_SOURCES = test/RegressTests.py
EXTRA_DIST += test/regress test/convert.py test/LedgerHarness.py
RegressTests: $(srcdir)/test/RegressTests.py
- echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir)/test/regress \"\$$@\"" > $@
+ echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/regress \"\$$@\"" > $@
chmod 755 $@
BaselineTests_SOURCES = test/RegressTests.py
@@ -378,7 +378,15 @@ BaselineTests_SOURCES = test/RegressTests.py
EXTRA_DIST += test/baseline
BaselineTests: $(srcdir)/test/RegressTests.py
- echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir)/test/baseline \"\$$@\"" > $@
+ echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/baseline \"\$$@\"" > $@
+ chmod 755 $@
+
+ManualTests_SOURCES = test/RegressTests.py
+
+EXTRA_DIST += test/manual
+
+ManualTests: $(srcdir)/test/RegressTests.py
+ echo "$(PYTHON) $(srcdir)/test/RegressTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/manual \"\$$@\"" > $@
chmod 755 $@
ConfirmTests_SOURCES = test/ConfirmTests.py
@@ -393,13 +401,13 @@ test/input/mondo.dat: test/input/standard.dat
done
ConfirmTests: $(srcdir)/test/ConfirmTests.py
- echo "$(PYTHON) $(srcdir)/test/ConfirmTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir)/test/input \"\$$@\"" > $@
+ echo "$(PYTHON) $(srcdir)/test/ConfirmTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) $(srcdir)/test/input \"\$$@\"" > $@
chmod 755 $@
GenerateTests_SOURCES = test/GenerateTests.py
GenerateTests: $(srcdir)/test/GenerateTests.py
- echo "$(PYTHON) $(srcdir)/test/GenerateTests.py $(top_builddir)/ledger$(EXEEXT) 1 20 \"\$$@\"" > $@
+ echo "$(PYTHON) $(srcdir)/test/GenerateTests.py $(top_builddir)/ledger$(EXEEXT) $(srcdir) 1 20 \"\$$@\"" > $@
chmod 755 $@
FULLCHECK=$(srcdir)/test/fullcheck.sh
@@ -424,10 +432,12 @@ endif
fullcheck: cppunittests
@$(top_builddir)/RegressTests --verify
@$(top_builddir)/BaselineTests --verify
+ @$(top_builddir)/ManualTests --verify
@$(top_builddir)/ConfirmTests --verify
@$(top_builddir)/GenerateTests --verify
@$(top_builddir)/RegressTests --gmalloc
@$(top_builddir)/BaselineTests --gmalloc
+ @$(top_builddir)/ManualTests --gmalloc
# @$(top_builddir)/ConfirmTests --gmalloc
# @$(top_builddir)/GenerateTests --gmalloc
diff --git a/tools/proof b/tools/proof
index ede22558..7c5a16f2 100755
--- a/tools/proof
+++ b/tools/proof
@@ -14,7 +14,7 @@ fi
rm -fr ~/Products/ledger*
-./acprep -j16 --warn proof 2>&1 | tee ~/Desktop/proof.log
+time ./acprep -j16 --warn proof 2>&1 | tee ~/Desktop/proof.log
if egrep -q '(ERROR|CRITICAL)' ~/Desktop/proof.log; then
if [[ "$1" = "--alert" ]]; then