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.
This commit is contained in:
John Wiegley 2006-02-16 21:10:50 +00:00
parent b041425846
commit f43370cae5
8 changed files with 98 additions and 47 deletions

View file

@ -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<istream_pos_type>(out, xact->beg_pos);
write_binary_number<unsigned long>(out, xact->beg_line);
write_binary_number<istream_pos_type>(out, xact->end_pos);
write_binary_number<unsigned long>(out, xact->end_line);
}
void write_binary_entry_base(std::ostream& out, entry_base_t * entry)

View file

@ -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) {

View file

@ -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)

View file

@ -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,

View file

@ -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();

View file

@ -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");
}

View file

@ -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))

View file

@ -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);
}