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:
parent
085420dd28
commit
2df14a5b86
8 changed files with 98 additions and 47 deletions
12
binary.cc
12
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<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)
|
||||
|
|
|
|||
3
emacs.cc
3
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) {
|
||||
|
|
|
|||
48
format.cc
48
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)
|
||||
|
|
|
|||
12
format.h
12
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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
31
journal.h
31
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");
|
||||
}
|
||||
|
||||
|
|
|
|||
25
ledger.el
25
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))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue