diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | ledger.cc | 6 | ||||
-rw-r--r-- | ledger.el | 89 | ||||
-rw-r--r-- | ledger.h | 9 | ||||
-rw-r--r-- | parse.cc | 3 | ||||
-rw-r--r-- | reports.cc | 2 |
6 files changed, 105 insertions, 8 deletions
@@ -3,8 +3,8 @@ OBJS = $(patsubst %.cc,%.o,$(CODE)) CFLAGS = -Wall -ansi -pedantic DFLAGS = -O3 -fomit-frame-pointer #DFLAGS = -g -DDEBUG=1 -INCS = -LIBS = -lgmpxx -lgmp -lpcre +INCS = -I/sw/include +LIBS = -L/sw/lib -lgmpxx -lgmp -lpcre ifdef GNUCASH CODE := $(CODE) gnucash.cc @@ -6,6 +6,8 @@ namespace ledger { book * main_ledger; +extern int linenum; + commodity::~commodity() { if (price) @@ -197,7 +199,7 @@ bool entry::finalize(bool do_compute) if (! empty_allowed || balance.amounts.empty() || balance.amounts.size() != 1) { - std::cerr << "Error, line " //<< linenum + std::cerr << "Error, line " << linenum << ": Transaction entry is lacking an amount." << std::endl; return false; @@ -271,7 +273,7 @@ bool entry::finalize(bool do_compute) // right (i.e., zero for every commodity). if (! validate()) { - std::cerr << "Error, line " //<< (linenum - 1) + std::cerr << "Error, line " << (linenum - 1) << ": Failed to balance the following transaction:" << std::endl; validate(true); @@ -9,8 +9,95 @@ (delete-char 5) (exchange-point-and-mark))) +(defun ledger-clear-current () + (interactive) + (save-excursion + (when (re-search-backward "^[0-9]" nil t) + (skip-chars-forward "0-9./") + (insert " *")))) + (define-derived-mode ledger-mode text-mode "Ledger" "A mode for editing ledger data files." (setq comment-start ";" comment-end nil) (let ((map (current-local-map))) - (define-key map [(control ?c) ?n] 'ledger-add-entry))) + (define-key map [(control ?c) (control ?n)] 'ledger-add-entry) + (define-key map [(control ?c) (control ?c)] + 'ledger-clear-current))) + +(defun ledger-parse-entries (account) + (let* ((now (current-time)) + (current-year (nth 5 (decode-time now))) + (then now) + entries) + ;; `then' is 45 days ago + (setq then (time-subtract then (seconds-to-time (* 45 24 60 60)))) + (while (not (eobp)) + (when (looking-at + (concat "\\(Y\\s-+\\([0-9]+\\)\\|\\([0-9]{4}+\\)?[./]?" + "\\([0-9]+\\)[./]\\([0-9]+\\)\\s-+" + "\\(\\*\\s-+\\)?\\(.+\\)\\)")) + (let ((found (match-string 2)) + when) + (if found + (setq current-year (string-to-number found)) + (let ((start (match-beginning 0)) + (year (match-string 3)) + (month (string-to-number (match-string 4))) + (day (string-to-number (match-string 5))) + (mark (match-string 6)) + (desc (match-string 7))) + (if (and year (> (length year) 0)) + (setq year (string-to-number year))) + (setq when (encode-time 0 0 0 day month + (or year current-year))) + (when (or (not mark) (time-less-p then when)) + (forward-line) + (while (looking-at + (concat "\\s-+\\([A-Za-z_].+?\\) \\s-*" + "\\([^0-9]+\\)\\s-*\\([0-9.]+\\)")) + (let ((acct (match-string 1)) + (amt (match-string 3))) + (if (string= account acct) + (setq entries + (cons (list (copy-marker start) + mark when desc amt) + entries)))) + (forward-line))))))) + (forward-line)) + (nreverse entries))) + +(define-derived-mode ledger-reconcile-mode text-mode "Reconcile" + "A mode for reconciling ledger entries." + (let ((map (make-sparse-keymap))) + (define-key map [space] 'ledger-reconcile-toggle) + (use-local-map map))) + +(defvar ledger-buf nil) +(make-variable-buffer-local 'ledger-buf) + +(defun ledger-reconcile-toggle () + (interactive) + (let ((where (get-text-property (point) 'where))) + (with-current-buffer ledger-buf + (goto-char where) + (ledger-clear-current)))) + +(defun ledger-reconcile (account) + (interactive "sAccount to reconcile: ") + (let ((items (save-excursion + (goto-char (point-min)) + (ledger-parse-entries account))) + (buf (current-buffer))) + (pop-to-buffer (generate-new-buffer "*Reconcile*")) + (ledger-reconcile-mode) + (setq ledger-buf buf) + (dolist (item items) + (let ((beg (point))) + (insert (format "%s %-30s %8.2f\n" + (format-time-string "%Y.%m.%d" (nth 2 item)) + (nth 3 item) + (string-to-number (nth 4 item)))) + (if (nth 1 item) + (set-text-properties beg (1- (point)) + (list 'face 'bold + 'where (nth 0 item)))))))) @@ -1,5 +1,5 @@ #ifndef _LEDGER_H -#define _LEDGER_H "$Revision: 1.27 $" +#define _LEDGER_H "$Revision: 1.28 $" ////////////////////////////////////////////////////////////////////// // @@ -20,6 +20,9 @@ #ifdef DEBUG #include <cassert> #else +#ifdef assert +#undef assert +#endif #define assert(x) #endif @@ -297,9 +300,13 @@ inline commodity::commodity(const std::string& sym, bool pre, bool sep, bool thou, bool euro, int prec) : symbol(sym), price(NULL), prefix(pre), separate(sep), thousands(thou), european(euro), precision(prec) { +#ifdef DEBUG std::pair<commodities_map_iterator, bool> result = +#endif main_ledger->commodities.insert(commodities_map_pair(sym, this)); +#ifdef DEBUG assert(result.second); +#endif } // Parsing routines @@ -117,7 +117,8 @@ void parse_price_setting(const std::string& setting) #define MAX_LINE 1024 -static int linenum; +int linenum; + static bool do_compute; transaction * parse_transaction(std::istream& in, book * ledger) @@ -491,7 +491,7 @@ void book::print(std::ostream& out, regexps_map& regexps, for (entries_list_const_iterator i = entries.begin(); i != entries.end(); i++) { - if ((show_cleared && ! (*i)->cleared) || + if ((! show_cleared && (*i)->cleared) || ! matches_date_range(*i) || ! (*i)->matches(regexps)) continue; |