summaryrefslogtreecommitdiff
path: root/src/register.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2007-04-30 06:26:38 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 03:38:33 -0400
commitc8899addfd2deed3d84be2de234681db64987722 (patch)
tree07f9a5eb603ff4ec83fe18c83083575d2b7a439a /src/register.cc
parentaa9cc125796711afcaa459898e95527fdae8e912 (diff)
downloadfork-ledger-c8899addfd2deed3d84be2de234681db64987722.tar.gz
fork-ledger-c8899addfd2deed3d84be2de234681db64987722.tar.bz2
fork-ledger-c8899addfd2deed3d84be2de234681db64987722.zip
Rearranged the sources a bit.
Diffstat (limited to 'src/register.cc')
-rw-r--r--src/register.cc166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/register.cc b/src/register.cc
new file mode 100644
index 00000000..9f33bd0c
--- /dev/null
+++ b/src/register.cc
@@ -0,0 +1,166 @@
+#include "register.h"
+#include "journal.h"
+
+namespace ledger {
+
+string abbreviate(const string& str,
+ unsigned int width,
+ elision_style_t elision_style,
+ const bool is_account,
+ int abbrev_length)
+{
+ const unsigned int len = str.length();
+ if (len <= width)
+ return str;
+
+ assert(width < 4095);
+
+ static char buf[4096];
+
+ switch (elision_style) {
+ case TRUNCATE_LEADING:
+ // This method truncates at the beginning.
+ std::strncpy(buf, str.c_str() + (len - width), width);
+ buf[0] = '.';
+ buf[1] = '.';
+ break;
+
+ case TRUNCATE_MIDDLE:
+ // This method truncates in the middle.
+ std::strncpy(buf, str.c_str(), width / 2);
+ std::strncpy(buf + width / 2,
+ str.c_str() + (len - (width / 2 + width % 2)),
+ width / 2 + width % 2);
+ buf[width / 2 - 1] = '.';
+ buf[width / 2] = '.';
+ break;
+
+ case ABBREVIATE:
+ if (is_account) {
+ std::list<string> parts;
+ string::size_type beg = 0;
+ for (string::size_type pos = str.find(':');
+ pos != string::npos;
+ beg = pos + 1, pos = str.find(':', beg))
+ parts.push_back(string(str, beg, pos - beg));
+ parts.push_back(string(str, beg));
+
+ string result;
+ unsigned int newlen = len;
+ for (std::list<string>::iterator i = parts.begin();
+ i != parts.end();
+ i++) {
+ // Don't contract the last element
+ std::list<string>::iterator x = i;
+ if (++x == parts.end()) {
+ result += *i;
+ break;
+ }
+
+ if (newlen > width) {
+ result += string(*i, 0, abbrev_length);
+ result += ":";
+ newlen -= (*i).length() - abbrev_length;
+ } else {
+ result += *i;
+ result += ":";
+ }
+ }
+
+ if (newlen > width) {
+ // Even abbreviated its too big to show the last account, so
+ // abbreviate all but the last and truncate at the beginning.
+ std::strncpy(buf, result.c_str() + (result.length() - width), width);
+ buf[0] = '.';
+ buf[1] = '.';
+ } else {
+ std::strcpy(buf, result.c_str());
+ }
+ break;
+ }
+ // fall through...
+
+ case TRUNCATE_TRAILING:
+ // This method truncates at the end (the default).
+ std::strncpy(buf, str.c_str(), width - 2);
+ buf[width - 2] = '.';
+ buf[width - 1] = '.';
+ break;
+ }
+ buf[width] = '\0';
+
+ return buf;
+}
+
+static void scan_for_transactions(std::ostream& out, const xml::node_t * node)
+{
+ if (! (node->flags & XML_NODE_IS_PARENT))
+ return;
+
+ const xml::parent_node_t * parent =
+ static_cast<const xml::parent_node_t *>(node);
+
+ for (const xml::node_t * child = parent->children();
+ child;
+ child = child->next)
+ if (child->name_id == xml::document_t::TRANSACTION) {
+ const xml::transaction_node_t * xact_node =
+ dynamic_cast<const xml::transaction_node_t *>(child);
+ assert(xact_node);
+
+ const transaction_t * xact = xact_node->transaction;
+ assert(xact);
+
+ out << xact->entry->date() << ' '
+ << std::setw(21) << std::left
+ << abbreviate(xact->entry->payee, 21) << ' '
+ << std::setw(21) << std::left
+ << abbreviate(xact->account->fullname(), 21,
+ ABBREVIATE, true) << ' '
+ << std::setw(12) << std::right
+ << xact->amount << '\n';
+ } else {
+ scan_for_transactions(out, child);
+ }
+}
+
+void register_command::print_document(std::ostream& out,
+ xml::document_t * doc)
+{
+#if 1
+ scan_for_transactions(out, doc->top);
+ out.flush();
+#else
+ value_t nodelist;
+ xml::xpath_t::eval(nodelist, "//transaction", doc);
+
+ const value_t::sequence_t * xact_list = nodelist.to_sequence();
+ assert(xact_list);
+
+ for (value_t::sequence_t::const_iterator i = xact_list->begin();
+ i != xact_list->end();
+ i++) {
+ const xml::node_t * node = (*i).to_xml_node();
+ assert(node);
+
+ const xml::transaction_node_t * xact_node =
+ dynamic_cast<const xml::transaction_node_t *>(node);
+ assert(xact_node);
+
+ const transaction_t * xact = xact_node->transaction;
+ assert(xact);
+
+ std::cout << xact->entry->date() << ' '
+ << std::setw(21) << std::left
+ << abbreviate(xact->entry->payee, 21) << ' '
+ << std::setw(21) << std::left
+ << abbreviate(xact->account->fullname(), 21,
+ ABBREVIATE, true) << ' '
+ << std::setw(12) << std::right
+ << xact->amount
+ << std::endl;
+ }
+#endif
+}
+
+} // namespace ledger