summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore10
-rw-r--r--doc/ledger.texi19
-rw-r--r--lisp/ldg-post.el122
-rw-r--r--lisp/ldg-regex.el167
-rw-r--r--lisp/ldg-texi.el121
-rw-r--r--lisp/ledger.el4
-rw-r--r--src/account.cc2
-rw-r--r--src/account.h2
-rw-r--r--src/accum.cc2
-rw-r--r--src/accum.h2
-rw-r--r--src/amount.cc2
-rw-r--r--src/amount.h2
-rw-r--r--src/annotate.cc2
-rw-r--r--src/annotate.h2
-rw-r--r--src/archive.cc2
-rw-r--r--src/archive.h2
-rw-r--r--src/balance.cc2
-rw-r--r--src/balance.h2
-rw-r--r--src/chain.cc6
-rw-r--r--src/chain.h2
-rw-r--r--src/commodity.cc2
-rw-r--r--src/commodity.h2
-rw-r--r--src/compare.cc2
-rw-r--r--src/compare.h2
-rw-r--r--src/convert.cc156
-rw-r--r--src/convert.h55
-rw-r--r--src/csv.cc298
-rw-r--r--src/csv.h110
-rw-r--r--src/draft.cc49
-rw-r--r--src/draft.h2
-rw-r--r--src/emacs.cc2
-rw-r--r--src/emacs.h2
-rw-r--r--src/error.cc2
-rw-r--r--src/error.h2
-rw-r--r--src/expr.cc2
-rw-r--r--src/expr.h2
-rw-r--r--src/exprbase.h2
-rw-r--r--src/filters.cc10
-rw-r--r--src/filters.h9
-rw-r--r--src/flags.h2
-rw-r--r--src/format.cc2
-rw-r--r--src/format.h2
-rw-r--r--src/generate.cc2
-rw-r--r--src/generate.h2
-rw-r--r--src/global.cc2
-rw-r--r--src/global.h4
-rw-r--r--src/interactive.cc2
-rw-r--r--src/interactive.h2
-rw-r--r--src/item.cc55
-rw-r--r--src/item.h15
-rw-r--r--src/iterators.cc2
-rw-r--r--src/iterators.h2
-rw-r--r--src/journal.cc2
-rw-r--r--src/journal.h10
-rw-r--r--src/lookup.cc283
-rw-r--r--src/lookup.h56
-rw-r--r--src/main.cc2
-rw-r--r--src/mask.cc36
-rw-r--r--src/mask.h6
-rw-r--r--src/op.cc2
-rw-r--r--src/op.h2
-rw-r--r--src/option.cc2
-rw-r--r--src/option.h2
-rw-r--r--src/output.cc26
-rw-r--r--src/output.h4
-rw-r--r--src/parser.cc2
-rw-r--r--src/parser.h2
-rw-r--r--src/pool.cc2
-rw-r--r--src/pool.h2
-rw-r--r--src/post.cc6
-rw-r--r--src/post.h11
-rw-r--r--src/precmd.cc2
-rw-r--r--src/precmd.h2
-rw-r--r--src/predicate.cc2
-rw-r--r--src/predicate.h2
-rw-r--r--src/print.cc208
-rw-r--r--src/print.h79
-rw-r--r--src/pstream.h2
-rw-r--r--src/py_account.cc2
-rw-r--r--src/py_amount.cc2
-rw-r--r--src/py_balance.cc2
-rw-r--r--src/py_commodity.cc2
-rw-r--r--src/py_expr.cc2
-rw-r--r--src/py_format.cc2
-rw-r--r--src/py_item.cc2
-rw-r--r--src/py_journal.cc2
-rw-r--r--src/py_post.cc2
-rw-r--r--src/py_times.cc2
-rw-r--r--src/py_utils.cc2
-rw-r--r--src/py_value.cc2
-rw-r--r--src/py_xact.cc2
-rw-r--r--src/pyfstream.h2
-rw-r--r--src/pyinterp.cc2
-rw-r--r--src/pyinterp.h2
-rw-r--r--src/pyledger.cc2
-rw-r--r--src/pyutils.h2
-rw-r--r--src/query.cc2
-rw-r--r--src/query.h2
-rw-r--r--src/quotes.cc2
-rw-r--r--src/quotes.h2
-rw-r--r--src/report.cc87
-rw-r--r--src/report.h42
-rw-r--r--src/scope.cc2
-rw-r--r--src/scope.h2
-rw-r--r--src/session.cc2
-rw-r--r--src/session.h2
-rw-r--r--src/stats.cc2
-rw-r--r--src/stats.h2
-rw-r--r--src/stream.cc2
-rw-r--r--src/stream.h2
-rw-r--r--src/system.hh.in5
-rw-r--r--src/temps.cc2
-rw-r--r--src/temps.h2
-rw-r--r--src/textual.cc129
-rw-r--r--src/timelog.cc2
-rw-r--r--src/timelog.h2
-rw-r--r--src/times.cc2
-rw-r--r--src/times.h2
-rw-r--r--src/token.cc2
-rw-r--r--src/token.h2
-rw-r--r--src/unistring.h21
-rw-r--r--src/utils.cc2
-rw-r--r--src/utils.h12
-rw-r--r--src/value.cc10
-rw-r--r--src/value.h12
-rw-r--r--src/xact.cc13
-rw-r--r--src/xact.h2
-rw-r--r--src/xml.cc2
-rw-r--r--src/xml.h2
-rw-r--r--test/baseline/opt-by-payee.test32
-rw-r--r--test/baseline/opt-effective.test4
-rw-r--r--test/baseline/opt-forecast-while.test46
-rw-r--r--test/baseline/opt-lots_basis.test12
-rw-r--r--test/baseline/opt-lots_basis_base.test12
-rw-r--r--test/baseline/opt-print-format.test10
-rw-r--r--test/baseline/opt-strict.test4
-rw-r--r--tools/Makefile.am31
137 files changed, 2254 insertions, 347 deletions
diff --git a/.gitignore b/.gitignore
index 43c726a5..8eb4ebbb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,6 +53,16 @@
/doc/ledger.info
/doc/refman.pdf
/doc/report/
+/doc/*.aux
+/doc/*.cp
+/doc/*.fn
+/doc/*.ky
+/doc/*.log
+/doc/*.pdf
+/doc/*.pg
+/doc/*.toc
+/doc/*.tp
+/doc/*.vr
/expr_tests
/libtool
/math_tests
diff --git a/doc/ledger.texi b/doc/ledger.texi
index 3b0785eb..10e80a60 100644
--- a/doc/ledger.texi
+++ b/doc/ledger.texi
@@ -5,7 +5,7 @@
@dircategory User Applications
@copying
-Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+Copyright (c) 2003-2010, John Wiegley. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -35,7 +35,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@end copying
-@documentencoding iso-8859-1
+@documentencoding utf-8
@iftex
@finalout
@@ -4107,4 +4107,19 @@ parser_t
@section General Utility
+@c data: foo
+@smallexample
+2004/05/01 * Checking balance
+ Assets:Bank:Checking $1,000.00
+ Equity:Opening Balances
+@end smallexample
+
+@c smex utility-1: $LEDGER -f $foo bal
+@smallexample
+ $1,000.00 Assets:Bank:Checking
+ $-1,000.00 Equity:Opening Balances
+--------------------
+ 0
+@end smallexample
+
@bye
diff --git a/lisp/ldg-post.el b/lisp/ldg-post.el
new file mode 100644
index 00000000..30edd035
--- /dev/null
+++ b/lisp/ldg-post.el
@@ -0,0 +1,122 @@
+(require 'ldg-regex)
+
+(defgroup ledger-post nil
+ ""
+ :group 'ledger)
+
+(defcustom ledger-post-auto-adjust-amounts t
+ "If non-nil, ."
+ :type 'boolean
+ :group 'ledger-post)
+
+(declare-function iswitchb-read-buffer "iswitchb"
+ (prompt &optional default require-match start matches-set))
+(defvar iswitchb-temp-buflist)
+
+(defvar ledger-post-current-list nil)
+
+(defun ledger-post-find-all ()
+ (let ((origin (point))
+ (ledger-post-list nil)
+ account-path elements)
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward
+ "^[ \t]+\\([*!]\\s-+\\)?[[(]?\\(.+?\\)\\(\t\\|\n\\| [ \t]\\)" nil t)
+ (unless (and (>= origin (match-beginning 0))
+ (< origin (match-end 0)))
+ (setq account-path (match-string-no-properties 2))
+ (unless (string-match "\\`\\s-*;" account-path)
+ (add-to-list 'ledger-post-list account-path))))
+ (setq ledger-post-current-list
+ (nreverse ledger-post-list)))))
+
+(defun ledger-post-completing-read (prompt choices)
+ "Use iswitchb as a completing-read replacement to choose from choices.
+PROMPT is a string to prompt with. CHOICES is a list of strings
+to choose from."
+ (let* ((iswitchb-use-virtual-buffers nil)
+ (iswitchb-make-buflist-hook
+ (lambda ()
+ (setq iswitchb-temp-buflist choices))))
+ (iswitchb-read-buffer prompt)))
+
+(defun ledger-post-pick-account ()
+ (interactive)
+ (let* ((account
+ (ledger-post-completing-read "Account: "
+ (or ledger-post-current-list
+ (ledger-post-find-all))))
+ (account-len (length account))
+ (pos (point)))
+ (goto-char (line-beginning-position))
+ (when (re-search-forward ledger-regex-post-line (line-end-position) t)
+ (let ((existing-len (length (match-string 3))))
+ (goto-char (match-beginning 3))
+ (delete-region (match-beginning 3) (match-end 3))
+ (insert account)
+ (cond
+ ((> existing-len account-len)
+ (insert (make-string (- existing-len account-len) ? )))
+ ((< existing-len account-len)
+ (dotimes (n (- account-len existing-len))
+ (if (looking-at "[ \t]\\( [ \t]\\|\t\\)")
+ (delete-char 1)))))))
+ (goto-char pos)))
+
+(defun ledger-post-align-amount ()
+ (interactive)
+ (save-excursion
+ (set-mark (line-beginning-position))
+ (goto-char (1+ (line-end-position)))
+ (ledger-align-amounts)))
+
+(defun ledger-post-maybe-align (beg end len)
+ (save-excursion
+ (goto-char beg)
+ (when (< end (line-end-position))
+ (goto-char (line-beginning-position))
+ (if (looking-at ledger-regex-post-line)
+ (ledger-post-align-amount)))))
+
+(defun ledger-post-edit-amount ()
+ (interactive)
+ (goto-char (line-beginning-position))
+ (when (re-search-forward ledger-regex-post-line (line-end-position) t)
+ (goto-char (match-end 3))
+ (when (re-search-forward "[-.,0-9]+" (line-end-position) t)
+ (let ((val (match-string 0)))
+ (goto-char (match-beginning 0))
+ (delete-region (match-beginning 0) (match-end 0))
+ (calc)
+ (while (string-match "," val)
+ (setq val (replace-match "" nil nil val)))
+ (calc-eval val 'push)))))
+
+(defun ledger-post-prev-xact ()
+ (interactive)
+ (backward-paragraph)
+ (when (re-search-backward ledger-regex-xact-line nil t)
+ (goto-char (match-beginning 0))
+ (re-search-forward ledger-regex-post-line)
+ (goto-char (match-end 3))))
+
+(defun ledger-post-next-xact ()
+ (interactive)
+ (when (re-search-forward ledger-regex-xact-line nil t)
+ (goto-char (match-beginning 0))
+ (re-search-forward ledger-regex-post-line)
+ (goto-char (match-end 3))))
+
+(defun ledger-post-setup ()
+ (let ((map (current-local-map)))
+ (define-key map [(meta ?p)] 'ledger-post-prev-xact)
+ (define-key map [(meta ?n)] 'ledger-post-next-xact)
+ (define-key map [(control ?c) (control ?c)] 'ledger-post-pick-account)
+ (define-key map [(control ?c) (control ?e)] 'ledger-post-edit-amount))
+ (if ledger-post-auto-adjust-amounts
+ (add-hook 'after-change-functions 'ledger-post-maybe-align t t)))
+
+(add-hook 'ledger-mode-hook 'ledger-post-setup)
+
+(provide 'ldg-post)
diff --git a/lisp/ldg-regex.el b/lisp/ldg-regex.el
new file mode 100644
index 00000000..14c41f63
--- /dev/null
+++ b/lisp/ldg-regex.el
@@ -0,0 +1,167 @@
+(require 'rx)
+
+(defconst ledger-regex-date
+ (let ((sep '(or ?- (any ?. ?/)))) ; can't do (any ?- ?. ?/) due to bug
+ (rx (group
+ (and (? (= 4 num)
+ (eval sep))
+ (and num (? num))
+ (eval sep)
+ (and num (? num))))))
+ "Match a single date, in its 'written' form.")
+
+(defconst ledger-regex-date-group 1)
+(defconst ledger-regex-date-group--count 1)
+
+(defconst ledger-regex-full-date
+ (macroexpand
+ `(rx (and (regexp ,ledger-regex-date)
+ (? (and ?= (regexp ,ledger-regex-date))))))
+ "Match a compound date, of the form ACTUAL=EFFECTIVE")
+
+(defconst ledger-regex-full-date-group-actual
+ ledger-regex-date-group)
+(defconst ledger-regex-full-date-group-effective
+ (+ ledger-regex-date-group--count
+ ledger-regex-date-group))
+(defconst ledger-regex-full-date-group--count
+ (* 2 ledger-regex-date-group--count))
+
+(defconst ledger-regex-state
+ (rx (group (any ?! ?*))))
+
+(defconst ledger-regex-state-group 1)
+(defconst ledger-regex-state-group--count 1)
+
+(defconst ledger-regex-code
+ (rx (and ?\( (group (+? (not (any ?\))))) ?\))))
+
+(defconst ledger-regex-code-group 1)
+(defconst ledger-regex-code-group--count 1)
+
+(defconst ledger-regex-long-space
+ (rx (and (*? space)
+ (or (and ? (or ? ?\t)) ?\t))))
+
+(defconst ledger-regex-note
+ (rx (group (+ nonl))))
+
+(defconst ledger-regex-note-group 1)
+(defconst ledger-regex-note-group--count 1)
+
+(defconst ledger-regex-end-note
+ (macroexpand `(rx (and (regexp ,ledger-regex-long-space) ?\;
+ (regexp ,ledger-regex-note)))))
+
+(defconst ledger-regex-end-note-group
+ ledger-regex-note-group)
+(defconst ledger-regex-end-note-group--count
+ ledger-regex-note-group--count)
+
+(defconst ledger-regex-full-note
+ (macroexpand `(rx (and line-start (+ space)
+ ?\; (regexp ,ledger-regex-note)))))
+
+(defconst ledger-regex-full-note-group
+ ledger-regex-note-group)
+(defconst ledger-regex-full-note-group--count
+ ledger-regex-note-group--count)
+
+(defconst ledger-regex-xact-line
+ (macroexpand
+ `(rx (and line-start
+ (regexp ,ledger-regex-full-date)
+ (? (and (+ space) (regexp ,ledger-regex-state)))
+ (? (and (+ space) (regexp ,ledger-regex-code)))
+ (+ space) (+? nonl)
+ (? (regexp ,ledger-regex-end-note))
+ line-end))))
+
+(defconst ledger-regex-xact-line-group-actual-date
+ ledger-regex-full-date-group-actual)
+(defconst ledger-regex-xact-line-group-effective-date
+ ledger-regex-full-date-group-effective)
+(defconst ledger-regex-xact-line-group-state
+ (+ ledger-regex-full-date-group--count
+ ledger-regex-state-group))
+(defconst ledger-regex-xact-line-group-code
+ (+ ledger-regex-full-date-group--count
+ ledger-regex-state-group--count
+ ledger-regex-code-group))
+(defconst ledger-regex-xact-line-group-note
+ (+ ledger-regex-full-date-group--count
+ ledger-regex-state-group--count
+ ledger-regex-code-group--count
+ ledger-regex-note-group))
+(defconst ledger-regex-full-note-group--count
+ (+ ledger-regex-full-date-group--count
+ ledger-regex-state-group--count
+ ledger-regex-code-group--count
+ ledger-regex-note-group--count))
+
+(defun ledger-regex-xact-line-actual-date
+ (&optional string)
+ (match-string ledger-regex-xact-line-group-actual-date string))
+
+(defconst ledger-regex-account
+ (rx (group (and (not (any ?:)) (*? nonl)))))
+
+(defconst ledger-regex-full-account
+ (macroexpand
+ `(rx (and (group (? (any ?\[ ?\))))
+ (regexp ,ledger-regex-account)
+ (? (any ?\] ?\)))))))
+
+(defconst ledger-regex-commodity
+ (rx (or (and ?\" (+ (not (any ?\"))) ?\")
+ (not (any space ?\n
+ digit
+ ?- ?\[ ?\]
+ ?. ?, ?\; ?+ ?* ?/ ?^ ?? ?: ?& ?| ?! ?=
+ ?\< ?\> ?\{ ?\} ?\( ?\) ?@)))))
+
+(defconst ledger-regex-amount
+ (rx (and (? ?-)
+ (and (+ digit)
+ (*? (and (any ?. ?,) (+ digit))))
+ (? (and (any ?. ?,) (+ digit))))))
+
+(defconst ledger-regex-commoditized-amount
+ (macroexpand
+ `(rx (or (and (regexp ,ledger-regex-commodity)
+ (*? space)
+ (regexp ,ledger-regex-amount))
+ (and (regexp ,ledger-regex-amount)
+ (*? space)
+ (regexp ,ledger-regex-commodity))))))
+
+(defconst ledger-regex-commodity-annotations
+ (macroexpand
+ `(rx (* (+ space)
+ (or (and ?\{ (regexp ,ledger-regex-commoditized-amount) ?\})
+ (and ?\[ (regexp ,ledger-regex-date) ?\])
+ (and ?\( (not (any ?\))) ?\)))))))
+
+(defconst ledger-regex-cost
+ (macroexpand
+ `(rx (and (or "@" "@@") (+ space)
+ (regexp ,ledger-regex-commoditized-amount)))))
+
+(defconst ledger-regex-balance-assertion
+ (macroexpand
+ `(rx (and ?= (+ space)
+ (regexp ,ledger-regex-commoditized-amount)))))
+
+(defconst ledger-regex-full-amount
+ (macroexpand `(rx (group (+? (not (any ?\;)))))))
+
+(defconst ledger-regex-post-line
+ (macroexpand
+ `(rx (and line-start
+ (? (and (+ space) (regexp ,ledger-regex-state)))
+ (+ space) (regexp ,ledger-regex-full-account)
+ (+ space) (regexp ,ledger-regex-full-amount)
+ (? (regexp ,ledger-regex-end-note))
+ line-end))))
+
+(provide 'ldg-regex)
diff --git a/lisp/ldg-texi.el b/lisp/ldg-texi.el
new file mode 100644
index 00000000..982ea0ed
--- /dev/null
+++ b/lisp/ldg-texi.el
@@ -0,0 +1,121 @@
+(defvar ledger-path "/Users/johnw/bin/ledger")
+(defvar ledger-sample-doc-path "/Users/johnw/src/ledger/doc/sample.dat")
+(defvar ledger-normalization-args "--args-only --columns 80")
+
+(defun ledger-texi-write-test (name command input output &optional category)
+ (let ((buf (current-buffer)))
+ (with-current-buffer (find-file-noselect
+ (expand-file-name (concat name ".test") category))
+ (erase-buffer)
+ (let ((case-fold-search nil))
+ (if (string-match "\\$LEDGER\\s-+" command)
+ (setq command (replace-match "" t t command)))
+ (if (string-match " -f \\$\\([-a-z]+\\)" command)
+ (setq command (replace-match "" t t command))))
+ (insert command ?\n)
+ (insert "<<<" ?\n)
+ (insert input)
+ (insert ">>>1" ?\n)
+ (insert output)
+ (insert ">>>2" ?\n)
+ (insert "=== 0" ?\n)
+ (save-buffer)
+ (unless (eq buf (current-buffer))
+ (kill-buffer (current-buffer))))))
+
+(defun ledger-texi-update-test ()
+ (interactive)
+ (let ((details (ledger-texi-test-details))
+ (name (file-name-sans-extension
+ (file-name-nondirectory (buffer-file-name)))))
+ (ledger-texi-write-test
+ name (nth 0 details)
+ (nth 1 details)
+ (ledger-texi-invoke-command
+ (ledger-texi-expand-command
+ (nth 0 details)
+ (ledger-texi-write-test-data name (nth 1 details)))))))
+
+(defun ledger-texi-test-details ()
+ (goto-char (point-min))
+ (let ((command (buffer-substring (point) (line-end-position)))
+ input output)
+ (re-search-forward "^<<<")
+ (let ((input-beg (1+ (match-end 0))))
+ (re-search-forward "^>>>1")
+ (let ((output-beg (1+ (match-end 0))))
+ (setq input (buffer-substring input-beg (match-beginning 0)))
+ (re-search-forward "^>>>2")
+ (setq output (buffer-substring output-beg (match-beginning 0)))
+ (list command input output)))))
+
+(defun ledger-texi-expand-command (command data-file)
+ (if (string-match "\\$LEDGER" command)
+ (replace-match (format "%s -f \"%s\" %s" ledger-path
+ data-file ledger-normalization-args) t t command)
+ (concat (format "%s -f \"%s\" %s " ledger-path
+ data-file ledger-normalization-args) command)))
+
+(defun ledger-texi-invoke-command (command)
+ (with-temp-buffer (shell-command command t (current-buffer))
+ (if (= (point-min) (point-max))
+ (progn
+ (push-mark nil t)
+ (message "Command '%s' yielded no result at %d" command (point))
+ (ding))
+ (buffer-string))))
+
+(defun ledger-texi-write-test-data (name input)
+ (let ((path (expand-file-name name temporary-file-directory)))
+ (with-current-buffer (find-file-noselect path)
+ (erase-buffer)
+ (insert input)
+ (save-buffer))
+ path))
+
+(defun ledger-texi-update-examples ()
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward "^@c \\(\\(?:sm\\)?ex\\) \\(\\S-+\\): \\(.*\\)" nil t)
+ (let ((section (match-string 1))
+ (example-name (match-string 2))
+ (command (match-string 3)) expanded-command
+ (data-file ledger-sample-doc-path)
+ input output)
+ (goto-char (match-end 0))
+ (forward-line)
+ (when (looking-at "@\\(\\(?:small\\)?example\\)")
+ (let ((beg (point)))
+ (re-search-forward "^@end \\(\\(?:small\\)?example\\)")
+ (delete-region beg (1+ (point)))))
+
+ (when (let ((case-fold-search nil))
+ (string-match " -f \\$\\([-a-z]+\\)" command))
+ (let ((label (match-string 1 command)))
+ (setq command (replace-match "" t t command))
+ (save-excursion
+ (goto-char (point-min))
+ (search-forward (format "@c data: %s" label))
+ (re-search-forward "@\\(\\(?:small\\)?example\\)")
+ (forward-line)
+ (let ((beg (point)))
+ (re-search-forward "@end \\(\\(?:small\\)?example\\)")
+ (setq data-file (ledger-texi-write-test-data
+ (format "%s.dat" label)
+ (buffer-substring-no-properties
+ beg (match-beginning 0))))))))
+
+ (let ((section-name (if (string= section "smex")
+ "smallexample"
+ "example"))
+ (output (ledger-texi-invoke-command
+ (ledger-texi-expand-command command data-file))))
+ (insert "@" section-name ?\n output
+ "@end " section-name ?\n))
+
+ ;; Update the regression test associated with this example
+ (ledger-texi-write-test example-name command input output
+ "../test/manual")))))
+
+(provide 'ldg-texi)
diff --git a/lisp/ledger.el b/lisp/ledger.el
index c2407261..9fa28781 100644
--- a/lisp/ledger.el
+++ b/lisp/ledger.el
@@ -73,7 +73,7 @@
(require 'esh-arg)
(require 'pcomplete)
-(defvar ledger-version "1.2"
+(defvar ledger-version "1.3"
"The version of ledger.el currently loaded")
(defgroup ledger nil
@@ -1226,7 +1226,7 @@ the default."
"Align amounts in the current region.
This is done so that the last digit falls in COLUMN, which defaults to 52."
(interactive "p")
- (if (= column 1)
+ (if (or (null column) (= column 1))
(setq column 52))
(save-excursion
(let* ((mark-first (< (mark) (point)))
diff --git a/src/account.cc b/src/account.cc
index f8729409..245d61fc 100644
--- a/src/account.cc
+++ b/src/account.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/account.h b/src/account.h
index 73cd35ac..0a3a75e4 100644
--- a/src/account.h
+++ b/src/account.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/accum.cc b/src/accum.cc
index b918c76a..62e36deb 100644
--- a/src/accum.cc
+++ b/src/accum.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/accum.h b/src/accum.h
index 878c2b7c..94e79948 100644
--- a/src/accum.h
+++ b/src/accum.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/amount.cc b/src/amount.cc
index eddbca18..3a64577f 100644
--- a/src/amount.cc
+++ b/src/amount.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/amount.h b/src/amount.h
index a37efdb8..5c1bca46 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/annotate.cc b/src/annotate.cc
index 146a7afd..99c12fc3 100644
--- a/src/annotate.cc
+++ b/src/annotate.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/annotate.h b/src/annotate.h
index 38ebaeae..6ef26476 100644
--- a/src/annotate.h
+++ b/src/annotate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/archive.cc b/src/archive.cc
index 7306f8d3..e7fc072e 100644
--- a/src/archive.cc
+++ b/src/archive.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/archive.h b/src/archive.h
index 03fc970a..e954cd3e 100644
--- a/src/archive.h
+++ b/src/archive.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/balance.cc b/src/balance.cc
index 4fcc83fa..9b39a49a 100644
--- a/src/balance.cc
+++ b/src/balance.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/balance.h b/src/balance.h
index 826de134..f8455d49 100644
--- a/src/balance.h
+++ b/src/balance.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/chain.cc b/src/chain.cc
index ecb39e0b..86f639ad 100644
--- a/src/chain.cc
+++ b/src/chain.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -112,10 +112,12 @@ post_handler_ptr chain_post_handlers(report_t& report,
else
handler.reset(new sort_posts(handler, report.HANDLER(sort_).str()));
}
+#if 0
else if (! report.HANDLED(period_) &&
! report.HANDLED(unsorted)) {
handler.reset(new sort_posts(handler, "date"));
}
+#endif
// collapse_posts causes xacts with multiple posts to appear as xacts
// with a subtotaled post for each commodity used.
@@ -167,7 +169,7 @@ post_handler_ptr chain_post_handlers(report_t& report,
}
else if (report.HANDLED(pivot_)) {
string pivot = report.HANDLER(pivot_).str();
- pivot = string("\"") + pivot + ":\" + tag(/" + pivot + "/)";
+ pivot = string("\"") + pivot + ":\" + tag(\"" + pivot + "\")";
handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
report.session.journal->master, pivot,
report));
diff --git a/src/chain.h b/src/chain.h
index a2b75b3a..94d54317 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/commodity.cc b/src/commodity.cc
index 24016830..e5f10e34 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/commodity.h b/src/commodity.h
index d2d8af21..10f209fa 100644
--- a/src/commodity.h
+++ b/src/commodity.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/compare.cc b/src/compare.cc
index 36884a46..f3c13cea 100644
--- a/src/compare.cc
+++ b/src/compare.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/compare.h b/src/compare.h
index 740ba275..eeecd7cf 100644
--- a/src/compare.h
+++ b/src/compare.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/convert.cc b/src/convert.cc
new file mode 100644
index 00000000..6c02cff3
--- /dev/null
+++ b/src/convert.cc
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <system.hh>
+
+#include "convert.h"
+#include "csv.h"
+#include "scope.h"
+#include "interactive.h"
+#include "iterators.h"
+#include "report.h"
+#include "xact.h"
+#include "print.h"
+#include "lookup.h"
+
+namespace ledger {
+
+value_t convert_command(call_scope_t& scope)
+{
+ interactive_t args(scope, "s");
+ report_t& report(find_scope<report_t>(scope));
+ journal_t& journal(*report.session.journal.get());
+
+ string bucket_name;
+ if (report.HANDLED(account_))
+ bucket_name = report.HANDLER(account_).str();
+ else
+ bucket_name = "Equity:Unknown";
+
+ account_t * bucket = journal.master->find_account(bucket_name);
+ account_t * unknown = journal.master->find_account(_("Expenses:Unknown"));
+
+ // Make an amounts mapping for the account under consideration
+
+ typedef std::map<value_t, std::list<post_t *> > post_map_t;
+ post_map_t post_map;
+
+ xacts_iterator journal_iter(journal);
+ while (xact_t * xact = journal_iter()) {
+ post_t * post = NULL;
+ xact_posts_iterator xact_iter(*xact);
+ while ((post = xact_iter()) != NULL) {
+ if (post->account == bucket)
+ break;
+ }
+ if (post) {
+ post_map_t::iterator i = post_map.find(post->amount);
+ if (i == post_map.end()) {
+ std::list<post_t *> post_list;
+ post_list.push_back(post);
+ post_map.insert(post_map_t::value_type(post->amount, post_list));
+ } else {
+ (*i).second.push_back(post);
+ }
+ }
+ }
+
+ // Create a flat list o
+ xacts_list current_xacts(journal.xacts_begin(), journal.xacts_end());
+
+ // Read in the series of transactions from the CSV file
+
+ print_xacts formatter(report);
+ ifstream data(path(args.get<string>(0)));
+ csv_reader reader(data);
+
+ while (xact_t * xact = reader.read_xact(journal, bucket)) {
+ bool matched = false;
+ post_map_t::iterator i = post_map.find(- xact->posts.front()->amount);
+ if (i != post_map.end()) {
+ std::list<post_t *>& post_list((*i).second);
+ foreach (post_t * post, post_list) {
+ if (xact->code && post->xact->code &&
+ *xact->code == *post->xact->code) {
+ matched = true;
+ break;
+ }
+ else if (xact->actual_date() == post->actual_date()) {
+ matched = true;
+ break;
+ }
+ }
+ }
+
+ if (matched) {
+ DEBUG("convert.csv", "Ignored xact with code: " << *xact->code);
+ delete xact; // ignore it
+ }
+ else {
+ if (xact->posts.front()->account == NULL) {
+ xacts_iterator xi;
+ xi.xacts_i = current_xacts.begin();
+ xi.xacts_end = current_xacts.end();
+ xi.xacts_uninitialized = false;
+
+ // jww (2010-03-07): Bind this logic to an option: --auto-match
+ if (account_t * acct =
+ lookup_probable_account(xact->payee, xi, bucket).second)
+ xact->posts.front()->account = acct;
+ else
+ xact->posts.front()->account = unknown;
+ }
+
+ if (! journal.add_xact(xact)) {
+ delete xact;
+ throw_(std::runtime_error,
+ _("Failed to finalize derived transaction (check commodities)"));
+ }
+ else {
+ xact_posts_iterator xact_iter(*xact);
+ while (post_t * post = xact_iter())
+ formatter(*post);
+ }
+ }
+ }
+ formatter.flush();
+
+ // If not, transform the payee according to regexps
+
+ // Set the account to a default vaule, then transform the account according
+ // to the payee
+
+ // Print out the final form of the transaction
+
+ return true;
+}
+
+} // namespace ledger
diff --git a/src/convert.h b/src/convert.h
new file mode 100644
index 00000000..6d02f24a
--- /dev/null
+++ b/src/convert.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file convert.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _CONVERT_H
+#define _CONVERT_H
+
+#include "value.h"
+
+namespace ledger {
+
+class call_scope_t;
+
+value_t convert_command(call_scope_t& scope);
+
+} // namespace ledger
+
+#endif // _CONVERT_H
diff --git a/src/csv.cc b/src/csv.cc
new file mode 100644
index 00000000..5a74232f
--- /dev/null
+++ b/src/csv.cc
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <system.hh>
+
+#include "csv.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "journal.h"
+#include "pool.h"
+
+namespace ledger {
+
+string csv_reader::read_field(std::istream& in)
+{
+ string field;
+
+ char c;
+ if (in.peek() == '"' || in.peek() == '|') {
+ in.get(c);
+ char x;
+ while (in.good() && ! in.eof()) {
+ in.get(x);
+ if (x == '\\') {
+ in.get(x);
+ }
+ else if (x == '"' && in.peek() == '"') {
+ in.get(x);
+ }
+ else if (x == c) {
+ if (x == '|')
+ in.unget();
+ else if (in.peek() == ',')
+ in.get(c);
+ break;
+ }
+ if (x != '\0')
+ field += x;
+ }
+ }
+ else {
+ while (in.good() && ! in.eof()) {
+ in.get(c);
+ if (c == ',')
+ break;
+ if (c != '\0')
+ field += c;
+ }
+ }
+ trim(field);
+ return field;
+}
+
+char * csv_reader::next_line(std::istream& in)
+{
+ static char linebuf[MAX_LINE + 1];
+
+ while (in.good() && ! in.eof() && in.peek() == '#')
+ in.getline(linebuf, MAX_LINE);
+
+ if (! in.good() || in.eof())
+ return NULL;
+
+ in.getline(linebuf, MAX_LINE);
+
+ return linebuf;
+}
+
+void csv_reader::read_index(std::istream& in)
+{
+ char * line = next_line(in);
+ if (! line)
+ return;
+
+ std::istringstream instr(line);
+
+ while (instr.good() && ! instr.eof()) {
+ string field = read_field(instr);
+ names.push_back(field);
+
+ if (date_mask.match(field))
+ index.push_back(FIELD_DATE);
+ else if (date_eff_mask.match(field))
+ index.push_back(FIELD_DATE_EFF);
+ else if (code_mask.match(field))
+ index.push_back(FIELD_CODE);
+ else if (payee_mask.match(field))
+ index.push_back(FIELD_PAYEE);
+ else if (amount_mask.match(field))
+ index.push_back(FIELD_AMOUNT);
+ else if (cost_mask.match(field))
+ index.push_back(FIELD_COST);
+ else if (total_mask.match(field))
+ index.push_back(FIELD_TOTAL);
+ else if (note_mask.match(field))
+ index.push_back(FIELD_NOTE);
+ else
+ index.push_back(FIELD_UNKNOWN);
+
+ DEBUG("csv.parse", "Header field: " << field);
+ }
+}
+
+xact_t * csv_reader::read_xact(journal_t& journal, account_t * bucket)
+{
+ restart:
+ char * line = next_line(in);
+ if (! line || index.empty())
+ return NULL;
+
+ std::istringstream instr(line);
+
+ std::auto_ptr<xact_t> xact(new xact_t);
+ std::auto_ptr<post_t> post(new post_t);
+
+ xact->set_state(item_t::CLEARED);
+
+ xact->pos = position_t();
+ xact->pos->pathname = "jww (2010-03-05): unknown";
+ xact->pos->beg_pos = in.tellg();
+ xact->pos->beg_line = 0;
+ xact->pos->sequence = 0;
+
+ post->xact = xact.get();
+
+#if 0
+ post->pos = position_t();
+ post->pos->pathname = pathname;
+ post->pos->beg_pos = line_beg_pos;
+ post->pos->beg_line = linenum;
+ post->pos->sequence = context.sequence++;
+#endif
+
+ post->set_state(item_t::CLEARED);
+ post->account = NULL;
+
+ int n = 0;
+ amount_t amt;
+ string total;
+
+ while (instr.good() && ! instr.eof()) {
+ string field = read_field(instr);
+
+ switch (index[n]) {
+ case FIELD_DATE:
+ if (field.empty())
+ goto restart;
+ try {
+ xact->_date = parse_date(field);
+ }
+ catch (date_error&) {
+ goto restart;
+ }
+ break;
+
+ case FIELD_DATE_EFF:
+ xact->_date_eff = parse_date(field);
+ break;
+
+ case FIELD_CODE:
+ if (! field.empty())
+ xact->code = field;
+ break;
+
+ case FIELD_PAYEE: {
+ bool found = false;
+ foreach (payee_mapping_t& value, journal.payee_mappings) {
+ DEBUG("csv.mappings", "Looking for payee mapping: " << value.first);
+ if (value.first.match(field)) {
+ xact->payee = value.second;
+ found = true;
+ break;
+ }
+ }
+ if (! found)
+ xact->payee = field;
+ break;
+ }
+
+ case FIELD_AMOUNT: {
+ std::istringstream amount_str(field);
+ amt.parse(amount_str, PARSE_NO_REDUCE);
+ if (! amt.has_commodity() &&
+ commodity_pool_t::current_pool->default_commodity)
+ amt.set_commodity(*commodity_pool_t::current_pool->default_commodity);
+ post->amount = amt;
+ break;
+ }
+
+ case FIELD_COST: {
+ std::istringstream amount_str(field);
+ amt.parse(amount_str, PARSE_NO_REDUCE);
+ if (! amt.has_commodity() &&
+ commodity_pool_t::current_pool->default_commodity)
+ amt.set_commodity
+ (*commodity_pool_t::current_pool->default_commodity);
+ post->cost = amt;
+ break;
+ }
+
+ case FIELD_TOTAL:
+ total = field;
+ break;
+
+ case FIELD_NOTE:
+ xact->note = field;
+ break;
+
+ case FIELD_UNKNOWN:
+ if (! names[n].empty() && ! field.empty())
+ xact->set_tag(names[n], field);
+ break;
+ }
+ n++;
+ }
+
+#if 0
+ xact->set_tag(_("Imported"),
+ string(format_date(CURRENT_DATE(), FMT_WRITTEN)));
+ xact->set_tag(_("Original"), string(line));
+ xact->set_tag(_("SHA1"), string(sha1sum(line)));
+#endif
+
+ // Translate the account name, if we have enough information to do so
+
+ foreach (account_mapping_t& value, journal.account_mappings) {
+ if (value.first.match(xact->payee)) {
+ post->account = value.second;
+ break;
+ }
+ }
+
+ xact->add_post(post.release());
+
+ // Create the "balancing post", which refers to the account for this data
+
+ post.reset(new post_t);
+
+ post->xact = xact.get();
+
+#if 0
+ post->pos = position_t();
+ post->pos->pathname = pathname;
+ post->pos->beg_pos = line_beg_pos;
+ post->pos->beg_line = linenum;
+ post->pos->sequence = context.sequence++;
+#endif
+
+ post->set_state(item_t::CLEARED);
+ post->account = bucket;
+
+ if (! amt.is_null())
+ post->amount = - amt;
+
+ if (! total.empty()) {
+ std::istringstream assigned_amount_str(total);
+ amt.parse(assigned_amount_str, PARSE_NO_REDUCE);
+ if (! amt.has_commodity() &&
+ commodity_pool_t::current_pool->default_commodity)
+ amt.set_commodity(*commodity_pool_t::current_pool->default_commodity);
+ post->assigned_amount = amt;
+ }
+
+ xact->add_post(post.release());
+
+ return xact.release();
+}
+
+} // namespace ledger
diff --git a/src/csv.h b/src/csv.h
new file mode 100644
index 00000000..5ff8b59e
--- /dev/null
+++ b/src/csv.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file csv.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _CSV_H
+#define _CSV_H
+
+#include "value.h"
+
+namespace ledger {
+
+class xact_t;
+class journal_t;
+class account_t;
+
+class csv_reader
+{
+ static const std::size_t MAX_LINE = 1024;
+
+ std::istream& in;
+
+ enum headers_t {
+ FIELD_DATE = 0,
+ FIELD_DATE_EFF,
+ FIELD_CODE,
+ FIELD_PAYEE,
+ FIELD_AMOUNT,
+ FIELD_COST,
+ FIELD_TOTAL,
+ FIELD_NOTE,
+
+ FIELD_UNKNOWN
+ };
+
+ mask_t date_mask;
+ mask_t date_eff_mask;
+ mask_t code_mask;
+ mask_t payee_mask;
+ mask_t amount_mask;
+ mask_t cost_mask;
+ mask_t total_mask;
+ mask_t note_mask;
+
+ std::vector<int> index;
+ std::vector<string> names;
+ std::vector<string> fields;
+
+ typedef std::map<string, string> string_map;
+
+public:
+ csv_reader(std::istream& _in)
+ : in(_in),
+ date_mask("date"),
+ date_eff_mask("posted( ?date)?"),
+ code_mask("code"),
+ payee_mask("(payee|desc(ription)?|title)"),
+ amount_mask("amount"),
+ cost_mask("cost"),
+ total_mask("total"),
+ note_mask("note") {
+ read_index(in);
+ }
+
+ string read_field(std::istream& in);
+ char * next_line(std::istream& in);
+ void read_index(std::istream& in);
+
+ xact_t * read_xact(journal_t& journal, account_t * bucket);
+};
+
+} // namespace ledger
+
+#endif // _CSV_H
diff --git a/src/draft.cc b/src/draft.cc
index fc53e956..18075731 100644
--- a/src/draft.cc
+++ b/src/draft.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -38,7 +38,8 @@
#include "journal.h"
#include "session.h"
#include "report.h"
-#include "output.h"
+#include "lookup.h"
+#include "print.h"
namespace ledger {
@@ -240,20 +241,27 @@ void draft_t::parse_args(const value_t& args)
xact_t * draft_t::insert(journal_t& journal)
{
if (tmpl->payee_mask.empty())
- throw std::runtime_error(_("xact' command requires at least a payee"));
+ throw std::runtime_error(_("'xact' command requires at least a payee"));
- xact_t * matching = NULL;
+ xact_t * matching = NULL;
std::auto_ptr<xact_t> added(new xact_t);
- for (xacts_list::reverse_iterator j = journal.xacts.rbegin();
- j != journal.xacts.rend();
- j++) {
- if (tmpl->payee_mask.match((*j)->payee)) {
- matching = *j;
- DEBUG("derive.xact",
- "Found payee match: transaction on line " << (*j)->pos->beg_line);
- break;
+ xacts_iterator xi(journal);
+ if (xact_t * xact = lookup_probable_account(tmpl->payee_mask.str(), xi).first) {
+ DEBUG("derive.xact", "Found payee by lookup: transaction on line "
+ << xact->pos->beg_line);
+ matching = xact;
+ } else {
+ for (xacts_list::reverse_iterator j = journal.xacts.rbegin();
+ j != journal.xacts.rend();
+ j++) {
+ if (tmpl->payee_mask.match((*j)->payee)) {
+ matching = *j;
+ DEBUG("derive.xact",
+ "Found payee match: transaction on line " << (*j)->pos->beg_line);
+ break;
+ }
}
}
@@ -269,15 +277,15 @@ xact_t * draft_t::insert(journal_t& journal)
if (matching) {
added->payee = matching->payee;
- added->code = matching->code;
- added->note = matching->note;
+ //added->code = matching->code;
+ //added->note = matching->note;
#if defined(DEBUG_ON)
DEBUG("derive.xact", "Setting payee from match: " << added->payee);
- if (added->code)
- DEBUG("derive.xact", "Setting code from match: " << *added->code);
- if (added->note)
- DEBUG("derive.xact", "Setting note from match: " << *added->note);
+ //if (added->code)
+ // DEBUG("derive.xact", "Setting code from match: " << *added->code);
+ //if (added->note)
+ // DEBUG("derive.xact", "Setting note from match: " << *added->note);
#endif
} else {
added->payee = tmpl->payee_mask.str();
@@ -520,10 +528,7 @@ value_t xact_command(call_scope_t& args)
// Only consider actual postings for the "xact" command
report.HANDLER(limit_).on(string("#xact"), "actual");
- report.xact_report(post_handler_ptr
- (new format_posts(report,
- report.HANDLER(print_format_).str())),
- *new_xact);
+ report.xact_report(post_handler_ptr(new print_xacts(report)), *new_xact);
return true;
}
diff --git a/src/draft.h b/src/draft.h
index 93e98ff5..59039f77 100644
--- a/src/draft.h
+++ b/src/draft.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/emacs.cc b/src/emacs.cc
index dc1a18ae..d47f04ad 100644
--- a/src/emacs.cc
+++ b/src/emacs.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/emacs.h b/src/emacs.h
index 4b2a452a..97292728 100644
--- a/src/emacs.h
+++ b/src/emacs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/error.cc b/src/error.cc
index d5abe4de..cfc91ff1 100644
--- a/src/error.cc
+++ b/src/error.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/error.h b/src/error.h
index 5369faf1..0d33f020 100644
--- a/src/error.h
+++ b/src/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/expr.cc b/src/expr.cc
index c59f8a57..79fb3611 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/expr.h b/src/expr.h
index 638855b1..09285966 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/exprbase.h b/src/exprbase.h
index 0b3466b0..0dbf3bff 100644
--- a/src/exprbase.h
+++ b/src/exprbase.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/filters.cc b/src/filters.cc
index 2926eb08..0c45d356 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -107,6 +107,9 @@ void truncate_xacts::flush()
void truncate_xacts::operator()(post_t& post)
{
+ if (completed)
+ return;
+
if (last_xact != post.xact) {
if (last_xact)
xacts_seen++;
@@ -114,8 +117,11 @@ void truncate_xacts::operator()(post_t& post)
}
if (tail_count == 0 && head_count > 0 &&
- static_cast<int>(xacts_seen) >= head_count)
+ static_cast<int>(xacts_seen) >= head_count) {
+ flush();
+ completed = true;
return;
+ }
posts.push_back(&post);
}
diff --git a/src/filters.h b/src/filters.h
index 92148dbe..82fbf687 100644
--- a/src/filters.h
+++ b/src/filters.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -125,8 +125,9 @@ public:
class truncate_xacts : public item_handler<post_t>
{
- int head_count;
- int tail_count;
+ int head_count;
+ int tail_count;
+ bool completed;
posts_list posts;
std::size_t xacts_seen;
@@ -139,7 +140,7 @@ public:
int _head_count, int _tail_count)
: item_handler<post_t>(handler),
head_count(_head_count), tail_count(_tail_count),
- xacts_seen(0), last_xact(NULL) {
+ completed(false), xacts_seen(0), last_xact(NULL) {
TRACE_CTOR(truncate_xacts, "post_handler_ptr, int, int");
}
virtual ~truncate_xacts() {
diff --git a/src/flags.h b/src/flags.h
index 69e40e4b..03f47ff9 100644
--- a/src/flags.h
+++ b/src/flags.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/format.cc b/src/format.cc
index f26a86a1..c546926e 100644
--- a/src/format.cc
+++ b/src/format.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/format.h b/src/format.h
index a2bf1015..72d44ee5 100644
--- a/src/format.h
+++ b/src/format.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/generate.cc b/src/generate.cc
index 3549adc8..c1eb1d14 100644
--- a/src/generate.cc
+++ b/src/generate.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/generate.h b/src/generate.h
index 66513fc8..3d9965a5 100644
--- a/src/generate.h
+++ b/src/generate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/global.cc b/src/global.cc
index e120e5d5..170509b0 100644
--- a/src/global.cc
+++ b/src/global.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/global.h b/src/global.h
index ab3afed4..05e3bdb7 100644
--- a/src/global.h
+++ b/src/global.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -110,7 +110,7 @@ public:
out <<
"Ledger " << ledger::version << _(", the command-line accounting tool");
out <<
- _("\n\nCopyright (c) 2003-2009, John Wiegley. All rights reserved.\n\n\
+ _("\n\nCopyright (c) 2003-2010, John Wiegley. All rights reserved.\n\n\
This program is made available under the terms of the BSD Public License.\n\
See LICENSE file included with the distribution for details and disclaimer.");
out << std::endl;
diff --git a/src/interactive.cc b/src/interactive.cc
index 35382e8f..d0baf07a 100644
--- a/src/interactive.cc
+++ b/src/interactive.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/interactive.h b/src/interactive.h
index 199b7b71..fbc4ffeb 100644
--- a/src/interactive.h
+++ b/src/interactive.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/item.cc b/src/item.cc
index 8d1ba34f..14a0896f 100644
--- a/src/item.cc
+++ b/src/item.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -65,8 +65,8 @@ bool item_t::has_tag(const mask_t& tag_mask,
if (tag_mask.match(data.first)) {
if (! value_mask)
return true;
- else if (data.second)
- return value_mask->match(*data.second);
+ else if (data.second.first)
+ return value_mask->match(*data.second.first);
}
}
}
@@ -81,7 +81,7 @@ optional<string> item_t::get_tag(const string& tag) const
string_map::const_iterator i = metadata->find(tag);
if (i != metadata->end()) {
DEBUG("item.meta", "Found the item!");
- return (*i).second;
+ return (*i).second.first;
}
}
return none;
@@ -94,28 +94,44 @@ optional<string> item_t::get_tag(const mask_t& tag_mask,
foreach (const string_map::value_type& data, *metadata) {
if (tag_mask.match(data.first) &&
(! value_mask ||
- (data.second && value_mask->match(*data.second))))
- return data.second;
+ (data.second.first && value_mask->match(*data.second.first))))
+ return data.second.first;
}
}
return none;
}
-void item_t::set_tag(const string& tag,
- const optional<string>& value)
+item_t::string_map::iterator
+item_t::set_tag(const string& tag,
+ const optional<string>& value,
+ const bool overwrite_existing)
{
+ assert(! tag.empty());
+
if (! metadata)
metadata = string_map();
DEBUG("item.meta", "Setting tag '" << tag << "' to value '"
<< (value ? *value : string("<none>")) << "'");
- std::pair<string_map::iterator, bool> result
- = metadata->insert(string_map::value_type(tag, value));
- assert(result.second);
+ optional<string> data = value;
+ if (data && data->empty())
+ data = none;
+
+ string_map::iterator i = metadata->find(tag);
+ if (i == metadata->end()) {
+ std::pair<string_map::iterator, bool> result
+ = metadata->insert(string_map::value_type(tag, tag_data_t(data, false)));
+ assert(result.second);
+ return result.first;
+ } else {
+ if (overwrite_existing)
+ (*i).second = tag_data_t(data, false);
+ return i;
+ }
}
-void item_t::parse_tags(const char * p,
+void item_t::parse_tags(const char * p, bool overwrite_existing,
optional<date_t::year_type> current_year)
{
if (const char * b = std::strchr(p, '[')) {
@@ -149,15 +165,18 @@ void item_t::parse_tags(const char * p,
q = std::strtok(NULL, " \t")) {
const string::size_type len = std::strlen(q);
if (! tag.empty()) {
- if (! has_tag(tag))
- set_tag(tag, string(p + (q - buf.get())));
+ string_map::iterator i = set_tag(tag, string(p + (q - buf.get())),
+ overwrite_existing);
+ (*i).second.second = true;
break;
}
else if (q[0] == ':' && q[len - 1] == ':') { // a series of tags
for (char * r = std::strtok(q + 1, ":");
r;
- r = std::strtok(NULL, ":"))
- set_tag(r);
+ r = std::strtok(NULL, ":")) {
+ string_map::iterator i = set_tag(r, none, overwrite_existing);
+ (*i).second.second = true;
+ }
}
else if (q[len - 1] == ':') { // a metadata setting
tag = string(q, len - 1);
@@ -165,7 +184,7 @@ void item_t::parse_tags(const char * p,
}
}
-void item_t::append_note(const char * p,
+void item_t::append_note(const char * p, bool overwrite_existing,
optional<date_t::year_type> current_year)
{
if (note) {
@@ -175,7 +194,7 @@ void item_t::append_note(const char * p,
note = p;
}
- parse_tags(p, current_year);
+ parse_tags(p, overwrite_existing, current_year);
}
namespace {
diff --git a/src/item.h b/src/item.h
index f23350fc..7045c875 100644
--- a/src/item.h
+++ b/src/item.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -106,7 +106,8 @@ public:
enum state_t { UNCLEARED = 0, CLEARED, PENDING };
- typedef std::map<string, optional<string> > string_map;
+ typedef std::pair<optional<string>, bool> tag_data_t;
+ typedef std::map<string, tag_data_t> string_map;
state_t _state;
optional<date_t> _date;
@@ -156,12 +157,14 @@ public:
virtual optional<string> get_tag(const mask_t& tag_mask,
const optional<mask_t>& value_mask = none) const;
- virtual void set_tag(const string& tag,
- const optional<string>& value = none);
+ virtual string_map::iterator
+ set_tag(const string& tag,
+ const optional<string>& value = none,
+ const bool overwrite_existing = true);
- virtual void parse_tags(const char * p,
+ virtual void parse_tags(const char * p, bool overwrite_existing = true,
optional<date_t::year_type> current_year = none);
- virtual void append_note(const char * p,
+ virtual void append_note(const char * p, bool overwrite_existing = true,
optional<date_t::year_type> current_year = none);
static bool use_effective_date;
diff --git a/src/iterators.cc b/src/iterators.cc
index 540ba8ae..f3a68978 100644
--- a/src/iterators.cc
+++ b/src/iterators.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/iterators.h b/src/iterators.h
index 1cbe4c25..5e9f5fbe 100644
--- a/src/iterators.h
+++ b/src/iterators.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/journal.cc b/src/journal.cc
index 5aa2e7f7..158fac42 100644
--- a/src/journal.cc
+++ b/src/journal.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/journal.h b/src/journal.h
index 8d59e3b4..e54814aa 100644
--- a/src/journal.h
+++ b/src/journal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -44,6 +44,7 @@
#include "utils.h"
#include "times.h"
+#include "mask.h"
namespace ledger {
@@ -58,6 +59,11 @@ typedef std::list<xact_t *> xacts_list;
typedef std::list<auto_xact_t *> auto_xacts_list;
typedef std::list<period_xact_t *> period_xacts_list;
+typedef std::pair<mask_t, string> payee_mapping_t;
+typedef std::list<payee_mapping_t> payee_mappings_t;
+typedef std::pair<mask_t, account_t *> account_mapping_t;
+typedef std::list<account_mapping_t> account_mappings_t;
+
class journal_t : public noncopyable
{
public:
@@ -110,6 +116,8 @@ public:
period_xacts_list period_xacts;
std::list<fileinfo_t> sources;
bool was_loaded;
+ payee_mappings_t payee_mappings;
+ account_mappings_t account_mappings;
journal_t();
journal_t(const path& pathname);
diff --git a/src/lookup.cc b/src/lookup.cc
new file mode 100644
index 00000000..40b6c185
--- /dev/null
+++ b/src/lookup.cc
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <system.hh>
+
+#include "lookup.h"
+#include "unistring.h"
+
+namespace ledger {
+
+namespace {
+ typedef std::pair<xact_t *, int> score_entry_t;
+ typedef std::deque<score_entry_t> scorecard_t;
+ typedef std::map<uint32_t, std::size_t> char_positions_map;
+
+ struct score_sorter {
+ bool operator()(const score_entry_t& left,
+ const score_entry_t& right) const {
+ return left.second > right.second;
+ }
+ };
+
+ typedef std::map<account_t *, int> account_use_map;
+ typedef std::pair<account_t *, int> account_use_pair;
+
+ struct usage_sorter {
+ bool operator()(const account_use_pair& left,
+ const account_use_pair& right) const {
+ return left.second > right.second;
+ }
+ };
+}
+
+std::pair<xact_t *, account_t *>
+lookup_probable_account(const string& ident,
+ xacts_iterator& iter_func,
+ account_t * ref_account)
+{
+ scorecard_t scores;
+
+#if !defined(HAVE_BOOST_REGEX_UNICODE)
+ string lident = ident;
+ to_lower(lident);
+ unistring lowered_ident(lident);
+#else
+ // jww (2010-03-07): Not yet implemented
+ unistring lowered_ident(ident);
+#endif
+
+ DEBUG("lookup.account",
+ "Looking up identifier '" << lowered_ident.extract() << "'");
+#if defined(DEBUG_ON)
+ if (ref_account != NULL)
+ DEBUG("lookup.account",
+ " with reference account: " << ref_account->fullname());
+#endif
+
+ while (xact_t * xact = iter_func()) {
+#if 0
+ // Only consider transactions from the last two years (jww (2010-03-07):
+ // make this an option)
+ if ((CURRENT_DATE() - xact->date()).days() > 700)
+ continue;
+#endif
+
+ // An exact match is worth a score of 100 and terminates the search
+ if (ident == xact->payee) {
+ DEBUG("lookup", " we have an exact match, score = 100");
+ scores.push_back(score_entry_t(xact, 100));
+ break;
+ }
+
+#if !defined(HAVE_BOOST_REGEX_UNICODE)
+ string payee = xact->payee;
+ to_lower(payee);
+ unistring value_key(payee);
+#else
+ // jww (2010-03-07): Not yet implemented
+ unistring value_key(xact->payee);
+#endif
+
+ DEBUG("lookup", "Considering payee: " << value_key.extract());
+
+ std::size_t index = 0;
+ std::size_t last_match_pos = unistring::npos;
+ int bonus = 0;
+ int score = 0;
+ std::size_t pos;
+ char_positions_map positions;
+
+ // Walk each letter in the source identifier
+ foreach (const uint32_t& ch, lowered_ident.utf32chars) {
+ int addend = 0;
+ bool added_bonus = false;
+ std::size_t value_len = value_key.length();
+
+ pos = value_key.find(ch);
+
+ // Ensure that a letter which has been matched is not matched twice, so
+ // that the two x's of Exxon don't both match to the single x in Oxford.
+ // This part of the loop is very expensive, but avoids a lot of bogus
+ // matches.
+
+ char_positions_map::iterator pi = positions.find(ch);
+ while (pi != positions.end() &&
+ pos != unistring::npos && pos <= (*pi).second &&
+ (*pi).second + 1 < value_len)
+ pos = value_key.find(ch, (*pi).second + 1);
+
+ if (pos != unistring::npos) {
+ if (pi != positions.end())
+ (*pi).second = pos;
+ else
+ positions.insert(char_positions_map::value_type(ch, pos));
+
+ // If it occurs in the same order as the source identifier -- that is,
+ // without intervening letters to break the pattern -- it's worth 10
+ // points. Plus, an extra point is added for every letter in chains
+ // of 3 or more.
+
+ if (last_match_pos == unistring::npos ?
+ index == 0 && pos == 0 : pos == last_match_pos + 1) {
+ DEBUG("lookup",
+ " char " << index << " in-sequence match with bonus " << bonus);
+ addend += 10;
+ if (bonus > 2)
+ addend += bonus - 2;
+ bonus++;
+ added_bonus = true;
+
+ last_match_pos = pos;
+ }
+
+ // If it occurs in the same general sequence as the source identifier,
+ // it's worth 5 points, plus an extra point if it's within the next 3
+ // characters, and an extra point if it's preceded by a non-alphabetic
+ // character.
+ //
+ // If the letter occurs at all in the target identifier, it's worth 1
+ // point, plus an extra point if it's within 3 characters, and an
+ // extra point if it's preceded by a non-alphabetic character.
+
+ else {
+ bool in_order_match = (last_match_pos != unistring::npos &&
+ pos > last_match_pos);
+ DEBUG("lookup", " char " << index << " " <<
+ (in_order_match ? "in-order" : "out-of-order")
+ << " match" << (in_order_match && pos - index < 3 ?
+ " with proximity bonus of 1" : ""));
+
+ if (pos < index)
+ addend += 1;
+ else
+ addend += 5;
+
+ if (in_order_match && pos - index < 3)
+ addend++;
+
+#if !defined(HAVE_BOOST_REGEX_UNICODE)
+ if (pos == 0 || (pos > 0 && !std::isalnum(value_key[pos - 1])))
+ addend++;
+#else
+ // jww (2010-03-07): Not yet implemented
+#endif
+
+ last_match_pos = pos;
+ }
+
+ // If the letter does not appear at all, decrease the score by 1
+
+ } else {
+ last_match_pos = unistring::npos;
+
+ DEBUG("lookup", " char " << index << " does not match");
+ addend--;
+ }
+
+ // Finally, decay what is to be added to the score based on its position
+ // in the word. Since credit card payees in particular often share
+ // information at the end (such as the location where the purchase was
+ // made), we want to give much more credence to what occurs at the
+ // beginning. Every 5 character positions from the beginning becomes a
+ // divisor for the addend.
+
+ if ((int(index / 5) + 1) > 1) {
+ DEBUG("lookup",
+ " discounting the addend by / " << (int(index / 5) + 1));
+ addend = int(double(addend) / (int(index / 5) + 1));
+ }
+
+ DEBUG("lookup", " final addend is " << addend);
+ score += addend;
+ DEBUG("lookup", " score is " << score);
+
+ if (! added_bonus)
+ bonus = 0;
+
+ index++;
+ }
+
+ // Only consider payees with a score of 30 or greater
+ if (score >= 30)
+ scores.push_back(score_entry_t(xact, score));
+ }
+
+ // Sort the results by descending score, then look at every account ever
+ // used among the top five. Rank these by number of times used. Lastly,
+ // "decay" any latter accounts, so that we give recently used accounts a
+ // slightly higher rating in case of a tie.
+
+ std::stable_sort(scores.begin(), scores.end(), score_sorter());
+
+ scorecard_t::iterator si = scores.begin();
+ int decay = 0;
+ xact_t * best_xact = si != scores.end() ? (*si).first : NULL;
+ account_use_map account_usage;
+
+ for (int i = 0; i < 5 && si != scores.end(); i++, si++) {
+ DEBUG("lookup.account",
+ "Payee: " << std::setw(5) << std::right << (*si).second <<
+ " - " << (*si).first->payee);
+
+ foreach (post_t * post, (*si).first->posts) {
+ if (! post->has_flags(ITEM_TEMP | ITEM_GENERATED) &&
+ post->account != ref_account &&
+ ! post->account->has_flags(ACCOUNT_TEMP | ACCOUNT_GENERATED)) {
+ account_use_map::iterator x = account_usage.find(post->account);
+ if (x == account_usage.end())
+ account_usage.insert(account_use_pair(post->account,
+ ((*si).second - decay)));
+ else
+ (*x).second += ((*si).second - decay);
+ }
+ decay++;
+ }
+ }
+
+ if (account_usage.size() > 0) {
+#if defined(DEBUG_ON)
+ if (SHOW_DEBUG("lookup.account")) {
+ foreach (const account_use_pair& value, account_usage) {
+ DEBUG("lookup.account",
+ "Account: " << value.second << " - " << value.first->fullname());
+ }
+ }
+#endif
+ return std::pair<xact_t *, account_t *>
+ (best_xact, (*std::max_element(account_usage.begin(), account_usage.end(),
+ usage_sorter())).first);
+ } else {
+ return std::pair<xact_t *, account_t *>(best_xact, NULL);
+ }
+}
+
+} // namespace ledger
diff --git a/src/lookup.h b/src/lookup.h
new file mode 100644
index 00000000..53cb5837
--- /dev/null
+++ b/src/lookup.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file lookup.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _LOOKUP_H
+#define _LOOKUP_H
+
+#include "iterators.h"
+
+namespace ledger {
+
+std::pair<xact_t *, account_t *>
+lookup_probable_account(const string& ident,
+ xacts_iterator& iter_func,
+ account_t * ref_account = NULL);
+
+} // namespace ledger
+
+#endif // _LOOKUP_H
diff --git a/src/main.cc b/src/main.cc
index 0aec8886..23593533 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/mask.cc b/src/mask.cc
index c1e66ced..cd516fe2 100644
--- a/src/mask.cc
+++ b/src/mask.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -52,4 +52,38 @@ mask_t& mask_t::operator=(const string& pat)
return *this;
}
+mask_t& mask_t::assign_glob(const string& pat)
+{
+ string re_pat = "";
+ string::size_type len = pat.length();
+ for (string::size_type i = 0; i < len; i++) {
+ switch (pat[i]) {
+ case '?':
+ re_pat += '.';
+ break;
+ case '*':
+ re_pat += ".*";
+ break;
+ case '[':
+ while (i < len && pat[i] != ']')
+ re_pat += pat[i++];
+ if (i < len)
+ re_pat += pat[i];
+ break;
+
+ case '\\':
+ if (i + 1 < len) {
+ re_pat += pat[++i];
+ break;
+ } else {
+ // fallthrough...
+ }
+ default:
+ re_pat += pat[i];
+ break;
+ }
+ }
+ return (*this = re_pat);
+}
+
} // namespace ledger
diff --git a/src/mask.h b/src/mask.h
index 4608898f..ed9e8ac1 100644
--- a/src/mask.h
+++ b/src/mask.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -73,7 +73,11 @@ public:
}
mask_t& operator=(const string& other);
+ mask_t& assign_glob(const string& other);
+ bool operator<(const mask_t& other) const {
+ return expr < other.expr;
+ }
bool operator==(const mask_t& other) const {
return expr == other.expr;
}
diff --git a/src/op.cc b/src/op.cc
index f38fc86b..4020ecff 100644
--- a/src/op.cc
+++ b/src/op.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/op.h b/src/op.h
index 347eac1d..6a69527b 100644
--- a/src/op.h
+++ b/src/op.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/option.cc b/src/option.cc
index d2ec8808..b375dd8d 100644
--- a/src/option.cc
+++ b/src/option.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/option.h b/src/option.h
index b81c2ce7..9688171e 100644
--- a/src/option.h
+++ b/src/option.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/output.cc b/src/output.cc
index bb7eff5c..30775310 100644
--- a/src/output.cc
+++ b/src/output.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -42,10 +42,8 @@ namespace ledger {
format_posts::format_posts(report_t& _report,
const string& format,
- bool _print_raw,
const optional<string>& _prepend_format)
- : report(_report), last_xact(NULL), last_post(NULL),
- print_raw(_print_raw)
+ : report(_report), last_xact(NULL), last_post(NULL)
{
TRACE_CTOR(format_posts, "report&, const string&, bool");
@@ -80,24 +78,8 @@ void format_posts::operator()(post_t& post)
{
std::ostream& out(report.output_stream);
- if (print_raw) {
- if (! post.has_xdata() ||
- ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
- if (last_xact != post.xact) {
- if (last_xact) {
- bind_scope_t xact_scope(report, *last_xact);
- out << between_format(xact_scope);
- }
- print_item(out, *post.xact);
- out << '\n';
- last_xact = post.xact;
- }
- post.xdata().add_flags(POST_EXT_DISPLAYED);
- last_post = &post;
- }
- }
- else if (! post.has_xdata() ||
- ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
+ if (! post.has_xdata() ||
+ ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
bind_scope_t bound_scope(report, post);
if (prepend_format)
diff --git a/src/output.h b/src/output.h
index 778a9335..7618e567 100644
--- a/src/output.h
+++ b/src/output.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -63,11 +63,9 @@ protected:
format_t prepend_format;
xact_t * last_xact;
post_t * last_post;
- bool print_raw;
public:
format_posts(report_t& _report, const string& format,
- bool _print_raw = false,
const optional<string>& _prepend_format = none);
virtual ~format_posts() {
TRACE_DTOR(format_posts);
diff --git a/src/parser.cc b/src/parser.cc
index ef778411..5bb06f84 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/parser.h b/src/parser.h
index 7a69fe08..5eba4ffd 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pool.cc b/src/pool.cc
index f895a8bc..8d9f0c28 100644
--- a/src/pool.cc
+++ b/src/pool.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pool.h b/src/pool.h
index 995ab23c..915def16 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/post.cc b/src/post.cc
index 43cfe55f..41ae04dd 100644
--- a/src/post.cc
+++ b/src/post.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -576,7 +576,7 @@ void to_xml(std::ostream& out, const post_t& post)
if (post.metadata) {
push_xml y(out, "metadata");
foreach (const item_t::string_map::value_type& pair, *post.metadata) {
- if (pair.second) {
+ if (pair.second.first) {
push_xml z(out, "variable");
{
push_xml z(out, "key");
@@ -584,7 +584,7 @@ void to_xml(std::ostream& out, const post_t& post)
}
{
push_xml z(out, "value");
- out << y.guard(*pair.second);
+ out << y.guard(*pair.second.first);
}
} else {
push_xml z(out, "tag");
diff --git a/src/post.h b/src/post.h
index 8852e7b2..272cd9d8 100644
--- a/src/post.h
+++ b/src/post.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -52,10 +52,11 @@ class account_t;
class post_t : public item_t
{
public:
-#define POST_VIRTUAL 0x10 // the account was specified with (parens)
-#define POST_MUST_BALANCE 0x20 // posting must balance in the transaction
-#define POST_CALCULATED 0x40 // posting's amount was calculated
-#define POST_COST_CALCULATED 0x80 // posting's cost was calculated
+#define POST_VIRTUAL 0x08 // the account was specified with (parens)
+#define POST_MUST_BALANCE 0x10 // posting must balance in the transaction
+#define POST_CALCULATED 0x20 // posting's amount was calculated
+#define POST_COST_CALCULATED 0x40 // posting's cost was calculated
+#define POST_COST_IN_FULL 0x80 // cost specified using @@
xact_t * xact; // only set for posts of regular xacts
account_t * account;
diff --git a/src/precmd.cc b/src/precmd.cc
index 632caeae..e545a783 100644
--- a/src/precmd.cc
+++ b/src/precmd.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/precmd.h b/src/precmd.h
index 88d66ab2..277933c3 100644
--- a/src/precmd.h
+++ b/src/precmd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/predicate.cc b/src/predicate.cc
index 4da4decf..369120e6 100644
--- a/src/predicate.cc
+++ b/src/predicate.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/predicate.h b/src/predicate.h
index b3b81f9b..c21167d7 100644
--- a/src/predicate.h
+++ b/src/predicate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/print.cc b/src/print.cc
new file mode 100644
index 00000000..eb102a87
--- /dev/null
+++ b/src/print.cc
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <system.hh>
+
+#include "print.h"
+#include "xact.h"
+#include "post.h"
+#include "account.h"
+#include "session.h"
+#include "report.h"
+
+namespace ledger {
+
+print_xacts::print_xacts(report_t& _report,
+ bool _print_raw)
+ : report(_report), print_raw(_print_raw)
+{
+ TRACE_CTOR(print_xacts, "report&, bool");
+}
+
+namespace {
+ void print_note(std::ostream& out, const string& note)
+ {
+ if (note.length() > 15)
+ out << "\n ;";
+ else
+ out << " ;";
+
+ bool need_separator = false;
+ for (const char * p = note.c_str(); *p; p++) {
+ if (*p == '\n') {
+ need_separator = true;
+ } else {
+ if (need_separator) {
+ out << "\n ;";
+ need_separator = false;
+ }
+ out << *p;
+ }
+ }
+ }
+
+ void print_xact(report_t& report, std::ostream& out, xact_t& xact)
+ {
+ out << format_date(item_t::use_effective_date ?
+ xact.date() : xact.actual_date(),
+ FMT_WRITTEN);
+ if (! item_t::use_effective_date && xact.effective_date())
+ out << '=' << format_date(*xact.effective_date(), FMT_WRITTEN);
+ out << ' ';
+
+ out << (xact.state() == item_t::CLEARED ? "* " :
+ (xact.state() == item_t::PENDING ? "! " : ""));
+
+ if (xact.code)
+ out << '(' << *xact.code << ") ";
+
+ out << xact.payee;
+
+ if (xact.note)
+ print_note(out, *xact.note);
+ out << '\n';
+
+ if (xact.metadata) {
+ foreach (const item_t::string_map::value_type& data, *xact.metadata) {
+ if (! data.second.second) {
+ out << " ; ";
+ if (data.second.first)
+ out << data.first << ": " << *data.second.first;
+ else
+ out << ':' << data.first << ":";
+ out << '\n';
+ }
+ }
+ }
+
+ foreach (post_t * post, xact.posts) {
+ if (post->has_flags(ITEM_TEMP | ITEM_GENERATED) &&
+ ! report.HANDLED(print_virtual))
+ continue;
+
+ out << " ";
+
+ std::ostringstream buf;
+
+ if (xact.state() == item_t::UNCLEARED)
+ buf << (post->state() == item_t::CLEARED ? "* " :
+ (post->state() == item_t::PENDING ? "! " : ""));
+
+ if (post->has_flags(POST_VIRTUAL)) {
+ if (post->has_flags(POST_MUST_BALANCE))
+ buf << '[';
+ else
+ buf << '(';
+ }
+
+ buf << post->account->fullname();
+
+ if (post->has_flags(POST_VIRTUAL)) {
+ if (post->has_flags(POST_MUST_BALANCE))
+ buf << ']';
+ else
+ buf << ')';
+ }
+
+ if (! post->has_flags(POST_CALCULATED) || report.HANDLED(print_virtual)) {
+ unistring name(buf.str());
+
+ out << name.extract();
+ int slip = 36 - static_cast<int>(name.length());
+ if (slip > 0)
+ out << string(slip, ' ');
+
+ std::ostringstream amt_str;
+ report.scrub(post->amount).print(amt_str, 12, -1, true);
+ string amt = amt_str.str();
+ string trimmed_amt(amt);
+ trim_left(trimmed_amt);
+ int amt_slip = (static_cast<int>(amt.length()) -
+ static_cast<int>(trimmed_amt.length()));
+ if (slip + amt_slip < 2)
+ out << string(2 - (slip + amt_slip), ' ');
+ out << amt;
+
+ if (post->cost && ! post->has_flags(POST_CALCULATED)) {
+ if (post->has_flags(POST_COST_IN_FULL))
+ out << " @@ " << report.scrub(post->cost->abs());
+ else
+ out << " @ " << report.scrub((*post->cost / post->amount).abs());
+ }
+
+ if (post->assigned_amount)
+ out << " = " << report.scrub(*post->assigned_amount);
+ } else {
+ out << buf.str();
+ }
+
+ if (post->note)
+ print_note(out, *post->note);
+ out << '\n';
+ }
+ }
+}
+
+void print_xacts::flush()
+{
+ std::ostream& out(report.output_stream);
+
+ bool first = true;
+ foreach (xact_t * xact, xacts) {
+ if (first)
+ first = false;
+ else
+ out << '\n';
+
+ if (print_raw) {
+ print_item(out, *xact);
+ out << '\n';
+ } else {
+ print_xact(report, out, *xact);
+ }
+ }
+
+ out.flush();
+}
+
+void print_xacts::operator()(post_t& post)
+{
+ if (! post.has_xdata() ||
+ ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
+ if (xacts_present.find(post.xact) == xacts_present.end()) {
+ xacts_present.insert(xacts_present_map::value_type(post.xact, true));
+ xacts.push_back(post.xact);
+ }
+ post.xdata().add_flags(POST_EXT_DISPLAYED);
+ }
+}
+
+} // namespace ledger
diff --git a/src/print.h b/src/print.h
new file mode 100644
index 00000000..f323b153
--- /dev/null
+++ b/src/print.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @addtogroup data
+ */
+
+/**
+ * @file convert.h
+ * @author John Wiegley
+ *
+ * @ingroup data
+ */
+#ifndef _PRINT_H
+#define _PRINT_H
+
+#include "chain.h"
+#include "predicate.h"
+#include "format.h"
+
+namespace ledger {
+
+class xact_t;
+class post_t;
+class report_t;
+
+class print_xacts : public item_handler<post_t>
+{
+protected:
+ typedef std::list<xact_t *> xacts_list;
+ typedef std::map<xact_t *, bool> xacts_present_map;
+
+ report_t& report;
+ xacts_present_map xacts_present;
+ xacts_list xacts;
+ bool print_raw;
+
+public:
+ print_xacts(report_t& _report, bool _print_raw = false);
+ virtual ~print_xacts() {
+ TRACE_DTOR(print_xacts);
+ }
+
+ virtual void flush();
+ virtual void operator()(post_t& post);
+};
+
+
+} // namespace ledger
+
+#endif // _PRINT_H
diff --git a/src/pstream.h b/src/pstream.h
index 00caf4e0..bba2845e 100644
--- a/src/pstream.h
+++ b/src/pstream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/py_account.cc b/src/py_account.cc
index 056cd722..3114cc0b 100644
--- a/src/py_account.cc
+++ b/src/py_account.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_amount.cc b/src/py_amount.cc
index 8fb507a3..5afe8c6b 100644
--- a/src/py_amount.cc
+++ b/src/py_amount.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_balance.cc b/src/py_balance.cc
index 8c0c4c58..7be75444 100644
--- a/src/py_balance.cc
+++ b/src/py_balance.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_commodity.cc b/src/py_commodity.cc
index 984be5f0..22a4f153 100644
--- a/src/py_commodity.cc
+++ b/src/py_commodity.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_expr.cc b/src/py_expr.cc
index cad2c0fa..027125e2 100644
--- a/src/py_expr.cc
+++ b/src/py_expr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_format.cc b/src/py_format.cc
index d4825b42..36f89ae5 100644
--- a/src/py_format.cc
+++ b/src/py_format.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_item.cc b/src/py_item.cc
index 8a6e495a..edebd532 100644
--- a/src/py_item.cc
+++ b/src/py_item.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_journal.cc b/src/py_journal.cc
index 5be9cbe1..81ce290d 100644
--- a/src/py_journal.cc
+++ b/src/py_journal.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_post.cc b/src/py_post.cc
index 20cdba6b..e4a50980 100644
--- a/src/py_post.cc
+++ b/src/py_post.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_times.cc b/src/py_times.cc
index a62bb9b6..39b0df7a 100644
--- a/src/py_times.cc
+++ b/src/py_times.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_utils.cc b/src/py_utils.cc
index 5203599f..4b364e5d 100644
--- a/src/py_utils.cc
+++ b/src/py_utils.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_value.cc b/src/py_value.cc
index 713dc3d4..449320ec 100644
--- a/src/py_value.cc
+++ b/src/py_value.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_xact.cc b/src/py_xact.cc
index 59c599d9..c4e1fd32 100644
--- a/src/py_xact.cc
+++ b/src/py_xact.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pyfstream.h b/src/pyfstream.h
index 3da37523..02e4d240 100644
--- a/src/pyfstream.h
+++ b/src/pyfstream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
index 0701176f..1330fc5c 100644
--- a/src/pyinterp.cc
+++ b/src/pyinterp.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pyinterp.h b/src/pyinterp.h
index f2d7b760..e3a091ad 100644
--- a/src/pyinterp.h
+++ b/src/pyinterp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pyledger.cc b/src/pyledger.cc
index cf7e1527..4a53532a 100644
--- a/src/pyledger.cc
+++ b/src/pyledger.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pyutils.h b/src/pyutils.h
index 54d6fa28..e0f77003 100644
--- a/src/pyutils.h
+++ b/src/pyutils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/query.cc b/src/query.cc
index cfa321b0..1f086df8 100644
--- a/src/query.cc
+++ b/src/query.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/query.h b/src/query.h
index ebc14020..2b0bc75d 100644
--- a/src/query.h
+++ b/src/query.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/quotes.cc b/src/quotes.cc
index f892e93f..4e3ec33e 100644
--- a/src/quotes.cc
+++ b/src/quotes.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/quotes.h b/src/quotes.h
index d00c5bfd..e981fdad 100644
--- a/src/quotes.h
+++ b/src/quotes.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/report.cc b/src/report.cc
index b882ca92..2189812b 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -37,12 +37,14 @@
#include "format.h"
#include "query.h"
#include "output.h"
+#include "print.h"
#include "iterators.h"
#include "filters.h"
#include "precmd.h"
#include "stats.h"
#include "generate.h"
#include "draft.h"
+#include "convert.h"
#include "xml.h"
#include "emacs.h"
@@ -91,6 +93,33 @@ void report_t::normalize_options(const string& verb)
start_of_week = *weekday;
}
+ long meta_width = -1;
+
+ if (! HANDLED(prepend_format_) && HANDLED(meta_)) {
+ if (! HANDLED(meta_width_)) {
+ string::size_type i = HANDLER(meta_).str().find(':');
+ if (i != string::npos) {
+ HANDLED(meta_width_).on_with
+ (string("?normalize"),
+ lexical_cast<long>(string(HANDLER(meta_).str(), i + 1)));
+ HANDLED(meta_).on(string("?normalize"),
+ string(HANDLER(meta_).str(), 0, i));
+ }
+ }
+ if (HANDLED(meta_width_)) {
+ HANDLER(prepend_format_).on
+ (string("?normalize"),
+ string("%(justify(truncated(tag(\"") +
+ HANDLER(meta_).str() + "\"), " +
+ HANDLED(meta_width_).value.to_string() + " - 1), " +
+ HANDLED(meta_width_).value.to_string() + "))");
+ meta_width = HANDLED(meta_width_).value.to_long();
+ } else {
+ HANDLER(prepend_format_).on(string("?normalize"), string("%(tag(\"") +
+ HANDLER(meta_).str() + "\"))");
+ }
+ }
+
if (verb == "print" || verb == "xact" || verb == "dump") {
HANDLER(related).on_only(string("?normalize"));
HANDLER(related_all).on_only(string("?normalize"));
@@ -163,6 +192,9 @@ void report_t::normalize_options(const string& verb)
else
cols = 80L;
+ if (meta_width > 0)
+ cols -= meta_width;
+
if (cols > 0) {
DEBUG("auto.columns", "cols = " << cols);
@@ -185,11 +217,11 @@ void report_t::normalize_options(const string& verb)
HANDLER(total_width_).value.to_long() :
amount_width);
- DEBUG("auto.columns", "date_width = " << date_width);
- DEBUG("auto.columns", "payee_width = " << payee_width);
+ DEBUG("auto.columns", "date_width = " << date_width);
+ DEBUG("auto.columns", "payee_width = " << payee_width);
DEBUG("auto.columns", "account_width = " << account_width);
- DEBUG("auto.columns", "amount_width = " << amount_width);
- DEBUG("auto.columns", "total_width = " << total_width);
+ DEBUG("auto.columns", "amount_width = " << amount_width);
+ DEBUG("auto.columns", "total_width = " << total_width);
if (! HANDLER(date_width_).specified &&
! HANDLER(payee_width_).specified &&
@@ -205,6 +237,8 @@ void report_t::normalize_options(const string& verb)
}
}
+ if (! HANDLED(meta_width_))
+ HANDLER(meta_width_).on_with(string("?normalize"), 0L);
if (! HANDLER(date_width_).specified)
HANDLER(date_width_).on_with(string("?normalize"), date_width);
if (! HANDLER(payee_width_).specified)
@@ -409,15 +443,20 @@ value_t report_t::fn_trim(call_scope_t& args)
}
}
-value_t report_t::fn_scrub(call_scope_t& args)
+value_t report_t::scrub(value_t val)
{
- value_t temp(args.value().strip_annotations(what_to_keep()));
+ value_t temp(val.strip_annotations(what_to_keep()));
if (HANDLED(base))
return temp;
else
return temp.unreduced();
}
+value_t report_t::fn_scrub(call_scope_t& args)
+{
+ return scrub(args.value());
+}
+
value_t report_t::fn_rounded(call_scope_t& args)
{
return args.value().rounded();
@@ -469,11 +508,11 @@ value_t report_t::fn_justify(call_scope_t& scope)
value_t report_t::fn_quoted(call_scope_t& scope)
{
- interactive_t args(scope, "s");
+ interactive_t args(scope, "v");
std::ostringstream out;
out << '"';
- foreach (const char ch, args.get<string>(0)) {
+ foreach (const char ch, args.value_at(0).to_string()) {
if (ch == '"')
out << "\\\"";
else
@@ -855,6 +894,8 @@ option_t<report_t> * report_t::lookup_option(const char * p)
case 'm':
OPT(market);
else OPT(monthly);
+ else OPT(meta_);
+ else OPT(meta_width_);
break;
case 'n':
OPT_CH(collapse);
@@ -879,9 +920,9 @@ option_t<report_t> * report_t::lookup_option(const char * p)
else OPT(price);
else OPT(prices_format_);
else OPT(pricedb_format_);
- else OPT(print_format_);
else OPT(payee_width_);
else OPT(prepend_format_);
+ else OPT(print_virtual);
break;
case 'q':
OPT(quantity);
@@ -1199,21 +1240,21 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
else if (is_eq(p, "cleared")) {
HANDLER(amount_).set_expr(string("#cleared"),
"(amount, cleared ? amount : 0)");
-
return expr_t::op_t::wrap_functor
(reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
(new format_accounts(*this, report_format(HANDLER(cleared_format_)),
maybe_format(HANDLER(prepend_format_))),
*this, "#cleared"));
}
+ else if (is_eq(p, "convert"))
+ return WRAP_FUNCTOR(convert_command);
break;
case 'e':
- if (is_eq(p, "equity"))
- return WRAP_FUNCTOR
- (reporter<>
- (new format_posts(*this, report_format(HANDLER(print_format_))),
- *this, "#equity"));
+ if (is_eq(p, "equity")) {
+ HANDLER(print_virtual).on_only(string("#equity"));
+ return WRAP_FUNCTOR(reporter<>(new print_xacts(*this), *this, "#equity"));
+ }
else if (is_eq(p, "entry"))
return WRAP_FUNCTOR(xact_command);
else if (is_eq(p, "emacs"))
@@ -1226,9 +1267,7 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
case 'p':
if (*(p + 1) == '\0' || is_eq(p, "print"))
return WRAP_FUNCTOR
- (reporter<>
- (new format_posts(*this, report_format(HANDLER(print_format_)),
- HANDLED(raw)), *this, "#print"));
+ (reporter<>(new print_xacts(*this, HANDLED(raw)), *this, "#print"));
else if (is_eq(p, "prices"))
return expr_t::op_t::wrap_functor
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
@@ -1248,7 +1287,7 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
return WRAP_FUNCTOR
(reporter<>
(new format_posts(*this, report_format(HANDLER(register_format_)),
- false, maybe_format(HANDLER(prepend_format_))),
+ maybe_format(HANDLER(prepend_format_))),
*this, "#register"));
else if (is_eq(p, "reload"))
return MAKE_FUNCTOR(report_t::reload_command);
@@ -1283,11 +1322,13 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
return WRAP_FUNCTOR(format_command);
break;
case 'g':
- if (is_eq(p, "generate"))
+ if (is_eq(p, "generate")) {
+ HANDLER(print_virtual).on_only(string("#generate"));
return expr_t::op_t::wrap_functor
(reporter<post_t, post_handler_ptr, &report_t::generate_report>
- (new format_posts(*this, report_format(HANDLER(print_format_)),
- false), *this, "#generate"));
+ (new print_xacts(*this), *this, "#generate"));
+ }
+ break;
case 'p':
if (is_eq(p, "parse"))
return WRAP_FUNCTOR(parse_command);
diff --git a/src/report.h b/src/report.h
index 08819e23..50071940 100644
--- a/src/report.h
+++ b/src/report.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -144,6 +144,7 @@ public:
value_t fn_is_seq(call_scope_t& scope);
value_t fn_strip(call_scope_t& scope);
value_t fn_trim(call_scope_t& scope);
+ value_t scrub(value_t val);
value_t fn_scrub(call_scope_t& scope);
value_t fn_quantity(call_scope_t& scope);
value_t fn_rounded(call_scope_t& scope);
@@ -263,6 +264,7 @@ public:
HANDLER(lots).report(out);
HANDLER(lots_actual).report(out);
HANDLER(market).report(out);
+ HANDLER(meta_).report(out);
HANDLER(monthly).report(out);
HANDLER(no_total).report(out);
HANDLER(now_).report(out);
@@ -280,7 +282,7 @@ public:
HANDLER(price).report(out);
HANDLER(prices_format_).report(out);
HANDLER(pricedb_format_).report(out);
- HANDLER(print_format_).report(out);
+ HANDLER(print_virtual).report(out);
HANDLER(quantity).report(out);
HANDLER(quarterly).report(out);
HANDLER(raw).report(out);
@@ -311,6 +313,7 @@ public:
HANDLER(weekly).report(out);
HANDLER(wide).report(out);
HANDLER(yearly).report(out);
+ HANDLER(meta_width_).report(out);
HANDLER(date_width_).report(out);
HANDLER(payee_width_).report(out);
HANDLER(account_width_).report(out);
@@ -618,6 +621,8 @@ public:
.set_expr(string("--market"), "market(total_expr, date, exchange)");
});
+ OPTION(report_t, meta_);
+
OPTION_(report_t, monthly, DO() { // -M
parent->HANDLER(period_).on(string("--monthly"), "monthly");
});
@@ -748,23 +753,7 @@ public:
"P %(datetime) %(account) %(scrub(display_amount))\n");
});
- OPTION__(report_t, print_format_, CTOR(report_t, print_format_) {
- on(none,
- "%(xact.date)"
- "%(!effective & xact.effective_date ?"
- " \"=\" + xact.effective_date : \"\")"
- "%(xact.cleared ? \" *\" : (xact.pending ? \" !\" : \"\"))"
- "%(code ? \" (\" + code + \")\" :"
- " \"\") %(payee)%(xact.comment)\n"
- " %(xact.uncleared ?"
- " (cleared ? \"* \" : (pending ? \"! \" : \"\")) : \"\")"
- "%(calculated ? account : justify(account, 34, -1, false))"
- "%(calculated ? \"\" : \" \" + justify(scrub(amount), 12, -1, true))"
- "%(has_cost & !cost_calculated ?"
- " \" @ \" + justify(scrub(abs(cost / amount)), 0) : \"\")"
- "%(comment)\n%/"
- " %$7%$8%$9%$A%$B\n%/\n");
- });
+ OPTION(report_t, print_virtual);
OPTION_(report_t, quantity, DO() { // -O
parent->HANDLER(revalued).off();
@@ -791,12 +780,13 @@ public:
" %(ansify_if(justify(truncated(account, account_width, abbrev_len), "
" account_width), blue if color))"
" %(justify(scrub(display_amount), amount_width, "
- " 3 + date_width + payee_width + account_width + amount_width, "
- " true, color))"
+ " 3 + meta_width + date_width + payee_width + account_width"
+ " + amount_width, true, color))"
" %(justify(scrub(display_total), total_width, "
- " 4 + date_width + payee_width + account_width + amount_width "
- " + total_width, true, color))\n%/"
- "%(justify(\" \", 2 + date_width + payee_width))%$3 %$4 %$5\n");
+ " 4 + meta_width + date_width + payee_width + account_width"
+ " + amount_width + total_width, true, color))\n%/"
+ "%(justify(\" \", 2 + date_width + payee_width))"
+ "%$3 %$4 %$5\n");
});
OPTION(report_t, related); // -r
@@ -906,6 +896,10 @@ public:
parent->HANDLER(period_).on(string("--yearly"), "yearly");
});
+ OPTION__(report_t, meta_width_,
+ bool specified;
+ CTOR(report_t, meta_width_) { specified = false; }
+ DO_(args) { value = args[1].to_long(); specified = true; });
OPTION__(report_t, date_width_,
bool specified;
CTOR(report_t, date_width_) { specified = false; }
diff --git a/src/scope.cc b/src/scope.cc
index 64736ca3..72cf4ad3 100644
--- a/src/scope.cc
+++ b/src/scope.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/scope.h b/src/scope.h
index 93f80230..675fa4e1 100644
--- a/src/scope.h
+++ b/src/scope.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/session.cc b/src/session.cc
index 1882e554..8e5536b0 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/session.h b/src/session.h
index 5c4612a0..de1771ad 100644
--- a/src/session.h
+++ b/src/session.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/stats.cc b/src/stats.cc
index b89a5949..86a8338d 100644
--- a/src/stats.cc
+++ b/src/stats.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/stats.h b/src/stats.h
index d2d10de6..b7bf94c5 100644
--- a/src/stats.h
+++ b/src/stats.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/stream.cc b/src/stream.cc
index e39b74e0..272d4f1c 100644
--- a/src/stream.cc
+++ b/src/stream.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/stream.h b/src/stream.h
index e87da67a..356df08c 100644
--- a/src/stream.h
+++ b/src/stream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/system.hh.in b/src/system.hh.in
index 341ce129..5de7150e 100644
--- a/src/system.hh.in
+++ b/src/system.hh.in
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -136,8 +136,7 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <editline/readline.h>
#endif
-#include <boost/algorithm/string/classification.hpp>
-#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string.hpp>
#include <boost/bind.hpp>
#include <boost/cast.hpp>
#include <boost/current_function.hpp>
diff --git a/src/temps.cc b/src/temps.cc
index fd099e9a..68b9ffa0 100644
--- a/src/temps.cc
+++ b/src/temps.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/temps.h b/src/temps.h
index 4243079c..ac6d08cd 100644
--- a/src/temps.h
+++ b/src/temps.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/textual.cc b/src/textual.cc
index 8953d2b8..dfca7943 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -144,6 +144,8 @@ namespace {
void end_directive(char * line);
void alias_directive(char * line);
void fixed_directive(char * line);
+ void payee_mapping_directive(char * line);
+ void account_mapping_directive(char * line);
void tag_directive(char * line);
void define_directive(char * line);
bool general_directive(char * line);
@@ -663,14 +665,42 @@ void instance_t::include_directive(char * line)
filename = resolve_path(filename);
DEBUG("textual.include", "resolved path: " << filename.string());
- if (! exists(filename))
+ mask_t glob;
+#if BOOST_VERSION >= 103700
+ path parent_path = filename.parent_path();
+ glob.assign_glob(filename.filename());
+#else // BOOST_VERSION >= 103700
+ path parent_path = filename.branch_path();
+ glob.assign_glob(filename.leaf());
+#endif // BOOST_VERSION >= 103700
+
+ bool files_found = false;
+ if (exists(parent_path)) {
+ filesystem::directory_iterator end;
+ for (filesystem::directory_iterator iter(parent_path);
+ iter != end;
+ ++iter) {
+ if (is_regular_file(*iter)) {
+#if BOOST_VERSION >= 103700
+ string base = (*iter).filename();
+#else // BOOST_VERSION >= 103700
+ string base = (*iter).leaf();
+#endif // BOOST_VERSION >= 103700
+ if (glob.match(base)) {
+ path inner_file(*iter);
+ ifstream stream(inner_file);
+ instance_t instance(context, stream, master, &inner_file, this);
+ instance.parse();
+ files_found = true;
+ }
+ }
+ }
+ }
+
+ if (! files_found)
throw_(std::runtime_error,
_("File to include was not found: '%1'") << filename);
- ifstream stream(filename);
-
- instance_t instance(context, stream, master, &filename, this);
- instance.parse();
}
void instance_t::master_account_directive(char * line)
@@ -735,6 +765,52 @@ void instance_t::fixed_directive(char * line)
}
}
+void instance_t::payee_mapping_directive(char * line)
+{
+ char * payee = skip_ws(line);
+ char * regex = next_element(payee, true);
+
+ if (regex)
+ context.journal.payee_mappings.push_back
+ (payee_mapping_t(mask_t(regex), payee));
+
+ while (peek_whitespace_line()) {
+ std::streamsize len = read_line(line);
+ assert(len > 0);
+
+ regex = skip_ws(line);
+ if (! *regex)
+ break;
+
+ context.journal.payee_mappings.push_back
+ (payee_mapping_t(mask_t(regex), payee));
+ }
+}
+
+void instance_t::account_mapping_directive(char * line)
+{
+ char * account_name = skip_ws(line);
+ char * payee_regex = next_element(account_name, true);
+
+ if (payee_regex)
+ context.journal.account_mappings.push_back
+ (account_mapping_t(mask_t(payee_regex),
+ context.top_account()->find_account(account_name)));
+
+ while (peek_whitespace_line()) {
+ std::streamsize len = read_line(line);
+ assert(len > 0);
+
+ payee_regex = skip_ws(line);
+ if (! *payee_regex)
+ break;
+
+ context.journal.account_mappings.push_back
+ (account_mapping_t(mask_t(payee_regex),
+ context.top_account()->find_account(account_name)));
+ }
+}
+
void instance_t::tag_directive(char * line)
{
string tag(trim_ws(line));
@@ -782,6 +858,13 @@ bool instance_t::general_directive(char * line)
}
break;
+ case 'c':
+ if (std::strcmp(p, "capture") == 0) {
+ account_mapping_directive(arg);
+ return true;
+ }
+ break;
+
case 'd':
if (std::strcmp(p, "def") == 0 || std::strcmp(p, "define") == 0) {
define_directive(arg);
@@ -810,6 +893,13 @@ bool instance_t::general_directive(char * line)
}
break;
+ case 'p':
+ if (std::strcmp(p, "payee") == 0) {
+ payee_mapping_directive(arg);
+ return true;
+ }
+ break;
+
case 't':
if (std::strcmp(p, "tag") == 0) {
tag_directive(arg);
@@ -929,6 +1019,15 @@ post_t * instance_t::parse_post(char * line,
post->account->add_flags(ACCOUNT_KNOWN);
}
+ if (post->account->name == _("Unknown")) {
+ foreach (account_mapping_t& value, context.journal.account_mappings) {
+ if (value.first.match(xact->payee)) {
+ post->account = value.second;
+ break;
+ }
+ }
+ }
+
// Parse the optional amount
bool saw_amount = false;
@@ -988,6 +1087,7 @@ post_t * instance_t::parse_post(char * line,
if (*++next == '@') {
per_unit = false;
+ post->add_flags(POST_COST_IN_FULL);
DEBUG("textual.parse", "line " << linenum << ": "
<< "And it's for a total price");
}
@@ -1127,7 +1227,7 @@ post_t * instance_t::parse_post(char * line,
// Parse the optional note
if (next && *next == ';') {
- post->append_note(++next, current_year);
+ post->append_note(++next, true, current_year);
next = line + len;
DEBUG("textual.parse", "line " << linenum << ": "
<< "Parsed a posting note");
@@ -1146,7 +1246,7 @@ post_t * instance_t::parse_post(char * line,
if (! context.state_stack.empty()) {
foreach (const state_t& state, context.state_stack)
if (state.type() == typeid(string))
- post->parse_tags(boost::get<string>(state).c_str());
+ post->parse_tags(boost::get<string>(state).c_str(), true);
}
TRACE_STOP(post_details, 1);
@@ -1242,7 +1342,14 @@ xact_t * instance_t::parse_xact(char * line,
if (next && *next) {
char * p = next_element(next, true);
- xact->payee = next;
+ foreach (payee_mapping_t& value, context.journal.payee_mappings) {
+ if (value.first.match(next)) {
+ xact->payee = value.second;
+ break;
+ }
+ }
+ if (xact->payee.empty())
+ xact->payee = next;
next = p;
} else {
xact->payee = _("<Unspecified payee>");
@@ -1276,7 +1383,7 @@ xact_t * instance_t::parse_xact(char * line,
item = xact.get();
// This is a trailing note, and possibly a metadata info tag
- item->append_note(p + 1, current_year);
+ item->append_note(p + 1, true, current_year);
item->pos->end_pos = curr_pos;
item->pos->end_line++;
} else {
@@ -1310,7 +1417,7 @@ xact_t * instance_t::parse_xact(char * line,
if (! context.state_stack.empty()) {
foreach (const state_t& state, context.state_stack)
if (state.type() == typeid(string))
- xact->parse_tags(boost::get<string>(state).c_str());
+ xact->parse_tags(boost::get<string>(state).c_str(), false);
}
TRACE_STOP(xact_details, 1);
diff --git a/src/timelog.cc b/src/timelog.cc
index 25bf8e94..217aa581 100644
--- a/src/timelog.cc
+++ b/src/timelog.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/timelog.h b/src/timelog.h
index 83256dfa..caa23ec0 100644
--- a/src/timelog.h
+++ b/src/timelog.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/times.cc b/src/times.cc
index 963639f1..be488baf 100644
--- a/src/times.cc
+++ b/src/times.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/times.h b/src/times.h
index 826937bb..48a9dd2a 100644
--- a/src/times.h
+++ b/src/times.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/token.cc b/src/token.cc
index 81c54a82..a34cdcd0 100644
--- a/src/token.cc
+++ b/src/token.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/token.h b/src/token.h
index 670f16e3..8d70996b 100644
--- a/src/token.h
+++ b/src/token.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/unistring.h b/src/unistring.h
index 7c433d9d..d42f2b28 100644
--- a/src/unistring.h
+++ b/src/unistring.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -55,6 +55,8 @@ namespace ledger {
class unistring
{
public:
+ static const std::size_t npos = static_cast<std::size_t>(-1);
+
std::vector<boost::uint32_t> utf32chars;
unistring() {
@@ -96,6 +98,23 @@ public:
return utf8result;
}
+
+ std::size_t find(const boost::uint32_t __s, std::size_t __pos = 0) const {
+ std::size_t idx = 0;
+ foreach (const boost::uint32_t& ch, utf32chars) {
+ if (idx >= __pos && ch == __s)
+ return idx;
+ idx++;
+ }
+ return npos;
+ }
+
+ boost::uint32_t& operator[](const std::size_t index) {
+ return utf32chars[index];
+ }
+ const boost::uint32_t& operator[](const std::size_t index) const {
+ return utf32chars[index];
+ }
};
inline void justify(std::ostream& out,
diff --git a/src/utils.cc b/src/utils.cc
index f2460ba1..c3fecca0 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/utils.h b/src/utils.h
index ab8fb495..a0c3f49f 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -659,6 +659,16 @@ inline string to_hex(uint_least32_t * message_digest, const int len = 1)
return buf.str();
}
+inline string sha1sum(const string& str)
+{
+ SHA1 sha;
+ sha.Reset();
+ sha << str.c_str();
+ uint_least32_t message_digest[5];
+ sha.Result(message_digest);
+ return to_hex(message_digest, 5);
+}
+
class push_xml
{
std::ostream& out;
diff --git a/src/value.cc b/src/value.cc
index 7d079caf..54798162 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -857,12 +857,12 @@ bool value_t::is_less_than(const value_t& val) const
case INTEGER:
return as_amount() < val.as_long();
case AMOUNT:
- try {
+ if (as_amount().commodity() == val.as_amount().commodity() ||
+ ! as_amount().has_commodity() ||
+ ! val.as_amount().has_commodity())
return as_amount() < val.as_amount();
- }
- catch (const amount_error&) {
+ else
return commodity_t::compare_by_commodity()(&as_amount(), &val.as_amount());
- }
default:
break;
}
diff --git a/src/value.h b/src/value.h
index ffbb89e8..1c1d8b6c 100644
--- a/src/value.h
+++ b/src/value.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -919,11 +919,11 @@ public:
/**
* Printing methods.
*/
- void print(std::ostream& out,
- const int first_width = -1,
- const int latter_width = -1,
- const bool right_justify = false,
- const bool colorize = false) const;
+ void print(std::ostream& out,
+ const int first_width = -1,
+ const int latter_width = -1,
+ const bool right_justify = false,
+ const bool colorize = false) const;
void dump(std::ostream& out, const bool relaxed = true) const;
/**
diff --git a/src/xact.cc b/src/xact.cc
index 623c5772..1a022387 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -454,12 +454,7 @@ string xact_t::idstring() const
string xact_t::id() const
{
- SHA1 sha;
- sha.Reset();
- sha << idstring().c_str();
- uint_least32_t message_digest[5];
- sha.Result(message_digest);
- return to_hex(message_digest, 5);
+ return sha1sum(idstring());
}
namespace {
@@ -760,7 +755,7 @@ void to_xml(std::ostream& out, const xact_t& xact)
if (xact.metadata) {
push_xml y(out, "metadata");
foreach (const item_t::string_map::value_type& pair, *xact.metadata) {
- if (pair.second) {
+ if (pair.second.first) {
push_xml z(out, "variable");
{
push_xml w(out, "key");
@@ -768,7 +763,7 @@ void to_xml(std::ostream& out, const xact_t& xact)
}
{
push_xml w(out, "value");
- out << y.guard(*pair.second);
+ out << y.guard(*pair.second.first);
}
} else {
push_xml z(out, "tag");
diff --git a/src/xact.h b/src/xact.h
index c819b2a0..c6c61f95 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/xml.cc b/src/xml.cc
index 9cff980a..5dd10012 100644
--- a/src/xml.cc
+++ b/src/xml.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/xml.h b/src/xml.h
index 30a7b1b1..320096f8 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2009, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/test/baseline/opt-by-payee.test b/test/baseline/opt-by-payee.test
index ec8d0a73..2c70ecfb 100644
--- a/test/baseline/opt-by-payee.test
+++ b/test/baseline/opt-by-payee.test
@@ -192,29 +192,29 @@ reg --by-payee not @End
Expenses:Books $120.00
Assets:Cash
>>>1
-08-Jan-01 January Assets:Cash $-20.00 $-20.00
- Expenses:Books $20.00 0
+08-Apr-01 April Assets:Cash $-80.00 $-80.00
+ Expenses:Books $80.00 0
+08-Aug-01 August Assets:Cash $-160.00 $-160.00
+ Expenses:Books $160.00 0
+08-Dec-01 December Assets:Cash $-240.00 $-240.00
+ Expenses:Books $240.00 0
08-Feb-01 February Assets:Cash $-40.00 $-40.00
Expenses:Books $40.00 0
+08-Jan-01 January Assets:Cash $-20.00 $-20.00
+ Expenses:Books $20.00 0
+08-Jul-01 July Assets:Cash $-140.00 $-140.00
+ Expenses:Books $140.00 0
+08-Jun-01 June Assets:Cash $-120.00 $-120.00
+ Expenses:Books $120.00 0
08-Mar-01 March Assets:Cash $-60.00 $-60.00
Expenses:Books $60.00 0
-08-Apr-01 April Assets:Cash $-80.00 $-80.00
- Expenses:Books $80.00 0
08-May-01 May Assets:Cash $-100.00 $-100.00
Expenses:Books $100.00 0
-08-Jun-01 June Assets:Cash $-120.00 $-120.00
- Expenses:Books $120.00 0
-08-Jul-01 July Assets:Cash $-140.00 $-140.00
- Expenses:Books $140.00 0
-08-Aug-01 August Assets:Cash $-160.00 $-160.00
- Expenses:Books $160.00 0
-08-Sep-01 September Assets:Cash $-180.00 $-180.00
- Expenses:Books $180.00 0
-08-Oct-01 October Assets:Cash $-200.00 $-200.00
- Expenses:Books $200.00 0
08-Nov-01 November Assets:Cash $-220.00 $-220.00
Expenses:Books $220.00 0
-08-Dec-01 December Assets:Cash $-240.00 $-240.00
- Expenses:Books $240.00 0
+08-Oct-01 October Assets:Cash $-200.00 $-200.00
+ Expenses:Books $200.00 0
+08-Sep-01 September Assets:Cash $-180.00 $-180.00
+ Expenses:Books $180.00 0
>>>2
=== 0
diff --git a/test/baseline/opt-effective.test b/test/baseline/opt-effective.test
index adf9f8af..0ce08550 100644
--- a/test/baseline/opt-effective.test
+++ b/test/baseline/opt-effective.test
@@ -14,8 +14,8 @@ reg --effective
>>>1
08-Jan-01 January Expenses:Books $10.00 $10.00
Assets:Cash $-10.00 0
-08-Jan-01 End of January Assets:Cash $-10.00 $-10.00
-08-Feb-01 End of January Expenses:Books $10.00 0
+08-Feb-01 End of January Expenses:Books $10.00 $10.00
+08-Jan-01 End of January Assets:Cash $-10.00 0
08-Feb-01 February Expenses:Books $20.00 $20.00
Assets:Cash $-20.00 0
>>>2
diff --git a/test/baseline/opt-forecast-while.test b/test/baseline/opt-forecast-while.test
index aebb127f..c2563a75 100644
--- a/test/baseline/opt-forecast-while.test
+++ b/test/baseline/opt-forecast-while.test
@@ -229,29 +229,29 @@ reg --now=2009/03/21 --forecast-while='total < $3500' books
09-Apr-01 April Expenses:Books $40.00 $1720.00
09-Apr-30 End of April Expenses:Books $40.00 $1760.00
09-May-01 May Expenses:Books $50.00 $1810.00
-09-May-01 Forecast transaction Expenses:Books $10.00 $1820.00
-09-May-31 End of May Expenses:Books $50.00 $1870.00
-09-Jun-01 June Expenses:Books $60.00 $1930.00
-09-Jun-01 Forecast transaction Expenses:Books $10.00 $1940.00
-09-Jun-30 End of June Expenses:Books $60.00 $2000.00
-09-Jul-01 July Expenses:Books $70.00 $2070.00
-09-Jul-01 Forecast transaction Expenses:Books $10.00 $2080.00
-09-Jul-31 End of July Expenses:Books $70.00 $2150.00
-09-Aug-01 August Expenses:Books $80.00 $2230.00
-09-Aug-01 Forecast transaction Expenses:Books $10.00 $2240.00
-09-Aug-31 End of August Expenses:Books $80.00 $2320.00
-09-Sep-01 September Expenses:Books $90.00 $2410.00
-09-Sep-01 Forecast transaction Expenses:Books $10.00 $2420.00
-09-Sep-30 End of September Expenses:Books $90.00 $2510.00
-09-Oct-01 October Expenses:Books $100.00 $2610.00
-09-Oct-01 Forecast transaction Expenses:Books $10.00 $2620.00
-09-Oct-31 End of October Expenses:Books $100.00 $2720.00
-09-Nov-01 November Expenses:Books $110.00 $2830.00
-09-Nov-01 Forecast transaction Expenses:Books $10.00 $2840.00
-09-Nov-30 End of November Expenses:Books $110.00 $2950.00
-09-Dec-01 December Expenses:Books $120.00 $3070.00
-09-Dec-01 Forecast transaction Expenses:Books $10.00 $3080.00
-09-Dec-31 End of December Expenses:Books $120.00 $3200.00
+09-May-31 End of May Expenses:Books $50.00 $1860.00
+09-Jun-01 June Expenses:Books $60.00 $1920.00
+09-Jun-30 End of June Expenses:Books $60.00 $1980.00
+09-Jul-01 July Expenses:Books $70.00 $2050.00
+09-Jul-31 End of July Expenses:Books $70.00 $2120.00
+09-Aug-01 August Expenses:Books $80.00 $2200.00
+09-Aug-31 End of August Expenses:Books $80.00 $2280.00
+09-Sep-01 September Expenses:Books $90.00 $2370.00
+09-Sep-30 End of September Expenses:Books $90.00 $2460.00
+09-Oct-01 October Expenses:Books $100.00 $2560.00
+09-Oct-31 End of October Expenses:Books $100.00 $2660.00
+09-Nov-01 November Expenses:Books $110.00 $2770.00
+09-Nov-30 End of November Expenses:Books $110.00 $2880.00
+09-Dec-01 December Expenses:Books $120.00 $3000.00
+09-Dec-31 End of December Expenses:Books $120.00 $3120.00
+09-May-01 Forecast transaction Expenses:Books $10.00 $3130.00
+09-Jun-01 Forecast transaction Expenses:Books $10.00 $3140.00
+09-Jul-01 Forecast transaction Expenses:Books $10.00 $3150.00
+09-Aug-01 Forecast transaction Expenses:Books $10.00 $3160.00
+09-Sep-01 Forecast transaction Expenses:Books $10.00 $3170.00
+09-Oct-01 Forecast transaction Expenses:Books $10.00 $3180.00
+09-Nov-01 Forecast transaction Expenses:Books $10.00 $3190.00
+09-Dec-01 Forecast transaction Expenses:Books $10.00 $3200.00
10-Jan-01 Forecast transaction Expenses:Books $10.00 $3210.00
10-Feb-01 Forecast transaction Expenses:Books $10.00 $3220.00
10-Mar-01 Forecast transaction Expenses:Books $10.00 $3230.00
diff --git a/test/baseline/opt-lots_basis.test b/test/baseline/opt-lots_basis.test
index 51235473..d392fe33 100644
--- a/test/baseline/opt-lots_basis.test
+++ b/test/baseline/opt-lots_basis.test
@@ -871,6 +871,12 @@ D 1.00G
Expenses:Fees:Mail 30c 1.50G
Expenses:Fees:Mail 30c 1.51G
Assets:Tajer -1.51G 0
+06-Mar-27 Player Assets:Tajer 160.00G 160.00G
+ Assets:Tajer:Items -160.00G 0
+ Expenses:Capital Loss 40.00G 40.00G
+ Equity:Capital Losses -40.00G 0
+06-Mar-27 Player Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
06-Mar-26 Player Expenses:Items 54.00G 54.00G
Expenses:Items 10.00G 64.00G
Expenses:Fees:Bank 10.00G 74.00G
@@ -878,12 +884,6 @@ D 1.00G
Expenses:Fees:Mail 3.30s 74.10G
Expenses:Fees:Mail 30c 74.10G
Assets:Tajer -74.10G 0
-06-Mar-27 Player Assets:Tajer 160.00G 160.00G
- Assets:Tajer:Items -160.00G 0
- Expenses:Capital Loss 40.00G 40.00G
- Equity:Capital Losses -40.00G 0
-06-Mar-27 Player Expenses:Fees:Mail 30c 30c
- Assets:Tajer -30c 0
06-Apr-01 Auction House Assets:Tajer:Items 155.00G 155.00G
Assets:Tajer -155.00G 0
>>>2
diff --git a/test/baseline/opt-lots_basis_base.test b/test/baseline/opt-lots_basis_base.test
index 2fa1fdb1..e3aca02d 100644
--- a/test/baseline/opt-lots_basis_base.test
+++ b/test/baseline/opt-lots_basis_base.test
@@ -872,6 +872,12 @@ D 1.00G
Expenses:Fees:Mail 30c 15030c
Expenses:Fees:Mail 30c 15060c
Assets:Tajer -15060c 0
+06-Mar-27 Player Assets:Tajer 1600000c 1600000c
+ Assets:Tajer:Items -1600000c 0
+ Expenses:Capital Loss 400000c 400000c
+ Equity:Capital Losses -400000c 0
+06-Mar-27 Player Expenses:Fees:Mail 30c 30c
+ Assets:Tajer -30c 0
06-Mar-26 Player Expenses:Items 540000c 540000c
Expenses:Items 100000c 640000c
Expenses:Fees:Bank 100000c 740000c
@@ -879,12 +885,6 @@ D 1.00G
Expenses:Fees:Mail 330c 740960c
Expenses:Fees:Mail 30c 740990c
Assets:Tajer -740990c 0
-06-Mar-27 Player Assets:Tajer 1600000c 1600000c
- Assets:Tajer:Items -1600000c 0
- Expenses:Capital Loss 400000c 400000c
- Equity:Capital Losses -400000c 0
-06-Mar-27 Player Expenses:Fees:Mail 30c 30c
- Assets:Tajer -30c 0
06-Apr-01 Auction House Assets:Tajer:Items 1550000c 1550000c
Assets:Tajer -1550000c 0
>>>2
diff --git a/test/baseline/opt-print-format.test b/test/baseline/opt-print-format.test
deleted file mode 100644
index 103ceb1e..00000000
--- a/test/baseline/opt-print-format.test
+++ /dev/null
@@ -1,10 +0,0 @@
-print --print-format='%(amount)\n'
-<<<
-2007/02/02 RD VMMXX
- Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
- Income:Dividends:Vanguard:VMMXX $-0.35
->>>1
-0.350 VMMXX {$1.00} [2007/02/02]
-$-0.35
->>>2
-=== 0
diff --git a/test/baseline/opt-strict.test b/test/baseline/opt-strict.test
index 1917d946..a0e593b2 100644
--- a/test/baseline/opt-strict.test
+++ b/test/baseline/opt-strict.test
@@ -14,10 +14,10 @@ reg --strict
>>>1
07-Feb-02 Foo Expenses:Food $10.00 $10.00
Assets:Cash $-10.00 0
-07-Feb-02 Baz Expenses:Foodx $30.00 $30.00
- Assets:Cash $-30.00 0
07-Feb-03 Bar Expenses:Food $20.00 $20.00
Assets:Cash $-20.00 0
+07-Feb-02 Baz Expenses:Foodx $30.00 $30.00
+ Assets:Cash $-30.00 0
>>>2
Warning: "$FILE", line 10: Unknown account 'Expenses:Foodx'
=== 0
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 09daafe6..e821f150 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,9 +1,9 @@
VERSION = 3.0.0
ACLOCAL_AMFLAGS = -I m4
dist_man_MANS = doc/ledger.1
-SUBDIRS = po intl
+SUBDIRS = po intl
EXTRA_DIST = autogen.sh config.rpath contrib src/system.hh.in
-DISTCLEANFILES = .timestamp
+DISTCLEANFILES = .timestamp
lib_LTLIBRARIES = \
libledger_report.la \
@@ -55,6 +55,7 @@ libledger_expr_la_CPPFLAGS = $(lib_cppflags)
libledger_expr_la_LDFLAGS = -release $(VERSION)
libledger_data_la_SOURCES = \
+ src/lookup.cc \
src/compare.cc \
src/iterators.cc \
src/timelog.cc \
@@ -72,9 +73,12 @@ libledger_data_la_LDFLAGS = -release $(VERSION)
libledger_report_la_SOURCES = \
src/stats.cc \
src/generate.cc \
+ src/csv.cc \
+ src/convert.cc \
src/draft.cc \
- src/emacs.cc \
- src/xml.cc \
+ src/emacs.cc \
+ src/xml.cc \
+ src/print.cc \
src/output.cc \
src/precmd.cc \
src/chain.cc \
@@ -126,6 +130,7 @@ pkginclude_HEADERS = \
src/timelog.h \
src/iterators.h \
src/compare.h \
+ src/lookup.h \
\
src/session.h \
src/report.h \
@@ -133,9 +138,12 @@ pkginclude_HEADERS = \
src/temps.h \
src/chain.h \
src/precmd.h \
+ src/csv.h \
+ src/convert.h \
src/draft.h \
src/generate.h \
src/stats.h \
+ src/print.h \
src/output.h \
src/xml.h \
src/emacs.h \
@@ -167,6 +175,7 @@ BUILT_SOURCES += system.hh.gch
CLEANFILES += system.hh.gch
system.hh.gch: system.hh
+ -rm -f $@
$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(lib_cppflags) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
-o $@ $<
@@ -190,7 +199,7 @@ dist_lisp_LISP = lisp/ledger.el lisp/timeclock.el
ELCFILES =
DISTCLEANFILES += ledger.elc timeclock.elc
-all_sources = $(libledger_util_la_SOURCES) \
+all_sources = $(libledger_util_la_SOURCES) \
$(libledger_math_la_SOURCES) \
$(libledger_expr_la_SOURCES) \
$(libledger_data_la_SOURCES) \
@@ -198,7 +207,7 @@ all_sources = $(libledger_util_la_SOURCES) \
$(libledger_python_la_SOURCES) \
src/pyledger.cc
-all_files = $(all_sources) $(pkginclude_HEADERS)
+all_files = $(all_sources) $(pkginclude_HEADERS)
######################################################################
@@ -271,7 +280,7 @@ UtilTests_SOURCES = \
test/unit/t_times.h
UtilTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
-UtilTests_LDADD = libledger_util.la -lcppunit
+UtilTests_LDADD = libledger_util.la -lcppunit
MathTests_SOURCES = \
test/UnitTests.cc \
@@ -285,7 +294,7 @@ MathTests_SOURCES = \
test/unit/t_balance.h
MathTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
-MathTests_LDADD = libledger_math.la $(UtilTests_LDADD)
+MathTests_LDADD = libledger_math.la $(UtilTests_LDADD)
ExprTests_SOURCES = \
test/UnitTests.cc \
@@ -295,7 +304,7 @@ ExprTests_SOURCES = \
test/unit/t_expr.h
ExprTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
-ExprTests_LDADD = libledger_expr.la $(MathTests_LDADD)
+ExprTests_LDADD = libledger_expr.la $(MathTests_LDADD)
DataTests_SOURCES = \
test/UnitTests.cc \
@@ -303,7 +312,7 @@ DataTests_SOURCES = \
test/DataTests.cc
DataTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
-DataTests_LDADD = libledger_data.la $(ExprTests_LDADD)
+DataTests_LDADD = libledger_data.la $(ExprTests_LDADD)
ReportTests_SOURCES = \
test/UnitTests.cc \
@@ -393,7 +402,7 @@ test/input/mondo.dat: test/input/standard.dat
@for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do \
for j in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do \
cat $< >> $@; \
- done; \
+ done; \
done
ConfirmTests: $(srcdir)/test/ConfirmTests.py