diff options
author | John Wiegley <johnw@newartisans.com> | 2003-09-30 11:31:45 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2003-09-30 11:31:45 +0000 |
commit | f6c2e3d51eb8cd0892e5beeae59b74f12d14c027 (patch) | |
tree | d8c9f649d32f95386ca0a34657d99aa707a42f0a /ledger.cc | |
parent | 30aef588bf32419718a4d0ea0488ed8a074ff784 (diff) | |
download | fork-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.cc | 126 |
1 files changed, 120 insertions, 6 deletions
@@ -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 |