From 2df14a5b86371cd8008c72f9d16421c1a404a4a8 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 16 Feb 2006 21:10:50 +0000 Subject: Transactions now track their beginning and ending position, as do entries. The new format strings %xB %xE %xb %xe can be used to display those values relative to a transaction. The Emacs module now relies on this support to exactly determine where a transaction is, rather than the Elisp logic it relied on previously. --- binary.cc | 12 ++++++++++-- emacs.cc | 3 ++- format.cc | 48 ++++++++++++++++++++++++++++++++++++++++-------- format.h | 12 ++++++++---- gnucash.cc | 5 +++++ journal.h | 31 ++++++++++++++++++------------- ledger.el | 25 ++++++------------------- textual.cc | 9 +++++++++ 8 files changed, 98 insertions(+), 47 deletions(-) diff --git a/binary.cc b/binary.cc index 687f3540..fd22c443 100644 --- a/binary.cc +++ b/binary.cc @@ -12,9 +12,9 @@ namespace ledger { static unsigned long binary_magic_number = 0xFFEED765; #ifdef DEBUG_ENABLED -static unsigned long format_version = 0x00020501; +static unsigned long format_version = 0x00020503; #else -static unsigned long format_version = 0x00020500; +static unsigned long format_version = 0x00020502; #endif static account_t ** accounts; @@ -198,6 +198,10 @@ inline void read_binary_transaction(char *& data, transaction_t * xact) read_binary_number(data, xact->flags); xact->flags |= TRANSACTION_BULK_ALLOC; read_binary_string(data, &xact->note); + read_binary_number(data, xact->beg_pos); + read_binary_number(data, xact->beg_line); + read_binary_number(data, xact->end_pos); + read_binary_number(data, xact->end_line); xact->data = NULL; } @@ -564,6 +568,10 @@ void write_binary_transaction(std::ostream& out, transaction_t * xact) write_binary_number(out, xact->state); write_binary_number(out, xact->flags); write_binary_string(out, xact->note); + write_binary_number(out, xact->beg_pos); + write_binary_number(out, xact->beg_line); + write_binary_number(out, xact->end_pos); + write_binary_number(out, xact->end_line); } void write_binary_entry_base(std::ostream& out, entry_base_t * entry) diff --git a/emacs.cc b/emacs.cc index b25fb9aa..823e0367 100644 --- a/emacs.cc +++ b/emacs.cc @@ -47,7 +47,8 @@ void format_emacs_transactions::operator()(transaction_t& xact) out << "\n"; } - out << " (\"" << xact_account(xact)->fullname() << "\" \"" + out << " (" << (((unsigned long)xact.beg_pos) + 1) << " "; + out << "\"" << xact_account(xact)->fullname() << "\" \"" << xact.amount << "\""; switch (xact.state) { diff --git a/format.cc b/format.cc index 12800778..8c7515be 100644 --- a/format.cc +++ b/format.cc @@ -191,6 +191,17 @@ element_t * format_t::parse_elements(const std::string& fmt) break; } + case 'x': + switch (*++p) { + case 'B': current->type = element_t::XACT_BEG_POS; break; + case 'b': current->type = element_t::XACT_BEG_LINE; break; + case 'E': current->type = element_t::XACT_END_POS; break; + case 'e': current->type = element_t::XACT_END_LINE; break; + case '\0': + goto END; + } + break; + case 'd': current->type = element_t::COMPLETE_DATE_STRING; current->chars = format_t::date_format; @@ -201,10 +212,10 @@ element_t * format_t::parse_elements(const std::string& fmt) break; case 'S': current->type = element_t::SOURCE; break; - case 'B': current->type = element_t::BEG_POS; break; - case 'b': current->type = element_t::BEG_LINE; break; - case 'E': current->type = element_t::END_POS; break; - case 'e': current->type = element_t::END_LINE; break; + case 'B': current->type = element_t::ENTRY_BEG_POS; break; + case 'b': current->type = element_t::ENTRY_BEG_LINE; break; + case 'E': current->type = element_t::ENTRY_END_POS; break; + case 'e': current->type = element_t::ENTRY_END_LINE; break; case 'X': current->type = element_t::CLEARED; break; case 'Y': current->type = element_t::ENTRY_CLEARED; break; case 'C': current->type = element_t::CODE; break; @@ -222,6 +233,7 @@ element_t * format_t::parse_elements(const std::string& fmt) } } + END: if (q != buf) { if (! result.get()) { result.reset(new element_t); @@ -389,26 +401,46 @@ void format_t::format(std::ostream& out_str, const details_t& details) const } break; - case element_t::BEG_POS: + case element_t::ENTRY_BEG_POS: if (details.entry) out << (unsigned long)details.entry->beg_pos; break; - case element_t::BEG_LINE: + case element_t::ENTRY_BEG_LINE: if (details.entry) out << details.entry->beg_line; break; - case element_t::END_POS: + case element_t::ENTRY_END_POS: if (details.entry) out << (unsigned long)details.entry->end_pos; break; - case element_t::END_LINE: + case element_t::ENTRY_END_LINE: if (details.entry) out << details.entry->end_line; break; + case element_t::XACT_BEG_POS: + if (details.xact) + out << (unsigned long)details.xact->beg_pos; + break; + + case element_t::XACT_BEG_LINE: + if (details.xact) + out << details.xact->beg_line; + break; + + case element_t::XACT_END_POS: + if (details.xact) + out << (unsigned long)details.xact->end_pos; + break; + + case element_t::XACT_END_LINE: + if (details.xact) + out << details.xact->end_line; + break; + case element_t::DATE_STRING: { std::time_t date = 0; if (details.xact) diff --git a/format.h b/format.h index b1b77fd8..eff23b2c 100644 --- a/format.h +++ b/format.h @@ -19,10 +19,14 @@ struct element_t STRING, VALUE_EXPR, SOURCE, - BEG_POS, - BEG_LINE, - END_POS, - END_LINE, + ENTRY_BEG_POS, + ENTRY_BEG_LINE, + ENTRY_END_POS, + ENTRY_END_LINE, + XACT_BEG_POS, + XACT_BEG_LINE, + XACT_END_POS, + XACT_END_LINE, DATE_STRING, COMPLETE_DATE_STRING, CLEARED, diff --git a/gnucash.cc b/gnucash.cc index b90c797e..8b27490c 100644 --- a/gnucash.cc +++ b/gnucash.cc @@ -189,6 +189,11 @@ static void endElement(void *userData, const char *name) if (value != curr_value) xact->cost = new amount_t(curr_value); + xact->beg_pos = beg_pos; + xact->beg_line = beg_line; + xact->end_pos = instreamp->tellg(); + xact->end_line = XML_GetCurrentLineNumber(parser) - offset; + // Clear the relevant variables for the next run curr_state = transaction_t::UNCLEARED; curr_value = amount_t(); diff --git a/journal.h b/journal.h index f4619bb1..54486c9d 100644 --- a/journal.h +++ b/journal.h @@ -31,23 +31,27 @@ class transaction_t public: enum state_t { UNCLEARED, CLEARED, PENDING }; - entry_t * entry; - std::time_t _date; - std::time_t _date_eff; - account_t * account; - amount_t amount; - amount_t * cost; - state_t state; - unsigned short flags; - std::string note; - mutable void * data; + entry_t * entry; + std::time_t _date; + std::time_t _date_eff; + account_t * account; + amount_t amount; + amount_t * cost; + state_t state; + unsigned short flags; + std::string note; + istream_pos_type beg_pos; + unsigned long beg_line; + istream_pos_type end_pos; + unsigned long end_line; + mutable void * data; static bool use_effective_date; transaction_t(account_t * _account = NULL) : entry(NULL), _date(0), _date_eff(0), account(_account), cost(NULL), state(UNCLEARED), flags(TRANSACTION_NORMAL), - data(NULL) { + data(NULL), beg_pos(0), beg_line(0), end_pos(0), end_line(0) { DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t"); } @@ -57,7 +61,8 @@ class transaction_t const std::string& _note = "") : entry(NULL), _date(0), _date_eff(0), account(_account), amount(_amount), cost(NULL), state(UNCLEARED), flags(_flags), - note(_note), data(NULL) { + note(_note), data(NULL), beg_pos(0), beg_line(0), end_pos(0), + end_line(0) { DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t"); } @@ -66,7 +71,7 @@ class transaction_t account(xact.account), amount(xact.amount), cost(xact.cost ? new amount_t(*xact.cost) : NULL), state(xact.state), flags(xact.flags), note(xact.note), - data(NULL) { + data(NULL), beg_pos(0), beg_line(0), end_pos(0), end_line(0) { DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_t"); } diff --git a/ledger.el b/ledger.el index 70f38b1e..cdea2009 100644 --- a/ledger.el +++ b/ledger.el @@ -372,15 +372,9 @@ dropped." ;; attempt to auto-reconcile in the background (with-temp-buffer (let ((exit-code - (ledger-run-ledger - buffer "--format" "%B\\n" "--reconcile" - (with-temp-buffer - (insert balance) - (goto-char (point-min)) - (while (re-search-forward "\\([&$]\\)" nil t) - (replace-match "\\\\\\1")) - (buffer-string)) - "--reconcile-date" date "register" account))) + (ledger-run-ledger buffer "--format" "%xB\\n" + "--reconcile" balance "--reconcile-date" date + "register" account))) (if (/= 0 exit-code) (error "Failed to reconcile account '%s' to balance '%s'" account balance) @@ -494,18 +488,11 @@ dropped." (nth 0 item) (if ledger-clear-whole-entries (copy-marker (nth 1 item)) - (save-excursion - (goto-char (nth 1 item)) - (let ((i 0)) - (while (< i index) - (re-search-forward - account (cdr (ledger-current-entry-bounds))) - (setq i (1+ i)))) - (point-marker))))))) + (copy-marker (nth 0 xact))))))) (insert (format "%s %-30s %-25s %15s\n" (format-time-string "%m/%d" (nth 2 item)) - (nth 4 item) (nth 0 xact) (nth 1 xact))) - (if (nth 2 xact) + (nth 4 item) (nth 1 xact) (nth 2 xact))) + (if (nth 3 xact) (set-text-properties beg (1- (point)) (list 'face 'bold 'where where)) diff --git a/textual.cc b/textual.cc index fe2185d6..8b4775a5 100644 --- a/textual.cc +++ b/textual.cc @@ -384,6 +384,9 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master, TIMER_START(entry_xacts); while (! in.eof() && (in.peek() == ' ' || in.peek() == '\t')) { + istream_pos_type beg_pos = in.tellg(); + unsigned long beg_line = linenum; + line[0] = '\0'; in.getline(line, MAX_LINE); if (in.eof() && line[0] == '\0') @@ -400,6 +403,12 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master, if (state != transaction_t::UNCLEARED && xact->state == transaction_t::UNCLEARED) xact->state = state; + + xact->beg_pos = beg_pos; + xact->beg_line = beg_line; + xact->end_pos = in.tellg(); + xact->end_line = linenum; + curr->add_transaction(xact); } -- cgit v1.2.3