summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2010-03-05 22:12:32 -0500
committerJohn Wiegley <johnw@newartisans.com>2010-03-05 22:14:14 -0500
commit33187220891dd8826ff4d5a53b724b0058f6fef9 (patch)
tree79328965f8c183d92267ca46585d4640f72eb982
parentdc1b3907207cc5ccf3d27a01aa877e841bf7ac6f (diff)
downloadfork-ledger-33187220891dd8826ff4d5a53b724b0058f6fef9.tar.gz
fork-ledger-33187220891dd8826ff4d5a53b724b0058f6fef9.tar.bz2
fork-ledger-33187220891dd8826ff4d5a53b724b0058f6fef9.zip
Added new "payee" and "capture" directives
The payee directive allows for transformation of payee names during the parsing of a Ledger file. This means you can record the payee name in one form, but always have it reported in another form. The syntax is (and will be): payee PAYEE_NAME REGEXP or payee PAYEE_NAME REGEXP1 REGEXP2 ... The account directive sets the account automatically based on the payee iff the base account name is Unknown. For example, if you have a bunch of transaction in Expenses:Unknown, you can assign accounts for several automatically using: account ACCOUNT_NAME PAYEE_REGEXP or account ACCOUNT_NAME PAYEE_REGEXP1 PAYEE_REGEXP2 ...
-rw-r--r--src/journal.h8
-rw-r--r--src/mask.h3
-rw-r--r--src/textual.cc52
3 files changed, 62 insertions, 1 deletions
diff --git a/src/journal.h b/src/journal.h
index 2711c3b5..e54814aa 100644
--- a/src/journal.h
+++ b/src/journal.h
@@ -44,6 +44,7 @@
#include "utils.h"
#include "times.h"
+#include "mask.h"
namespace ledger {
@@ -58,6 +59,11 @@ typedef std::list<xact_t *> xacts_list;
typedef std::list<auto_xact_t *> auto_xacts_list;
typedef std::list<period_xact_t *> period_xacts_list;
+typedef std::pair<mask_t, string> payee_mapping_t;
+typedef std::list<payee_mapping_t> payee_mappings_t;
+typedef std::pair<mask_t, account_t *> account_mapping_t;
+typedef std::list<account_mapping_t> account_mappings_t;
+
class journal_t : public noncopyable
{
public:
@@ -110,6 +116,8 @@ public:
period_xacts_list period_xacts;
std::list<fileinfo_t> sources;
bool was_loaded;
+ payee_mappings_t payee_mappings;
+ account_mappings_t account_mappings;
journal_t();
journal_t(const path& pathname);
diff --git a/src/mask.h b/src/mask.h
index 8c20e554..755a2229 100644
--- a/src/mask.h
+++ b/src/mask.h
@@ -74,6 +74,9 @@ public:
mask_t& operator=(const string& other);
+ bool operator<(const mask_t& other) const {
+ return expr < other.expr;
+ }
bool operator==(const mask_t& other) const {
return expr == other.expr;
}
diff --git a/src/textual.cc b/src/textual.cc
index 9ad70c60..764d15e8 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -144,6 +144,8 @@ namespace {
void end_directive(char * line);
void alias_directive(char * line);
void fixed_directive(char * line);
+ void payee_mapping_directive(char * line);
+ void account_mapping_directive(char * line);
void tag_directive(char * line);
void define_directive(char * line);
bool general_directive(char * line);
@@ -735,6 +737,24 @@ void instance_t::fixed_directive(char * line)
}
}
+void instance_t::payee_mapping_directive(char * line)
+{
+ char * payee = skip_ws(line);
+ char * regex = next_element(payee, true);
+
+ context.journal.payee_mappings.push_back(payee_mapping_t(mask_t(regex), payee));
+}
+
+void instance_t::account_mapping_directive(char * line)
+{
+ char * account_name = skip_ws(line);
+ char * payee_regex = next_element(account_name, true);
+
+ context.journal.account_mappings.push_back
+ (account_mapping_t(mask_t(payee_regex),
+ context.top_account()->find_account(account_name)));
+}
+
void instance_t::tag_directive(char * line)
{
string tag(trim_ws(line));
@@ -782,6 +802,13 @@ bool instance_t::general_directive(char * line)
}
break;
+ case 'c':
+ if (std::strcmp(p, "capture") == 0) {
+ account_mapping_directive(arg);
+ return true;
+ }
+ break;
+
case 'd':
if (std::strcmp(p, "def") == 0 || std::strcmp(p, "define") == 0) {
define_directive(arg);
@@ -810,6 +837,13 @@ bool instance_t::general_directive(char * line)
}
break;
+ case 'p':
+ if (std::strcmp(p, "payee") == 0) {
+ payee_mapping_directive(arg);
+ return true;
+ }
+ break;
+
case 't':
if (std::strcmp(p, "tag") == 0) {
tag_directive(arg);
@@ -929,6 +963,15 @@ post_t * instance_t::parse_post(char * line,
post->account->add_flags(ACCOUNT_KNOWN);
}
+ if (post->account->name == _("Unknown")) {
+ foreach (account_mapping_t& value, context.journal.account_mappings) {
+ if (value.first.match(xact->payee)) {
+ post->account = value.second;
+ break;
+ }
+ }
+ }
+
// Parse the optional amount
bool saw_amount = false;
@@ -1242,7 +1285,14 @@ xact_t * instance_t::parse_xact(char * line,
if (next && *next) {
char * p = next_element(next, true);
- xact->payee = next;
+ foreach (payee_mapping_t& value, context.journal.payee_mappings) {
+ if (value.first.match(next)) {
+ xact->payee = value.second;
+ break;
+ }
+ }
+ if (xact->payee.empty())
+ xact->payee = next;
next = p;
} else {
xact->payee = _("<Unspecified payee>");