Merge branch 'next'

This commit is contained in:
John Wiegley 2010-03-17 06:22:43 -04:00
commit 7ca8149ec5
137 changed files with 2256 additions and 349 deletions

10
.gitignore vendored
View file

@ -53,6 +53,16 @@
/doc/ledger.info /doc/ledger.info
/doc/refman.pdf /doc/refman.pdf
/doc/report/ /doc/report/
/doc/*.aux
/doc/*.cp
/doc/*.fn
/doc/*.ky
/doc/*.log
/doc/*.pdf
/doc/*.pg
/doc/*.toc
/doc/*.tp
/doc/*.vr
/expr_tests /expr_tests
/libtool /libtool
/math_tests /math_tests

View file

@ -5,7 +5,7 @@
@dircategory User Applications @dircategory User Applications
@copying @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 Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are 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. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@end copying @end copying
@documentencoding iso-8859-1 @documentencoding utf-8
@iftex @iftex
@finalout @finalout
@ -4107,4 +4107,19 @@ parser_t
@section General Utility @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 @bye

122
lisp/ldg-post.el Normal file
View file

@ -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)

167
lisp/ldg-regex.el Normal file
View file

@ -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)

121
lisp/ldg-texi.el Normal file
View file

@ -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)

View file

@ -73,7 +73,7 @@
(require 'esh-arg) (require 'esh-arg)
(require 'pcomplete) (require 'pcomplete)
(defvar ledger-version "1.2" (defvar ledger-version "1.3"
"The version of ledger.el currently loaded") "The version of ledger.el currently loaded")
(defgroup ledger nil (defgroup ledger nil
@ -1226,7 +1226,7 @@ the default."
"Align amounts in the current region. "Align amounts in the current region.
This is done so that the last digit falls in COLUMN, which defaults to 52." This is done so that the last digit falls in COLUMN, which defaults to 52."
(interactive "p") (interactive "p")
(if (= column 1) (if (or (null column) (= column 1))
(setq column 52)) (setq column 52))
(save-excursion (save-excursion
(let* ((mark-first (< (mark) (point))) (let* ((mark-first (< (mark) (point)))

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -112,10 +112,12 @@ post_handler_ptr chain_post_handlers(report_t& report,
else else
handler.reset(new sort_posts(handler, report.HANDLER(sort_).str())); handler.reset(new sort_posts(handler, report.HANDLER(sort_).str()));
} }
#if 0
else if (! report.HANDLED(period_) && else if (! report.HANDLED(period_) &&
! report.HANDLED(unsorted)) { ! report.HANDLED(unsorted)) {
handler.reset(new sort_posts(handler, "date")); handler.reset(new sort_posts(handler, "date"));
} }
#endif
// collapse_posts causes xacts with multiple posts to appear as xacts // collapse_posts causes xacts with multiple posts to appear as xacts
// with a subtotaled post for each commodity used. // 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_)) { else if (report.HANDLED(pivot_)) {
string pivot = report.HANDLER(pivot_).str(); 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, handler.reset(new transfer_details(handler, transfer_details::SET_ACCOUNT,
report.session.journal->master, pivot, report.session.journal->master, pivot,
report)); report));

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

156
src/convert.cc Normal file
View file

@ -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

55
src/convert.h Normal file
View file

@ -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

298
src/csv.cc Normal file
View file

@ -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

110
src/csv.h Normal file
View file

@ -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

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -38,7 +38,8 @@
#include "journal.h" #include "journal.h"
#include "session.h" #include "session.h"
#include "report.h" #include "report.h"
#include "output.h" #include "lookup.h"
#include "print.h"
namespace ledger { namespace ledger {
@ -240,20 +241,27 @@ void draft_t::parse_args(const value_t& args)
xact_t * draft_t::insert(journal_t& journal) xact_t * draft_t::insert(journal_t& journal)
{ {
if (tmpl->payee_mask.empty()) 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); std::auto_ptr<xact_t> added(new xact_t);
for (xacts_list::reverse_iterator j = journal.xacts.rbegin(); xacts_iterator xi(journal);
j != journal.xacts.rend(); if (xact_t * xact = lookup_probable_account(tmpl->payee_mask.str(), xi).first) {
j++) { DEBUG("derive.xact", "Found payee by lookup: transaction on line "
if (tmpl->payee_mask.match((*j)->payee)) { << xact->pos->beg_line);
matching = *j; matching = xact;
DEBUG("derive.xact", } else {
"Found payee match: transaction on line " << (*j)->pos->beg_line); for (xacts_list::reverse_iterator j = journal.xacts.rbegin();
break; 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) { if (matching) {
added->payee = matching->payee; added->payee = matching->payee;
added->code = matching->code; //added->code = matching->code;
added->note = matching->note; //added->note = matching->note;
#if defined(DEBUG_ON) #if defined(DEBUG_ON)
DEBUG("derive.xact", "Setting payee from match: " << added->payee); DEBUG("derive.xact", "Setting payee from match: " << added->payee);
if (added->code) //if (added->code)
DEBUG("derive.xact", "Setting code from match: " << *added->code); // DEBUG("derive.xact", "Setting code from match: " << *added->code);
if (added->note) //if (added->note)
DEBUG("derive.xact", "Setting note from match: " << *added->note); // DEBUG("derive.xact", "Setting note from match: " << *added->note);
#endif #endif
} else { } else {
added->payee = tmpl->payee_mask.str(); 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 // Only consider actual postings for the "xact" command
report.HANDLER(limit_).on(string("#xact"), "actual"); report.HANDLER(limit_).on(string("#xact"), "actual");
report.xact_report(post_handler_ptr report.xact_report(post_handler_ptr(new print_xacts(report)), *new_xact);
(new format_posts(report,
report.HANDLER(print_format_).str())),
*new_xact);
return true; return true;
} }

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -107,6 +107,9 @@ void truncate_xacts::flush()
void truncate_xacts::operator()(post_t& post) void truncate_xacts::operator()(post_t& post)
{ {
if (completed)
return;
if (last_xact != post.xact) { if (last_xact != post.xact) {
if (last_xact) if (last_xact)
xacts_seen++; xacts_seen++;
@ -114,8 +117,11 @@ void truncate_xacts::operator()(post_t& post)
} }
if (tail_count == 0 && head_count > 0 && 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; return;
}
posts.push_back(&post); posts.push_back(&post);
} }

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -125,8 +125,9 @@ public:
class truncate_xacts : public item_handler<post_t> class truncate_xacts : public item_handler<post_t>
{ {
int head_count; int head_count;
int tail_count; int tail_count;
bool completed;
posts_list posts; posts_list posts;
std::size_t xacts_seen; std::size_t xacts_seen;
@ -139,7 +140,7 @@ public:
int _head_count, int _tail_count) int _head_count, int _tail_count)
: item_handler<post_t>(handler), : item_handler<post_t>(handler),
head_count(_head_count), tail_count(_tail_count), 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"); TRACE_CTOR(truncate_xacts, "post_handler_ptr, int, int");
} }
virtual ~truncate_xacts() { virtual ~truncate_xacts() {

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -110,7 +110,7 @@ public:
out << out <<
"Ledger " << ledger::version << _(", the command-line accounting tool"); "Ledger " << ledger::version << _(", the command-line accounting tool");
out << 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\ 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."); See LICENSE file included with the distribution for details and disclaimer.");
out << std::endl; out << std::endl;

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * 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 (tag_mask.match(data.first)) {
if (! value_mask) if (! value_mask)
return true; return true;
else if (data.second) else if (data.second.first)
return value_mask->match(*data.second); 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); string_map::const_iterator i = metadata->find(tag);
if (i != metadata->end()) { if (i != metadata->end()) {
DEBUG("item.meta", "Found the item!"); DEBUG("item.meta", "Found the item!");
return (*i).second; return (*i).second.first;
} }
} }
return none; 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) { foreach (const string_map::value_type& data, *metadata) {
if (tag_mask.match(data.first) && if (tag_mask.match(data.first) &&
(! value_mask || (! value_mask ||
(data.second && value_mask->match(*data.second)))) (data.second.first && value_mask->match(*data.second.first))))
return data.second; return data.second.first;
} }
} }
return none; return none;
} }
void item_t::set_tag(const string& tag, item_t::string_map::iterator
const optional<string>& value) item_t::set_tag(const string& tag,
const optional<string>& value,
const bool overwrite_existing)
{ {
assert(! tag.empty());
if (! metadata) if (! metadata)
metadata = string_map(); metadata = string_map();
DEBUG("item.meta", "Setting tag '" << tag << "' to value '" DEBUG("item.meta", "Setting tag '" << tag << "' to value '"
<< (value ? *value : string("<none>")) << "'"); << (value ? *value : string("<none>")) << "'");
std::pair<string_map::iterator, bool> result optional<string> data = value;
= metadata->insert(string_map::value_type(tag, value)); if (data && data->empty())
assert(result.second); 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) optional<date_t::year_type> current_year)
{ {
if (const char * b = std::strchr(p, '[')) { if (const char * b = std::strchr(p, '[')) {
@ -149,15 +165,18 @@ void item_t::parse_tags(const char * p,
q = std::strtok(NULL, " \t")) { q = std::strtok(NULL, " \t")) {
const string::size_type len = std::strlen(q); const string::size_type len = std::strlen(q);
if (! tag.empty()) { if (! tag.empty()) {
if (! has_tag(tag)) string_map::iterator i = set_tag(tag, string(p + (q - buf.get())),
set_tag(tag, string(p + (q - buf.get()))); overwrite_existing);
(*i).second.second = true;
break; break;
} }
else if (q[0] == ':' && q[len - 1] == ':') { // a series of tags else if (q[0] == ':' && q[len - 1] == ':') { // a series of tags
for (char * r = std::strtok(q + 1, ":"); for (char * r = std::strtok(q + 1, ":");
r; r;
r = std::strtok(NULL, ":")) r = std::strtok(NULL, ":")) {
set_tag(r); string_map::iterator i = set_tag(r, none, overwrite_existing);
(*i).second.second = true;
}
} }
else if (q[len - 1] == ':') { // a metadata setting else if (q[len - 1] == ':') { // a metadata setting
tag = string(q, len - 1); 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) optional<date_t::year_type> current_year)
{ {
if (note) { if (note) {
@ -175,7 +194,7 @@ void item_t::append_note(const char * p,
note = p; note = p;
} }
parse_tags(p, current_year); parse_tags(p, overwrite_existing, current_year);
} }
namespace { namespace {

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -106,7 +106,8 @@ public:
enum state_t { UNCLEARED = 0, CLEARED, PENDING }; 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; state_t _state;
optional<date_t> _date; optional<date_t> _date;
@ -156,12 +157,14 @@ public:
virtual optional<string> get_tag(const mask_t& tag_mask, virtual optional<string> get_tag(const mask_t& tag_mask,
const optional<mask_t>& value_mask = none) const; const optional<mask_t>& value_mask = none) const;
virtual void set_tag(const string& tag, virtual string_map::iterator
const optional<string>& value = none); 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); 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); optional<date_t::year_type> current_year = none);
static bool use_effective_date; static bool use_effective_date;

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -44,6 +44,7 @@
#include "utils.h" #include "utils.h"
#include "times.h" #include "times.h"
#include "mask.h"
namespace ledger { 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<auto_xact_t *> auto_xacts_list;
typedef std::list<period_xact_t *> period_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 class journal_t : public noncopyable
{ {
public: public:
@ -110,6 +116,8 @@ public:
period_xacts_list period_xacts; period_xacts_list period_xacts;
std::list<fileinfo_t> sources; std::list<fileinfo_t> sources;
bool was_loaded; bool was_loaded;
payee_mappings_t payee_mappings;
account_mappings_t account_mappings;
journal_t(); journal_t();
journal_t(const path& pathname); journal_t(const path& pathname);

283
src/lookup.cc Normal file
View file

@ -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

56
src/lookup.h Normal file
View file

@ -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

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -52,4 +52,38 @@ mask_t& mask_t::operator=(const string& pat)
return *this; 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 } // namespace ledger

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -73,7 +73,11 @@ public:
} }
mask_t& operator=(const string& other); 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 { bool operator==(const mask_t& other) const {
return expr == other.expr; return expr == other.expr;
} }

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -42,10 +42,8 @@ namespace ledger {
format_posts::format_posts(report_t& _report, format_posts::format_posts(report_t& _report,
const string& format, const string& format,
bool _print_raw,
const optional<string>& _prepend_format) const optional<string>& _prepend_format)
: report(_report), last_xact(NULL), last_post(NULL), : report(_report), last_xact(NULL), last_post(NULL)
print_raw(_print_raw)
{ {
TRACE_CTOR(format_posts, "report&, const string&, bool"); 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); std::ostream& out(report.output_stream);
if (print_raw) { if (! post.has_xdata() ||
if (! post.has_xdata() || ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
! 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)) {
bind_scope_t bound_scope(report, post); bind_scope_t bound_scope(report, post);
if (prepend_format) if (prepend_format)

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -63,11 +63,9 @@ protected:
format_t prepend_format; format_t prepend_format;
xact_t * last_xact; xact_t * last_xact;
post_t * last_post; post_t * last_post;
bool print_raw;
public: public:
format_posts(report_t& _report, const string& format, format_posts(report_t& _report, const string& format,
bool _print_raw = false,
const optional<string>& _prepend_format = none); const optional<string>& _prepend_format = none);
virtual ~format_posts() { virtual ~format_posts() {
TRACE_DTOR(format_posts); TRACE_DTOR(format_posts);

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * 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) { if (post.metadata) {
push_xml y(out, "metadata"); push_xml y(out, "metadata");
foreach (const item_t::string_map::value_type& pair, *post.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, "variable");
{ {
push_xml z(out, "key"); push_xml z(out, "key");
@ -584,7 +584,7 @@ void to_xml(std::ostream& out, const post_t& post)
} }
{ {
push_xml z(out, "value"); push_xml z(out, "value");
out << y.guard(*pair.second); out << y.guard(*pair.second.first);
} }
} else { } else {
push_xml z(out, "tag"); push_xml z(out, "tag");

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@ -52,10 +52,11 @@ class account_t;
class post_t : public item_t class post_t : public item_t
{ {
public: public:
#define POST_VIRTUAL 0x10 // the account was specified with (parens) #define POST_VIRTUAL 0x08 // the account was specified with (parens)
#define POST_MUST_BALANCE 0x20 // posting must balance in the transaction #define POST_MUST_BALANCE 0x10 // posting must balance in the transaction
#define POST_CALCULATED 0x40 // posting's amount was calculated #define POST_CALCULATED 0x20 // posting's amount was calculated
#define POST_COST_CALCULATED 0x80 // posting's cost 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 xact_t * xact; // only set for posts of regular xacts
account_t * account; account_t * account;

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

208
src/print.cc Normal file
View file

@ -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

79
src/print.h Normal file
View file

@ -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

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

View file

@ -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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are

Some files were not shown because too many files have changed in this diff Show more