summaryrefslogtreecommitdiff
path: root/src/textual.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2010-03-17 06:22:43 -0400
committerJohn Wiegley <johnw@newartisans.com>2010-03-17 06:22:43 -0400
commit7ca8149ec5c7fa88d98df83e6260210372223036 (patch)
tree4c5741d682e89b1ea4e567c32a78d32ba17737db /src/textual.cc
parent3bb4cb6b6055f180112f357cf23463a1b8c186c5 (diff)
parent8dd362b57cf2b49c5268e72898ae873522d8756f (diff)
downloadledger-7ca8149ec5c7fa88d98df83e6260210372223036.tar.gz
ledger-7ca8149ec5c7fa88d98df83e6260210372223036.tar.bz2
ledger-7ca8149ec5c7fa88d98df83e6260210372223036.zip
Merge branch 'next'
Diffstat (limited to 'src/textual.cc')
-rw-r--r--src/textual.cc129
1 files changed, 118 insertions, 11 deletions
diff --git a/src/textual.cc b/src/textual.cc
index 8953d2b8..dfca7943 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -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);
@@ -663,14 +665,42 @@ void instance_t::include_directive(char * line)
filename = resolve_path(filename);
DEBUG("textual.include", "resolved path: " << filename.string());
- if (! exists(filename))
+ mask_t glob;
+#if BOOST_VERSION >= 103700
+ path parent_path = filename.parent_path();
+ glob.assign_glob(filename.filename());
+#else // BOOST_VERSION >= 103700
+ path parent_path = filename.branch_path();
+ glob.assign_glob(filename.leaf());
+#endif // BOOST_VERSION >= 103700
+
+ bool files_found = false;
+ if (exists(parent_path)) {
+ filesystem::directory_iterator end;
+ for (filesystem::directory_iterator iter(parent_path);
+ iter != end;
+ ++iter) {
+ if (is_regular_file(*iter)) {
+#if BOOST_VERSION >= 103700
+ string base = (*iter).filename();
+#else // BOOST_VERSION >= 103700
+ string base = (*iter).leaf();
+#endif // BOOST_VERSION >= 103700
+ if (glob.match(base)) {
+ path inner_file(*iter);
+ ifstream stream(inner_file);
+ instance_t instance(context, stream, master, &inner_file, this);
+ instance.parse();
+ files_found = true;
+ }
+ }
+ }
+ }
+
+ if (! files_found)
throw_(std::runtime_error,
_("File to include was not found: '%1'") << filename);
- ifstream stream(filename);
-
- instance_t instance(context, stream, master, &filename, this);
- instance.parse();
}
void instance_t::master_account_directive(char * line)
@@ -735,6 +765,52 @@ 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);
+
+ if (regex)
+ context.journal.payee_mappings.push_back
+ (payee_mapping_t(mask_t(regex), payee));
+
+ while (peek_whitespace_line()) {
+ std::streamsize len = read_line(line);
+ assert(len > 0);
+
+ regex = skip_ws(line);
+ if (! *regex)
+ break;
+
+ 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);
+
+ if (payee_regex)
+ context.journal.account_mappings.push_back
+ (account_mapping_t(mask_t(payee_regex),
+ context.top_account()->find_account(account_name)));
+
+ while (peek_whitespace_line()) {
+ std::streamsize len = read_line(line);
+ assert(len > 0);
+
+ payee_regex = skip_ws(line);
+ if (! *payee_regex)
+ break;
+
+ 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 +858,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 +893,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 +1019,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;
@@ -988,6 +1087,7 @@ post_t * instance_t::parse_post(char * line,
if (*++next == '@') {
per_unit = false;
+ post->add_flags(POST_COST_IN_FULL);
DEBUG("textual.parse", "line " << linenum << ": "
<< "And it's for a total price");
}
@@ -1127,7 +1227,7 @@ post_t * instance_t::parse_post(char * line,
// Parse the optional note
if (next && *next == ';') {
- post->append_note(++next, current_year);
+ post->append_note(++next, true, current_year);
next = line + len;
DEBUG("textual.parse", "line " << linenum << ": "
<< "Parsed a posting note");
@@ -1146,7 +1246,7 @@ post_t * instance_t::parse_post(char * line,
if (! context.state_stack.empty()) {
foreach (const state_t& state, context.state_stack)
if (state.type() == typeid(string))
- post->parse_tags(boost::get<string>(state).c_str());
+ post->parse_tags(boost::get<string>(state).c_str(), true);
}
TRACE_STOP(post_details, 1);
@@ -1242,7 +1342,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>");
@@ -1276,7 +1383,7 @@ xact_t * instance_t::parse_xact(char * line,
item = xact.get();
// This is a trailing note, and possibly a metadata info tag
- item->append_note(p + 1, current_year);
+ item->append_note(p + 1, true, current_year);
item->pos->end_pos = curr_pos;
item->pos->end_line++;
} else {
@@ -1310,7 +1417,7 @@ xact_t * instance_t::parse_xact(char * line,
if (! context.state_stack.empty()) {
foreach (const state_t& state, context.state_stack)
if (state.type() == typeid(string))
- xact->parse_tags(boost::get<string>(state).c_str());
+ xact->parse_tags(boost::get<string>(state).c_str(), false);
}
TRACE_STOP(xact_details, 1);