*** empty log message ***
This commit is contained in:
parent
47eebe8d73
commit
c68b502156
3 changed files with 107 additions and 69 deletions
|
|
@ -63,7 +63,7 @@ void transaction::print(std::ostream& out, bool display_quantity,
|
||||||
void entry::print(std::ostream& out, bool shortcut) const
|
void entry::print(std::ostream& out, bool shortcut) const
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
std::strftime(buf, 31, "%Y.%m.%d ", std::localtime(&date));
|
std::strftime(buf, 31, "%Y/%m/%d ", std::localtime(&date));
|
||||||
out << buf;
|
out << buf;
|
||||||
|
|
||||||
if (cleared)
|
if (cleared)
|
||||||
|
|
|
||||||
144
ledger.el
144
ledger.el
|
|
@ -37,16 +37,66 @@
|
||||||
(defvar ledger-version "1.1"
|
(defvar ledger-version "1.1"
|
||||||
"The version of ledger.el currently loaded")
|
"The version of ledger.el currently loaded")
|
||||||
|
|
||||||
|
(defun ledger-iterate-entries (callback)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(let* ((now (current-time))
|
||||||
|
(current-year (nth 5 (decode-time now))))
|
||||||
|
(while (not (eobp))
|
||||||
|
(when (looking-at
|
||||||
|
(concat "\\(Y\\s-+\\([0-9]+\\)\\|"
|
||||||
|
"\\([0-9]\\{4\\}+\\)?[./]?"
|
||||||
|
"\\([0-9]+\\)[./]\\([0-9]+\\)\\s-+"
|
||||||
|
"\\(\\*\\s-+\\)?\\(.+\\)\\)"))
|
||||||
|
(let ((found (match-string 2)))
|
||||||
|
(if found
|
||||||
|
(setq current-year (string-to-number found))
|
||||||
|
(let ((start (match-beginning 0))
|
||||||
|
(year (match-string 3))
|
||||||
|
(month (string-to-number (match-string 4)))
|
||||||
|
(day (string-to-number (match-string 5)))
|
||||||
|
(mark (match-string 6))
|
||||||
|
(desc (match-string 7)))
|
||||||
|
(if (and year (> (length year) 0))
|
||||||
|
(setq year (string-to-number year)))
|
||||||
|
(funcall callback start
|
||||||
|
(encode-time 0 0 0 day month
|
||||||
|
(or year current-year))
|
||||||
|
mark desc)))))
|
||||||
|
(forward-line))))
|
||||||
|
|
||||||
|
(defun ledger-find-slot (moment)
|
||||||
|
(catch 'found
|
||||||
|
(ledger-iterate-entries
|
||||||
|
(function
|
||||||
|
(lambda (start date mark desc)
|
||||||
|
(if (time-less-p moment date)
|
||||||
|
(throw 'found t)))))))
|
||||||
|
|
||||||
(defun ledger-add-entry (entry)
|
(defun ledger-add-entry (entry)
|
||||||
(interactive
|
(interactive
|
||||||
(list (read-string "Entry: "
|
(list (read-string "Entry: " (format-time-string "%m/%d "))))
|
||||||
(format-time-string "%m.%d " (current-time)))))
|
(let ((args (mapcar 'shell-quote-argument (split-string entry)))
|
||||||
(let ((args (mapcar 'shell-quote-argument (split-string entry))))
|
date entry)
|
||||||
(shell-command
|
(with-temp-buffer
|
||||||
(concat "ledger entry "
|
(shell-command
|
||||||
(mapconcat 'identity args " ")) t)
|
(concat "ledger entry "
|
||||||
(delete-char 5)
|
(mapconcat 'identity args " ")) t)
|
||||||
(exchange-point-and-mark)))
|
(setq date (buffer-substring (point) (+ (point) 10)))
|
||||||
|
(setq entry (buffer-substring (+ (point) 5) (point-max))))
|
||||||
|
(if (string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" date)
|
||||||
|
(setq date (encode-time 0 0 0 (string-to-int (match-string 3 date))
|
||||||
|
(string-to-int (match-string 2 date))
|
||||||
|
(string-to-int (match-string 1 date)))))
|
||||||
|
(ledger-find-slot date)
|
||||||
|
(insert entry)))
|
||||||
|
|
||||||
|
(defun ledger-expand-entry ()
|
||||||
|
(interactive)
|
||||||
|
(ledger-add-entry (prog1
|
||||||
|
(buffer-substring (line-beginning-position)
|
||||||
|
(line-end-position))
|
||||||
|
(delete-region (line-beginning-position)
|
||||||
|
(1+ (line-end-position))))))
|
||||||
|
|
||||||
(defun ledger-toggle-current ()
|
(defun ledger-toggle-current ()
|
||||||
(interactive)
|
(interactive)
|
||||||
|
|
@ -64,57 +114,37 @@
|
||||||
|
|
||||||
(define-derived-mode ledger-mode text-mode "Ledger"
|
(define-derived-mode ledger-mode text-mode "Ledger"
|
||||||
"A mode for editing ledger data files."
|
"A mode for editing ledger data files."
|
||||||
(setq comment-start ";" comment-end nil)
|
(setq comment-start ";" comment-end nil
|
||||||
|
indent-tabs-mode nil)
|
||||||
(let ((map (current-local-map)))
|
(let ((map (current-local-map)))
|
||||||
(define-key map [(control ?c) (control ?n)] 'ledger-add-entry)
|
(define-key map [(control ?c) (control ?a)] 'ledger-add-entry)
|
||||||
(define-key map [(control ?c) (control ?c)]
|
(define-key map [(control ?c) (control ?c)] 'ledger-toggle-current)))
|
||||||
'ledger-toggle-current)))
|
|
||||||
|
|
||||||
(defun ledger-parse-entries (account)
|
(defun ledger-parse-entries (account &optional all-p)
|
||||||
(let* ((now (current-time))
|
;; `then' is 45 days ago
|
||||||
(current-year (nth 5 (decode-time now)))
|
(let ((then (time-subtract (current-time)
|
||||||
(then now)
|
(seconds-to-time (* 45 24 60 60))))
|
||||||
entries)
|
total entries)
|
||||||
;; `then' is 45 days ago
|
(ledger-iterate-entries
|
||||||
(setq then (time-subtract then (seconds-to-time (* 45 24 60 60))))
|
(function
|
||||||
(while (not (eobp))
|
(lambda (start date mark desc)
|
||||||
(when (looking-at
|
(when (or all-p (not mark) (time-less-p then date))
|
||||||
(concat "\\(Y\\s-+\\([0-9]+\\)\\|"
|
(forward-line)
|
||||||
"\\([0-9]\\{4\\}+\\)?[./]?"
|
(setq total 0.0)
|
||||||
"\\([0-9]+\\)[./]\\([0-9]+\\)\\s-+"
|
(while (looking-at
|
||||||
"\\(\\*\\s-+\\)?\\(.+\\)\\)"))
|
(concat "\\s-+\\([A-Za-z_].+?\\)\\(\\s-*$\\| \\s-*"
|
||||||
(let ((found (match-string 2))
|
"\\([^0-9]+\\)\\s-*\\([0-9.]+\\)\\)"))
|
||||||
total when)
|
(let ((acct (match-string 1))
|
||||||
(if found
|
(amt (match-string 4)))
|
||||||
(setq current-year (string-to-number found))
|
(if amt
|
||||||
(let ((start (match-beginning 0))
|
(setq amt (string-to-number amt)
|
||||||
(year (match-string 3))
|
total (+ total amt)))
|
||||||
(month (string-to-number (match-string 4)))
|
(if (string= account acct)
|
||||||
(day (string-to-number (match-string 5)))
|
(setq entries
|
||||||
(mark (match-string 6))
|
(cons (list (copy-marker start)
|
||||||
(desc (match-string 7)))
|
mark date desc (or amt total))
|
||||||
(if (and year (> (length year) 0))
|
entries))))
|
||||||
(setq year (string-to-number year)))
|
(forward-line))))))
|
||||||
(setq when (encode-time 0 0 0 day month
|
|
||||||
(or year current-year)))
|
|
||||||
(when (or (not mark) (time-less-p then when))
|
|
||||||
(forward-line)
|
|
||||||
(setq total 0.0)
|
|
||||||
(while (looking-at
|
|
||||||
(concat "\\s-+\\([A-Za-z_].+?\\)\\(\\s-*$\\| \\s-*"
|
|
||||||
"\\([^0-9]+\\)\\s-*\\([0-9.]+\\)\\)"))
|
|
||||||
(let ((acct (match-string 1))
|
|
||||||
(amt (match-string 4)))
|
|
||||||
(if amt
|
|
||||||
(setq amt (string-to-number amt)
|
|
||||||
total (+ total amt)))
|
|
||||||
(if (string= account acct)
|
|
||||||
(setq entries
|
|
||||||
(cons (list (copy-marker start)
|
|
||||||
mark when desc (or amt total))
|
|
||||||
entries))))
|
|
||||||
(forward-line)))))))
|
|
||||||
(forward-line))
|
|
||||||
(nreverse entries)))
|
(nreverse entries)))
|
||||||
|
|
||||||
(define-derived-mode ledger-reconcile-mode text-mode "Reconcile"
|
(define-derived-mode ledger-reconcile-mode text-mode "Reconcile"
|
||||||
|
|
|
||||||
30
reports.cc
30
reports.cc
|
|
@ -369,7 +369,7 @@ void add_new_entry(int index, int argc, char **argv)
|
||||||
assert(index < argc);
|
assert(index < argc);
|
||||||
|
|
||||||
if (! parse_date(argv[index++], &added.date)) {
|
if (! parse_date(argv[index++], &added.date)) {
|
||||||
std::cerr << "Error: Bad add date: " << argv[index - 1]
|
std::cerr << "Error: Bad entry date: " << argv[index - 1]
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
@ -377,7 +377,7 @@ void add_new_entry(int index, int argc, char **argv)
|
||||||
added.cleared = show_cleared;
|
added.cleared = show_cleared;
|
||||||
|
|
||||||
if (index == argc) {
|
if (index == argc) {
|
||||||
std::cerr << "Error: Too few arguments to 'add'." << std::endl;
|
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -396,7 +396,7 @@ void add_new_entry(int index, int argc, char **argv)
|
||||||
added.desc = matching ? matching->desc : regexps.front().pattern;
|
added.desc = matching ? matching->desc : regexps.front().pattern;
|
||||||
|
|
||||||
if (index == argc) {
|
if (index == argc) {
|
||||||
std::cerr << "Error: Too few arguments to 'add'." << std::endl;
|
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -437,11 +437,13 @@ void add_new_entry(int index, int argc, char **argv)
|
||||||
mask acct_regex(argv[index++]);
|
mask acct_regex(argv[index++]);
|
||||||
|
|
||||||
account * acct = NULL;
|
account * acct = NULL;
|
||||||
|
commodity * cmdty = NULL;
|
||||||
for (std::list<transaction *>::iterator x = matching->xacts.begin();
|
for (std::list<transaction *>::iterator x = matching->xacts.begin();
|
||||||
x != matching->xacts.end();
|
x != matching->xacts.end();
|
||||||
x++) {
|
x++) {
|
||||||
if (acct_regex.match((*x)->acct->as_str())) {
|
if (acct_regex.match((*x)->acct->as_str())) {
|
||||||
acct = (*x)->acct;
|
acct = (*x)->acct;
|
||||||
|
cmdty = (*x)->cost->commdty();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -458,16 +460,18 @@ void add_new_entry(int index, int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == argc) {
|
if (index == argc) {
|
||||||
std::cerr << "Error: Too few arguments to 'add'." << std::endl;
|
std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
xact->cost = create_amount(argv[index++]);
|
xact->cost = create_amount(argv[index++]);
|
||||||
|
if (! xact->cost->commdty())
|
||||||
|
xact->cost->set_commdty(cmdty);
|
||||||
|
|
||||||
added.xacts.push_back(xact);
|
added.xacts.push_back(xact);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((index + 1) < argc && std::string(argv[index]) == "-from")
|
if ((index + 1) < argc && std::string(argv[index]) == "-from") {
|
||||||
if (account * acct = main_ledger->re_find_account(argv[++index])) {
|
if (account * acct = main_ledger->re_find_account(argv[++index])) {
|
||||||
transaction * xact = new transaction();
|
transaction * xact = new transaction();
|
||||||
xact->acct = acct;
|
xact->acct = acct;
|
||||||
|
|
@ -475,15 +479,21 @@ void add_new_entry(int index, int argc, char **argv)
|
||||||
|
|
||||||
added.xacts.push_back(xact);
|
added.xacts.push_back(xact);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
transaction * xact = new transaction();
|
||||||
|
xact->acct = matching->xacts.back()->acct;
|
||||||
|
xact->cost = NULL;
|
||||||
|
added.xacts.push_back(xact);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (added.finalize())
|
if (added.finalize())
|
||||||
added.print(std::cout);
|
added.print(std::cout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print out the entire ledger that was read in, sorted by date.
|
// Print out the entire ledger that was read in. This can be used to
|
||||||
// This can be used to "wash" ugly ledger files. It's written here,
|
// "wash" ugly ledger files. It's written here, instead of ledger.cc,
|
||||||
// instead of ledger.cc, in order to access the static globals above.
|
// in order to access the static globals above.
|
||||||
|
|
||||||
void book::print(std::ostream& out, regexps_map& regexps,
|
void book::print(std::ostream& out, regexps_map& regexps,
|
||||||
bool shortcut) const
|
bool shortcut) const
|
||||||
|
|
@ -491,9 +501,7 @@ void book::print(std::ostream& out, regexps_map& regexps,
|
||||||
for (entries_list_const_iterator i = entries.begin();
|
for (entries_list_const_iterator i = entries.begin();
|
||||||
i != entries.end();
|
i != entries.end();
|
||||||
i++) {
|
i++) {
|
||||||
if ((! show_cleared && (*i)->cleared) ||
|
if (! matches_date_range(*i) || ! (*i)->matches(regexps))
|
||||||
! matches_date_range(*i) ||
|
|
||||||
! (*i)->matches(regexps))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
(*i)->print(out, shortcut);
|
(*i)->print(out, shortcut);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue