summaryrefslogtreecommitdiff
path: root/ledger.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2003-09-30 11:31:45 +0000
committerJohn Wiegley <johnw@newartisans.com>2003-09-30 11:31:45 +0000
commitf6c2e3d51eb8cd0892e5beeae59b74f12d14c027 (patch)
treed8c9f649d32f95386ca0a34657d99aa707a42f0a /ledger.cc
parent30aef588bf32419718a4d0ea0488ed8a074ff784 (diff)
downloadfork-ledger-f6c2e3d51eb8cd0892e5beeae59b74f12d14c027.tar.gz
fork-ledger-f6c2e3d51eb8cd0892e5beeae59b74f12d14c027.tar.bz2
fork-ledger-f6c2e3d51eb8cd0892e5beeae59b74f12d14c027.zip
*** empty log message ***
Diffstat (limited to 'ledger.cc')
-rw-r--r--ledger.cc126
1 files changed, 120 insertions, 6 deletions
diff --git a/ledger.cc b/ledger.cc
index 7829173b..d8b3143c 100644
--- a/ledger.cc
+++ b/ledger.cc
@@ -1,5 +1,7 @@
#include "ledger.h"
+#include <fstream>
+
namespace ledger {
commodities_t commodities;
@@ -8,6 +10,11 @@ ledger_t ledger;
bool use_warnings = false;
+#ifdef HUQUQULLAH
+bool compute_huquq;
+std::list<mask> huquq_categories;
+#endif
+
void entry::print(std::ostream& out) const
{
char buf[32];
@@ -23,6 +30,11 @@ void entry::print(std::ostream& out) const
out << std::endl;
+ bool shortcut = xacts.size() == 2;
+ if (shortcut &&
+ xacts.front()->cost->comm() != xacts.back()->cost->comm())
+ shortcut = false;
+
for (std::list<transaction *>::const_iterator i = xacts.begin();
i != xacts.end();
i++) {
@@ -39,10 +51,13 @@ void entry::print(std::ostream& out) const
}
out.width(30);
- out << std::left << acct_name << " ";
+ out << std::left << acct_name;
- out.width(10);
- out << std::right << (*i)->cost->as_str(true);
+ if (! shortcut || i == xacts.begin()) {
+ out << " ";
+ out.width(10);
+ out << std::right << (*i)->cost->as_str(true);
+ }
if (! (*i)->note.empty())
out << " ; " << (*i)->note;
@@ -58,9 +73,8 @@ bool entry::validate() const
for (std::list<transaction *>::const_iterator i = xacts.begin();
i != xacts.end();
- i++) {
+ i++)
balance.credit((*i)->cost->value());
- }
if (balance) {
std::cerr << "Totals are:" << std::endl;
@@ -120,6 +134,25 @@ amount * totals::value(const std::string& commodity)
void print_ledger(int argc, char *argv[], std::ostream& out)
{
+ std::list<mask> regexps;
+
+ int c;
+ optind = 1;
+ while (-1 != (c = getopt(argc, argv, "i:"))) {
+ switch (char(c)) {
+ // -i path-to-file-of-regexps
+ case 'i':
+ read_regexps(optarg, regexps);
+ break;
+ }
+ }
+
+ // Compile the list of specified regular expressions, which can be
+ // specified on the command line, or using an include/exclude file
+
+ for (; optind < argc; optind++)
+ record_regexp(argv[optind], regexps);
+
// Sort the list of entries by date, then print them in order.
std::sort(ledger.begin(), ledger.end(), cmp_entry_date());
@@ -127,8 +160,89 @@ void print_ledger(int argc, char *argv[], std::ostream& out)
for (std::vector<entry *>::const_iterator i = ledger.begin();
i != ledger.end();
i++) {
- (*i)->print(out);
+ if (regexps.empty() ||
+ (matches(regexps, (*i)->code) ||
+ matches(regexps, (*i)->desc))) {
+ (*i)->print(out);
+ }
+ else {
+ bool match = false;
+
+ for (std::list<transaction *>::const_iterator x = (*i)->xacts.begin();
+ x != (*i)->xacts.end();
+ x++) {
+ if (matches(regexps, (*x)->acct->name) ||
+ matches(regexps, (*x)->note)) {
+ match = true;
+ break;
+ }
+ }
+
+ if (match)
+ (*i)->print(out);
+ }
}
}
+void record_regexp(char * pattern, std::list<mask>& regexps)
+{
+ bool exclude = false;
+
+ char * pat = pattern;
+ if (*pat == '-') {
+ exclude = true;
+ pat++;
+ while (std::isspace(*pat))
+ pat++;
+ }
+ else if (*pat == '+') {
+ pat++;
+ while (std::isspace(*pat))
+ pat++;
+ }
+
+ const char *error;
+ int erroffset;
+ pcre * re = pcre_compile(pat, PCRE_CASELESS, &error, &erroffset, NULL);
+ if (! re)
+ std::cerr << "Warning: Failed to compile regexp: " << pattern
+ << std::endl;
+ else
+ regexps.push_back(mask(exclude, re));
+}
+
+void read_regexps(const char * path, std::list<mask>& regexps)
+{
+ if (access(path, R_OK) != -1) {
+ std::ifstream file(path);
+
+ while (! file.eof()) {
+ char buf[80];
+ file.getline(buf, 79);
+ if (*buf && ! std::isspace(*buf))
+ record_regexp(buf, regexps);
+ }
+ }
+}
+
+bool matches(const std::list<mask>& regexps, const std::string& str)
+{
+ // If the first pattern is an exclude, we assume all patterns match
+ // if they don't match the exclude. If the first pattern is an
+ // include, then only accounts matching the include will match.
+
+ bool match = (*regexps.begin()).exclude;
+
+ for (std::list<mask>::const_iterator r = regexps.begin();
+ r != regexps.end();
+ r++) {
+ int ovec[3];
+ if (pcre_exec((*r).regexp, NULL, str.c_str(), str.length(),
+ 0, 0, ovec, 3) >= 0)
+ match = ! (*r).exclude;
+ }
+
+ return match;
+}
+
} // namespace ledger