diff options
-rw-r--r-- | lisp/ldg-mode.el | 38 | ||||
-rw-r--r-- | lisp/ldg-reconcile.el | 136 | ||||
-rw-r--r-- | lisp/ldg-report.el | 15 | ||||
-rw-r--r-- | src/output.cc | 28 | ||||
-rw-r--r-- | src/output.h | 27 | ||||
-rw-r--r-- | src/report.cc | 20 | ||||
-rw-r--r-- | src/report.h | 2 |
7 files changed, 199 insertions, 67 deletions
diff --git a/lisp/ldg-mode.el b/lisp/ldg-mode.el index 04c6ee1b..caa57e8e 100644 --- a/lisp/ldg-mode.el +++ b/lisp/ldg-mode.el @@ -19,6 +19,7 @@ (defvar ledger-mode-abbrev-table) + ;;;###autoload (define-derived-mode ledger-mode text-mode "Ledger" "A mode for editing ledger data files." @@ -51,8 +52,41 @@ (define-key map [tab] 'pcomplete) (define-key map [(control ?i)] 'pcomplete) (define-key map [(control ?c) tab] 'ledger-fully-complete-entry) - (define-key map [(control ?c) (control ?i)] 'ledger-fully-complete-entry)) - + (define-key map [(control ?c) (control ?i)] 'ledger-fully-complete-entry) + (define-key map [(control ?c) (control ?o) (control ?r)] 'ledger-report) + (define-key map [(control ?c) (control ?o) (control ?g)] 'ledger-report-goto) + (define-key map [(control ?c) (control ?o) (control ?a)] 'ledger-report-redo) + (define-key map [(control ?c) (control ?o) (control ?s)] 'ledger-report-save) + (define-key map [(control ?c) (control ?o) (control ?e)] 'ledger-report-edit) + (define-key map [(control ?c) (control ?o) (control ?k)] 'ledger-report-kill) + + + (define-key map [menu-bar] (make-sparse-keymap "ldg-menu")) + (define-key map [menu-bar ldg-menu] (cons "Ledger" map)) + + (define-key map [menu-bar ldg-menu lrk] '("Kill Report" . ledger-report-kill)) + (define-key map [menu-bar ldg-menu lre] '("Edit Report" . ledger-report-edit)) + (define-key map [menu-bar ldg-menu lrs] '("Save Report" . ledger-report-save)) + (define-key map [menu-bar ldg-menu lrr] '("Re-run Report" . ledger-report-redo)) + (define-key map [menu-bar ldg-menu lrg] '("Goto Report" . ledger-report-goto)) + (define-key map [menu-bar ldg-menu lr] '("Run Report" . ledger-report)) + (define-key map [menu-bar ldg-menu s5] '("--")) + (define-key map [menu-bar ldg-menu sm] '("Set Month" . ledger-set-month)) + (define-key map [menu-bar ldg-menu sy] '("Set Year" . ledger-set-year)) + (define-key map [menu-bar ldg-menu s1] '("--")) + (define-key map [menu-bar ldg-menu so] '("Sort Buffer" . ledger-sort)) + (define-key map [menu-bar ldg-menu s2] '("--")) + (define-key map [menu-bar ldg-menu te] '("Toggle Current Posting" . ledger-toggle-current)) + (define-key map [menu-bar ldg-menu tt] '("Toggle Current Transaction" . ledger-toggle-current-entry)) + (define-key map [menu-bar ldg-menu s4] '("--")) + (define-key map [menu-bar ldg-menu de] '("Delete Entry" . ledger-delete-current-entry)) + (define-key map [menu-bar ldg-menu ae] '("Add Entry" . ledger-add-entry)) + (define-key map [menu-bar ldg-menu s3] '("--")) + (define-key map [menu-bar ldg-menu re] '("Reconcile Account" . ledger-reconcile))) + + + + (ledger-report-patch-reports (current-buffer))) (defun ledger-time-less-p (t1 t2) diff --git a/lisp/ldg-reconcile.el b/lisp/ldg-reconcile.el index d3dda60f..73409e66 100644 --- a/lisp/ldg-reconcile.el +++ b/lisp/ldg-reconcile.el @@ -4,18 +4,24 @@ (defvar ledger-acct nil) (defun ledger-display-balance () + "Calculate the cleared balance of the account being reconciled" (let ((buffer ledger-buf) (account ledger-acct)) (with-temp-buffer - (let ((exit-code (ledger-run-ledger buffer "-C" "balance" account))) - (if (/= 0 exit-code) - (message "Error determining cleared balance") - (goto-char (1- (point-max))) - (goto-char (line-beginning-position)) - (delete-horizontal-space) - (message "Cleared balance = %s" - (buffer-substring-no-properties (point) - (line-end-position)))))))) + (ledger-exec-ledger buffer (current-buffer) "-C" "balance" account) + (goto-char (1- (point-max))) + (goto-char (line-beginning-position)) + (delete-horizontal-space) + (message "Cleared balance = %s" + (buffer-substring-no-properties (point) + (line-end-position)))))) + +(defun is-stdin (file) + "True if ledger file is standard input" + (or + (equal file "") + (equal file "<stdin>") + (equal file "/dev/stdin"))) (defun ledger-reconcile-toggle () (interactive) @@ -23,18 +29,19 @@ (account ledger-acct) (inhibit-read-only t) cleared) - (when (or (equal (car where) "<stdin>") (equal (car where) "/dev/stdin")) + (when (is-stdin (car where)) (with-current-buffer ledger-buf - (goto-char (cdr where)) - (setq cleared (ledger-toggle-current 'pending))) + (goto-char (cdr where)) + (setq cleared (ledger-toggle-current-entry))) (if cleared - (add-text-properties (line-beginning-position) - (line-end-position) - (list 'face 'bold)) - (remove-text-properties (line-beginning-position) - (line-end-position) - (list 'face)))) - (forward-line))) + (add-text-properties (line-beginning-position) + (line-end-position) + (list 'face 'bold)) + (remove-text-properties (line-beginning-position) + (line-end-position) + (list 'face)))) + (forward-line) + (ledger-display-balance))) (defun ledger-reconcile-refresh () (interactive) @@ -62,7 +69,7 @@ (defun ledger-reconcile-delete () (interactive) (let ((where (get-text-property (point) 'where))) - (when (or (equal (car where) "<stdin>") (equal (car where) "/dev/stdin")) + (when (is-stdin (car where)) (with-current-buffer ledger-buf (goto-char (cdr where)) (ledger-delete-current-entry)) @@ -74,7 +81,7 @@ (defun ledger-reconcile-visit () (interactive) (let ((where (get-text-property (point) 'where))) - (when (or (equal (car where) "<stdin>") (equal (car where) "/dev/stdin")) + (when (is-stdin (car where)) (switch-to-buffer-other-window ledger-buf) (goto-char (cdr where))))) @@ -97,7 +104,7 @@ (let ((where (get-text-property (point) 'where)) (face (get-text-property (point) 'face))) (if (and (eq face 'bold) - (or (equal (car where) "<stdin>") (equal (car where) "/dev/stdin"))) + (when (is-stdin (car where)))) (with-current-buffer ledger-buf (goto-char (cdr where)) (ledger-toggle-current 'cleared)))) @@ -105,45 +112,48 @@ (ledger-reconcile-save)) (defun ledger-do-reconcile () - (let* ((buf ledger-buf) + "get the uncleared transactions in the account and display them in the *Reconcile* buffer" + (let* ((buf ledger-buf) (account ledger-acct) (items - (with-current-buffer - (apply #'ledger-exec-ledger - buf nil "emacs" account "--uncleared" '("--real")) + (with-temp-buffer + (ledger-exec-ledger buf (current-buffer) "--uncleared" "--real" + "emacs" account) (goto-char (point-min)) (unless (eobp) (unless (looking-at "(") (error (buffer-string))) - (read (current-buffer)))))) - (dolist (item items) - (let ((index 1)) - (dolist (xact (nthcdr 5 item)) - (let ((beg (point)) - (where - (with-current-buffer buf - (cons - (nth 0 item) - (if ledger-clear-whole-entries - (save-excursion - (goto-line (nth 1 item)) - (point-marker)) - (save-excursion - (goto-line (nth 0 xact)) - (point-marker))))))) - (insert (format "%s %-30s %-25s %15s\n" - (format-time-string "%m/%d" (nth 2 item)) - (nth 4 item) (nth 1 xact) (nth 2 xact))) - (if (nth 3 xact) - (set-text-properties beg (1- (point)) - (list 'face 'bold - 'where where)) - (set-text-properties beg (1- (point)) - (list 'where where)))) - (setq index (1+ index))))) - (goto-char (point-min)) - (set-buffer-modified-p nil) - (toggle-read-only t))) + (read (current-buffer)))))) + (dolist (item items) + (let ((index 1)) + (dolist (xact (nthcdr 5 item)) + (let ((beg (point)) + (where + (with-current-buffer buf + (cons + (nth 0 item) + (if ledger-clear-whole-entries + (save-excursion + (goto-line (nth 1 item)) + (point-marker)) + (save-excursion + (goto-line (nth 0 xact)) + (point-marker))))))) + (insert (format "%s %-4s %-30s %-30s %15s\n" + (format-time-string "%Y/%m/%d" (nth 2 item)) + (nth 3 item) + (nth 4 item) (nth 1 xact) (nth 2 xact))) + (if (nth 3 xact) + (set-text-properties beg (1- (point)) + (list 'face 'bold + 'where where)) + (set-text-properties beg (1- (point)) + (list 'where where)))) + (setq index (1+ index))))) + (goto-char (point-min)) + (set-buffer-modified-p nil) + (toggle-read-only t))) + (defun ledger-reconcile (account) (interactive "sAccount to reconcile: ") @@ -176,4 +186,20 @@ (define-key map [?p] 'previous-line) (define-key map [?s] 'ledger-reconcile-save) (define-key map [?q] 'ledger-reconcile-quit) + + (define-key map [menu-bar] (make-sparse-keymap "ldg-recon-menu")) + (define-key map [menu-bar ldg-recon-menu] (cons "Reconcile" map)) + (define-key map [menu-bar ldg-recon-menu qui] '("Quit" . ledger-reconcile-quit)) + (define-key map [menu-bar ldg-recon-menu sep1] '("--")) + (define-key map [menu-bar ldg-recon-menu pre] '("Previous Entry" . previous-line)) + (define-key map [menu-bar ldg-recon-menu vis] '("Visit Entry" . ledger-reconcile-visit)) + (define-key map [menu-bar ldg-recon-menu nex] '("Next Entry" . next-line)) + (define-key map [menu-bar ldg-recon-menu sep2] '("--")) + (define-key map [menu-bar ldg-recon-menu del] '("Delete Entry" . ledger-reconcile-delete)) + (define-key map [menu-bar ldg-recon-menu add] '("Add Entry" . ledger-reconcile-add)) + (define-key map [menu-bar ldg-recon-menu tog] '("Toggle Entry" . ledger-reconcile-toggle)) + (define-key map [menu-bar ldg-recon-menu sep3] '("--")) + (define-key map [menu-bar ldg-recon-menu ref] '("Refresh" . ledger-reconcile-refresh)) + (define-key map [menu-bar ldg-recon-menu sav] '("Save" . ledger-reconcile-save)) + (use-local-map map))) diff --git a/lisp/ldg-report.el b/lisp/ldg-report.el index f9c6afca..efd9bdb4 100644 --- a/lisp/ldg-report.el +++ b/lisp/ldg-report.el @@ -70,6 +70,21 @@ text that should replace the format specifier." (define-key map [(control ?c) (control ?l) (control ?e)] 'ledger-report-edit) (define-key map [(control ?c) (control ?c)] 'ledger-report-visit-source) + + + (define-key map [menu-bar] (make-sparse-keymap "ldg-rep")) + (define-key map [menu-bar ldg-rep] (cons "Reports" map)) + + (define-key map [menu-bar ldg-rep lrq] '("Quit" . ledger-report-quit)) + (define-key map [menu-bar ldg-rep s2] '("--")) + (define-key map [menu-bar ldg-rep lrd] '("Scroll Down" . scroll-down)) + (define-key map [menu-bar ldg-rep lru] '("Scroll Up" . scroll-up)) + (define-key map [menu-bar ldg-rep s1] '("--")) + (define-key map [menu-bar ldg-rep lrk] '("Kill Report" . ledger-report-kill)) + (define-key map [menu-bar ldg-rep lrr] '("Re-run Report" . ledger-report-redo)) + (define-key map [menu-bar ldg-rep lre] '("Edit Report" . ledger-report-edit)) + (define-key map [menu-bar ldg-rep lrs] '("Save Report" . ledger-report-save)) + (use-local-map map))) (defun ledger-report-read-name () diff --git a/src/output.cc b/src/output.cc index f433f8d1..6ed7f861 100644 --- a/src/output.cc +++ b/src/output.cc @@ -318,6 +318,34 @@ void report_payees::operator()(post_t& post) (*i).second++; } +void report_tags::flush() +{ + std::ostream& out(report.output_stream); + + foreach (tags_pair& entry, tags) { + if (report.HANDLED(count)) + out << entry.second << ' '; + out << entry.first << '\n'; + } +} + +void report_tags::operator()(post_t& post) +{ + if(post.metadata){ + foreach (const item_t::string_map::value_type& data, *post.metadata){ + string tag=data.first; + if(report.HANDLED(values) && (data.second).first){ + tag+=": "+ (data.second).first.get().to_string(); + } + std::map<string, std::size_t>::iterator i = tags.find(tag); + if (i == tags.end()) + tags.insert(tags_pair(tag, 1)); + else + (*i).second++; + } + } +} + void report_commodities::flush() { std::ostream& out(report.output_stream); diff --git a/src/output.h b/src/output.h index 281f69b6..9895cb44 100644 --- a/src/output.h +++ b/src/output.h @@ -189,6 +189,33 @@ public: } }; +class report_tags : public item_handler<post_t> +{ +protected: + report_t& report; + + std::map<string, std::size_t> tags; + + typedef std::map<string, std::size_t>::value_type tags_pair; + +public: + report_tags(report_t& _report) : report(_report) { + TRACE_CTOR(report_tags, "report&"); + } + virtual ~report_tags() { + TRACE_DTOR(report_tags); + } + + virtual void flush(); + virtual void operator()(post_t& post); + + virtual void clear() { + tags.clear(); + item_handler<post_t>::clear(); + } +}; + + class report_commodities : public item_handler<post_t> { protected: diff --git a/src/report.cc b/src/report.cc index d4beaf2a..f7b71b94 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1089,7 +1089,6 @@ option_t<report_t> * report_t::lookup_option(const char * p) else OPT(anon); else OPT_ALT(color, ansi); else OPT(auto_match); - else OPT(aux_date); else OPT(average); else OPT(account_width_); else OPT(amount_width_); @@ -1097,7 +1096,7 @@ option_t<report_t> * report_t::lookup_option(const char * p) case 'b': OPT(balance_format_); else OPT(base); - else OPT(basis); + else OPT_ALT(basis, cost); else OPT_(begin_); else OPT(bold_if_); else OPT(budget); @@ -1106,7 +1105,6 @@ option_t<report_t> * report_t::lookup_option(const char * p) break; case 'c': OPT(csv_format_); - else OPT_ALT(gain, change); else OPT(cleared); else OPT(collapse); else OPT(collapse_if_zero); @@ -1124,7 +1122,6 @@ option_t<report_t> * report_t::lookup_option(const char * p) else OPT(dc); else OPT(depth_); else OPT(deviation); - else OPT_ALT(rich_data, detail); else OPT_(display_); else OPT(display_amount_); else OPT(display_total_); @@ -1149,7 +1146,7 @@ option_t<report_t> * report_t::lookup_option(const char * p) else OPT_ALT(head_, first_); break; case 'g': - OPT(gain); + OPT_ALT(gain, change); else OPT(group_by_); else OPT(group_title_format_); else OPT(generated); @@ -1176,7 +1173,7 @@ option_t<report_t> * report_t::lookup_option(const char * p) else OPT_ALT(tail_, last_); break; case 'm': - OPT(market); + OPT_ALT(market, value); else OPT(monthly); else OPT(meta_); else OPT(meta_width_); @@ -1206,7 +1203,6 @@ option_t<report_t> * report_t::lookup_option(const char * p) else OPT(price); else OPT(prices_format_); else OPT(pricedb_format_); - else OPT(primary_date); else OPT(payee_width_); else OPT(prepend_format_); else OPT(prepend_width_); @@ -1224,7 +1220,7 @@ option_t<report_t> * report_t::lookup_option(const char * p) else OPT(revalued); else OPT(revalued_only); else OPT(revalued_total_); - else OPT(rich_data); + else OPT_ALT(rich_data, detail); break; case 's': OPT(sort_); @@ -1252,7 +1248,7 @@ option_t<report_t> * report_t::lookup_option(const char * p) else OPT(unround); break; case 'v': - OPT_ALT(market, value); + OPT(values); break; case 'w': OPT(weekly); @@ -1670,7 +1666,11 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, else if (is_eq(p, "select")) return WRAP_FUNCTOR(select_command); break; - + case 't': + if (is_eq(p, "tags")) { + return POSTS_REPORTER(new report_tags(*this)); + } + break; case 'x': if (is_eq(p, "xact")) return WRAP_FUNCTOR(xact_command); diff --git a/src/report.h b/src/report.h index 2eac61fe..b0044f60 100644 --- a/src/report.h +++ b/src/report.h @@ -358,6 +358,7 @@ public: HANDLER(account_width_).report(out); HANDLER(amount_width_).report(out); HANDLER(total_width_).report(out); + HANDLER(values).report(out); } option_t<report_t> * lookup_option(const char * p); @@ -1043,6 +1044,7 @@ public: OPTION(report_t, account_width_); OPTION(report_t, amount_width_); OPTION(report_t, total_width_); + OPTION(report_t, values); }; template <class Type = post_t, |