diff options
author | John Wiegley <johnw@newartisans.com> | 2004-07-26 23:33:51 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2004-07-26 23:33:51 -0400 |
commit | 161d6f79bd6f4ab45afa1cbae77548c8e508809a (patch) | |
tree | 55391f4997e20de173579d90b43316a968b27c9e /ledger.el | |
parent | fde56d0f1214b8fb9de5ba4d42d683ed494c45b0 (diff) | |
download | fork-ledger-161d6f79bd6f4ab45afa1cbae77548c8e508809a.tar.gz fork-ledger-161d6f79bd6f4ab45afa1cbae77548c8e508809a.tar.bz2 fork-ledger-161d6f79bd6f4ab45afa1cbae77548c8e508809a.zip |
initial rev of 2.0
Diffstat (limited to 'ledger.el')
-rw-r--r-- | ledger.el | 295 |
1 files changed, 0 insertions, 295 deletions
diff --git a/ledger.el b/ledger.el deleted file mode 100644 index ac52c37c..00000000 --- a/ledger.el +++ /dev/null @@ -1,295 +0,0 @@ -;;; ledger.el --- Helper code for using my "ledger" command-line tool - -;; Copyright (C) 2004 John Wiegley (johnw AT gnu DOT org) - -;; Emacs Lisp Archive Entry -;; Filename: ledger.el -;; Version: 1.1 -;; Date: Thu 02-Apr-2004 -;; Keywords: data -;; Author: John Wiegley (johnw AT gnu DOT org) -;; Maintainer: John Wiegley (johnw AT gnu DOT org) -;; Description: Helper code for using my "ledger" command-line tool -;; URL: http://www.newartisans.com/johnw/emacs.html -;; Compatibility: Emacs21 - -;; This file is not part of GNU Emacs. - -;; This is free software; you can redistribute it and/or modify it under -;; the terms of the GNU General Public License as published by the Free -;; Software Foundation; either version 2, or (at your option) any later -;; version. -;; -;; This is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -;; for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -;; MA 02111-1307, USA. - -;;; Commentary: - -;; This code is only meaningful if you are using "ledger". - -(defvar ledger-version "1.1" - "The version of ledger.el currently loaded") - -(defgroup ledger nil - "Interface to the Ledger command-line accounting program." - :group 'data) - -(defcustom ledger-binary-path (executable-find "ledger") - "Path to the ledger executable." - :type 'file - :group 'ledger) - -(defvar bold 'bold) - -(defvar ledger-font-lock-keywords - '(("^[0-9./]+\\s-+\\(?:([^)]+)\\s-+\\)?\\([^*].+\\)" 1 bold) - ("^\\s-+.+?\\( \\|\t\\|\\s-+$\\)" . font-lock-keyword-face)) - "Default expressions to highlight in Ledger mode.") - -(defun ledger-iterate-entries (callback) - (goto-char (point-min)) - (let* ((now (current-time)) - (current-year (nth 5 (decode-time now)))) - (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))) - (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))) - (funcall callback start - (encode-time 0 0 0 day month - (or year current-year)) - mark desc))))) - (forward-line)))) - -(defun ledger-find-slot (moment) - (catch 'found - (ledger-iterate-entries - (function - (lambda (start date mark desc) - (if (time-less-p moment date) - (throw 'found t))))))) - -(defun ledger-add-entry (entry) - (interactive - (list (read-string "Entry: " (format-time-string "%Y/%m/%d ")))) - (let* ((args (mapcar 'shell-quote-argument (split-string entry))) - (date (car args)) - (insert-year t) exit-code) - (if (string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" date) - (setq date (encode-time 0 0 0 (string-to-int (match-string 3 date)) - (string-to-int (match-string 2 date)) - (string-to-int (match-string 1 date))))) - (ledger-find-slot date) - (save-excursion - (if (re-search-backward "^Y " nil t) - (setq insert-year nil))) - (save-excursion - (insert - (with-temp-buffer - (setq exit-code - (apply 'call-process ledger-binary-path nil t nil - (cons "entry" args))) - (if (= 0 exit-code) - (if insert-year - (buffer-string) - (buffer-substring 5 (point-max))) - (concat (if insert-year entry - (substring entry 5)) "\n\n"))))))) - -(defun ledger-expand-entry () - (interactive) - (ledger-add-entry (prog1 - (buffer-substring (line-beginning-position) - (line-end-position)) - (delete-region (line-beginning-position) - (1+ (line-end-position)))))) - -(defun ledger-toggle-current () - (interactive) - (let (clear) - (save-excursion - (when (or (looking-at "^[0-9]") - (re-search-backward "^[0-9]" nil t)) - (skip-chars-forward "0-9./") - (delete-horizontal-space) - (if (equal ?\* (char-after)) - (delete-char 1) - (insert " * ") - (setq clear t)))) - clear)) - -(defun ledger-print-result (command) - (interactive "sLedger command: ") - (shell-command (format "%s -f %s %s" ledger-binary-path - buffer-file-name command))) - -(define-derived-mode ledger-mode text-mode "Ledger" - "A mode for editing ledger data files." - (set (make-local-variable 'comment-start) ";") - (set (make-local-variable 'comment-end) "") - (set (make-local-variable 'indent-tabs-mode) nil) - (if (boundp 'font-lock-defaults) - (set (make-local-variable 'font-lock-defaults) - '(ledger-font-lock-keywords nil t))) - (let ((map (current-local-map))) - (define-key map [(control ?c) (control ?a)] 'ledger-add-entry) - (define-key map [(control ?c) (control ?c)] 'ledger-toggle-current) - (define-key map [(control ?c) (control ?p)] 'ledger-print-result) - (define-key map [(control ?c) (control ?r)] 'ledger-reconcile))) - -(defun ledger-parse-entries (account &optional all-p after-date) - (let (total entries) - (ledger-iterate-entries - (function - (lambda (start date mark desc) - (when (and (or all-p (not mark)) - (time-less-p after-date date)) - (forward-line) - (setq total 0.0) - (while (looking-at - (concat "\\s-+\\([A-Za-z_].+?\\)\\(\\s-*$\\| \\s-*" - "\\([^0-9]+\\)\\s-*\\([0-9,.]+\\)\\)?" - "\\(\\s-+;.+\\)?$")) - (let ((acct (match-string 1)) - (amt (match-string 4))) - (when amt - (while (string-match "," amt) - (setq amt (replace-match "" nil nil amt))) - (setq amt (string-to-number amt) - total (+ total amt))) - (if (string= account acct) - (setq entries - (cons (list (copy-marker start) - mark date desc (or amt total)) - entries)))) - (forward-line)))))) - entries)) - -(defvar ledger-reconcile-text "Reconcile") - -(define-derived-mode ledger-reconcile-mode text-mode 'ledger-reconcile-text - "A mode for reconciling ledger entries." - (let ((map (make-sparse-keymap))) - (define-key map [? ] 'ledger-reconcile-toggle) - (define-key map [?q] - (function - (lambda () - (interactive) - (kill-buffer (current-buffer))))) - (use-local-map map))) - -(add-to-list 'minor-mode-alist - '(ledger-reconcile-mode ledger-reconcile-text)) - -(defvar ledger-buf nil) -(defvar ledger-acct nil) - -(defun ledger-update-balance-display () - (let ((account ledger-acct)) - (with-temp-buffer - (let ((exit-code - (apply 'call-process ledger-binary-path nil t nil - (list "-C" "balance" account)))) - (if (/= 0 exit-code) - (setq ledger-reconcile-text "Reconcile [ERR]") - (goto-char (point-min)) - (delete-horizontal-space) - (skip-syntax-forward "^ ") - (setq ledger-reconcile-text - (concat "Reconcile [" - (buffer-substring-no-properties (point-min) (point)) - "]")))))) - (redraw-modeline)) - -(defun ledger-reconcile-toggle () - (interactive) - (let ((where (get-text-property (point) 'where)) - (account ledger-acct) - cleared) - (with-current-buffer ledger-buf - (goto-char where) - (setq cleared (ledger-toggle-current)) - (save-buffer)) - (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) - (ledger-update-balance-display))) - -(defun ledger-reconcile (account &optional days) - (interactive "sAccount to reconcile: \nnBack how far (default 30 days): ") - (let* ((then (time-subtract (current-time) - (seconds-to-time (* (or days 30) 24 60 60)))) - (items (save-excursion - (goto-char (point-min)) - (ledger-parse-entries account t then))) - (buf (current-buffer))) - (with-current-buffer - (pop-to-buffer (generate-new-buffer "*Reconcile*")) - (ledger-reconcile-mode) - (set (make-local-variable 'ledger-buf) buf) - (set (make-local-variable 'ledger-acct) account) - (ledger-update-balance-display) - (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) (nth 4 item))) - (if (nth 1 item) - (set-text-properties beg (1- (point)) - (list 'face 'bold - 'where (nth 0 item))) - (set-text-properties beg (1- (point)) - (list 'where (nth 0 item))))) - (goto-char (point-min)))))) - -(defun ledger-align-dollars (&optional column) - (interactive "p") - (if (= column 1) - (setq column 48)) - (while (search-forward "$" nil t) - (backward-char) - (let ((col (current-column)) - (beg (point)) - target-col len) - (skip-chars-forward "-$0-9,.") - (setq len (- (point) beg)) - (setq target-col (- column len)) - (if (< col target-col) - (progn - (goto-char beg) - (insert (make-string (- target-col col) ? ))) - (move-to-column target-col) - (if (looking-back " ") - (delete-char (- col target-col)) - (skip-chars-forward "^ \t") - (delete-horizontal-space) - (insert " "))) - (forward-line)))) - -(provide 'ledger) - -;;; ledger.el ends here |