summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dir-locals.el4
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules0
-rw-r--r--.travis.yml15
-rw-r--r--CMakeLists.txt17
-rw-r--r--CONTRIBUTING.md40
-rw-r--r--INSTALL.md8
-rw-r--r--LICENSE.md2
-rw-r--r--README.md21
-rwxr-xr-xacprep38
-rw-r--r--appveyor.yml50
-rw-r--r--contrib/ParseCcStmt.cs2
-rwxr-xr-xcontrib/non-profit-audit-reports/cash-receipts-and-disbursments-journals.plx2
-rw-r--r--default.nix16
-rw-r--r--doc/CMakeLists.txt2
-rw-r--r--doc/NEWS27
-rw-r--r--doc/ledger-mode.texi1193
-rw-r--r--doc/ledger.116
-rw-r--r--doc/ledger3.texi278
-rw-r--r--lisp/CMakeLists.txt65
-rw-r--r--lisp/ledger-commodities.el151
-rw-r--r--lisp/ledger-complete.el251
-rw-r--r--lisp/ledger-context.el200
-rw-r--r--lisp/ledger-exec.el109
-rw-r--r--lisp/ledger-fontify.el201
-rw-r--r--lisp/ledger-fonts.el276
-rw-r--r--lisp/ledger-init.el75
-rw-r--r--lisp/ledger-mode.el381
-rw-r--r--lisp/ledger-navigate.el168
-rw-r--r--lisp/ledger-occur.el168
-rw-r--r--lisp/ledger-post.el199
-rw-r--r--lisp/ledger-reconcile.el624
-rw-r--r--lisp/ledger-regex.el383
-rw-r--r--lisp/ledger-report.el462
-rw-r--r--lisp/ledger-schedule.el327
-rw-r--r--lisp/ledger-sort.el123
-rw-r--r--lisp/ledger-state.el257
-rw-r--r--lisp/ledger-test.el139
-rw-r--r--lisp/ledger-texi.el172
-rw-r--r--lisp/ledger-xact.el196
-rw-r--r--src/CMakeLists.txt34
-rw-r--r--src/account.cc31
-rw-r--r--src/account.h9
-rw-r--r--src/amount.cc6
-rw-r--r--src/amount.h2
-rw-r--r--src/annotate.cc2
-rw-r--r--src/annotate.h2
-rw-r--r--src/balance.cc2
-rw-r--r--src/balance.h2
-rw-r--r--src/chain.cc6
-rw-r--r--src/chain.h2
-rw-r--r--src/commodity.cc2
-rw-r--r--src/commodity.h3
-rw-r--r--src/compare.cc18
-rw-r--r--src/compare.h18
-rw-r--r--src/context.h2
-rw-r--r--src/convert.cc2
-rw-r--r--src/convert.h2
-rw-r--r--src/csv.cc2
-rw-r--r--src/csv.h2
-rw-r--r--src/draft.cc2
-rw-r--r--src/draft.h2
-rw-r--r--src/emacs.cc2
-rw-r--r--src/emacs.h2
-rw-r--r--src/error.cc2
-rw-r--r--src/error.h2
-rw-r--r--src/expr.cc2
-rw-r--r--src/expr.h2
-rw-r--r--src/exprbase.h2
-rw-r--r--src/filters.cc39
-rw-r--r--src/filters.h39
-rw-r--r--src/flags.h2
-rw-r--r--src/format.cc2
-rw-r--r--src/format.h2
-rw-r--r--src/generate.cc2
-rw-r--r--src/generate.h2
-rw-r--r--src/global.cc8
-rw-r--r--src/global.h4
-rw-r--r--src/history.cc2
-rw-r--r--src/history.h2
-rw-r--r--src/item.cc2
-rw-r--r--src/item.h4
-rw-r--r--src/iterators.cc6
-rw-r--r--src/iterators.h21
-rw-r--r--src/journal.cc2
-rw-r--r--src/journal.h2
-rw-r--r--src/lookup.cc2
-rw-r--r--src/lookup.h2
-rw-r--r--src/main.cc4
-rw-r--r--src/mask.cc2
-rw-r--r--src/mask.h2
-rw-r--r--src/op.cc2
-rw-r--r--src/op.h2
-rw-r--r--src/option.cc2
-rw-r--r--src/option.h2
-rw-r--r--src/org.cc2
-rw-r--r--src/org.h2
-rw-r--r--src/output.cc50
-rw-r--r--src/output.h4
-rw-r--r--src/parser.cc2
-rw-r--r--src/parser.h2
-rw-r--r--src/pool.cc5
-rw-r--r--src/pool.h2
-rw-r--r--src/post.cc2
-rw-r--r--src/post.h2
-rw-r--r--src/precmd.cc2
-rw-r--r--src/precmd.h2
-rw-r--r--src/predicate.h2
-rw-r--r--src/print.cc6
-rw-r--r--src/print.h2
-rw-r--r--src/pstream.h2
-rw-r--r--src/ptree.cc2
-rw-r--r--src/ptree.h2
-rw-r--r--src/py_account.cc2
-rw-r--r--src/py_amount.cc2
-rw-r--r--src/py_balance.cc2
-rw-r--r--src/py_commodity.cc5
-rw-r--r--src/py_expr.cc2
-rw-r--r--src/py_format.cc2
-rw-r--r--src/py_item.cc2
-rw-r--r--src/py_journal.cc18
-rw-r--r--src/py_post.cc2
-rw-r--r--src/py_session.cc2
-rw-r--r--src/py_times.cc2
-rw-r--r--src/py_utils.cc2
-rw-r--r--src/py_value.cc4
-rw-r--r--src/py_xact.cc2
-rw-r--r--src/pyfstream.h2
-rw-r--r--src/pyinterp.cc2
-rw-r--r--src/pyinterp.h2
-rw-r--r--src/pyledger.cc2
-rw-r--r--src/pyutils.h2
-rw-r--r--src/query.cc2
-rw-r--r--src/query.h2
-rw-r--r--src/quotes.cc4
-rw-r--r--src/quotes.h2
-rw-r--r--src/report.cc60
-rw-r--r--src/report.h20
-rw-r--r--src/scope.cc2
-rw-r--r--src/scope.h2
-rw-r--r--src/select.cc6
-rw-r--r--src/select.h2
-rw-r--r--src/session.cc8
-rw-r--r--src/session.h12
-rw-r--r--src/stats.cc2
-rw-r--r--src/stats.h2
-rw-r--r--src/stream.cc6
-rw-r--r--src/stream.h2
-rw-r--r--src/strptime.cc37
-rw-r--r--src/system.hh.in20
-rw-r--r--src/temps.cc2
-rw-r--r--src/temps.h2
-rw-r--r--src/textual.cc86
-rw-r--r--src/timelog.cc2
-rw-r--r--src/timelog.h2
-rw-r--r--src/times.cc73
-rw-r--r--src/times.h2
-rw-r--r--src/token.cc6
-rw-r--r--src/token.h2
-rw-r--r--src/unistring.h2
-rw-r--r--src/utils.cc6
-rw-r--r--src/utils.h8
-rw-r--r--src/value.cc2
-rw-r--r--src/value.h2
-rw-r--r--src/views.cc2
-rw-r--r--src/views.h2
-rw-r--r--src/xact.cc14
-rw-r--r--src/xact.h2
-rwxr-xr-xtest/CheckBaselineTests.py1
-rwxr-xr-xtest/DocTests.py2
-rwxr-xr-xtest/LedgerHarness.py7
-rwxr-xr-xtest/RegressTests.py28
-rw-r--r--test/baseline/cmd-tags.test3
-rw-r--r--test/baseline/feat-balance_assert-off.test2
-rw-r--r--test/baseline/feat-balance_assert_split.test4
-rw-r--r--test/baseline/feat-value-expr.test2
-rw-r--r--test/baseline/opt-color.test8
-rw-r--r--test/baseline/opt-force-color.test19
-rw-r--r--test/baseline/opt-prepend-format.test5
-rw-r--r--test/baseline/opt-prepend-width.test5
-rwxr-xr-xtest/convert.py2
-rw-r--r--test/regress/1055.test26
-rw-r--r--test/regress/1057.test2
-rw-r--r--test/regress/1127.test15
-rw-r--r--test/regress/1132.test16
-rw-r--r--test/regress/1147-a.test12
-rw-r--r--test/regress/1147-b.test10
-rw-r--r--test/regress/1159.test29
-rw-r--r--test/regress/1182_1.test12
-rw-r--r--test/regress/1182_2.test17
-rw-r--r--test/regress/1187_1.test19
-rw-r--r--test/regress/1187_2.test18
-rw-r--r--test/regress/1187_3.test36
-rw-r--r--test/regress/1187_4.test32
-rw-r--r--test/regress/1187_5.test36
-rw-r--r--test/regress/1626.test28
-rw-r--r--test/regress/370-budget_period_days.test27
-rw-r--r--test/regress/370-budget_period_weeks.test29
-rw-r--r--test/regress/370-forecast_period_days.test17
-rw-r--r--test/regress/370-forecast_period_weeks.test16
-rw-r--r--test/regress/370-period.test443
-rw-r--r--test/regress/383.test2
-rw-r--r--test/regress/550-584.test (renamed from test/input/spaces.dat)18
-rw-r--r--test/regress/727B2DF8.test2
-rw-r--r--test/regress/7F3650FD.test2
-rw-r--r--test/regress/981.test29
-rw-r--r--test/regress/B21BF389.py9
-rw-r--r--test/regress/B21BF389_py.test8
-rw-r--r--test/regress/BBFA1759.test2
-rw-r--r--test/regress/GH520.test33
-rw-r--r--test/regress/fix-missing-trans-in-last-budget-period.test79
-rw-r--r--test/regress/market-group-by.test26
-rw-r--r--test/regress/total-1.test28
-rw-r--r--test/regress/total-2.test30
-rw-r--r--test/unit/t_value.cc4
-rw-r--r--tools/excludes1
-rwxr-xr-xtools/nix-build.sh20
-rwxr-xr-xtools/update_copyright_year.sh2
218 files changed, 2144 insertions, 6626 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
index ca104fb0..34761815 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -4,7 +4,7 @@
((nil
(tab-width . 2)
(sentence-end-double-space . t)
- (bug-reference-url-format . "http://bugs.ledger-cli.org/show_bug.cgi?id=%s"))
+ (bug-reference-url-format . "https://github.com/ledger/ledger/issues/%s"))
(c-mode
(c-file-style . "ledger")
(c-style-alist
@@ -32,5 +32,5 @@
(c-special-indent-hook . c-gnu-impose-minimum)
(c-block-comment-prefix . ""))))
(emacs-lisp-mode
- (indent-tabs-mode)))
+ (indent-tabs-mode . nil)))
diff --git a/.gitignore b/.gitignore
index e0bba1a6..3a5fc0de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,7 +57,6 @@ doc/latex/
doc/refman.pdf
doc/report/
doc/version.texi
-elisp-comp
install-sh
intl/
ledger
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index e69de29b..00000000
--- a/.gitmodules
+++ /dev/null
diff --git a/.travis.yml b/.travis.yml
index dcd23312..94489bdc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,7 +22,7 @@ env:
# _MIN is used when building the master branch
# _MAX is used when building any other branch
- BOOST_VERSION_MIN="1.49.0"
- - BOOST_VERSION_MAX="1.60.0"
+ - BOOST_VERSION_MAX="1.61.0"
# List of required boost libraries to build
- BOOST_LIBS="date_time,filesystem,iostreams,python,regex,system,test"
# List of required Homebrew formulae to install
@@ -47,6 +47,12 @@ matrix:
# "boost::re_detail::perl_matcher<char const*, std::allocator<boost::sub_match<char const*> >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::find()", referenced from:
# bool boost::regex_search<char const*, char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >(char const*, char const*, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags) in main.cc.o
# bool boost::regex_search<char const*, char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >(char const*, char const*, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags) in global.cc.o
+ - os: osx
+ compiler: clang
+ # On Mac OS X building ledger with clang fails due to
+ # dyld: Library not loaded: libboost_python.dylib
+ # Referenced from: /Users/travis/build/ledger/ledger/ledger
+ # Reason: image not found
addons:
coverity_scan:
@@ -110,3 +116,10 @@ notifications:
channels: [ "chat.freenode.net#ledger" ]
on_success: change
on_failure: change
+ webhooks:
+ urls:
+ - https://webhooks.gitter.im/e/0050d91909a8cde39e35
+ on_success: change # options: [always|never|change] default: always
+ on_failure: always # options: [always|never|change] default: always
+ on_start: never # options: [always|never|change] default: always
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ad96b345..f8dbd892 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,7 +35,6 @@ option(BUILD_DEBUG "Build support for runtime debugging" OFF)
option(BUILD_LIBRARY "Build and install Ledger as a library" ON)
option(BUILD_DOCS "Build and install documentation" OFF)
option(BUILD_WEB_DOCS "Build version of documentation suitable for viewing online" OFF)
-option(BUILD_EMACSLISP "Build and install ledger-mode for Emacs" OFF)
if (BUILD_DEBUG)
set(CMAKE_BUILD_TYPE Debug)
@@ -93,6 +92,7 @@ include(CheckIncludeFiles)
include(CheckLibraryExists)
include(CheckFunctionExists)
include(CheckCSourceCompiles)
+include(CheckCXXSourceCompiles)
include(CheckCXXSourceRuns)
include(CMakePushCheckState)
@@ -173,7 +173,7 @@ set(CMAKE_REQUIRED_INCLUDES
set(CMAKE_REQUIRED_LIBRARIES
${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${PROFILE_LIBS})
-check_cxx_source_runs("
+check_cxx_source_compiles("
#include <boost/python.hpp>
struct X { int y; };
@@ -181,9 +181,10 @@ struct X { int y; };
int main()
{
boost::python::make_setter(&X::y);
-}" BOOST_MAKE_SETTER_RUNS)
+ return 0;
+}" BOOST_MAKE_SETTER_COMPILES)
-if (BOOST_MAKE_SETTER_RUNS)
+if (BOOST_MAKE_SETTER_COMPILES)
set(HAVE_BOOST_159_ISSUE_39 0)
else()
set(HAVE_BOOST_159_ISSUE_39 1)
@@ -297,17 +298,13 @@ configure_file(
${PROJECT_SOURCE_DIR}/src/system.hh.in
${PROJECT_BINARY_DIR}/system.hh)
-if (CMAKE_CXX_COMPILER MATCHES "clang")
- set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-isystem ")
-elseif(CMAKE_CXX_COMPILER MATCHES "g\\+\\+")
+if((CMAKE_CXX_COMPILER MATCHES "clang") OR
+ (CMAKE_CXX_COMPILER MATCHES "clang\\+\\+"))
set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-isystem ")
endif()
add_subdirectory(src)
add_subdirectory(doc)
-if (BUILD_EMACSLISP)
- add_subdirectory(lisp)
-endif()
add_subdirectory(test)
########################################################################
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index bab3f7c8..80a413f3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,11 +1,12 @@
Tips for contributors
---------------------
-* Please **make pull requests against `next`, not `master`**.
- Ledger follows a [git-flow] branching model,
- in which development happens on the `next` branch and is subsequently merged into `master` for releases.
-* If you're making **changes to `ledger-mode`, or other files for which the Travis build is not
+* Please **make pull requests against `next`, not `master`**. Ledger follows
+ a [git-flow] branching model, in which development happens on the `next`
+ branch and is subsequently merged into `master` for releases.
+* If you're making **changes to files for which the Travis build is not
relevant**, please **add `[ci skip]` to the end of the commit message**.
+* Report bugs using [GitHub Issues].
GLOSSARY
----
@@ -82,8 +83,6 @@ orientation:
**./lib/**: a couple of libraries used in development.
-**./lisp/**: the [Emacs][] [ledger-mode] lisp code, under the [GPLv2] license.
-
**./python/**: samples using the Python ledger module.
**./src/**: the C++ header and source files in a flat directory.
@@ -93,8 +92,34 @@ orientation:
**./tools/**: an accretion of tools, mostly small scripts, to aid development
+Building
+---
+
+If you are going to be working on Ledger, you'll want to enable both debug
+builds (which are the default, using `acprep`), and also the use of
+pre-compiled headers. To do this, specify your compiler as either `clang++`
+or `g++` as follows:
+
+ mkdir build
+ ./acprep --compiler=clang++
+ cd build
+ make
+
+This will set up a debug build using clang++ (and pre-compiled headers, which
+is enabled by the combination of those two), and then start a build.
+
+For even quicker rebuilds, try the Ninja build tool, which is very fast at
+determining what to rebuild, and automatically takes advantage of multiple
+cores:
+
+ mkdir build
+ ./acprep --compiler=clang++ --ninja
+ cd build
+ ninja
+
[Boost]: http://boost.org
[Boost.Python]: http://www.boost.org/libs/python/
+[GitHub Issues]: https://github.com/ledger/ledger/issues
[GMP]: http://gmplib.org/
[MPFR]: http://www.mpfr.org/
[Cheetah]: http://www.cheetahtemplate.org
@@ -110,7 +135,4 @@ orientation:
[small badge]: https://img.shields.io/travis/ledger/ledger/master.svg?&style=flat
[git-flow]: http://nvie.com/posts/a-successful-git-branching-model/
[README.md]: https://github.com/ledger/ledger/blob/master/README.md
-[Emacs]: http://www.gnu.org/software/emacs/
-[ledger-mode]: http://ledger-cli.org/3.0/doc/ledger-mode.html
-[GPLv2]: http://www.gnu.org/licenses/gpl-2.0.html
[clang]: http://clang.llvm.org
diff --git a/INSTALL.md b/INSTALL.md
index 62de2a97..23d0566b 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -96,10 +96,10 @@ A: Actually, the real segfault is in libstdc++'s facet code. It's being
Q: Something else fails, or Ledger crashes on startup
-A: This, I am most interested in hearing about. Please file a bug
- at the Ledger Bugzilla, http://bugs.ledger-cli.org/. The more
- details you can provide, the better. Also, if Ledger is crashing,
- try running it under gdb like so:
+A: This, I am most interested in hearing about. Please file a bug at the
+ Ledger Issue Tracker, https://github.com/ledger/ledger/issues. The more
+ details you can provide, the better. Also, if Ledger is crashing, try
+ running it under gdb like so:
$ gdb ledger
(gdb) run <ARGS TO LEDGER>
diff --git a/LICENSE.md b/LICENSE.md
index c160fd1f..93cc207c 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,4 +1,4 @@
-Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+Copyright (c) 2003-2018, John Wiegley. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
diff --git a/README.md b/README.md
index 759fa26a..0aa634b4 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
+[![Join the chat at https://gitter.im/use-package/Lobby](https://badges.gitter.im/use-package/Lobby.svg)](https://gitter.im/use-package/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status master](https://img.shields.io/travis/ledger/ledger/master.svg?label=master&style=flat)](https://travis-ci.org/ledger/ledger)
[![Build Status next](https://img.shields.io/travis/ledger/ledger/next.svg?label=next&style=flat)](https://travis-ci.org/ledger/ledger)
[![Status](https://img.shields.io/badge/status-active-brightgreen.svg?style=flat)](https://github.com/ledger/ledger/pulse/monthly)
[![License](https://img.shields.io/badge/license-BSD-blue.svg?style=flat)](http://opensource.org/licenses/BSD-3-Clause)
[![GitHub release](https://img.shields.io/github/release/ledger/ledger.svg?style=flat)](https://github.com/ledger/ledger/releases)
-
# Ledger: Command-Line Accounting
Ledger is a powerful, double-entry accounting system that is accessed from the
@@ -23,8 +23,8 @@ and easy to use.
## For the Impatient
-I know, you just want to build and play. If you have all the dependencies
-installed (see below), then simply do this:
+I know, you just want to build and play. If you have all the [dependencies](#dependencies)
+installed, then simply do this:
$ git clone git://github.com/ledger/ledger.git
$ cd ledger && ./acprep update # Update to the latest, configure, make
@@ -35,8 +35,9 @@ Now try your first ledger command:
For help on keeping your journal have a look at the
[documentation] and the [wiki][] (Also see the “Resources” section at the
-end of this file). An emacs mode for ledger files can be found in the `lisp`
-directory and a vim plugin is located in the [ledger/vim-ledger repository].
+end of this file). An Emacs mode for Ledger files can be found in the
+[ledger/ledger-mode repository] and a vim plugin is located in the
+[ledger/vim-ledger repository].
## To the Rest
@@ -102,10 +103,6 @@ You can use [Homebrew] or [MacPorts] to install Ledger easily on OS X.
You can see the parameters you can pass while installing with brew by the command `brew options ledger`. To install ledger, simply type the following command:
$ brew install ledger
-
-If everything worked well, you should have ledger working now. If you want to install this with python bindings, you can use the following command:
-
- $ brew install ledger --with-python
If you to want to startup python, use the following command:
@@ -148,9 +145,9 @@ Or, for Ubuntu 12.04:
Debian squeeze (6.0): the version of boost in squeeze is too old
for ledger and unfortunately no backport is available at the moment.
-Debian 7 (wheezy), Debian 8 (jessie), Debian testing (stretch) and Debian
-unstable (sid) contain all components needed to build ledger. You can
-install all required build dependencies using the following command:
+Debian 7 (wheezy), Debian 8 (jessie), Debian 9 (stretch), Debian testing
+and Debian unstable (sid) contain all components needed to build ledger.
+You can install all required build dependencies using the following command:
$ sudo apt-get install build-essential cmake autopoint texinfo python-dev \
zlib1g-dev libbz2-dev libgmp3-dev gettext libmpfr-dev \
diff --git a/acprep b/acprep
index 90b486ec..8d9d67f7 100755
--- a/acprep
+++ b/acprep
@@ -12,11 +12,7 @@ import optparse
import os
import re
import shutil
-import string
import sys
-import time
-import tempfile
-import datetime
try:
import hashlib
@@ -66,6 +62,16 @@ class BoostInfo(object):
if system == 'centos':
return [ 'boost-devel' ]
+ elif system == 'ubuntu-xenial':
+ return [ 'libboost-dev',
+ 'libboost-date-time-dev',
+ 'libboost-filesystem-dev',
+ 'libboost-iostreams-dev',
+ 'libboost-python-dev',
+ 'libboost-regex-dev',
+ 'libboost-system-dev',
+ 'libboost-test-dev' ]
+
elif system == 'ubuntu-trusty':
return [ 'libboost-dev',
'libboost-date-time-dev',
@@ -484,7 +490,7 @@ class PrepareBuild(CommandLineApp):
def phase_sloc(self, *args):
self.log.info('Executing phase: sloc')
- self.execute('sloccount', 'src', 'python', 'lisp', 'test')
+ self.execute('sloccount', 'src', 'python', 'test')
#########################################################################
# Update local files with the latest information #
@@ -516,7 +522,7 @@ class PrepareBuild(CommandLineApp):
'libiconv', '+universal',
'zlib', '+universal',
'gmp' ,'+universal', 'mpfr', '+universal',
- 'ncurses', '+universal', 'ncursesw', '+universal',
+ 'ncurses', '+universal',
'gettext' ,'+universal',
'libedit' ,'+universal',
'texlive-xetex', 'doxygen', 'graphviz', 'texinfo',
@@ -565,6 +571,26 @@ class PrepareBuild(CommandLineApp):
'libutfcpp-dev',
'sloccount'
] + BoostInfo().dependencies('ubuntu-trusty')
+ elif re.search('xenial', info):
+ self.log.info('Looks like you are using APT on Ubuntu Xenial')
+ packages = [
+ 'sudo', 'apt-get', 'install',
+ 'build-essential',
+ 'doxygen',
+ 'cmake',
+ 'ninja-build',
+ 'zlib1g-dev',
+ 'libbz2-dev',
+ 'python-dev',
+ 'libgmp3-dev',
+ 'libmpfr-dev',
+ 'gettext',
+ 'libedit-dev',
+ 'texinfo',
+ 'lcov',
+ 'libutfcpp-dev',
+ 'sloccount'
+ ] + BoostInfo().dependencies('ubuntu-xenial')
elif re.search('saucy', info):
self.log.info('Looks like you are using APT on Ubuntu Saucy')
packages = [
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 00000000..21fec71c
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,50 @@
+version: build-{build}
+
+image: Visual Studio 2013
+
+shallow_clone: true # don't download repo history
+
+install:
+- time /t
+- tzutil /s "Eastern Standard Time_dstoff"
+- time /t
+
+branches:
+ only:
+ - master
+ - next
+
+build_script:
+- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sy pacman"
+- C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors"
+- C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Syu"
+- C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -S mingw-w64-i686-boost"
+- C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -S mingw-w64-i686-mpfr"
+- C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -S mingw-w64-i686-cmake"
+- C:\msys64\usr\bin\bash -lc "export PATH=/mingw32/bin:$PATH && cd $APPVEYOR_BUILD_FOLDER &&
+ cmake -G 'MSYS Makefiles'"
+- C:\msys64\usr\bin\bash -lc "export PATH=/mingw32/bin:$PATH && cd $APPVEYOR_BUILD_FOLDER &&
+ make -j2"
+
+after_build:
+- set LIB_DIR=C:\msys64\mingw32\bin
+- 7z a ledger-win.zip %APPVEYOR_BUILD_FOLDER%\ledger.exe
+ %LIB_DIR%\libboost_filesystem-mt.dll
+ %LIB_DIR%\libboost_regex-mt.dll
+ %LIB_DIR%\libboost_system-mt.dll
+ %LIB_DIR%\libgcc_s_dw2-1.dll
+ %LIB_DIR%\libgmp-10.dll
+ %LIB_DIR%\libicudt57.dll
+ %LIB_DIR%\libicuuc57.dll
+ %LIB_DIR%\libstdc++-6.dll
+ %LIB_DIR%\libwinpthread-1.dll
+ %APPVEYOR_BUILD_FOLDER%\libledger.dll
+
+artifacts:
+ - path: ledger-win.zip
+ name: Ledger Win32 binaries
+
+test_script:
+- C:\msys64\usr\bin\bash -lc "export MINGW_PREFIX=C:/msys64/mingw32/ CTEST_OUTPUT_ON_FAILURE=1
+ PATH=/mingw32/bin:$PATH && cd $APPVEYOR_BUILD_FOLDER &&
+ make test || echo Errors from tests were ignored"
diff --git a/contrib/ParseCcStmt.cs b/contrib/ParseCcStmt.cs
index d5a42fbd..52fc6f64 100644
--- a/contrib/ParseCcStmt.cs
+++ b/contrib/ParseCcStmt.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/contrib/non-profit-audit-reports/cash-receipts-and-disbursments-journals.plx b/contrib/non-profit-audit-reports/cash-receipts-and-disbursments-journals.plx
index 937d2a45..f2055a62 100755
--- a/contrib/non-profit-audit-reports/cash-receipts-and-disbursments-journals.plx
+++ b/contrib/non-profit-audit-reports/cash-receipts-and-disbursments-journals.plx
@@ -127,7 +127,7 @@ foreach my $typeData ({ name => 'disbursements', query => 'a<=0' },
# I thought '--sort', 'd', '--sort-xact', 'a', should
# have worked below for a good sort. Then I tried
# rather than '--sort', "d,n,a", which didn't work either.
- # I opened a bug: http://bugs.ledger-cli.org/show_bug.cgi?id=901
+ # I opened a bug: https://github.com/ledger/ledger/issues/901
my @csvRegLedgerOpts = ('-f', $tempFile, '-V', '-F', $formatString, '-w', '--sort', 'd',
'-b', $beginDate, '-e', $endDate, 'reg');
diff --git a/default.nix b/default.nix
index 30da83ec..85932da9 100644
--- a/default.nix
+++ b/default.nix
@@ -2,12 +2,16 @@
, texinfo, gnused }:
let
- rev = "20141005";
+ version = "3.1.1";
+ rev = "20161114";
in
stdenv.mkDerivation {
- name = "ledger-3.1.0.${rev}";
- src = builtins.filterSource (path: type: type != "unknown") ./.;
+ name = "ledger-${version}-${rev}";
+
+ # NOTE: fetchgit because ledger has submodules not included in the
+ # default github tarball.
+ src = ./.;
buildInputs = [ cmake boost gmp mpfr libedit python texinfo gnused ];
@@ -20,10 +24,12 @@ stdenv.mkDerivation {
cp -v "$src/lisp/"*.el $out/share/emacs/site-lisp/
'';
+ cmakeFlags = [ "-DCMAKE_INSTALL_LIBDIR=lib" ];
+
meta = {
homepage = "http://ledger-cli.org/";
description = "A double-entry accounting system with a command-line reporting interface";
- license = "BSD";
+ license = stdenv.lib.licenses.bsd3;
longDescription = ''
Ledger is a powerful, double-entry accounting system that is accessed
@@ -33,6 +39,6 @@ stdenv.mkDerivation {
'';
platforms = stdenv.lib.platforms.all;
- maintainers = with stdenv.lib.maintainers; [ simons the-kenny jwiegley ];
+ maintainers = with stdenv.lib.maintainers; [ the-kenny jwiegley ];
};
}
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index e463c721..d8242eeb 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -42,7 +42,7 @@ if (BUILD_DOCS)
find_program(TEX tex)
find_program(MAN2HTML man2html)
find_program(GROFF groff)
- set(ledger_info_files ledger3.texi ledger-mode.texi)
+ set(ledger_info_files ledger3.texi)
if (NOT MAKEINFO)
message(WARNING "Could not find makeinfo. Info version of documentation cannot be built.")
diff --git a/doc/NEWS b/doc/NEWS
index af89de0c..0cb4b2b9 100644
--- a/doc/NEWS
+++ b/doc/NEWS
@@ -1,5 +1,32 @@
Ledger NEWS
+* 3.1.2
+
+- Increased maximum length for regex from 255 to 4095 (bug #981).
+
+- Initialize periods from from/since clause rather than earliest
+ transaction date (bug #1159).
+
+- Check balance assertions against the amount after the posting (bug #1147).
+
+- Allow balance assertions with multiple posts to same account (bug #1187).
+
+- Fixed period duration of "every X days" and similar statements (bug #370).
+
+- Option --force-color does not require --color anymore (bug #1109).
+
+- Added quoted_rfc4180 to allow CVS output with RFC 4180 compliant quoting.
+
+- Python: Removed double quotes from Unicode values.
+
+- Emacs Lisp files have been moved to https://github.com/ledger/ledger-mode
+
+- Fixed build under MSYS (32-bit).
+
+- Fixed build under Cygwin.
+
+- Various documentation improvements
+
* 3.1.1
- Added a --no-revalued option
diff --git a/doc/ledger-mode.texi b/doc/ledger-mode.texi
deleted file mode 100644
index 8ff284b1..00000000
--- a/doc/ledger-mode.texi
+++ /dev/null
@@ -1,1193 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-
-@setfilename ledger-mode.info
-@settitle Ledger: Command-Line Accounting
-
-@c Before release, run C-u C-c C-u C-a (texinfo-all-menus-update with
-@c a prefix arg). This updates the node pointers, which texinfmt.el
-@c needs.
-
-@copying
-
-Copyright @copyright{} 2013, Craig Earls. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-@itemize
-
-@item
-Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-
-@item
-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.
-
-@item
-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.
-
-@end itemize
-
-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.
-
-@end copying
-
-@dircategory Major Modes
-@direntry
-* Ledger Mode: (ledger-mode). Command-Line Accounting
-@end direntry
-
-@documentencoding UTF-8
-
-@iftex
-@finalout
-@end iftex
-
-@titlepage
-@title Ledger Mode
-@subtitle Emacs Support For Version 3.0 of Ledger
-@author Craig Earls
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@contents
-
-@ifnottex
-
-@node Top, Introduction to Ledger-mode, (dir), (dir)
-@top Overview
-
-Ledger is a command line accounting tool that provides double-entry
-accounting based on a text journal. It provides no bells or whistles,
-and returns the user to the days before user interfaces were even
-a 1twinkling in their father's CRT.
-
-Ledger-mode assists you in maintaining input files for Ledger, running
-reports and much more...
-
-@end ifnottex
-
-@menu
-* Introduction to Ledger-mode::
-* The Ledger Buffer::
-* The Reconcile Buffer::
-* The Report Buffer::
-* Scheduling Transactions::
-* Customizing Ledger-mode::
-* Generating Ledger Regression Tests::
-* Embedding Example results in Ledger Documentation::
-* Hacking Ledger-mode::
-* Concept Index::
-* Command & Variable Index::
-* Keystroke Index::
-@end menu
-
-@node Introduction to Ledger-mode, The Ledger Buffer, Top, Top
-@chapter Introduction to Ledger-mode
-
-@menu
-* Quick Installation::
-* Menus::
-* Quick Demo::
-@end menu
-
-@node Quick Installation, Menus, Introduction to Ledger-mode, Introduction to Ledger-mode
-@section Quick Installation
-@cindex installation
-
-The Emacs lisp source for Ledger-mode is included with the source
-distribution of Ledger. It is entirely included in the @file{lisp}
-subdirectory. To use Ledger-mode, include the following in your Emacs
-initialization file (@file{~/.emacs}, @file{~/.emacs.d/init.el}, or
-@file{~/.Aquamacs/Preferences.el}).
-
-@lisp
-(autoload 'ledger-mode "ledger-mode" "A major mode for Ledger" t)
-(add-to-list 'load-path
- (expand-file-name "/path/to/ledger/source/lisp/"))
-(add-to-list 'auto-mode-alist '("\\.ledger$" . ledger-mode))
-@end lisp
-
-This sets up Emacs to automatically recognize files that end with
-@file{.ledger} and start Ledger-mode. Nothing else should be required
-as long as the ledger command line utility is properly installed.
-
-@node Menus, Quick Demo, Quick Installation, Introduction to Ledger-mode
-@section Menus
-@cindex menu
-
-The vast majority of Ledger-mode functionality is available from the
-Emacs menu system. The keystrokes are shown in the menu to help you
-learn the faster keyboard methods.
-
-@node Quick Demo, , Menus, Introduction to Ledger-mode
-@section Quick Demo
-@cindex demo
-
-Load the demo file @file{demo.ledger} from the Ledger source
-@file{test/input} directory. The ledger will be loaded and font
-highlighted. At this point you could manually edit transactions and run
-Ledger from a convenient command line.
-
-@menu
-* Quick Add::
-* Reconciliation::
-* Reports::
-* Narrowing::
-@end menu
-
-@node Quick Add, Reconciliation, Quick Demo, Quick Demo
-@subsection Quick Add
-@kindex C-c TAB
-@kindex C-c C-a
-
-As simple as the Ledger transaction format is, it can still be daunting
-to add many transactions manually. Ledger provides two way to add
-transactions with minimal typing. Both are based on the idea that most
-transactions are repetitions of earlier transactions.
-
-In the @file{demo.ledger} buffer enter a date using the correct
-format. Then type the first few characters of another payee in the
-@file{demo.ledger} buffer. Type @kbd{C-c TAB}. Ledger-mode will
-search for a Payee that has the same beginning and copy the rest of the
-transaction to you new entry.
-
-Additionally you can use the ledger @command{xact} command, by either
-typing @kbd{C-c C-a} or using @samp{Add Transaction} menu entry. Then
-typing a close match to the payee. Ledger-mode will call @command{ledger
-xact} with the data you enter and place the transaction in the proper
-chronological place in the ledger.
-
-If you need to add a lot of transactions that are not near your current
-date you can set the current year and month so that using @samp{Add
-Transaction} will prompt you with a more convenient month and year. To
-set the month type @kbd{C-c RET} and enter the month you want. @kbd{C-c
-C-y} will prompt you for the year. These settings only effect the
-@samp{Add Transaction} command.
-
-@node Reconciliation, Reports, Quick Add, Quick Demo
-@subsection Reconciliation
-@kindex C-c C-r
-@kindex SPC
-@kindex C-c C-c
-@kindex q
-
-The biggest task of maintaining a ledger is ensuring that it matches the
-outside world. This process is called reconciliation (@pxref{Basics of
-Reconciliation}) and can be quite onerous. Ledger-mode attempts to make
-it as painless as possible.
-
-In the @file{demo.ledger} buffer type @kbd{C-c C-r}. If cursor is on an
-account, Ledger-mode will propose this account, or in the Minibuffer,
-will prompt for an account to reconcile. Hit @kbd{RET} if you are happy
-with proposed account, or enter @samp{Checking} as example.
-Emacs will then prompt for a target value. The target value is the
-amount you want the cleared transactions in the buffer to total.
-Normally this would be the ending value from your bank statement, or the
-latest value in your on-line transaction summary. Enter @samp{1710}.
-Note that Ledger-mode assumes your are using @samp{$} (USD) as your
-default commodity, this can be easily changed in the customization
-variables. @xref{Ledger-mode Customization}.
-
-You now see a list of uncleared transactions in a buffer below the
-@file{demo.ledger} buffer. Touching the @kbd{SPC} bar will mark
-a transaction as pending and display the current cleared (and pending)
-balance, along with the difference remaining to meet your target. Clear
-the first three transactions, and you will see the difference to target
-reach @samp{$0}. End the reconciliation by typing @kbd{C-c C-c}. This
-saves the @file{demo.ledger} buffer and marks the transactions and
-finally cleared. Type @kbd{q} to close out the reconciliation buffer.
-
-@node Reports, Narrowing, Reconciliation, Quick Demo
-@subsection Reports
-@kindex C-c C-o C-r
-@kindex C-c C-c
-
-The real power of Ledger is in it reporting capabilities. Reports can
-be run and displayed in a separate Emacs buffer. In the
-@file{demo.ledger} buffer, type @kbd{C-c C-o C-r}. In the Minibuffer
-Emacs will prompt for a report name. There are a few built-in reports,
-and you can add any report you need @xref{Adding and Editing Reports}.
-
-In the Minibuffer type @samp{account}. When prompted for an account
-type @samp{checking}. In a buffer named @file{*Ledger Report*}, you
-will see a Ledger register report. You can move around the buffer, with
-the point on a transaction, type @kbd{RET}. Ledger-mode will take you
-directly to that transaction in the @file{demo.ledger} buffer.
-
-Another built-in report is the balance report. In the
-@file{demo.ledger} buffer, type @kbd{C-c C-o C-r}. When prompted for
-a report to run, type @samp{bal}, and a balance report of all accounts
-will be shown.
-
-@node Narrowing, , Reports, Quick Demo
-@subsection Narrowing
-@kindex C-c C-f
-@kindex C-c C-g
-
-A ledger file can get very large. It can be helpful to collapse the
-buffer to display only the transactions you are interested in.
-Ledger-mode copies the @command{occur} mode functionality. Typing
-@kbd{C-c C-f} and entering any regex in the Minibuffer will show only
-transactions that match the regex. The regex can be on any field, or
-amount. Use @kbd{C-c C-g} after editing transactions to re-apply the
-current regex. Cancel the narrowing by typing @kbd{C-c C-f} again.
-
-@node The Ledger Buffer, The Reconcile Buffer, Introduction to Ledger-mode, Top
-@chapter The Ledger Buffer
-
-@menu
-* Adding Transactions::
-* Copying Transactions::
-* Editing Amounts::
-* Marking Transactions::
-* Formatting Transactions::
-* Deleting Transactions::
-* Sorting Transactions::
-* Narrowing Transactions::
-@end menu
-
-
-@node Adding Transactions, Copying Transactions, The Ledger Buffer, The Ledger Buffer
-@section Adding Transactions
-@findex ledger-post-auto-adjust-amounts
-@findex ledger-post-amount-alignment-column
-@kindex TAB
-@cindex transaction, adding
-
-Beyond the two ways of quickly adding transactions (@pxref{Quick Add})
-Ledger-mode assists you by providing robust @kbd{TAB} completion for
-payees and accounts. Ledger-mode will scan the existing buffer for
-payees and accounts. Included files are not currently included in the
-completion scan. Repeatedly hitting @kbd{TAB} will cycle through the
-possible completions.
-
-Ledger-mode can also help you keep your amounts aligned. Setting
-@option{ledger-post-auto-adjust-amounts} to true tells Ledger-mode to
-automatically place any amounts such that their last digit is aligned to
-the column specified by @option{ledger-post-amount-alignment-column},
-which defaults to @samp{52}. @xref{Ledger Post Customization Group}.
-
-@menu
-* Setting a Transactions Effective Date::
-* Quick Balance Display::
-@end menu
-
-@node Setting a Transactions Effective Date, Quick Balance Display, Adding Transactions, Adding Transactions
-@subsection Setting a Transactions Effective Date
-@kindex C-c C-t
-@cindex effective date
-
-Ledger provides for adding information to a transaction that add details
-to the dates. For example, you can specify when the transaction was
-entered, when the transaction was cleared, or when individual postings
-were cleared.
-Ledger-mode refers to these additional dates as @emph{effective} dates.
-To set the effective date of a transaction, place the point in the first
-line of a transaction and type @kbd{C-c C-t}. The effective date will
-be added to the transaction. To set the effective date for an
-individual posting, place point in the posting and type @kbd{C-c C-t} and
-the effective date for that posting will be added at the end of the
-posting.
-
-@node Quick Balance Display, , Setting a Transactions Effective Date, Adding Transactions
-@subsection Quick Balance Display
-@kindex C-c C-p
-@cindex balance
-
-You will often want to quickly check the balance of an account. The
-easiest way it to position point on the account you are interested in,
-and type @kbd{C-c C-p}. The Minibuffer will ask you to verify the name
-of the account you want, if it is already correct hit @kbd{RET}, then
-the balance of the account will be displayed in the Minibuffer.
-
-@node Copying Transactions, Editing Amounts, Adding Transactions, The Ledger Buffer
-@section Copying Transactions
-@kindex C-c C-k
-@cindex transaction, copying
-
-An easy way to copy a transaction is to type @kbd{C-c C-k} or menu entry
-@samp{Copy Trans at Point}. You will be prompted the new date for the
-copied transaction, and after having confirmed with @kbd{RET}, new
-transaction will be inserted at @emph{date} position in buffer.
-
-@node Editing Amounts, Marking Transactions, Copying Transactions, The Ledger Buffer
-@section Editing Amounts
-@kindex C-c C-b
-@kindex y
-@cindex Calc
-@cindex GNU Emacs Calculator
-@cindex transaction, editing amounts
-
-GNU Emacs Calculator, aka @samp{Calc}, is a very powerful Reverse Polish
-Notation calculator built into all recent version of Emacs. Ledger-mode
-makes it easy to calculate values for amount by integrating
-@command{Calc}. With the point anywhere in the same line as a posting,
-typing @kbd{C-c C-b} will bring up the @file{Calc} buffer, and push the
-current amount for the posting onto the top of the @command{Calc} stack.
-Perform any calculations you need to arrive at the final value, then
-type @kbd{y} to yank the value at the top of stack back into the ledger
-buffer. Note: @command{Calc} does not directly support commas as
-decimal separators. Ledger-mode will translate values from
-decimal-comma format to decimal-period format for use in @command{Calc},
-but it cannot intercept the value being yanked form the @command{Calc}
-stack, so decimal-comma users will have to manually replace the period
-with a comma.
-
-@node Marking Transactions, Formatting Transactions, Editing Amounts, The Ledger Buffer
-@section Marking Transactions
-@cindex transaction, marking
-@cindex uncleared
-@cindex pending
-@cindex cleared
-
-Ledger considers transaction or posting to be in one of three states:
-uncleared, cleared, and pending. For calculation Ledger ignores these
-states unless specifically instructed to use them. Ledger-mode assigns
-some additional meaning to the states:
-
-@itemize
-
-@item Uncleared.
-No state. This is equivalent to sticking a check in the mail. It has
-been obligated, but not been cashed by the recipient. It could also
-apply to credit/debit card transactions that have not been cleared into
-your account balance. You bank may call these transactions @emph{pending},
-but Ledger-mode uses a slightly different meaning.
-
-@item Pending.
-Ledger-mode's reconciliation function see pending transactions as an
-intermediate step in reconciling an account. When doing
-a reconciliation (@pxref{Reconciliation}), marking a transaction as
-pending means that you have seen the transaction finally recorded by the
-recipient, but you have not completely reconciled the account.
-
-@item Cleared.
-The transaction has been completely recognized by all parties to the
-transaction.
-
-@end itemize
-
-@kindex C-c C-c
-@kindex C-c C-e
-
-Typing @kbd{C-c C-c}, depending where is the point, will clear the
-complete transaction, or an individual posting. This places an asterisk
-@samp{*} prior to the payee for the complete transaction, or prior to
-the account for an individual posting. When point is inside
-a transaction, specifically on an individual posting, you can still
-clear the complete transaction by typing @kbd{C-c C-e}.
-
-@node Formatting Transactions, Deleting Transactions, Marking Transactions, The Ledger Buffer
-@section Formatting Transactions
-@cindex transaction, formatting
-
-When editing a transaction, liberal use of the @kbd{TAB} key can keep
-the transaction well formatted. If you want to have Ledger-mode cleanup
-the formatting of a transaction you can use @samp{Align Transaction} or
-@samp{Align Region} from the menu bar.
-
-The menu item @samp{Clean-up Buffer} sorts all transactions in the buffer
-by date, removes extraneous empty lines and aligns every transaction.
-
-
-@node Deleting Transactions, Sorting Transactions, Formatting Transactions, The Ledger Buffer
-@section Deleting Transactions
-@kindex C-c C-d
-@cindex transaction, deleting
-
-Along with normal buffer editing methods to delete text, Ledger-mode
-provides an easy way to delete the transaction under point: @kbd{C-c
-C-d}. The advantage to using this method is that the complete
-transaction operation is in the undo buffer.
-
-@node Sorting Transactions, Narrowing Transactions, Deleting Transactions, The Ledger Buffer
-@section Sorting Transactions
-@kindex C-c C-s
-@cindex transaction, sorting
-
-As you operating on the Ledger files, they may become disorganized. For
-the most part, Ledger doesn't care, but our human brains prefer a bit of
-order. Sorting the transactions in a buffer into chronological order
-can help bring order to chaos. Either using @samp{Sort Region} menu
-entry or typing @kbd{C-c C-s} will sort all of the transactions in
-a region by date. Ledger-mode isn't particularly smart about handling
-dates and it simply sorts the transactions using the string at the
-beginning of the transaction. So, you should use the preferred ISO 8601
-standard date format @samp{YYYY/MM/DD} which easily sorts.
-
-Note, there is a menu entry @samp{Sort Buffer} to sort the entire
-buffer. Special transactions like automated transaction, will be moved
-in the sorting process and may not function correctly afterwards. For
-this reason there is no key sequence.
-
-You can limit the allowed sort region by using embedded Ledger-mode
-markup within your ledger. For example:
-
-@example
-<<< information to not sort >>>
-
-; Ledger-mode: Start sort
-
-<<< transactions to sort >>>
-
-; Ledger-mode: End sort
-
-<<< information to not sort >>>
-@end example
-
-You can use menu entries @samp{Mark Sort Beginning} to insert start and
-@samp{Mark Sort End} to insert end markers. These functions will
-automatically delete old markers and put new new marker at point.
-
-@node Narrowing Transactions, , Sorting Transactions, The Ledger Buffer
-@section Narrowing Transactions
-@kindex C-c C-f
-@kindex C-c C-g
-@cindex transaction, narrowing
-@cindex transaction, display filtering
-
-Often you will want to run Ledger register reports just to look at
-a specific set of transactions. If you don't need the running total
-calculation handled by Ledger, Ledger-mode provides a rapid way of
-narrowing what is displayed in the buffer in a way that is simpler than
-the Ledger register command.
-
-Based on the Emacs Occur mode by Alexey Veretennikov, Ledger-occur hides
-all transactions that do @emph{not} meet a specific regular expression.
-The regular expression can match on any part of the transaction. If you
-want to find all transactions whose amount ends in @samp{.37}, you can
-do that (I don't know why, but hey, whatever ever floats you aerostat).
-
-Using @kbd{C-c C-f} or the @samp{Narrow to Regex} menu entry, enter a
-regular expression in the Minibuffer. Ledger-mode will hide all other
-transactions. For details of the regular expression syntax, see your
-Emacs documentation. A few examples using the @file{demo.ledger} are
-given here:
-
-@table @samp
-
-@item Groceries
-Show only transactions that have a posting to the @samp{Groceries}
-account.
-
-@item ^2011/01
-Show only transactions occurring in January of 2011.
-
-@item ^2011/.*/25
-Show only transactions occurring on the 25th of the month in 2011.
-
-@item auto
-Show only transactions with payees or accounts or comments containing.
-@samp{auto}
-
-@item harley$
-Show only transactions with any line ending with @samp{harley}.
-
-@end table
-
-To show back all transactions simply invoke @samp{Narrow to Regex} or
-@kbd{C-c C-f} again.
-
-If you've edited some transactions after narrowing such that they would
-no longer match the regular expression, you can refresh the narrowed
-view using @kbd{C-c C-g}.
-
-@node The Reconcile Buffer, The Report Buffer, The Ledger Buffer, Top
-@chapter The Reconcile Buffer
-
-@menu
-* Basics of Reconciliation::
-* Starting a Reconciliation::
-* Mark Transactions Pending::
-* Edit Transactions During Reconciliation::
-* Finalize Reconciliation::
-* Adding and Deleting Transactions during Reconciliation::
-* Changing Reconciliation Account::
-* Changing Reconciliation Target::
-@end menu
-
-@node Basics of Reconciliation, Starting a Reconciliation, The Reconcile Buffer, The Reconcile Buffer
-@section Basics of Reconciliation
-@cindex reconciliation, basics
-
-Even in this relatively modern era, financial transactions do not happen
-instantaneously, unless you are paying cash. When you swipe your debit
-card the money may take several days to actually come out of your
-account, or a check may take several days to @emph{clear}. That is the
-root of the difference between @emph{obligating} funds and
-@emph{expending} funds. Obligation says you have agreed to pay it, the
-expenditure doesn't happen until the money actually leaves your
-account. Or in the case of receiving payment, you have an account
-receivable until the money has actually made it to you.
-
-After an account has been reconciled you have verified that all the
-transactions in that account have been correctly recorded and all
-parties agree.
-
-@node Starting a Reconciliation, Mark Transactions Pending, Basics of Reconciliation, The Reconcile Buffer
-@section Starting a Reconciliation
-@findex ledger-reconcile-default-commodity
-@kindex C-c C-r
-@cindex reconciliation, starting
-
-To start reconciling an account you must have a target, both the
-transactions that you know about and the transactions the bank knows
-about. You can get this from a monthly statement, or from checking your
-on-line transaction history. It also helps immensely to know the final
-cleared balance you are aiming for.
-
-Use menu @samp{Reconcile Account} or keyboard shortcut @kbd{C-c C-r} to
-start reconciliation.
-
-If cursor is on an account, Ledger-mode will propose this account, or in
-the Minibuffer, will prompt for an account to reconcile. Hit @kbd{RET}
-if you are happy with proposed account, or enter @samp{Checking} as
-example. Ledger-mode is not particular about what you enter for the
-account. You can leave it blank and @file{*Reconcile*} buffer will show
-you @emph{all} uncleared transactions.
-
-After you enter the account enter the target amount. It is helpful to
-enter an amount with a commodity. You can also leave it blank, you will
-be able to clear transactions but not benefit from balance calculations.
-It assumes initially that you are using @samp{$} (USD) as your default
-commodity. If you are working in a different currency you can change
-the default in variable @option{ledger-reconcile-default-commodity} to
-whatever you need. If you work in multiple commodities simply enter the
-commoditized amount (for example @samp{340 VSDX}, for 340 shares of
-VSDX).
-
-Ledger-mode reconcile cannot currently reconcile accounts that have
-multiple commodities, such as brokerage accounts. You may use
-reconciliation mode to clear transactions, but balance calculations will
-not display the complete list of commodities.
-
-@node Mark Transactions Pending, Edit Transactions During Reconciliation, Starting a Reconciliation, The Reconcile Buffer
-@section Mark Transactions Pending
-@kindex SPC
-@cindex reconciliation, transaction marking
-
-The @file{*Reconcile*} buffer will show all the uncleared transactions
-that meet the criteria set in the regex. By default uncleared
-transactions are shown in red. When you have verified that
-a transaction has been correctly and completely recorded by the opposing
-party, mark the transaction as pending using the @kbd{SPC} bar.
-Continue this process until you agree with the opposing party and the
-difference from your target is zero.
-
-@node Edit Transactions During Reconciliation, Finalize Reconciliation, Mark Transactions Pending, The Reconcile Buffer
-@section Edit Transactions during Reconciliation
-@kindex RET
-@kindex C-c C-c
-@cindex reconciliation, transaction editing
-
-If you find errors during reconciliation. You can visit the transaction
-under point in the @file{*Reconcile*} buffer by hitting the @kbd{RET}
-key. This will take you to the transaction in the Ledger buffer. When
-you have finished editing the transaction, saving the buffer will
-automatically return you to the @file{*Reconcile*} buffer and you can
-mark the transaction if appropriate.
-
-@node Finalize Reconciliation, Adding and Deleting Transactions during Reconciliation, Edit Transactions During Reconciliation, The Reconcile Buffer
-@section Finalize Reconciliation
-@cindex reconciliation, finalizing
-@kindex C-c C-c
-@kindex q
-
-Once you have marked all transactions as pending and the cleared balance
-is correct. Finish the reconciliation by typing @kbd{C-c C-c}. This
-marks all pending transactions as cleared and saves the ledger buffer.
-
-Type @kbd{q} to close out the reconciliation buffer. If variable
-@var{ledger-reconcile-finish-force-quit} is set, the reconciliation
-buffer will be killed automatically after @kbd{C-c C-c}.
-
-@node Adding and Deleting Transactions during Reconciliation, Changing Reconciliation Account, Finalize Reconciliation, The Reconcile Buffer
-@section Adding and Deleting Transactions during Reconciliation
-@kindex a
-@kindex d
-@cindex reconciliation, transaction adding and deleting
-
-While reconciling, you may find new transactions that need to be entered
-into your ledger. Simply type @kbd{a} to bring up the quick add for the
-ledger buffer.
-
-Typing @kbd{d} will delete the transaction under point in the
-@file{*Reconcile*} buffer from the ledger buffer.
-
-@node Changing Reconciliation Account, Changing Reconciliation Target, Adding and Deleting Transactions during Reconciliation, The Reconcile Buffer
-@section Changing Reconciliation Account
-@kindex g
-@cindex reconciliation, account changing
-
-You can conveniently switch the account being reconciled by typing
-@kbd{g}, and entering a new account to reconcile. This simply restarts
-the reconcile process. Any transactions that were marked @emph{pending} in
-the ledger buffer are left in that state when the account is switched.
-
-@node Changing Reconciliation Target, , Changing Reconciliation Account, The Reconcile Buffer
-@section Changing Reconciliation Target
-@kindex t
-@cindex reconciliation, target changing
-
-If for some reason during reconciliation your target amount changes,
-type @kbd{t} and enter the new target value.
-
-@node The Report Buffer, Scheduling Transactions, The Reconcile Buffer, Top
-@chapter The Report Buffer
-
-@menu
-* Running Basic Reports::
-* Adding and Editing Reports::
-* Reversing Report Order::
-@end menu
-
-@node Running Basic Reports, Adding and Editing Reports, The Report Buffer, The Report Buffer
-@section Running Reports
-@kindex C-c C-o C-r
-@kindex C-c C-o C-g
-@kindex C-c C-o C-a
-@cindex report, running
-
-The real power behind Ledger is in its amazing reporting capability.
-Ledger-mode provides easy facility to run reports directly from Emacs.
-It has four reports built-in and facilities for adding custom reports.
-
-Typing @kbd{C-c C-o C-r} or using menu @samp{Run Report} prompts
-for the name of a saved report. The built-in reports are:
-
-@table @var
-
-@item bal
-Produce a balance reports of all accounts.
-
-@item reg
-Produce a register report of all transactions.
-
-@item payee
-Prompt for a payee, then produce a register report of all transactions
-involving that payee.
-
-@item account
-Prompt for an account, then produce a register report of all
-transactions involving that account.
-
-@end table
-
-While viewing reports you can easily switch back and forth between the
-ledger buffer and the @file{*Ledger Report*} buffer. In @file{*Ledger
-Report*} buffer, typing @kbd{RET} will take you to that transaction in
-the ledger buffer. While in the ledger buffer @kbd{C-c C-o C-g} returns
-you to the @file{*Ledger Report*} buffer.
-
-By default Ledger-mode will refresh the report buffer when the ledger
-buffer is saved. If you want to rerun the report at another time
-@kbd{C-c C-o C-a}. This is useful if you have other programs altering
-your ledger file outside of Emacs.
-
-
-@node Adding and Editing Reports, Reversing Report Order, Running Basic Reports, The Report Buffer
-@section Adding and Editing Reports
-@findex ledger-reports
-@kindex M-1 C-c C-o C-r
-@kindex S
-@kindex C-c C-o C-e
-@kindex e
-@cindex report, adding and editing
-
-@menu
-* Expansion Formats::
-* Make Report Transactions Active::
-@end menu
-
-If you type a report name that Ledger-mode doesn't recognize it will
-prompt you for a ledger command line to run. That command is
-automatically saved with the name given and you can re-run it at any
-time.
-
-There are two ways to edit the command line for a report. The first is
-to provide a prefix argument to the run-report command. For example,
-type @kbd{M-1 C-c C-o C-r}. This will prompt you for the report name,
-then present the report command line to be edited. When you hit
-@kbd{RET}, the report will be run, but it will not be permanently saved.
-If you want to save it, type @kbd{S} in the @file{*Ledger Report*}
-buffer you will have the option to give it a new name, or overwrite the
-old report.
-
-Deleting reports is accomplished by typing @kbd{C-c C-o C-e} or using
-@samp{Edit Report} menu in the ledger buffer, or typing @kbd{e} in the
-@file{*Ledger Report*} buffer. This takes you to the Emacs
-customization window for the Ledger Reports variables. Use the widgets
-to delete the report you want removed.
-
-Typing @kbd{C-c C-o C-s} will prompt for a name and save the current
-report.
-
-@node Expansion Formats, Make Report Transactions Active, Adding and Editing Reports, Adding and Editing Reports
-@subsection Expansion Formats
-@cindex report, custom variable
-
-It is sometimes convenient to leave room to customize a report without
-saving the command line every time. For example running a register
-report for a specific account entered at runtime by the user. The
-built-in report @var{account} does exactly that, using a variable
-expansion to prompt the user for the account to use. There are four
-variables that can be expanded to run a report:
-
-@table @var
-
-@item ledger-file
-Returns the file to be operated on.
-
-@item payee
-Prompts for a payee.
-
-@item account
-Prompt for an account.
-
-@item tagname
-Prompt for a meta-data tag name.
-
-@item tagvalue
-Prompt for a meta-data tag value.
-
-@end table
-
-You can use these expansion values in your ledger report commands. For
-example, if you wanted to specify a register report the displayed
-transactions from a user-determined account with a particular meta-data
-tag value, you specify the following command line:
-
-@example
-ledger -f %(ledger-file) reg %(account) \
- --limit \"tag('my-tag') =~/%(value)/\"
-@end example
-
-Note how the double-quotes are escaped with back-slashes.
-
-@node Make Report Transactions Active, , Expansion Formats, Adding and Editing Reports
-@subsection Make Report Transactions Active
-@cindex report, custom command
-
-In a large register report it is convenient to be able to jump to the
-source transaction. Ledger-mode will automatically include source
-information in every register file that doesn't contain
-a @option{--subtotal} option. It does this by adding
-@option{--prepend-format='%(filename):%(beg_line):'} to the register
-report command-line you specify. You should never have to see this, but
-if there is an error in your ledger output this additional information
-may not get stripped out of the visible report.
-
-@node Reversing Report Order, , Adding and Editing Reports, The Report Buffer
-@section Reversing Report Order
-@kindex R
-@cindex report, order reversing
-
-Often, banks show their on-line transaction histories with the most
-recent transaction at the top. Ledger itself cannot do a sensible
-ledger report in reverse chronological order, if you sort on reverse
-date the calculation will also run in the opposite direction. If you
-want to compare a ledger register report to a bank report with the most
-recent transactions at the top, type @kbd{R} in the @file{*Ledger
-Report*} buffer and it will reverse the order of the transactions and
-maintain the proper mathematical sense.
-
-@node Scheduling Transactions, Customizing Ledger-mode, The Report Buffer, Top
-@chapter Scheduling Transactions
-
-The Ledger program provides for automating transactions but these
-transaction aren't @emph{real}, they only exist inside a ledger session and
-are not reflected in the actual data file. Many transactions are very
-repetitive, but may vary slightly in the date they occur on, or the
-amount. Some transactions are weekly, monthly, quarterly or annually.
-Ledger mode provides a way to schedule upcoming transaction with a
-flexible scheduler that allows you to specify the transactions in a
-separate ledger file and calculate the upcoming occurrences of those
-transactions. You can then copy the transactions into your live data
-file.
-
-@menu
-* Specifying Upcoming Transactions::
-@end menu
-
-@node Specifying Upcoming Transactions, , Scheduling Transactions, Scheduling Transactions
-@section Specifying Upcoming Transactions
-
-The format for specifying transactions is identical to Ledger's file
-format with the exception of the date field. The data field is modified
-by surrounding it with brackets and using wild cards and special
-characters to specify when the transactions should appear.
-
-@menu
-* Transactions that occur on specific dates::
-* Transactions that occur on specific days::
-@end menu
-
-@node Transactions that occur on specific dates, Transactions that occur on specific days, Specifying Upcoming Transactions, Specifying Upcoming Transactions
-@subsection Transactions that occur on specific dates
-
-Many times you will enter repetitive transactions that occur on the same
-day of the month each month. These can be specified using a wild card
-in the year and month with a fixed date in the day. The following entry
-specifies a transaction that occurs on the first and fifteenth of every
-month in every year.
-@example
-[*/*/1,15] Paycheck
- Income:Job $1000.00
- Assets:Checking
-@end example
-
-Some transactions do not occur every month. Comma separated lists of
-the months, or @samp{E} for even, or @samp{O} for odd number months can
-also be specified. The following entry specifies a bi-monthly
-exterminator bill that occurs in the even months:
-@example
-[*/E/01] Exterminator
- Expenses:Home $100.00
- Assets:Checking
-@end example
-
-@node Transactions that occur on specific days, , Transactions that occur on specific dates, Specifying Upcoming Transactions
-@subsection Transactions that occur on specific days
-
-Some transactions occur every relative to the day of the week rather
-than the date of the month. For example, many people are paid every two
-weeks without regard to the day of the month. Other events may occur on
-specific days regardless of the date. For example the following
-transactions creates a transaction every other Thursday:
-
-@example
-[2014/11/27+2Th] Paycheck
- Income:Job $1000.00
- Assets:Checking
-@end example
-
-It is necessary to specify a starting date in order for this type of
-recurrence relation to be specified. The day names are two character
-codes that default to Mo, Tu, We, Th, Fr, Sa, Su, for Monday, Tuesday,
-Wednesday, Thursday, Friday, Saturday, Sunday respectively. You can
-change the codes to something more convenient for your locale by
-customizing the ledger @option{ledger-schedule-week-days}. They must be two
-characters long.
-
-
-
-@node Customizing Ledger-mode, Generating Ledger Regression Tests, Scheduling Transactions, Top
-@chapter Customizing Ledger-mode
-
-@menu
-* Ledger-mode Customization::
-* Customization Variables::
-@end menu
-
-@node Ledger-mode Customization, Customization Variables, Customizing Ledger-mode, Customizing Ledger-mode
-@section Ledger-mode Customization
-
-Ledger-mode has several options available for configuration. All
-options can be configured through the Emacs customization menus, or
-specified in your Emacs initialization file. The complete list of
-options is shown below. To change the option using the Emacs
-customization menu, simply chose customize in the Options menu and look
-for Ledger under the data options. Alternately you can choose
-@samp{Customize Specific Group} and enter @samp{Ledger} as the group.
-
-@node Customization Variables, , Ledger-mode Customization, Customizing Ledger-mode
-@section Customization Variables
-
-@menu
-* Ledger Customization Group::
-* Ledger Reconcile Customization Group::
-* Ledger Report Customization Group::
-* Ledger Faces Customization Group::
-* Ledger Post Customization Group::
-* Ledger Exec Customization Group::
-* Ledger Test Customization Group::
-* Ledger Texi Customization Group::
-@end menu
-
-@node Ledger Customization Group, Ledger Reconcile Customization Group, Customization Variables, Customization Variables
-@subsection Ledger Customization Group
-@cindex customization, ledger-mode
-
-@ftable @option
-
-@item ledger-occur-use-face-shown
-If non-nil, use a custom face for transactions shown in
-@option{ledger-occur} mode using @option{ledger-occur-xact-face}.
-
-@item ledger-clear-whole-transactions
-If non-nil, clear whole transactions, not individual postings.
-
-@item ledger-highlight-xact-under-point
-If non-nil, highlight transaction under point using
-@option{ledger-font-highlight-face}.
-
-@end ftable
-
-@node Ledger Reconcile Customization Group, Ledger Report Customization Group, Ledger Customization Group, Customization Variables
-@subsection Ledger Reconcile Customization Group
-@cindex customization, reconcile
-
-@ftable @option
-
-@item ledger-recon-buffer-name
-Name to use for reconciliation buffer. Defaults to @file{*Reconcile*}.
-
-@item ledger-narrow-on-reconcile
-If t, limit transactions shown in main buffer to those matching
-the reconcile regex.
-
-@item ledger-buffer-tracks-reconcile-buffer
-If t, then when the cursor is moved to a new transaction in the
-@file{*Reconcile*} buffer. Then that transaction will be shown in its
-source buffer.
-
-@item ledger-reconcile-force-window-bottom
-If t, make the @file{*Reconcile*} window appear along the bottom
-of the register window and resize.
-
-@item ledger-reconcile-toggle-to-pending
-If t, then toggle between uncleared and pending @samp{!}. If
-false toggle between uncleared and cleared @samp{*}.
-
-@item ledger-reconcile-default-date-format
-Date format for the reconcile buffer. Defaults to
-@option{ledger-default-date-format}.
-
-@item ledger-reconcile-target-prompt-string
-Prompt for recon target. Defaults to "Target amount for reconciliation ".
-
-@item ledger-reconcile-buffer-header
-Header string for the reconcile buffer. If non-nil, the name of the
-account being reconciled will be substituted into the '%s'. If nil, no
-header will be displayed. Defaults to "Reconciling account %s\n\n".
-
-@item ledger-reconcile-buffer-line-format
-Format string for the ledger reconcile posting format. Available fields
-are date, status, code, payee, account, amount. The format for each
-field is %WIDTH(FIELD), WIDTH can be preceded by a minus sign which mean
-to left justify and pad the field. WIDTH is the minimum number of
-characters to display; if string is longer, it is not truncated unless
-@option{ledger-reconcile-buffer-payee-max-chars} or
-@option{ledger-reconcile-buffer-account-max-chars} is defined. Defaults to
-"%(date)s %-4(code)s %-50(payee)s %-30(account)s %15(amount)s\n"
-
-@item ledger-reconcile-buffer-payee-max-chars
-If positive, truncate payee name right side to max number of characters.
-
-@item ledger-reconcile-buffer-account-max-chars
-If positive, truncate account name left side to max number of characters.
-
-@item ledger-reconcile-sort-key
-Key for sorting reconcile buffer. Possible values are '(date)',
-'(amount)', '(payee)' or '(0)' for no sorting, i.e. using
-ledger file order. Defaults to '(0)'.
-
-@item ledger-reconcile-insert-effective-date nil
-If t, prompt for effective date when clearing transactions during
-reconciliation.
-
-@item ledger-reconcile-finish-force-quit nil
-If t, will force closing reconcile window after @kbd{C-c C-c}.
-
-@end ftable
-
-@node Ledger Report Customization Group, Ledger Faces Customization Group, Ledger Reconcile Customization Group, Customization Variables
-@subsection Ledger Report Customization Group
-@cindex customization, report
-
-@ftable @option
-
-@item ledger-reports
-Definition of reports to run.
-
-@item ledger-report-format-specifiers
-An alist mapping ledger report format specifiers to implementing
-functions.
-
-@end ftable
-
-@node Ledger Faces Customization Group, Ledger Post Customization Group, Ledger Report Customization Group, Customization Variables
-@subsection Ledger Faces Customization Group
-@cindex customization, faces
-
-Ledger Faces: Ledger-mode highlighting
-
-@ftable @option
-
-@item ledger-font-uncleared-face
-Default face for Ledger.
-
-@item ledger-font-cleared-face
-Default face for cleared @samp{*} transactions.
-
-@item ledger-font-highlight-face
-Default face for transaction under point.
-
-@item ledger-font-pending-face
-Default face for pending @samp{!} transactions.
-
-@item ledger-font-other-face
-Default face for other transactions.
-
-@item ledger-font-posting-account-face
-Face for Ledger accounts.
-
-@item ledger-font-posting-account-cleared-face
-Face for cleared Ledger accounts.
-
-@item ledger-font-posting-account-pending-face
-Face for Ledger pending accounts.
-
-@item ledger-font-posting-amount-face
-Face for Ledger amounts.
-
-@item ledger-occur-narrowed-face
-Default face for Ledger occur mode hidden transactions.
-
-@item ledger-occur-xact-face
-Default face for Ledger occur mode shown transactions.
-
-@item ledger-font-comment-face
-Face for Ledger comments.
-
-@item ledger-font-reconciler-uncleared-face
-Default face for uncleared transactions in the @file{*Reconcile*} buffer.
-
-@item ledger-font-reconciler-cleared-face
-Default face for cleared @samp{*} transactions in the @file{*Reconcile*}
-buffer.
-
-@item ledger-font-reconciler-pending-face
-Default face for pending @samp{!} transactions in the @file{*Reconcile*}
-buffer.
-
-@item ledger-font-report-clickable-face
-FIXME
-
-@end ftable
-
-@node Ledger Post Customization Group, Ledger Exec Customization Group, Ledger Faces Customization Group, Customization Variables
-@subsection Ledger Post Customization Group
-@cindex customization, post
-
-Ledger Post:
-
-@ftable @option
-
-@item ledger-post-auto-adjust-amounts
-If non-nil, then automatically align amounts to column specified in
-@option{ledger-post-amount-alignment-column}.
-
-@item ledger-post-amount-alignment-column
-The column Ledger-mode uses to align amounts.
-
-@item ledger-default-acct-transaction-indent
-Default indentation for account transactions in an entry.
-
-@item ledger-post-use-completion-engine
-Which completion engine to use: @var{iswitchb}, @var{ido}, or built-in.
-
-@item ledger-post-use-ido
-
-@end ftable
-
-@node Ledger Exec Customization Group, Ledger Test Customization Group, Ledger Post Customization Group, Customization Variables
-@subsection Ledger Exec Customization Group
-@cindex customization, executable
-
-Ledger Exec: Interface to the Ledger command-line accounting program.
-
-@ftable @option
-
-@item ledger-binary-path
-Path to the ledger executable.
-
-@item ledger-init-file-name
-Location of the ledger initialization file. nil if you don't have one.
-
-@end ftable
-
-@node Ledger Test Customization Group, Ledger Texi Customization Group, Ledger Exec Customization Group, Customization Variables
-@subsection Ledger Test Customization Group
-@cindex customization, test
-
-@ftable @option
-
-@item ledger-source-directory
-Directory where the Ledger sources are located.
-
-@item ledger-test-binary
-Directory where the debug binary.
-
-@end ftable
-
-@node Ledger Texi Customization Group, , Ledger Test Customization Group, Customization Variables
-@subsection Ledger Texi Customization Group
-@cindex customization, texi
-
-@ftable @option
-
-@item ledger-texi-sample-doc-path
-Location for sample data to be used in texi tests, defaults to
-@file{~/ledger/doc/sample.dat}.
-
-@item ledger-texi-normalization-args
-texi normalization for producing ledger output, defaults to
-@samp{--args-only --columns 80}.
-
-@end ftable
-
-@node Generating Ledger Regression Tests, Embedding Example results in Ledger Documentation, Customizing Ledger-mode, Top
-@chapter Generating Ledger Regression Tests
-
-Work in Progress.
-
-@node Embedding Example results in Ledger Documentation, Hacking Ledger-mode, Generating Ledger Regression Tests, Top
-@chapter Embedding Example results in Ledger Documentation
-
-Work in Progress.
-
-@node Hacking Ledger-mode, Concept Index, Embedding Example results in Ledger Documentation, Top
-@chapter Hacking Ledger-mode
-
-Work in Progress.
-
-@node Concept Index, Command & Variable Index, Hacking Ledger-mode, Top
-@unnumbered Concept Index
-
-@printindex cp
-
-@node Command & Variable Index, Keystroke Index, Concept Index, Top
-@unnumbered Command & Variable Index
-
-@printindex fn
-
-@node Keystroke Index, , Command & Variable Index, Top
-@unnumbered Keystroke Index
-
-@printindex ky
-
-@bye
-
-@c Local Variables:
-@c mode: texinfo
-@c TeX-master: t
-@c End:
diff --git a/doc/ledger.1 b/doc/ledger.1
index ffc7decf..fc4dd3c0 100644
--- a/doc/ledger.1
+++ b/doc/ledger.1
@@ -1,4 +1,4 @@
-.Dd March 23, 2012
+.Dd February 16, 2017
.Dt LEDGER 1
.Os
.Sh NAME
@@ -6,8 +6,8 @@
.Nd Command-line, double-entry account reporting tool
.Sh SYNOPSIS
.Nm
-.Op Ar command
.Op Ar options
+.Op Ar command
.Op Ar arguments
.Sh DESCRIPTION
.Nm
@@ -111,9 +111,8 @@ The synonym
is also accepted.
.It Ic emacs Oo Ar query Oc
Output posting and transaction data in a format readily consumed by the Emacs
-editor, in a series of Lisp forms. This is used by the
-.Pa ledger.el
-Emacs mode to process reporting data from
+editor, in a series of Lisp forms. This is used by the Emacs ledger-mode to
+process reporting data from
.Nm .
.It Ic equity Oo Ar report-query Oc
Print a transaction with a series of postings that balance current totals for
@@ -215,6 +214,9 @@ Note that a comma-separated list of expressions is allowed, in which case each
sorting term is used in order to determine the final ordering. For example,
to search by date and then amount, one would use:
.Dl ledger reg --sort 'date, amount'
+The sort order may be controlled with the '-' sign. For example, to sort in
+reverse chronological order:
+.Dl ledger reg --sort '-date'
.It Fl \-tail Ar number
Only show the last
.Ar number
@@ -1284,6 +1286,10 @@ for values that have a per-unit cost.
Surround
.Ar expression
with double-quotes.
+.It Fn quoted_rfc4180 expression
+Surround
+.Ar expression
+with double-quotes, compatible with rfc 4180.
.It Sy real
.\" Is there a difference between real and actual?
Return true if the transaction is real, i.e not a automated or virtual
diff --git a/doc/ledger3.texi b/doc/ledger3.texi
index 5e266253..45afe1ae 100644
--- a/doc/ledger3.texi
+++ b/doc/ledger3.texi
@@ -111,7 +111,7 @@
@copying
-Copyright @copyright{} 2003–2015, John Wiegley. All rights reserved.
+Copyright @copyright{} 2003--2018, 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
@@ -179,7 +179,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Ledger is a command-line accounting tool that provides double-entry
accounting based on a text journal. It provides no bells or whistles,
and returns the user to the days before user interfaces were even a
-twinkling in their father's CRT.
+twinkling in their fathers' CRTs.
@end ifnottex
@@ -212,6 +212,7 @@ twinkling in their father's CRT.
* Fat-free Accounting::
* Building the program::
* Getting help::
+* Third-Party Ledger Tutorials::
@end menu
@node Fat-free Accounting, Building the program, Introduction to Ledger, Introduction to Ledger
@@ -400,7 +401,7 @@ options. You can run `make check` to confirm the result, and `make
install` to install. If these intructions do not work for you can check the
`INSTALL.md` in the source directory for more up do date build instructions.
-@node Getting help, , Building the program, Introduction to Ledger
+@node Getting help, , Building the program, Introduction to Ledger
@section Getting help
@findex help
@@ -417,6 +418,23 @@ join the Ledger mailing list at
You can also find help in the @code{#ledger} channel on the IRC server
@code{irc.freenode.net}.
+@node Third-Party Ledger Tutorials, , Getting help, Introduction to Ledger
+@section Third-Party Ledger Tutorials
+
+There are plenty of people using Ledger for accounting applications.
+Some have documented how they use Ledger's features to solve their
+accounting problems.
+
+Once such tutorial, specifically designed for non-profit charities that seek
+to use Ledger, can be found at
+@url{https://k.sfconservancy.org/npo-ledger-cli} (with a copy on GitHub also
+available at @url{https://github.com/conservancy/npo-ledger-cli/}). If
+you're looking for information about how to use Ledger's tagging system to
+handle invoicing, track expenses by program targets, and other such concepts,
+you might find the tutorial useful. (Some of the auditor reporting scripts
+that relate to the aformentioned Ledger setup can be found
+@var{contrib/non-profit-audit-reports/} in Ledger's own source repository.)
+
@node Ledger Tutorial, Principles of Accounting with Ledger, Introduction to Ledger, Top
@chapter Ledger Tutorial
@cindex tutorial
@@ -1078,7 +1096,7 @@ $40880.00 Assets:Brokerage
You can convert from any commodity to any other commodity. Let's say
you had $5000 in your checking account, and for whatever reason you
-wanted to know many ounces of gold that would buy, in terms of the
+wanted to know how many ounces of gold that would buy, in terms of the
current price of gold:
@smallexample
@@ -1255,7 +1273,7 @@ worth $5000, then you have $5000 in equity in that car. In order to
turn that car (a commodity) into a cash flow, or a credit to your bank
account, you will have to debit the equity by selling it.
-When you start a ledger, you are probably already worth something.
+When you start a ledger, you probably already have a net worth.
Your net worth is your current equity. By transferring the money in
the ledger from your equity to your bank accounts, you are crediting
the ledger account based on your prior equity. That is why, when you
@@ -1339,7 +1357,7 @@ account point of view and from the fund point of view---yet both sets
should reflect the same overall expenses and cash flow. It's simply
where the money resides that differs.
-This situation can be handled one of two ways. The first is using
+This situation can be handled in one of two ways. The first is using
virtual postings to represent the fact that money is moving to and
from two kind of accounts at the same time:
@@ -1490,13 +1508,14 @@ nature of your transactions.
For example, you do not need to tell Ledger about the accounts you
use. Any time Ledger sees a posting involving an account it knows
nothing about, it will create it@footnote{This also means if you
-misspell an account it will end up getting counted separately from what
-you intended. The provided Emacs major mode provides for automatically
-filling in account names.}. If you use a commodity that is new to
-Ledger, it will create that commodity, and determine its display
-characteristics (placement of the symbol before or after the amount,
-display precision, etc.) based on how you used the commodity in the
-posting.
+misspell an account it will end up getting counted separately from
+what you intended. An Emacs major mode
+@uref{https://github.com/ledger/ledger-mode/, ledger-mode} provides
+tab completion for automatically filling in account names.}. If you
+use a commodity that is new to Ledger, it will create that commodity,
+and determine its display characteristics (placement of the symbol
+before or after the amount, display precision, etc.) based on how you
+used the commodity in the posting.
@menu
* The Most Basic Entry::
@@ -1976,7 +1995,7 @@ amount using the @samp{(( ))} commodity annotation.
2012-03-07 KFC
Expenses:Food7 1 CAD
- Assets:Cas7
+ Assets:Cash7
2012-03-08 XACT
Expenses:Food8 $1
@@ -2236,6 +2255,41 @@ Would result in all postings going into
@samp{Personal:Expenses:Groceries} and @samp{Personal:Assets:Checking}
until an @samp{end apply account} directive was found.
+@item apply fixed
+@findex fixed
+@cindex fixated prices
+@c instance_t::fixed_directive in textual.cc
+
+A fixed block is used to set fixated prices (@pxref{Fixated prices and
+costs}) for a series of transactions. It's purely a typing saver, for
+use when entering many transactions with fixated prices.
+
+Thus, the following:
+
+@smallexample @c input:validate
+apply fixed CAD $0.90
+2012-04-10 Lunch in Canada
+ Assets:Wallet -15.50 CAD
+ Expenses:Food 15.50 CAD
+
+2012-04-11 Second day Dinner in Canada
+ Assets:Wallet -25.75 CAD
+ Expenses:Food 25.75 CAD
+end apply fixed
+@end smallexample
+
+is equivalent to this:
+
+@smallexample @c input:validate
+2012-04-10 Lunch in Canada
+ Assets:Wallet -15.50 CAD @{=$0.90@}
+ Expenses:Food 15.50 CAD @{=$0.90@}
+
+2012-04-11 Second day Dinner in Canada
+ Assets:Wallet -25.75 CAD @{=$0.90@}
+ Expenses:Food 25.75 CAD @{=$0.90@}
+@end smallexample
+
@item alias
@findex alias
@cindex account, alias
@@ -2383,6 +2437,7 @@ commodity $
note American Dollars
format $1,000.00
nomarket
+ alias USD
default
@end smallexample
@@ -2397,6 +2452,9 @@ provide the ``canonical'' representation.
The @code{nomarket} sub-directive states that the commodity's price
should never be auto-downloaded.
+The @code{alias} sub-directive states that any commodity matching this
+symbol is to use the commodity declared in this block.
+
The @code{default} sub-directive marks this as the ``default'' commodity.
@item define
@@ -2417,59 +2475,18 @@ The posting will have a cost of $400.
@item end
@findex end
@c instance_t::end_directive in textual.cc
-Closes block commands like @code{tag} or @code{comment}.
+Closes block commands like @code{apply} or @code{comment}.
@item expr
@findex expr
@c instance_t::expr_directive in textual.cc
-@item fixed
-@findex fixed
-@cindex fixated prices
-@c instance_t::fixed_directive in textual.cc
-
-A fixed block is used to set fixated prices (@pxref{Fixated prices and
-costs}) for a series of transactions. It's purely a typing saver, for
-use when entering many transactions with fixated prices.
-
-Thus, the following:
-
-@smallexample @c input:validate
-fixed CAD $0.90
-2012-04-10 Lunch in Canada
- Assets:Wallet -15.50 CAD
- Expenses:Food 15.50 CAD
-
-2012-04-11 Second day Dinner in Canada
- Assets:Wallet -25.75 CAD
- Expenses:Food 25.75 CAD
-endfixed CAD
-@end smallexample
-
-is equivalent to this:
-
-@smallexample @c input:validate
-2012-04-10 Lunch in Canada
- Assets:Wallet -15.50 CAD @{=$0.90@}
- Expenses:Food 15.50 CAD @{=$0.90@}
-
-2012-04-11 Second day Dinner in Canada
- Assets:Wallet -25.75 CAD @{=$0.90@}
- Expenses:Food 25.75 CAD @{=$0.90@}
-@end smallexample
-
-Note that ending a @code{fixed} is done differently than other
-directives, as @code{fixed} is closed with an @code{endfixed} (i.e.,
-there is @emph{no space} between @code{end} and @code{fixed}).
-
-For the moment, users may wish to study
-@uref{http://bugs.ledger-cli.org/show_bug.cgi?id=789, Bug Report 789}
-before using the @code{fixed} directive in production.
-
@item include
@findex include
@c instance_t::include_directive in textual.cc
-Include the stated file as if it were part of the current file.
+Include the stated file as if it were part of the current file. The file
+name can contain a wildcard (@samp{*}) to refer to multiple files (e.g.
+@samp{bank/*.ledger}).
@item payee
@findex payee
@@ -2714,14 +2731,17 @@ that make it very simple: @command{print}, and @command{equity}.
Let's take an example file, with data ranging from year 2000 until
2004. We want to archive years 2000 and 2001 to their own file,
-leaving just 2003 and 2004 in the current file. So, use
-@command{print} to output all the earlier transactions to a file
-called @file{ledger-old.dat}:
+leaving 2002--2004 in the current file. So, use @command{print} to
+output all the earlier transactions to a file called
+@file{ledger-old.dat}:
@smallexample
-$ ledger -f ledger.dat -b 2000 -e 2001 print > ledger-old.dat
+$ ledger -f ledger.dat -b 2000 -e 2002 print > ledger-old.dat
@end smallexample
+Note that @option{-e} limits output to transactions @emph{before} the
+date specified.
+
To delete older data from the current ledger file, use @command{print}
again, this time specifying year 2002 as the starting date:
@@ -2892,7 +2912,7 @@ you a place to put those codes:
A transaction can have a ``state'': cleared, pending, or uncleared. The
default is uncleared. To mark a transaction cleared, put an asterisk
-@samp{*} before the payee, after the date or code:
+@samp{*} after the date, before the code or payee:
@smallexample @c input:validate
2012-03-10 * KFC
@@ -2950,7 +2970,7 @@ You can mark individual postings as cleared or pending, in case one
@section Transaction notes
After the payee, and after at least one tab or two spaces (or a space
-and a tab, which Ledger calls a ``hard separator''), you may
+and a tab), which Ledger calls a ``hard separator'', you may
introduce a note about the transaction using the @samp{;} character:
@smallexample @c input:validate
@@ -3052,7 +3072,7 @@ used as the payee name for that posting. This affects the
This is useful when for example you deposit 4 checks at a time to the
bank. On the bank statement, there is just one amount @samp{$400}, but
-you can specify from whom each check came from, as shown by example
+you can specify from whom each check came, as shown by example
below:
@smallexample @c input:9B43E57
@@ -3210,6 +3230,45 @@ A balance assertion has this general form:
This simply asserts that after subtracting $20.00 from Assets:Cash,
that the resulting total matches $500.00. If not, it is an error.
+The assertion has an effect only on the specified commodity. If an account has
+multiple commodities, then only the one asserted is verified:
+
+@smallexample
+2012-03-10 KFC New York
+ Expenses:Food $20.00
+ Assets:Cash $-20.00 = $500.00
+
+2012-03-11 KFC Montreal
+ Expenses:Food 15.00 CAD
+ Assets:Cash -15.00 CAD = $500.00
+@end smallexample
+
+In this case, the amount in USD of cash (which has not changed) is validated.
+Nothing is asserted about the current amount of Canadian dollars in @samp{Asset:Cash}.
+
+@subsubsection Special assertion value 0
+
+The only value that can be asserted without a commodity is @samp{0}.
+This results in a cross-commodities assertion, which makes it possible to
+assert that an account is totally empty.
+
+@smallexample
+2012-03-09 Fill Wallet
+ Revenue $20.00
+ Revenue 15.00 CAD
+ Assets:Cash
+
+2012-03-10 KFC New York
+ Expenses:Food $20.00
+ Assets:Cash $-20.00
+
+2012-03-11 KFC Montreal
+ Expenses:Food 15.00 CAD
+ Assets:Cash -15.00 CAD = 0
+@end smallexample
+
+The last transaction will assert that we are out of cash of any sort.
+
@node Balance assignments, Resetting a balance, Balance assertions, Balance verification
@subsection Balance assignments
@@ -3238,7 +3297,7 @@ adjustment transaction using balance assignments:
Equity:Adjustments
@end smallexample
-Since the second posting is also null, it's value will become the
+Since the second posting is also null, its value will become the
inverse of whatever amount is generated for the first posting.
This is the only time in ledger when more than one posting's amount
@@ -3501,7 +3560,7 @@ But this does not do what you might expect:
@smallexample
2012-04-10 My Broker
Assets:Brokerage 10 AAPL @@ $50.00
- Assets:Brokerage:Cash $750.00
+ Assets:Brokerage:Cash $-500.00
2012-04-10 My Broker
Assets:Brokerage:Cash $375.00
@@ -3527,11 +3586,11 @@ following two transactions are equivalent:
@smallexample
2012-04-10 My Broker
Assets:Brokerage 10 AAPL @@ $50.00
- Assets:Brokerage:Cash $750.00
+ Assets:Brokerage:Cash $-500.00
2012-04-10 My Broker
Assets:Brokerage 10 AAPL @{$50.00@}
- Assets:Brokerage:Cash $750.00
+ Assets:Brokerage:Cash $-500.00
@end smallexample
However, note that what you see in some reports may differ, for
@@ -3542,15 +3601,16 @@ sensitive to this difference.
@node Fixated prices and costs, Lot dates, Prices versus costs, Transactions
@section Fixated prices and costs
-If you buy a stock last year, and ask for its value today, Ledger will
-consult its price database to see what the most recent price for that
-stock is. You can short-circuit this lookup by ``fixing'' the price
-at the time of a transaction. This is done using @samp{@{=AMOUNT@}}:
+If you bought a stock last year, and ask for its value today, Ledger
+will consult its price database to see what the most recent price for
+that stock is. You can short-circuit this lookup by ``fixing'' the
+price at the time of a transaction. This is done using
+@samp{@{=AMOUNT@}}:
@smallexample
2012-04-10 My Broker
Assets:Brokerage 10 AAPL @{=$50.00@}
- Assets:Brokerage:Cash $750.00
+ Assets:Brokerage:Cash $-500.00
@end smallexample
These 10 AAPL will now always be reported as being worth $50, no
@@ -3566,7 +3626,7 @@ fixated prices by way of the cost:
@smallexample
2012-04-10 My Broker
Assets:Brokerage 10 AAPL @@ =$50.00
- Assets:Brokerage:Cash $750.00
+ Assets:Brokerage:Cash $-500.00
@end smallexample
This is the same as the previous transaction, with the same caveats
@@ -6234,11 +6294,25 @@ Specify the format to use for the @command{budget} report (@pxref{Format
Strings}). The default is:
@smallexample
-"%(justify(scrub(display_total), 20, -1, true, color))"
+"%(justify(scrub(get_at(display_total, 0)), 12, -1, true, color))"
+" %(justify(-scrub(get_at(display_total, 1)), 12, "
+" 12 + 1 + 12, true, color))"
+" %(justify(scrub(get_at(display_total, 1) + "
+" get_at(display_total, 0)), 12, "
+" 12 + 1 + 12 + 1 + 12, true, color))"
+" %(ansify_if("
+" justify((get_at(display_total, 1) ? "
+" (100% * quantity(scrub(get_at(display_total, 0)))) / "
+" -quantity(scrub(get_at(display_total, 1))) : 0), "
+" 5, -1, true, false),"
+" magenta if (color and get_at(display_total, 1) and "
+" (abs(quantity(scrub(get_at(display_total, 0))) / "
+" quantity(scrub(get_at(display_total, 1)))) >= 1))))"
" %(!options.flat ? depth_spacer : \"\")"
-"%-(ansify_if(partial_account(options.flat), blue if color))\n%/"
-"%$1\n%/"
-"--------------------\n"
+"%-(ansify_if(partial_account(options.flat), blue if color))\n"
+"%/%$1 %$2 %$3 %$4\n%/"
+"%(prepend_width ? \" \" * int(prepend_width) : \"\")"
+"------------ ------------ ------------ -----\n"
@end smallexample
@item --by-payee
@@ -7581,7 +7655,9 @@ option settings in the file @file{~/.ledgerrc} one option per line, for example:
@c TODO use @var below
A period expression indicates a span of time, or a reporting interval,
-or both. The full syntax is:
+or both. Ledger's end dates are always exclusive, imagine the date is
+followed by 00:00:00 time. They are instants in time not entire days.
+The full syntax is:
@smallexample
[INTERVAL] [BEGIN] [END]
@@ -8122,6 +8198,19 @@ posting.
A regular expression that matches against the transaction code (the
text that occurs between parentheses before the payee).
+@item expr any(KEYWORD =~ /REGEX/)
+The @command{any} keyword is used to specify that at least one posting of
+the transaction must match the expression in brackets. For example,
+@samp{ledger -f d reg expr "any(account =~ /Assets:/)"} can be used to
+display all transactions which involve at least one @samp{Assets:}
+account.
+
+@item expr all(KEYWORD =~ /REGEX/)
+The @command{all} keyword is used to specify that all postings of a
+transactions must match the expression in brackets. For example,
+@samp{ledger -f d reg expr "all(account =~ /Assets:/)"} can be used to
+display all transactions where all accounts are @samp{Assets:}.
+
@end table
The @command{query} command can be used to see how Ledger interprets
@@ -8340,7 +8429,7 @@ Return the quantity of @var{value} for values that have a per-unit cost.
@end defun
@defun quoted expression
-Surround @var{expression} with double-quotes.
+Surround @var{expression} with double-quotes. If expression contains a double-quote, it will be escaped with a backslash.
@smallexample @c command:EAD8AA7,with_input:3406FC1
$ ledger -f expr.dat --format "%(quoted(account)) %(quoted(amount))\n" reg
@end smallexample
@@ -8350,6 +8439,17 @@ $ ledger -f expr.dat --format "%(quoted(account)) %(quoted(amount))\n" reg
@end smallexample
@end defun
+@c @defun quoted_rfc4180 expression
+@c Surround @var{expression} with double-quotes, compliant with RFC 4180. If expression contains a double-quote, it will be represented with two double-quotes.
+@c @smallexample @c command:EAD8AA7,with_input:3406FC1
+@c $ ledger -f expr.dat --format "%(quoted_rfc4180(account)) %(quoted_rfc4180(amount))\n" reg
+@c @end smallexample
+@c @smallexample @c output:EAD8AA7
+@c "Assets:Cash" "¤ -123,45"
+@c "Expenses:Office Supplies" "¤ 123,45"
+@c @end smallexample
+@c @end defun
+
@defun round
@value{FIXME:UNDOCUMENTED}
@end defun
@@ -8935,7 +9035,7 @@ day of the month (dd), zero padded up to 10.
day of the month (dd), no leading zero up to 10.
@item %j
-day of year, zero padded 000–366.
+day of year, zero padded 000--366.
@item %u
day of week starting with Monday (1), i.e. @code{mtwtfss} 3.
@@ -8986,16 +9086,16 @@ Additional date format parameters which can be used:
@table @code
@item %U
-week number Sunday as first day of week, ranging 01–53.
+week number Sunday as first day of week, ranging 01--53.
@item %W
-week number Monday as first day of week, ranging 01–53.
+week number Monday as first day of week, ranging 01--53.
@item %V
-week of the year, ranging 01–53.
+week of the year, ranging 01--53.
@item %C
-century, ranging 00–99.
+century, ranging 00--99.
@item %D
yields @code{%m/%d/%y} as in @samp{02/10/10}.
@@ -9095,7 +9195,7 @@ Even if you don't create a session manually, one is created for you by
the top-level interface functions. The Session is where objects live
like the Commodities that Amounts refer to.
-The make a Session useful, you must read a Journal into it, using the
+To make a Session useful, you must read a Journal into it, using the
function `@code{read_journal}`. This reads Ledger data from the given
file, populates a Journal object within the current Session, and
returns a reference to that Journal object.
@@ -9168,7 +9268,7 @@ looking at its @code{xact} member:
last_xact = None
for post in ledger.read_journal("sample.dat").query(""):
if post.xact != last_xact:
- for post in post.xact.posts:
+ for post in post.xact.posts():
print "Transferring %s to/from %s" % (post.amount,
post.account)
last_xact = post.xact
diff --git a/lisp/CMakeLists.txt b/lisp/CMakeLists.txt
deleted file mode 100644
index 9dee2abb..00000000
--- a/lisp/CMakeLists.txt
+++ /dev/null
@@ -1,65 +0,0 @@
-set(EMACS_LISP_SOURCES
- ledger-commodities.el
- ledger-complete.el
- ledger-exec.el
- ledger-fontify.el
- ledger-fonts.el
- ledger-fontify.el
- ledger-init.el
- ledger-mode.el
- ledger-navigate.el
- ledger-occur.el
- ledger-post.el
- ledger-reconcile.el
- ledger-regex.el
- ledger-report.el
- ledger-schedule.el
- ledger-sort.el
- ledger-state.el
- ledger-test.el
- ledger-texi.el
- ledger-xact.el)
-
-set(EMACS_LISP_SOURCES_UNCOMPILABLE
- ledger-context.el)
-
-# find emacs and complain if not found
-find_program(EMACS_EXECUTABLE emacs)
-
-macro(add_emacs_lisp_target el)
- configure_file(${el} ${CMAKE_CURRENT_BINARY_DIR}/${el})
-
- # add rule (i.e. command) how to generate the byte-compiled file
- add_custom_command(
- OUTPUT ${el}c
- COMMAND ${EMACS_EXECUTABLE}
- -L ${CMAKE_CURRENT_BINARY_DIR}
- -l ${CMAKE_CURRENT_BINARY_DIR}/ledger-regex.el
- -batch -f batch-byte-compile
- ${CMAKE_CURRENT_BINARY_DIR}/${el}
- DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${el}
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMENT "Creating byte-compiled Emacs lisp ${CMAKE_CURRENT_BINARY_DIR}/${el}c")
-endmacro(add_emacs_lisp_target el)
-
-if (EMACS_EXECUTABLE)
- # uncompilable .el files
- foreach(el ${EMACS_LISP_SOURCES_UNCOMPILABLE})
- configure_file(${el} ${CMAKE_CURRENT_BINARY_DIR}/${el})
- list(APPEND EMACS_LISP_UNCOMPILABLE ${CMAKE_CURRENT_BINARY_DIR}/${el})
- endforeach()
-
- # compilable .el files
- foreach(el ${EMACS_LISP_SOURCES})
- add_emacs_lisp_target(${el})
- list(APPEND EMACS_LISP_BINARIES ${CMAKE_CURRENT_BINARY_DIR}/${el}c)
- endforeach()
-
- add_custom_target(emacs_lisp_byte_compile ALL DEPENDS ${EMACS_LISP_BINARIES})
-
- # install the byte-compiled emacs-lisp sources
- install(FILES ${EMACS_LISP_SOURCES} ${EMACS_LISP_BINARIES} ${EMACS_LISP_UNCOMPILABLE}
- DESTINATION share/emacs/site-lisp/ledger-mode)
-endif()
-
-### CMakeLists.txt ends here
diff --git a/lisp/ledger-commodities.el b/lisp/ledger-commodities.el
deleted file mode 100644
index b5244bdb..00000000
--- a/lisp/ledger-commodities.el
+++ /dev/null
@@ -1,151 +0,0 @@
-;;; ledger-commodities.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-;;; Commentary:
-;; Helper functions to deal with commoditized numbers. A commoditized
-;; number will be a list of value and string where the string contains
-;; the commodity
-
-;;; Code:
-
-(require 'ledger-regex)
-
-(defcustom ledger-reconcile-default-commodity "$"
- "The default commodity for use in target calculations in ledger reconcile."
- :type 'string
- :group 'ledger-reconcile)
-
-(defun ledger-read-commodity-with-prompt (prompt)
- "Read commodity name after PROMPT.
-
-Default value is `ledger-reconcile-default-commodity'."
- (let* ((buffer (current-buffer))
- (commodities (with-temp-buffer
- (ledger-exec-ledger buffer (current-buffer) "commodities")
- (split-string (buffer-string) "\n" t))))
- (completing-read prompt commodities nil t nil nil ledger-reconcile-default-commodity)))
-
-(defun ledger-split-commodity-string (str)
- "Split a commoditized string, STR, into two parts.
-Returns a list with (value commodity)."
- (let ((number-regex (if (assoc "decimal-comma" ledger-environment-alist)
- ledger-amount-decimal-comma-regex
- ledger-amount-decimal-period-regex)))
- (if (> (length str) 0)
- (with-temp-buffer
- (insert str)
- (goto-char (point-min))
- (cond
- ((re-search-forward "\"\\(.*\\)\"" nil t) ; look for quoted commodities
- (let ((com (delete-and-extract-region
- (match-beginning 1)
- (match-end 1))))
- (if (re-search-forward
- number-regex nil t)
- (list
- (ledger-string-to-number
- (delete-and-extract-region (match-beginning 0) (match-end 0)))
- com))))
- ((re-search-forward number-regex nil t)
- ;; found a number in the current locale, return it in the
- ;; car. Anything left over is annotation, the first
- ;; thing should be the commodity, separated by
- ;; whitespace, return it in the cdr. I can't think of
- ;; any counterexamples
- (list
- (ledger-string-to-number
- (delete-and-extract-region (match-beginning 0) (match-end 0)))
- (nth 0 (split-string (buffer-substring-no-properties (point-min) (point-max))))))
- ((re-search-forward "0" nil t)
- ;; couldn't find a decimal number, look for a single 0,
- ;; indicating account with zero balance
- (list 0 ledger-reconcile-default-commodity))))
- ;; nothing found, return 0
- (list 0 ledger-reconcile-default-commodity))))
-
-(defun ledger-string-balance-to-commoditized-amount (str)
- "Return a commoditized amount (val, 'comm') from STR."
- ; break any balances with multi commodities into a list
- (mapcar #'(lambda (st)
- (ledger-split-commodity-string st))
- (split-string str "[\n\r]")))
-
-(defun -commodity (c1 c2)
- "Subtract C2 from C1, ensuring their commodities match."
- (if (string= (cadr c1) (cadr c2))
- (list (-(car c1) (car c2)) (cadr c1))
- (error "Can't subtract different commodities %S from %S" c2 c1)))
-
-(defun +commodity (c1 c2)
- "Add C1 and C2, ensuring their commodities match."
- (if (string= (cadr c1) (cadr c2))
- (list (+ (car c1) (car c2)) (cadr c1))
- (error "Can't add different commodities, %S to %S" c1 c2)))
-
-(defun ledger-strip (str char)
- "Return STR with CHAR removed."
- (replace-regexp-in-string char "" str))
-
-(defun ledger-string-to-number (str &optional decimal-comma)
- "improve builtin string-to-number by handling internationalization, and return nil if number can't be parsed"
- (let ((nstr (if (or decimal-comma
- (assoc "decimal-comma" ledger-environment-alist))
- (ledger-strip str ".")
- (ledger-strip str ","))))
- (while (string-match "," nstr) ;if there is a comma now, it is a thousands separator
- (setq nstr (replace-match "." nil nil nstr)))
- (string-to-number nstr)))
-
-(defun ledger-number-to-string (n &optional decimal-comma)
- "number-to-string that handles comma as decimal."
- (let ((str (number-to-string n)))
- (when (or decimal-comma
- (assoc "decimal-comma" ledger-environment-alist))
- (while (string-match "\\." str)
- (setq str (replace-match "," nil nil str))))
- str))
-
-(defun ledger-commodity-to-string (c1)
- "Return string representing C1.
-Single character commodities are placed ahead of the value,
-longer ones are after the value."
- (let ((str (ledger-number-to-string (car c1)))
- (commodity (cadr c1)))
- (if (> (length commodity) 1)
- (concat str " " commodity)
- (concat commodity " " str))))
-
-(defun ledger-read-commodity-string (prompt)
- "Read an amount from mini-buffer using PROMPT."
- (let ((str (read-from-minibuffer
- (concat prompt " (" ledger-reconcile-default-commodity "): ")))
- comm)
- (if (and (> (length str) 0)
- (ledger-split-commodity-string str))
- (progn
- (setq comm (ledger-split-commodity-string str))
- (if (cadr comm)
- comm
- (list (car comm) ledger-reconcile-default-commodity))))))
-
-(provide 'ledger-commodities)
-
-;;; ledger-commodities.el ends here
diff --git a/lisp/ledger-complete.el b/lisp/ledger-complete.el
deleted file mode 100644
index 28b6b37a..00000000
--- a/lisp/ledger-complete.el
+++ /dev/null
@@ -1,251 +0,0 @@
-;;; ledger-complete.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-;;; Commentary:
-;; Functions providing payee and account auto complete.
-
-(require 'pcomplete)
-
-;; In-place completion support
-
-;;; Code:
-
-(defun ledger-parse-arguments ()
- "Parse whitespace separated arguments in the current region."
- ;; this is more complex than it appears to need, so that it can work
- ;; with pcomplete. See pcomplete-parse-arguments-function for
- ;; details
- (let* ((begin (save-excursion
- (ledger-thing-at-point) ;; leave point at beginning of thing under point
- (point)))
- (end (point))
- begins args)
- ;; to support end of line metadata
- (save-excursion
- (when (search-backward ";"
- (line-beginning-position) t)
- (setq begin (match-beginning 0))))
- (save-excursion
- (goto-char begin)
- (when (< (point) end)
- (skip-chars-forward " \t\n")
- (setq begins (cons (point) begins))
- (setq args (cons (buffer-substring-no-properties
- (car begins) end)
- args)))
- (cons (reverse args) (reverse begins)))))
-
-
-(defun ledger-payees-in-buffer ()
- "Scan buffer and return list of all payees."
- (let ((origin (point))
- payees-list)
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward
- ledger-payee-any-status-regex nil t) ;; matches first line
- (unless (and (>= origin (match-beginning 0))
- (< origin (match-end 0)))
- (setq payees-list (cons (match-string-no-properties 3)
- payees-list))))) ;; add the payee
- ;; to the list
- (pcomplete-uniqify-list (nreverse payees-list))))
-
-
-(defun ledger-find-accounts-in-buffer ()
- (interactive)
- (let ((origin (point))
- accounts
- (account-tree (list t))
- (account-elements nil)
- (seed-regex (ledger-account-any-status-with-seed-regex
- (regexp-quote (car pcomplete-args)))))
- (save-excursion
- (goto-char (point-min))
-
- (dolist (account
- (delete-dups
- (progn
- (while (re-search-forward seed-regex nil t)
- (unless (between origin (match-beginning 0) (match-end 0))
- (setq accounts (cons (match-string-no-properties 2) accounts))))
- accounts)))
- (let ((root account-tree))
- (setq account-elements
- (split-string
- account ":"))
- (while account-elements
- (let ((xact (assoc (car account-elements) root)))
- (if xact
- (setq root (cdr xact))
- (setq xact (cons (car account-elements) (list t)))
- (nconc root (list xact))
- (setq root (cdr xact))))
- (setq account-elements (cdr account-elements))))))
- account-tree))
-
-(defun ledger-accounts ()
- "Return a tree of all accounts in the buffer."
- (let* ((current (caar (ledger-parse-arguments)))
- (elements (and current (split-string current ":")))
- (root (ledger-find-accounts-in-buffer))
- (prefix nil))
- (while (cdr elements)
- (let ((xact (assoc (car elements) root)))
- (if xact
- (setq prefix (concat prefix (and prefix ":")
- (car elements))
- root (cdr xact))
- (setq root nil elements nil)))
- (setq elements (cdr elements)))
- (setq root (delete (list (car elements) t) root))
- (and root
- (sort
- (mapcar (function
- (lambda (x)
- (let ((term (if prefix
- (concat prefix ":" (car x))
- (car x))))
- (if (> (length (cdr x)) 1)
- (concat term ":")
- term))))
- (cdr root))
- 'string-lessp))))
-
-(defun ledger-complete-at-point ()
- "Do appropriate completion for the thing at point."
- (interactive)
- (while (pcomplete-here
- (if (eq (save-excursion
- (ledger-thing-at-point)) 'transaction)
- (if (null current-prefix-arg)
- (delete
- (caar (ledger-parse-arguments))
- (ledger-payees-in-buffer)) ;; this completes against payee names
- (progn
- (let ((text (buffer-substring-no-properties
- (line-beginning-position)
- (line-end-position))))
- (delete-region (line-beginning-position)
- (line-end-position))
- (condition-case nil
- (ledger-add-transaction text t)
- (error nil)))
- (forward-line)
- (goto-char (line-end-position))
- (search-backward ";" (line-beginning-position) t)
- (skip-chars-backward " \t0123456789.,")
- (throw 'pcompleted t)))
- (ledger-accounts)))))
-
-(defun ledger-trim-trailing-whitespace (str)
- (replace-regexp-in-string "[ \t]*$" "" str))
-
-(defun ledger-fully-complete-xact ()
- "Completes a transaction if there is another matching payee in the buffer.
-Does not use ledger xact"
- (interactive)
- (let* ((name (ledger-trim-trailing-whitespace (caar (ledger-parse-arguments))))
- (rest-of-name name)
- xacts)
- (save-excursion
- (when (eq 'transaction (ledger-thing-at-point))
- (delete-region (point) (+ (length name) (point)))
- ;; Search backward for a matching payee
- (when (re-search-backward
- (concat "^[0-9/.=-]+\\(\\s-+\\*\\)?\\(\\s-+(.*?)\\)?\\s-+\\(.*"
- (regexp-quote name) ".*\\)" ) nil t)
- (setq rest-of-name (match-string 3))
- ;; Start copying the postings
- (forward-line)
- (while (looking-at ledger-account-any-status-regex)
- (setq xacts (cons (buffer-substring-no-properties
- (line-beginning-position)
- (line-end-position))
- xacts))
- (forward-line))
- (setq xacts (nreverse xacts)))))
- ;; Insert rest-of-name and the postings
- (when xacts
- (save-excursion
- (insert rest-of-name ?\n)
- (while xacts
- (insert (car xacts) ?\n)
- (setq xacts (cdr xacts))))
- (forward-line)
- (goto-char (line-end-position))
- (if (re-search-backward "\\(\t\\| [ \t]\\)" nil t)
- (goto-char (match-end 0))))))
-
-
-(defcustom ledger-complete-ignore-case t
- "Non-nil means that ledger-complete-at-point will be case-insensitive"
- :type 'boolean
- :group 'ledger)
-
-(defun ledger-pcomplete (&optional interactively)
- "Complete rip-off of pcomplete from pcomplete.el, only added
-ledger-magic-tab in the previous commands list so that
-ledger-magic-tab would cycle properly"
- (interactive "p")
- (let ((pcomplete-ignore-case ledger-complete-ignore-case))
- (if (and interactively
- pcomplete-cycle-completions
- pcomplete-current-completions
- (memq last-command '(ledger-magic-tab
- ledger-pcomplete
- pcomplete-expand-and-complete
- pcomplete-reverse)))
- (progn
- (delete-char (* -1 pcomplete-last-completion-length))
- (if (eq this-command 'pcomplete-reverse)
- (progn
- (push (car (last pcomplete-current-completions))
- pcomplete-current-completions)
- (setcdr (last pcomplete-current-completions 2) nil))
- (nconc pcomplete-current-completions
- (list (car pcomplete-current-completions)))
- (setq pcomplete-current-completions
- (cdr pcomplete-current-completions)))
- (pcomplete-insert-entry pcomplete-last-completion-stub
- (car pcomplete-current-completions)
- nil pcomplete-last-completion-raw))
- (setq pcomplete-current-completions nil
- pcomplete-last-completion-raw nil)
- (catch 'pcompleted
- (let* (pcomplete-stub
- pcomplete-seen pcomplete-norm-func
- pcomplete-args pcomplete-last pcomplete-index
- pcomplete-autolist
- (completions (pcomplete-completions))
- (result (pcomplete-do-complete pcomplete-stub completions))
- (pcomplete-termination-string ""))
- (and result
- (not (eq (car result) 'listed))
- (cdr result)
- (pcomplete-insert-entry pcomplete-stub (cdr result)
- (memq (car result)
- '(sole shortest))
- pcomplete-last-completion-raw)))))))
-
-(provide 'ledger-complete)
-
-;;; ledger-complete.el ends here
diff --git a/lisp/ledger-context.el b/lisp/ledger-context.el
deleted file mode 100644
index fb5f4c10..00000000
--- a/lisp/ledger-context.el
+++ /dev/null
@@ -1,200 +0,0 @@
-;;; ledger-context.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-
-;;; Commentary:
-;; Provide facilities for reflection in ledger buffers
-
-;;; Code:
-
-(eval-when-compile
- (require 'cl))
-
-;; ledger-*-string constants are assembled in the
-;; `ledger-single-line-config' macro to form the regex and list of
-;; elements
-(defconst ledger-indent-string "\\(^[ \t]+\\)")
-(defconst ledger-status-string "\\(* \\|! \\)?")
-(defconst ledger-account-string "[\\[(]?\\(.*?\\)[])]?")
-(defconst ledger-separator-string "\\(\\s-\\s-+\\)")
-(defconst ledger-amount-string "\\(-?[0-9]+\\(?:[\\.,][0-9]*\\)?\\)")
-(defconst ledger-comment-string "[ \t]*;[ \t]*\\(.*?\\)")
-(defconst ledger-nil-string "\\([ \t]\\)")
-(defconst ledger-commodity-string "\\(.+?\\)")
-(defconst ledger-date-string "^\\([0-9]\\{4\\}[/-][01]?[0-9][/-][0123]?[0-9]\\)")
-(defconst ledger-code-string "\\((.*)\\)?")
-(defconst ledger-payee-string "\\(.*\\)")
-
-(defun ledger-get-regex-str (name)
- "Get the ledger regex of type NAME."
- (symbol-value (intern (concat "ledger-" (symbol-name name) "-string"))))
-
-(defun ledger-line-regex (elements)
- "Get a regex to match ELEMENTS on a single line."
- (concat (apply 'concat (mapcar 'ledger-get-regex-str elements)) "[ \t]*$"))
-
-(defmacro ledger-single-line-config (&rest elements)
- "Take list of ELEMENTS and return regex and element list for use in context-at-point"
- `(list (ledger-line-regex (quote ,elements)) (quote ,elements)))
-
-(defconst ledger-line-config
- (list (list 'xact (list (ledger-single-line-config date nil status nil code nil payee nil comment)
- (ledger-single-line-config date nil status nil code nil payee)
- (ledger-single-line-config date nil status nil payee)))
- (list 'acct-transaction (list (ledger-single-line-config indent comment)
- (ledger-single-line-config indent status account separator commodity amount nil comment)
- (ledger-single-line-config indent status account separator commodity amount)
- (ledger-single-line-config indent status account separator amount nil commodity comment)
- (ledger-single-line-config indent status account separator amount nil commodity)
- (ledger-single-line-config indent status account separator amount)
- (ledger-single-line-config indent status account separator comment)
- (ledger-single-line-config indent status account)))))
-
-(defun ledger-extract-context-info (line-type pos)
- "Get context info for current line with LINE-TYPE.
-
-Assumes point is at beginning of line, and the POS argument specifies
-where the \"users\" point was."
- (let ((linfo (assoc line-type ledger-line-config))
- found field fields)
- (dolist (re-info (nth 1 linfo))
- (let ((re (nth 0 re-info))
- (names (nth 1 re-info)))
- (unless found
- (when (looking-at re)
- (setq found t)
- (dotimes (i (length names))
- (when (nth i names)
- (setq fields (append fields
- (list
- (list (nth i names)
- (match-string-no-properties (1+ i))
- (match-beginning (1+ i))))))))
- (dolist (f fields)
- (and (nth 1 f)
- (>= pos (nth 2 f))
- (setq field (nth 0 f))))))))
- (list line-type field fields)))
-
-(defun ledger-thing-at-point ()
- "Describe thing at points. Return 'transaction, 'posting, or nil.
-Leave point at the beginning of the thing under point"
- (let ((here (point)))
- (goto-char (line-beginning-position))
- (cond ((looking-at "^[0-9/.=-]+\\(\\s-+\\*\\)?\\(\\s-+(.+?)\\)?\\s-+")
- (goto-char (match-end 0))
- 'transaction)
- ((looking-at "^\\s-+\\([*!]\\s-+\\)?[[(]?\\([^\\s-]\\)")
- (goto-char (match-beginning 2))
- 'posting)
- ((looking-at "^\\(sun\\|mon\\|tue\\|wed\\|thu\\|fri\\|sat\\)\\s-+")
- (goto-char (match-end 0))
- 'day)
- (t
- (ignore (goto-char here))))))
-
-(defun ledger-context-at-point ()
- "Return a list describing the context around point.
-
-The contents of the list are the line type, the name of the field
-containing point, and for selected line types, the content of
-the fields in the line in a association list."
- (let ((pos (point)))
- (save-excursion
- (beginning-of-line)
- (let ((first-char (char-after)))
- (cond ((equal (point) (line-end-position))
- '(empty-line nil nil))
- ((memq first-char '(?\ ?\t))
- (ledger-extract-context-info 'acct-transaction pos))
- ((memq first-char '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))
- (ledger-extract-context-info 'xact pos))
- ((equal first-char ?\=)
- '(automated-xact nil nil))
- ((equal first-char ?\~)
- '(period-xact nil nil))
- ((equal first-char ?\!)
- '(command-directive))
- ((equal first-char ?\;)
- '(comment nil nil))
- ((equal first-char ?Y)
- '(default-year nil nil))
- ((equal first-char ?P)
- '(commodity-price nil nil))
- ((equal first-char ?N)
- '(price-ignored-commodity nil nil))
- ((equal first-char ?D)
- '(default-commodity nil nil))
- ((equal first-char ?C)
- '(commodity-conversion nil nil))
- ((equal first-char ?i)
- '(timeclock-i nil nil))
- ((equal first-char ?o)
- '(timeclock-o nil nil))
- ((equal first-char ?b)
- '(timeclock-b nil nil))
- ((equal first-char ?h)
- '(timeclock-h nil nil))
- (t
- '(unknown nil nil)))))))
-
-(defun ledger-context-other-line (offset)
- "Return a list describing context of line OFFSET from existing position.
-
-Offset can be positive or negative. If run out of buffer before reaching
-specified line, returns nil."
- (save-excursion
- (let ((left (forward-line offset)))
- (if (not (equal left 0))
- nil
- (ledger-context-at-point)))))
-
-(defun ledger-context-line-type (context-info)
- (nth 0 context-info))
-
-(defun ledger-context-current-field (context-info)
- (nth 1 context-info))
-
-(defun ledger-context-field-info (context-info field-name)
- (assoc field-name (nth 2 context-info)))
-
-(defun ledger-context-field-present-p (context-info field-name)
- (not (null (ledger-context-field-info context-info field-name))))
-
-(defun ledger-context-field-value (context-info field-name)
- (nth 1 (ledger-context-field-info context-info field-name)))
-
-(defun ledger-context-field-position (context-info field-name)
- (nth 2 (ledger-context-field-info context-info field-name)))
-
-(defun ledger-context-field-end-position (context-info field-name)
- (+ (ledger-context-field-position context-info field-name)
- (length (ledger-context-field-value context-info field-name))))
-
-(defun ledger-context-goto-field-start (context-info field-name)
- (goto-char (ledger-context-field-position context-info field-name)))
-
-(defun ledger-context-goto-field-end (context-info field-name)
- (goto-char (ledger-context-field-end-position context-info field-name)))
-
-(provide 'ledger-context)
-
-;;; ledger-context.el ends here
diff --git a/lisp/ledger-exec.el b/lisp/ledger-exec.el
deleted file mode 100644
index 75a05262..00000000
--- a/lisp/ledger-exec.el
+++ /dev/null
@@ -1,109 +0,0 @@
-;;; ledger-exec.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-
-;;; Commentary:
-;; Code for executing ledger synchronously.
-
-;;; Code:
-
-(defconst ledger-version-needed "3.0.0"
- "The version of ledger executable needed for interactive features.")
-
-(defvar ledger-works nil
- "Flag showing whether the ledger binary can support `ledger-mode' interactive features.")
-
-(defgroup ledger-exec nil
- "Interface to the Ledger command-line accounting program."
- :group 'ledger)
-
-(defcustom ledger-mode-should-check-version t
- "Should Ledger-mode verify that the executable is working?"
- :type 'boolean
- :group 'ledger-exec)
-
-(defcustom ledger-binary-path "ledger"
- "Path to the ledger executable."
- :type 'file
- :group 'ledger-exec)
-
-(defun ledger-exec-handle-error (ledger-output)
- "Deal with ledger errors contained in LEDGER-OUTPUT."
- (with-current-buffer (get-buffer-create "*Ledger Error*")
- (let ((inhibit-read-only t))
- (insert-buffer-substring ledger-output))
- (view-mode)
- (setq buffer-read-only t)))
-
-(defun ledger-exec-success-p (ledger-output-buffer)
- "Return t if the ledger output in LEDGER-OUTPUT-BUFFER is successful."
- (with-current-buffer ledger-output-buffer
- (goto-char (point-min))
- (if (and (> (buffer-size) 1) (looking-at (regexp-quote "While")))
- nil ;; failure, there is an error starting with "While"
- ledger-output-buffer)))
-
-(defun ledger-exec-ledger (input-buffer &optional output-buffer &rest args)
- "Run Ledger using INPUT-BUFFER and optionally capturing output in OUTPUT-BUFFER with ARGS."
- (if (null ledger-binary-path)
- (error "The variable `ledger-binary-path' has not been set")
- (let ((buf (or input-buffer (current-buffer)))
- (outbuf (or output-buffer
- (generate-new-buffer " *ledger-tmp*"))))
- (with-current-buffer buf
- (let ((coding-system-for-write 'utf-8)
- (coding-system-for-read 'utf-8))
- (apply #'call-process-region
- (append (list (point-min) (point-max)
- ledger-binary-path nil outbuf nil "-f" "-")
- args)))
- (if (ledger-exec-success-p outbuf)
- outbuf
- (ledger-exec-handle-error outbuf))))))
-
-(defun ledger-version-greater-p (needed)
- "Verify the ledger binary is usable for `ledger-mode' (version greater than NEEDED)."
- (let ((buffer ledger-buf)
- (version-strings '()))
- (with-temp-buffer
- (when (ledger-exec-ledger (current-buffer) (current-buffer) "--version")
- (goto-char (point-min))
- (delete-horizontal-space)
- (setq version-strings (split-string
- (buffer-substring-no-properties (point)
- (point-max))))
- (if (and (string-match (regexp-quote "Ledger") (car version-strings))
- (or (string= needed (cadr version-strings))
- (string< needed (cadr version-strings))))
- t ;; success
- nil))))) ;;failure
-
-(defun ledger-check-version ()
- "Verify that ledger works and is modern enough."
- (interactive)
- (if ledger-mode-should-check-version
- (if (setq ledger-works (ledger-version-greater-p ledger-version-needed))
- (message "Good Ledger Version")
- (message "Bad Ledger Version"))))
-
-(provide 'ledger-exec)
-
-;;; ledger-exec.el ends here
diff --git a/lisp/ledger-fontify.el b/lisp/ledger-fontify.el
deleted file mode 100644
index 076e52b7..00000000
--- a/lisp/ledger-fontify.el
+++ /dev/null
@@ -1,201 +0,0 @@
-;;; ledger-fontify.el --- Provide custom fontification for ledger-mode
-
-
-;; Copyright (C) 2014 Craig P. Earls (enderw88 at gmail dot com)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-;;; Commentary:
-;; Font-lock-mode doesn't handle multiline syntax very well. This
-;; code provides font lock that is sensitive to overall transaction
-;; states
-
-
-;;; Code:
-
-(require 'ledger-navigate)
-(require 'ledger-regex)
-(require 'ledger-state)
-
-(defcustom ledger-fontify-xact-state-overrides nil
- "If t the highlight entire xact with state."
- :type 'boolean
- :group 'ledger)
-
-(defun ledger-fontify-buffer-part (&optional beg end len)
- "Fontify buffer from BEG to END, length LEN."
- (save-excursion
- (unless beg (setq beg (point-min)))
- (unless end (setq end (point-max)))
- (goto-char beg)
- (beginning-of-line)
- (while (< (point) end)
- (cond ((or (looking-at ledger-xact-start-regex)
- (looking-at ledger-posting-regex)
- (looking-at ledger-recurring-line-regexp))
- (ledger-fontify-xact-at (point)))
- ((looking-at ledger-directive-start-regex)
- (ledger-fontify-directive-at (point))))
- (ledger-navigate-next-xact-or-directive))))
-
-(defun ledger-fontify-xact-at (position)
- "Fontify the xact at POSITION."
- (interactive "d")
- (save-excursion
- (goto-char position)
- (let ((extents (ledger-navigate-find-element-extents position))
- (state (ledger-transaction-state)))
- (if (and ledger-fontify-xact-state-overrides state)
- (cond ((eq state 'cleared)
- (ledger-fontify-set-face extents 'ledger-font-xact-cleared-face))
- ((eq state 'pending)
- (ledger-fontify-set-face extents 'ledger-font-xact-pending-face)))
- (ledger-fontify-xact-by-line extents)))))
-
-(defun ledger-fontify-xact-by-line (extents)
- "Do line-by-line detailed fontification of xact in EXTENTS."
- (save-excursion
- (ledger-fontify-xact-start (car extents))
- (while (< (point) (cadr extents))
- (if (looking-at "[ \t]+;")
- (ledger-fontify-set-face (list (point) (progn
- (end-of-line)
- (point))) 'ledger-font-comment-face)
- (ledger-fontify-posting (point)))
- (forward-line))))
-
-(defun ledger-fontify-xact-start (pos)
- "POS should be at the beginning of a line starting an xact.
-Fontify the first line of an xact"
- (goto-char pos)
- (let ((line-start (line-beginning-position)))
- (goto-char line-start)
- (re-search-forward "[ \t]")
- (ledger-fontify-set-face (list line-start (match-beginning 0)) 'ledger-font-posting-date-face)
- (goto-char line-start)
- (re-search-forward ledger-xact-after-date-regex)
- (let ((state (save-match-data (ledger-state-from-string (match-string 1)))))
- (ledger-fontify-set-face (list (match-beginning 3) (match-end 3))
- (cond ((eq state 'pending)
- 'ledger-font-payee-pending-face)
- ((eq state 'cleared)
- 'ledger-font-payee-cleared-face)
- (t
- 'ledger-font-payee-uncleared-face))))
- (when (match-beginning 4)
- (ledger-fontify-set-face (list (match-beginning 4)
- (match-end 4)) 'ledger-font-comment-face))
- (forward-line)))
-
-(defun ledger-fontify-posting (pos)
- "Fontify the posting at POS."
- (let* ((state nil)
- (end-of-line-comment nil)
- (end (progn (end-of-line)
- (point)))
- (start (progn (beginning-of-line)
- (point))))
-
- ;; Look for a posting status flag
- (set-match-data nil 'reseat)
- (re-search-forward " \\([*!]\\) " end t)
- (if (match-string 1)
- (setq state (ledger-state-from-string (match-string 1))))
- (beginning-of-line)
- (re-search-forward "[[:graph:]]\\([ \t][ \t]\\)" end 'end) ;; find the end of the account, or end of line
-
- (when (<= (point) end) ;; we are still on the line
- (ledger-fontify-set-face (list start (point))
- (cond ((eq state 'cleared)
- 'ledger-font-posting-account-cleared-face)
- ((eq state 'pending)
- 'ledger-font-posting-account-pending-face)
- (t
- 'ledger-font-posting-account-face)))
-
-
- (when (< (point) end) ;; there is still more to fontify
- (setq start (point)) ;; update start of next font region
- (setq end-of-line-comment (re-search-forward ";" end 'end)) ;; find the end of the line, or start of a comment
- (ledger-fontify-set-face (list start (point) )
- (cond ((eq state 'cleared)
- 'ledger-font-posting-amount-cleared-face)
- ((eq state 'pending)
- 'ledger-font-posting-amount-pending-face)
- (t
- 'ledger-font-posting-amount-face)))
- (when end-of-line-comment
- (setq start (point))
- (end-of-line)
- (ledger-fontify-set-face (list (- start 1) (point)) ;; subtract 1 from start because we passed the semi-colon
- 'ledger-font-comment-face))))))
-
-(defun ledger-fontify-directive-at (pos)
- "Fontify the directive at POS."
- (let ((extents (ledger-navigate-find-element-extents pos))
- (face 'ledger-font-default-face))
- (cond ((looking-at "=")
- (setq face 'ledger-font-auto-xact-face))
- ((looking-at "~")
- (setq face 'ledger-font-periodic-xact-face))
- ((looking-at "[;#%|\\*]")
- (setq face 'ledger-font-comment-face))
- ((looking-at "\\(year\\)\\|Y")
- (setq face 'ledger-font-year-directive-face))
- ((looking-at "account")
- (setq face 'ledger-font-account-directive-face))
- ((looking-at "apply")
- (setq face 'ledger-font-apply-directive-face))
- ((looking-at "alias")
- (setq face 'ledger-font-alias-directive-face))
- ((looking-at "assert")
- (setq face 'ledger-font-assert-directive-face))
- ((looking-at "\\(bucket\\)\\|A")
- (setq face 'ledger-font-bucket-directive-face))
- ((looking-at "capture")
- (setq face 'ledger-font-capture-directive-face))
- ((looking-at "check")
- (setq face 'ledger-font-check-directive-face))
- ((looking-at "commodity")
- (setq face 'ledger-font-commodity-directive-face))
- ((looking-at "define")
- (setq face 'ledger-font-define-directive-face))
- ((looking-at "end")
- (setq face 'ledger-font-end-directive-face))
- ((looking-at "expr")
- (setq face 'ledger-font-expr-directive-face))
- ((looking-at "fixed")
- (setq face 'ledger-font-fixed-directive-face))
- ((looking-at "include")
- (setq face 'ledger-font-include-directive-face))
- ((looking-at "payee")
- (setq face 'ledger-font-payee-directive-face))
- ((looking-at "P")
- (setq face 'ledger-font-price-directive-face))
- ((looking-at "tag")
- (setq face 'ledger-font-tag-directive-face)))
- (ledger-fontify-set-face extents face)))
-
-(defun ledger-fontify-set-face (extents face)
- "Set the text in EXTENTS to FACE."
- (put-text-property (car extents) (cadr extents) 'face face))
-
-
-(provide 'ledger-fontify)
-
-;;; ledger-fontify.el ends here
diff --git a/lisp/ledger-fonts.el b/lisp/ledger-fonts.el
deleted file mode 100644
index 60450e20..00000000
--- a/lisp/ledger-fonts.el
+++ /dev/null
@@ -1,276 +0,0 @@
-;;; ledger-fonts.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-
-
-;;; Commentary:
-;; All of the faces for ledger mode are defined here.
-
-;;; Code:
-
-(require 'ledger-regex)
-
-(defgroup ledger-faces nil "Ledger mode highlighting" :group 'ledger)
-
-(defface ledger-font-default-face
- `((t :inherit default))
- "Default face"
- :group 'ledger-faces)
-
-(defface ledger-font-auto-xact-face
- `((t :foreground "orange" :weight normal))
- "Default face for automatic transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-periodic-xact-face
- `((t :foreground "green" :weight normal))
- "Default face for automatic transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-xact-cleared-face
- `((t :foreground "#AAAAAA" :weight normal))
- "Default face for cleared transaction"
- :group 'ledger-faces)
-
-(defface ledger-font-xact-pending-face
- `((t :foreground "#444444" :weight normal))
- "Default face for pending transaction"
- :group 'ledger-faces)
-
-(defface ledger-font-xact-open-face
- `((t :foreground "#000000" :weight normal))
- "Default face for transaction under point"
- :group 'ledger-faces)
-
-(defface ledger-font-payee-uncleared-face
- `((t :foreground "#dc322f" :weight bold ))
- "Default face for Ledger"
- :group 'ledger-faces)
-
-(defface ledger-font-payee-cleared-face
- `((t :inherit ledger-font-other-face))
- "Default face for cleared (*) payees"
- :group 'ledger-faces)
-
-(defface ledger-font-payee-pending-face
- `((t :foreground "#F24B61" :weight normal))
- "Default face for pending (!) payees"
- :group 'ledger-faces)
-
-(defface ledger-font-xact-highlight-face
- `((t :inherit ledger-occur-xact-face))
- "Default face for transaction under point"
- :group 'ledger-faces)
-
-(defface ledger-font-pending-face
- `((t :foreground "#cb4b16" :weight normal ))
- "Default face for pending (!) transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-other-face
- `((t :foreground "#657b83" :weight normal))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-directive-face
- `((t :inherit font-lock-preprocessor-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-account-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-price-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-apply-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-alias-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-assert-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-bucket-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-capture-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-check-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-commodity-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-define-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-end-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-expr-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-fixed-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-include-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-payee-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-tag-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-year-directive-face
- `((t :inherit ledger-font-directive-face))
- "Default face for other transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-posting-account-face
- `((t :foreground "#268bd2" ))
- "Face for Ledger accounts"
- :group 'ledger-faces)
-
-(defface ledger-font-posting-account-cleared-face
- `((t :inherit ledger-font-other-face))
- "Face for Ledger accounts"
- :group 'ledger-faces)
-
-(defface ledger-font-posting-amount-cleared-face
- `((t :inherit ledger-font-posting-account-cleared-face))
- "Face for Ledger accounts"
- :group 'ledger-faces)
-
-(defface ledger-font-posting-account-pending-face
- `((t :inherit ledger-font-pending-face))
- "Face for Ledger accounts"
- :group 'ledger-faces)
-
-(defface ledger-font-posting-amount-pending-face
- `((t :inherit ledger-font-posting-account-pending-face))
- "Face for Ledger accounts"
- :group 'ledger-faces)
-
-(defface ledger-font-posting-amount-face
- `((t :foreground "#cb4b16" ))
- "Face for Ledger amounts"
- :group 'ledger-faces)
-
-(defface ledger-font-posting-date-face
- `((t :foreground "#cb4b16" ))
- "Face for Ledger dates"
- :group 'ledger-faces)
-
-(defface ledger-occur-narrowed-face
- `((t :inherit font-lock-comment-face :invisible t))
- "Default face for Ledger occur mode hidden transactions"
- :group 'ledger-faces)
-
-(defface ledger-occur-xact-face
- `((t :inherit highlight))
- "Default face for Ledger occur mode shown transactions"
- :group 'ledger-faces)
-
-(defface ledger-font-comment-face
- `((t :inherit font-lock-comment-face))
- "Face for Ledger comments"
- :group 'ledger-faces)
-
-(defface ledger-font-reconciler-uncleared-face
- `((t :inherit ledger-font-payee-uncleared-face))
- "Default face for uncleared transactions in the reconcile window"
- :group 'ledger-faces)
-
-(defface ledger-font-reconciler-cleared-face
- `((t :inherit ledger-font-other-face))
- "Default face for cleared (*) transactions in the reconcile window"
- :group 'ledger-faces)
-
-(defface ledger-font-reconciler-pending-face
- `((t :inherit ledger-font-pending-face))
- "Default face for pending (!) transactions in the reconcile window"
- :group 'ledger-faces)
-
-(defface ledger-font-report-clickable-face
- `((t :foreground "#cb4b16" :weight normal ))
- "Default face for pending (!) transactions in the reconcile window"
- :group 'ledger-faces)
-
- (defvar ledger-font-lock-keywords
- `(("account" . ledger-font-account-directive-face)
- ("apply" . ledger-font-apply-directive-face)
- ("alias" . ledger-font-alias-directive-face)
- ("assert" . ledger-font-assert-directive-face)
- ("bucket" . ledger-font-bucket-directive-face)
- ("capture" . ledger-font-capture-directive-face)
- ("check" . ledger-font-check-directive-face)
- ("commodity" . ledger-font-commodity-directive-face)
- ("define" . ledger-font-define-directive-face)
- ("end" . ledger-font-end-directive-face)
- ("expr" . ledger-font-expr-directive-face)
- ("fixed" . ledger-font-fixed-directive-face)
- ("include" . ledger-font-include-directive-face)
- ("payee" . ledger-font-payee-directive-face)
- ("tag" . ledger-font-tag-directive-face)
- ("year" . ledger-font-year-directive-face))
- "Expressions to highlight in Ledger mode.")
-
-
-
-(provide 'ledger-fonts)
-
-;;; ledger-fonts.el ends here
diff --git a/lisp/ledger-init.el b/lisp/ledger-init.el
deleted file mode 100644
index 0141d2e7..00000000
--- a/lisp/ledger-init.el
+++ /dev/null
@@ -1,75 +0,0 @@
-;;; ledger-init.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-;;; Commentary:
-;; Determine the ledger environment
-
-(require 'ledger-regex)
-
-;;; Code:
-
-(defcustom ledger-init-file-name "~/.ledgerrc"
- "Location of the ledger initialization file. nil if you don't have one."
- :group 'ledger-exec)
-
-(defvar ledger-environment-alist nil)
-
-(defvar ledger-default-date-format "%Y/%m/%d")
-
-(defun ledger-init-parse-initialization (buffer)
- "Parse the .ledgerrc file in BUFFER."
- (with-current-buffer buffer
- (let (environment-alist)
- (goto-char (point-min))
- (while (re-search-forward ledger-init-string-regex nil t )
- (let ((matchb (match-beginning 0)) ;; save the match data, string-match stamp on it
- (matche (match-end 0)))
- (end-of-line)
- (setq environment-alist
- (append environment-alist
- (list (cons (let ((flag (buffer-substring-no-properties (+ 2 matchb) matche)))
- (if (string-match "[ \t\n\r]+\\'" flag)
- (replace-match "" t t flag)
- flag))
- (let ((value (buffer-substring-no-properties matche (point) )))
- (if (> (length value) 0)
- value
- t))))))))
- environment-alist)))
-
-(defun ledger-init-load-init-file ()
- "Load and parse the .ledgerrc file."
- (interactive)
- (let ((init-base-name (file-name-nondirectory ledger-init-file-name)))
- (if (get-buffer init-base-name) ;; init file already loaded, parse it and leave it
- (setq ledger-environment-alist
- (ledger-init-parse-initialization init-base-name))
- (when (and ledger-init-file-name
- (file-exists-p ledger-init-file-name)
- (file-readable-p ledger-init-file-name))
- (find-file-noselect ledger-init-file-name)
- (setq ledger-environment-alist
- (ledger-init-parse-initialization init-base-name))
- (kill-buffer init-base-name)))))
-
-(provide 'ledger-init)
-
-;;; ledger-init.el ends here
diff --git a/lisp/ledger-mode.el b/lisp/ledger-mode.el
deleted file mode 100644
index 9eff6bc6..00000000
--- a/lisp/ledger-mode.el
+++ /dev/null
@@ -1,381 +0,0 @@
-;;; ledger-mode.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-
-
-;;; Commentary:
-;; Most of the general ledger-mode code is here.
-
-;;; Code:
-
-(require 'ledger-regex)
-(require 'cus-edit)
-(require 'esh-util)
-(require 'esh-arg)
-(require 'easymenu)
-(require 'ledger-commodities)
-(require 'ledger-complete)
-(require 'ledger-context)
-(require 'ledger-exec)
-(require 'ledger-fonts)
-(require 'ledger-fontify)
-(require 'ledger-init)
-(require 'ledger-navigate)
-(require 'ledger-occur)
-(require 'ledger-post)
-(require 'ledger-reconcile)
-(require 'ledger-report)
-(require 'ledger-sort)
-(require 'ledger-state)
-(require 'ledger-test)
-(require 'ledger-texi)
-(require 'ledger-xact)
-(require 'ledger-schedule)
-
-;;; Code:
-
-(defgroup ledger nil
- "Interface to the Ledger command-line accounting program."
- :group 'data)
-
-(defconst ledger-version "3.0"
- "The version of ledger.el currently loaded.")
-
-(defconst ledger-mode-version "3.0.0")
-
-(defun ledger-mode-dump-variable (var)
- "Format VAR for dump to buffer."
- (if var
- (insert (format " %s: %S\n" (symbol-name var) (eval var)))))
-
-(defun ledger-mode-dump-group (group)
- "Dump GROUP customizations to current buffer."
- (let ((members (custom-group-members group nil)))
- (dolist (member members)
- (cond ((eq (cadr member) 'custom-group)
- (insert (format "Group %s:\n" (symbol-name (car member))))
- (ledger-mode-dump-group (car member)))
- ((eq (cadr member) 'custom-variable)
- (ledger-mode-dump-variable (car member)))))))
-
-(defun ledger-mode-dump-configuration ()
- "Dump all customizations."
- (interactive)
- (find-file "ledger-mode-dump")
- (ledger-mode-dump-group 'ledger))
-
-
-(defun ledger-current-year ()
- "The default current year for adding transactions."
- (format-time-string "%Y"))
-
-(defun ledger-current-month ()
- "The default current month for adding transactions."
- (format-time-string "%m"))
-
-(defvar ledger-year (ledger-current-year)
- "Start a ledger session with the current year, but make it customizable to ease retro-entry.")
-
-(defvar ledger-month (ledger-current-month)
- "Start a ledger session with the current month, but make it customizable to ease retro-entry.")
-
-(defun ledger-read-account-with-prompt (prompt)
- "Read an account from the minibuffer with PROMPT."
- (let ((context (ledger-context-at-point)))
- (ledger-read-string-with-default prompt
- (if (eq (ledger-context-current-field context) 'account)
- (regexp-quote (ledger-context-field-value context 'account))
- nil))))
-
-(defun ledger-read-date (prompt)
- "Return user-supplied date after `PROMPT', defaults to today."
- (let* ((default (ledger-year-and-month))
- (date (read-string prompt default
- 'ledger-minibuffer-history)))
- (if (or (string= date default)
- (string= "" date))
- (format-time-string
- (or (cdr (assoc "date-format" ledger-environment-alist))
- ledger-default-date-format))
- date)))
-
-(defun ledger-read-string-with-default (prompt default)
- "Return user supplied string after PROMPT, or DEFAULT."
- (read-string (concat prompt
- (if default
- (concat " (" default "): ")
- ": "))
- nil 'ledger-minibuffer-history default))
-
-(defun ledger-display-balance-at-point (&optional arg)
- "Display the cleared-or-pending balance.
-And calculate the target-delta of the account being reconciled.
-
-With prefix argument \\[universal-argument] ask for the target commodity and convert
-the balance into that."
- (interactive "P")
- (let* ((account (ledger-read-account-with-prompt "Account balance to show"))
- (target-commodity (when arg (ledger-read-commodity-with-prompt "Target commodity: ")))
- (buffer (current-buffer))
- (balance (with-temp-buffer
- (apply 'ledger-exec-ledger buffer (current-buffer) "cleared" account
- (when target-commodity (list "-X" target-commodity)))
- (if (> (buffer-size) 0)
- (buffer-substring-no-properties (point-min) (1- (point-max)))
- (concat account " is empty.")))))
- (when balance
- (message balance))))
-
-(defun ledger-display-ledger-stats ()
- "Display the cleared-or-pending balance.
-And calculate the target-delta of the account being reconciled."
- (interactive)
- (let* ((buffer (current-buffer))
- (balance (with-temp-buffer
- (ledger-exec-ledger buffer (current-buffer) "stats")
- (buffer-substring-no-properties (point-min) (1- (point-max))))))
- (when balance
- (message balance))))
-
-(defun ledger-magic-tab (&optional interactively)
- "Decide what to with with <TAB>, INTERACTIVELY.
-Can indent, complete or align depending on context."
- (interactive "p")
- (if (= (point) (line-beginning-position))
- (indent-to ledger-post-account-alignment-column)
- (if (and (> (point) 1)
- (looking-back "\\([^ \t]\\)" 1))
- (ledger-pcomplete interactively)
- (ledger-post-align-postings (line-beginning-position) (line-end-position)))))
-
-(defvar ledger-mode-abbrev-table)
-
-(defvar ledger-date-string-today
- (format-time-string (or
- (cdr (assoc "date-format" ledger-environment-alist))
- ledger-default-date-format)))
-
-(defun ledger-remove-effective-date ()
- "Remove the effective date from a transaction or posting."
- (interactive)
- (let ((context (car (ledger-context-at-point))))
- (save-excursion
- (save-restriction
- (narrow-to-region (point-at-bol) (point-at-eol))
- (beginning-of-line)
- (cond ((eq 'xact context)
- (re-search-forward ledger-iso-date-regexp)
- (when (= (char-after) ?=)
- (let ((eq-pos (point)))
- (delete-region
- eq-pos
- (re-search-forward ledger-iso-date-regexp)))))
- ((eq 'acct-transaction context)
- ;; Match "; [=date]" & delete string
- (when (re-search-forward
- (concat ledger-comment-regex
- "\\[=" ledger-iso-date-regexp "\\]")
- nil 'noerr)
- (replace-match ""))))))))
-
-(defun ledger-insert-effective-date (&optional date)
- "Insert effective date `DATE' to the transaction or posting.
-
-If `DATE' is nil, prompt the user a date.
-
-Replace the current effective date if there's one in the same
-line.
-
-With a prefix argument, remove the effective date."
- (interactive)
- (if (and (listp current-prefix-arg)
- (= 4 (prefix-numeric-value current-prefix-arg)))
- (ledger-remove-effective-date)
- (let* ((context (car (ledger-context-at-point)))
- (date-string (or date (ledger-read-date "Effective date: "))))
- (save-restriction
- (narrow-to-region (point-at-bol) (point-at-eol))
- (cond
- ((eq 'xact context)
- (beginning-of-line)
- (re-search-forward ledger-iso-date-regexp)
- (when (= (char-after) ?=)
- (ledger-remove-effective-date))
- (insert "=" date-string))
- ((eq 'acct-transaction context)
- (end-of-line)
- (ledger-remove-effective-date)
- (insert " ; [=" date-string "]")))))))
-
-(defun ledger-mode-remove-extra-lines ()
- "Get rid of multiple empty lines."
- (goto-char (point-min))
- (while (re-search-forward "\n\n\\(\n\\)+" nil t)
- (replace-match "\n\n")))
-
-(defun ledger-mode-clean-buffer ()
- "Indent, remove multiple line feeds and sort the buffer."
- (interactive)
- (let ((start (point-min-marker))
- (end (point-max-marker)))
- (goto-char start)
- (ledger-navigate-beginning-of-xact)
- (beginning-of-line)
- (let ((target (buffer-substring (point) (progn
- (end-of-line)
- (point)))))
- (untabify start end)
- (ledger-sort-buffer)
- (ledger-post-align-postings start end)
- (ledger-mode-remove-extra-lines)
- (goto-char start)
- (search-forward target))))
-
-(defvar ledger-mode-syntax-table
- (let ((table (make-syntax-table text-mode-syntax-table)))
- (modify-syntax-entry ?\; "<" table)
- (modify-syntax-entry ?\n ">" table)
- table)
- "Syntax table in use in `ledger-mode' buffers.")
-
-(defvar ledger-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [(control ?c) (control ?a)] 'ledger-add-transaction)
- (define-key map [(control ?c) (control ?b)] 'ledger-post-edit-amount)
- (define-key map [(control ?c) (control ?c)] 'ledger-toggle-current)
- (define-key map [(control ?c) (control ?d)] 'ledger-delete-current-transaction)
- (define-key map [(control ?c) (control ?e)] 'ledger-toggle-current-transaction)
- (define-key map [(control ?c) (control ?f)] 'ledger-occur)
- (define-key map [(control ?c) (control ?k)] 'ledger-copy-transaction-at-point)
- (define-key map [(control ?c) (control ?m)] 'ledger-set-month)
- (define-key map [(control ?c) (control ?r)] 'ledger-reconcile)
- (define-key map [(control ?c) (control ?s)] 'ledger-sort-region)
- (define-key map [(control ?c) (control ?t)] 'ledger-insert-effective-date)
- (define-key map [(control ?c) (control ?u)] 'ledger-schedule-upcoming)
- (define-key map [(control ?c) (control ?y)] 'ledger-set-year)
- (define-key map [(control ?c) (control ?p)] 'ledger-display-balance-at-point)
- (define-key map [(control ?c) (control ?l)] 'ledger-display-ledger-stats)
- (define-key map [(control ?c) (control ?q)] 'ledger-post-align-xact)
-
- (define-key map [tab] 'ledger-magic-tab)
- (define-key map [(control tab)] 'ledger-post-align-xact)
- (define-key map [(control ?i)] 'ledger-magic-tab)
- (define-key map [(control ?c) tab] 'ledger-fully-complete-xact)
- (define-key map [(control ?c) (control ?i)] 'ledger-fully-complete-xact)
-
- (define-key map [(control ?c) (control ?o) (control ?a)] 'ledger-report-redo)
- (define-key map [(control ?c) (control ?o) (control ?e)] 'ledger-report-edit)
- (define-key map [(control ?c) (control ?o) (control ?g)] 'ledger-report-goto)
- (define-key map [(control ?c) (control ?o) (control ?k)] 'ledger-report-kill)
- (define-key map [(control ?c) (control ?o) (control ?r)] 'ledger-report)
- (define-key map [(control ?c) (control ?o) (control ?s)] 'ledger-report-save)
-
- (define-key map [(meta ?p)] 'ledger-navigate-prev-xact-or-directive)
- (define-key map [(meta ?n)] 'ledger-navigate-next-xact-or-directive)
- (define-key map [(meta ?q)] 'ledger-post-align-dwim)
- map)
- "Keymap for `ledger-mode'.")
-
-(easy-menu-define ledger-mode-menu ledger-mode-map
- "Ledger menu"
- '("Ledger"
- ["Narrow to REGEX" ledger-occur]
- ["Show all transactions" ledger-occur-mode ledger-occur-mode]
- ["Ledger Statistics" ledger-display-ledger-stats ledger-works]
- "---"
- ["Show upcoming transactions" ledger-schedule-upcoming]
- ["Add Transaction (ledger xact)" ledger-add-transaction ledger-works]
- ["Complete Transaction" ledger-fully-complete-xact]
- ["Delete Transaction" ledger-delete-current-transaction]
- "---"
- ["Calc on Amount" ledger-post-edit-amount]
- "---"
- ["Check Balance" ledger-display-balance-at-point ledger-works]
- ["Reconcile Account" ledger-reconcile ledger-works]
- "---"
- ["Toggle Current Transaction" ledger-toggle-current-transaction]
- ["Toggle Current Posting" ledger-toggle-current]
- ["Copy Trans at Point" ledger-copy-transaction-at-point]
- "---"
- ["Clean-up Buffer" ledger-mode-clean-buffer]
- ["Align Region" ledger-post-align-postings mark-active]
- ["Align Xact" ledger-post-align-xact]
- ["Sort Region" ledger-sort-region mark-active]
- ["Sort Buffer" ledger-sort-buffer]
- ["Mark Sort Beginning" ledger-sort-insert-start-mark]
- ["Mark Sort End" ledger-sort-insert-end-mark]
- ["Set effective date" ledger-insert-effective-date]
- "---"
- ["Customize Ledger Mode" (lambda () (interactive) (customize-group 'ledger))]
- ["Set Year" ledger-set-year ledger-works]
- ["Set Month" ledger-set-month ledger-works]
- "---"
- ["Run Report" ledger-report ledger-works]
- ["Goto Report" ledger-report-goto ledger-works]
- ["Re-run Report" ledger-report-redo ledger-works]
- ["Save Report" ledger-report-save ledger-works]
- ["Edit Report" ledger-report-edit ledger-works]
- ["Kill Report" ledger-report-kill ledger-works]))
-
-;;;###autoload
-(define-derived-mode ledger-mode text-mode "Ledger"
- "A mode for editing ledger data files."
- (ledger-check-version)
- (when (boundp 'font-lock-defaults)
- (setq font-lock-defaults
- '(ledger-font-lock-keywords t t nil nil
- (font-lock-fontify-region-function . ledger-fontify-buffer-part))))
-
- (set (make-local-variable 'pcomplete-parse-arguments-function) 'ledger-parse-arguments)
- (set (make-local-variable 'pcomplete-command-completion-function) 'ledger-complete-at-point)
- (add-hook 'completion-at-point-functions 'pcomplete-completions-at-point nil t)
- (add-hook 'after-save-hook 'ledger-report-redo)
-
- (add-hook 'post-command-hook 'ledger-highlight-xact-under-point nil t)
-
- (ledger-init-load-init-file)
- (setq comment-start ";")
-
- (set (make-local-variable 'indent-region-function) 'ledger-post-align-postings))
-
-
-
-(defun ledger-set-year (newyear)
- "Set ledger's idea of the current year to the prefix argument NEWYEAR."
- (interactive "p")
- (setq ledger-year
- (if (= newyear 1)
- (read-string "Year: " (ledger-current-year))
- (number-to-string newyear))))
-
-(defun ledger-set-month (newmonth)
- "Set ledger's idea of the current month to the prefix argument NEWMONTH."
- (interactive "p")
- (setq ledger-month
- (if (= newmonth 1)
- (read-string "Month: " (ledger-current-month))
- (format "%02d" newmonth))))
-
-
-
-(provide 'ledger-mode)
-
-;;; ledger-mode.el ends here
diff --git a/lisp/ledger-navigate.el b/lisp/ledger-navigate.el
deleted file mode 100644
index 7ac440f7..00000000
--- a/lisp/ledger-navigate.el
+++ /dev/null
@@ -1,168 +0,0 @@
-;;; ledger-navigate.el --- Provide navigation services through the ledger buffer.
-
-;; Copyright (C) 2014-2015 Craig Earls (enderw88 AT gmail DOT com)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-
-;;; Commentary:
-;;
-
-;;; Code:
-
-(require 'ledger-regex)
-(require 'ledger-context)
-
-(defun ledger-navigate-next-xact ()
- "Move point to beginning of next xact."
- ;; make sure we actually move to the next xact, even if we are the
- ;; beginning of one now.
- (if (looking-at ledger-payee-any-status-regex)
- (forward-line))
- (if (re-search-forward ledger-payee-any-status-regex nil t)
- (goto-char (match-beginning 0))
- (goto-char (point-max))))
-
-(defun ledger-navigate-start-xact-or-directive-p ()
- "Return t if at the beginning of an empty or all-whitespace line."
- (not (looking-at "[ \t]\\|\\(^$\\)")))
-
-(defun ledger-navigate-next-xact-or-directive ()
- "Move to the beginning of the next xact or directive."
- (interactive)
- (beginning-of-line)
- (if (ledger-navigate-start-xact-or-directive-p) ; if we are the start of an xact, move forward to the next xact
- (progn
- (forward-line)
- (if (not (ledger-navigate-start-xact-or-directive-p)) ; we have moved forward and are not at another xact, recurse forward
- (ledger-navigate-next-xact-or-directive)))
- (while (not (or (eobp) ; we didn't start off at the beginning of an xact
- (ledger-navigate-start-xact-or-directive-p)))
- (forward-line))))
-
-(defun ledger-navigate-prev-xact-or-directive ()
- "Move point to beginning of previous xact."
- (interactive)
- (let ((context (car (ledger-context-at-point))))
- (when (equal context 'acct-transaction)
- (ledger-navigate-beginning-of-xact))
- (beginning-of-line)
- (re-search-backward "^[[:graph:]]" nil t)))
-
-(defun ledger-navigate-beginning-of-xact ()
- "Move point to the beginning of the current xact."
- (interactive)
- ;; need to start at the beginning of a line incase we are in the first line of an xact already.
- (beginning-of-line)
- (let ((sreg (concat "^\\(=\\|~\\|" ledger-iso-date-regexp "\\)")))
- (unless (looking-at sreg)
- (re-search-backward sreg nil t)
- (beginning-of-line)))
- (point))
-
-(defun ledger-navigate-end-of-xact ()
- "Move point to end of xact."
- (interactive)
- (ledger-navigate-next-xact-or-directive)
- (re-search-backward ".$")
- (end-of-line)
- (point))
-
-(defun ledger-navigate-to-line (line-number)
- "Rapidly move point to line LINE-NUMBER."
- (goto-char (point-min))
- (forward-line (1- line-number)))
-
-(defun ledger-navigate-find-xact-extents (pos)
- "Return list containing point for beginning and end of xact containing POS.
-Requires empty line separating xacts."
- (interactive "d")
- (save-excursion
- (goto-char pos)
- (list (ledger-navigate-beginning-of-xact)
- (ledger-navigate-end-of-xact))))
-
-(defun ledger-navigate-find-directive-extents (pos)
- "Return the extents of the directive at POS."
- (goto-char pos)
- (let ((begin (progn (beginning-of-line)
- (point)))
- (end (progn (end-of-line)
- (+ 1 (point)))))
- ;; handle block comments here
- (beginning-of-line)
- (if (looking-at " *;")
- (progn
- (while (and (looking-at " *;")
- (> (point) (point-min)))
- (forward-line -1))
- ;; We are either at the beginning of the buffer, or we found
- ;; a line outside the comment. If we are not at the
- ;; beginning of the buffer then we need to move forward a
- ;; line.
- (if (> (point) (point-min))
- (progn (forward-line 1)
- (beginning-of-line)))
- (setq begin (point))
- (goto-char pos)
- (beginning-of-line)
- (while (and (looking-at " *;")
- (< (point) (point-max)))
- (forward-line 1))
- (setq end (point))))
- (list begin end)))
-
-(defun ledger-navigate-block-comment (pos)
- "Move past the block comment at POS, and return its extents."
- (interactive "d")
- (goto-char pos)
- (let ((begin (progn (beginning-of-line)
- (point)))
- (end (progn (end-of-line)
- (point))))
- ;; handle block comments here
- (beginning-of-line)
- (if (looking-at " *;")
- (progn
- (while (and (looking-at " *;")
- (> (point) (point-min)))
- (forward-line -1))
- (setq begin (point))
- (goto-char pos)
- (beginning-of-line)
- (while (and (looking-at " *;")
- (< (point) (point-max)))
- (forward-line 1))
- (setq end (point))))
- (list begin end)))
-
-
-(defun ledger-navigate-find-element-extents (pos)
- "Return list containing beginning and end of the entity surrounding POS."
- (interactive "d")
- (save-excursion
- (goto-char pos)
- (beginning-of-line)
- (if (looking-at "[ =~0-9\\[]")
- (ledger-navigate-find-xact-extents pos)
- (ledger-navigate-find-directive-extents pos))))
-
-
-(provide 'ledger-navigate)
-
-;;; ledger-navigate.el ends here
diff --git a/lisp/ledger-occur.el b/lisp/ledger-occur.el
deleted file mode 100644
index 810657a3..00000000
--- a/lisp/ledger-occur.el
+++ /dev/null
@@ -1,168 +0,0 @@
-;;; ledger-occur.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-;;; Commentary:
-;; Provide buffer narrowing to ledger mode. Adapted from original loccur
-;; mode by Alexey Veretennikov <alexey dot veretennikov at gmail dot
-;; com>
-;;
-;; Adapted to ledger mode by Craig Earls <enderww at gmail dot
-;; com>
-
-;;; Code:
-
-(require 'cl)
-(require 'ledger-navigate)
-
-(defconst ledger-occur-overlay-property-name 'ledger-occur-custom-buffer-grep)
-
-(defcustom ledger-occur-use-face-shown t
- "If non-nil, use a custom face for xacts shown in `ledger-occur' mode using ledger-occur-xact-face."
- :type 'boolean
- :group 'ledger)
-(make-variable-buffer-local 'ledger-occur-use-face-shown)
-
-
-(defvar ledger-occur-history nil
- "History of previously searched expressions for the prompt.")
-
-(defvar ledger-occur-current-regex nil
- "Pattern currently applied to narrow the buffer.")
-(make-variable-buffer-local 'ledger-occur-current-regex)
-
-(defvar ledger-occur-mode-map (make-sparse-keymap))
-
-(define-minor-mode ledger-occur-mode
- "A minor mode which display only transactions matching `ledger-occur-current-regex'."
- nil
- (:eval (format " Ledger-Narrow(%s)" ledger-occur-current-regex))
- ledger-occur-mode-map
- (if (and ledger-occur-current-regex ledger-occur-mode)
- (ledger-occur-refresh)
- (ledger-occur-remove-overlays)
- (message "Showing all transactions")))
-
-(define-key ledger-occur-mode-map (kbd "C-c C-g") 'ledger-occur-refresh)
-(define-key ledger-occur-mode-map (kbd "C-c C-f") 'ledger-occur-mode)
-
-(defun ledger-occur-refresh ()
- "Re-apply the current narrowing expression."
- (interactive)
- (let ((matches (ledger-occur-compress-matches
- (ledger-occur-find-matches ledger-occur-current-regex))))
- (if matches
- (ledger-occur-create-overlays matches)
- (message "No matches found for '%s'" ledger-occur-current-regex)
- (ledger-occur-mode -1))))
-
-(defun ledger-occur (regex)
- "Show only transactions in the current buffer which match REGEX.
-
-This command hides all xact in the current buffer except those
-matching REGEX. If REGEX is nil or empty, turn off any narrowing
-currently active."
- (interactive
- (list (read-regexp "Regexp" (ledger-occur-prompt) 'ledger-occur-history)))
- (if (or (null regex)
- (zerop (length regex))) ; empty regex, or already have narrowed, clear narrowing
- (ledger-occur-mode -1)
- (setq ledger-occur-current-regex regex)
- (ledger-occur-mode 1)))
-
-(defun ledger-occur-prompt ()
- "Return the default value of the prompt.
-
- Default value for prompt is a current word or active
- region(selection), if its size is 1 line"
- (if (use-region-p)
- (let ((pos1 (region-beginning))
- (pos2 (region-end)))
- ;; Check if the start and the of an active region is on
- ;; the same line
- (if (= (line-number-at-pos pos1)
- (line-number-at-pos pos2))
- (buffer-substring-no-properties pos1 pos2)))
- (current-word)))
-
-
-(defun ledger-occur-make-visible-overlay (beg end)
- (let ((ovl (make-overlay beg end (current-buffer))))
- (overlay-put ovl ledger-occur-overlay-property-name t)
- (overlay-put ovl 'face 'ledger-occur-xact-face)))
-
-(defun ledger-occur-make-invisible-overlay (beg end)
- (let ((ovl (make-overlay beg end (current-buffer))))
- (overlay-put ovl ledger-occur-overlay-property-name t)
- (overlay-put ovl 'invisible t)))
-
-(defun ledger-occur-create-overlays (ovl-bounds)
- "Create the overlays for the visible transactions.
-Argument OVL-BOUNDS contains bounds for the transactions to be left visible."
- (let* ((beg (caar ovl-bounds))
- (end (cadar ovl-bounds)))
- (ledger-occur-remove-overlays)
- (ledger-occur-make-invisible-overlay (point-min) (1- beg))
- (dolist (visible (cdr ovl-bounds))
- (ledger-occur-make-visible-overlay beg end)
- (ledger-occur-make-invisible-overlay (1+ end) (1- (car visible)))
- (setq beg (car visible))
- (setq end (cadr visible)))
- (ledger-occur-make-invisible-overlay (1+ end) (point-max))))
-
-(defun ledger-occur-remove-overlays ()
- "Remove the transaction hiding overlays."
- (interactive)
- (remove-overlays (point-min)
- (point-max) ledger-occur-overlay-property-name t))
-
-(defun ledger-occur-find-matches (regex)
- "Return a list of 2-number tuples describing the beginning and end of transactions meeting REGEX."
- (save-excursion
- (goto-char (point-min))
- ;; Set initial values for variables
- (let (endpoint lines bounds)
- ;; Search loop
- (while (not (eobp))
- ;; if something found
- (when (setq endpoint (re-search-forward regex nil 'end))
- (setq bounds (ledger-navigate-find-element-extents endpoint))
- (push bounds lines)
- ;; move to the end of the xact, no need to search inside it more
- (goto-char (cadr bounds))))
- (nreverse lines))))
-
-(defun ledger-occur-compress-matches (buffer-matches)
- "identify sequential xacts to reduce number of overlays required"
- (if buffer-matches
- (let ((points (list))
- (current-beginning (caar buffer-matches))
- (current-end (cadar buffer-matches)))
- (dolist (match (cdr buffer-matches))
- (if (< (- (car match) current-end) 2)
- (setq current-end (cadr match))
- (push (list current-beginning current-end) points)
- (setq current-beginning (car match))
- (setq current-end (cadr match))))
- (nreverse (push (list current-beginning current-end) points)))))
-
-(provide 'ledger-occur)
-
-;;; ledger-occur.el ends here
diff --git a/lisp/ledger-post.el b/lisp/ledger-post.el
deleted file mode 100644
index ef0370b4..00000000
--- a/lisp/ledger-post.el
+++ /dev/null
@@ -1,199 +0,0 @@
-;;; ledger-post.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-
-;;; Commentary:
-;; Utility functions for dealing with postings.
-
-(require 'ledger-regex)
-
-;;; Code:
-
-(defgroup ledger-post nil
- "Options for controlling how Ledger-mode deals with postings and completion"
- :group 'ledger)
-
-(defcustom ledger-post-account-alignment-column 4
- "The column Ledger-mode attempts to align accounts to."
- :type 'integer
- :group 'ledger-post)
-
-(defcustom ledger-post-amount-alignment-column 52
- "The column Ledger-mode attempts to align amounts to."
- :type 'integer
- :group 'ledger-post)
-
-(defcustom ledger-post-amount-alignment-at :end
- "Position at which the amount is ailgned.
-
-Can be :end to align on the last number of the amount (can be
-followed by unaligned commodity) or :decimal to align at the
-decimal separator."
- :type '(radio (const :tag "align at the end of amount" :end)
- (const :tag "align at the decimal separator" :decimal))
- :group 'ledger-post)
-
-(defcustom ledger-post-use-completion-engine :built-in
- "Which completion engine to use, :iswitchb or :ido chose those engines.
-:built-in uses built-in Ledger-mode completion"
- :type '(radio (const :tag "built in completion" :built-in)
- (const :tag "ido completion" :ido)
- (const :tag "iswitchb completion" :iswitchb) )
- :group 'ledger-post)
-
-(declare-function iswitchb-read-buffer "iswitchb"
- (prompt &optional default require-match start matches-set))
-
-(defvar iswitchb-temp-buflist)
-
-(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."
- (cond ((eq ledger-post-use-completion-engine :iswitchb)
- (let* ((iswitchb-use-virtual-buffers nil)
- (iswitchb-make-buflist-hook
- (lambda ()
- (setq iswitchb-temp-buflist choices))))
- (iswitchb-read-buffer prompt)))
- ((eq ledger-post-use-completion-engine :ido)
- (ido-completing-read prompt choices))
- (t
- (completing-read prompt choices))))
-
-
-(defun ledger-next-amount (&optional end)
- "Move point to the next amount, as long as it is not past END.
-Return the width of the amount field as an integer and leave
-point at beginning of the commodity."
- ;;(beginning-of-line)
- (let ((case-fold-search nil))
- (when (re-search-forward ledger-amount-regex end t)
- (goto-char (match-beginning 0))
- (skip-syntax-forward " ")
- (cond
- ((eq ledger-post-amount-alignment-at :end)
- (- (or (match-end 4) (match-end 3)) (point)))
- ((eq ledger-post-amount-alignment-at :decimal)
- (- (match-end 3) (point)))))))
-
-(defun ledger-next-account (&optional end)
- "Move to the beginning of the posting, or status marker, limit to END.
-Return the column of the beginning of the account and leave point
-at beginning of account"
- (if (> end (point))
- (when (re-search-forward ledger-account-any-status-regex (1+ end) t)
- ;; the 1+ is to make sure we can catch the newline
- (if (match-beginning 1)
- (goto-char (match-beginning 1))
- (goto-char (match-beginning 2)))
- (current-column))))
-
-(defun ledger-post-align-xact (pos)
- "Align all the posting in the xact at POS."
- (interactive "d")
- (let ((bounds (ledger-navigate-find-xact-extents pos)))
- (ledger-post-align-postings (car bounds) (cadr bounds))))
-
-(defun ledger-post-align-postings (beg end)
- "Align all accounts and amounts between BEG and END, or the current region, or, if no region, the current line."
- (interactive "r")
-
- (save-excursion
- (let ((inhibit-modification-hooks t)
- acct-start-column acct-end-column acct-adjust amt-width amt-adjust
- (lines-left 1))
-
- ;; Extend region to whole lines
- (let ((start-marker (set-marker (make-marker) (save-excursion
- (goto-char beg)
- (line-beginning-position))))
- (end-marker (set-marker (make-marker) (save-excursion
- (goto-char end)
- (line-end-position)))))
- (untabify start-marker end-marker)
- (goto-char start-marker)
-
- ;; This is the guts of the alignment loop
- (while (and (or (setq acct-start-column (ledger-next-account (line-end-position)))
- lines-left)
- (< (point) end-marker))
- (when acct-start-column
- (setq acct-end-column (save-excursion
- (goto-char (match-end 2))
- (current-column)))
- (when (/= (setq acct-adjust (- ledger-post-account-alignment-column acct-start-column)) 0)
- (setq acct-end-column (+ acct-end-column acct-adjust)) ;;adjust the account ending column
- (if (> acct-adjust 0)
- (insert (make-string acct-adjust ? ))
- (delete-char acct-adjust)))
- (when (setq amt-width (ledger-next-amount (line-end-position)))
- (if (/= 0 (setq amt-adjust (- (if (> (- ledger-post-amount-alignment-column amt-width)
- (+ 2 acct-end-column))
- ledger-post-amount-alignment-column ;;we have room
- (+ acct-end-column 2 amt-width))
- amt-width
- (current-column))))
- (if (> amt-adjust 0)
- (insert (make-string amt-adjust ? ))
- (delete-char amt-adjust)))))
- (forward-line)
- (setq lines-left (not (eobp)))))
- (setq inhibit-modification-hooks nil))))
-
-(defun ledger-post-align-dwim ()
- "Align all the posting of the current xact or the current region.
-
-If the point is in a comment, fill the comment paragraph as
-regular text."
- (interactive)
- (cond
- ((nth 4 (syntax-ppss))
- (call-interactively 'ledger-post-align-postings)
- (fill-paragraph))
- ((use-region-p) (call-interactively 'ledger-post-align-postings))
- (t (call-interactively 'ledger-post-align-xact))))
-
-(defun ledger-post-edit-amount ()
- "Call 'calc-mode' and push the amount in the posting to the top of stack."
- (interactive)
- (goto-char (line-beginning-position))
- (when (re-search-forward ledger-post-line-regexp (line-end-position) t)
- (goto-char (match-end ledger-regex-post-line-group-account)) ;; go to the and of the account
- (let ((end-of-amount (re-search-forward "[-.,0-9]+" (line-end-position) t)))
- ;; determine if there is an amount to edit
- (if end-of-amount
- (let ((val-string (match-string 0)))
- (goto-char (match-beginning 0))
- (delete-region (match-beginning 0) (match-end 0))
- (calc)
- (calc-eval val-string 'push)) ;; edit the amount
- (progn ;;make sure there are two spaces after the account name and go to calc
- (if (search-backward " " (- (point) 3) t)
- (goto-char (line-end-position))
- (insert " "))
- (calc))))))
-
-(provide 'ledger-post)
-
-
-
-;;; ledger-post.el ends here
diff --git a/lisp/ledger-reconcile.el b/lisp/ledger-reconcile.el
deleted file mode 100644
index a6a7dd86..00000000
--- a/lisp/ledger-reconcile.el
+++ /dev/null
@@ -1,624 +0,0 @@
-;;; ledger-reconcile.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-;; Reconcile mode
-
-
-;;; Commentary:
-;; Code to handle reconciling Ledger files wiht outside sources
-
-;;; Code:
-
-(require 'easymenu)
-(require 'ledger-init)
-
-(defvar ledger-buf nil)
-(defvar ledger-bufs nil)
-(defvar ledger-acct nil)
-(defvar ledger-target nil)
-
-(defgroup ledger-reconcile nil
- "Options for Ledger-mode reconciliation"
- :group 'ledger)
-
-(defcustom ledger-recon-buffer-name "*Reconcile*"
- "Name to use for reconciliation buffer."
- :group 'ledger-reconcile)
-
-(defcustom ledger-narrow-on-reconcile t
- "If t, limit transactions shown in main buffer to those matching the reconcile regex."
- :type 'boolean
- :group 'ledger-reconcile)
-
-(defcustom ledger-buffer-tracks-reconcile-buffer t
- "If t, then when the cursor is moved to a new transaction in the reconcile buffer.
-Then that transaction will be shown in its source buffer."
- :type 'boolean
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-force-window-bottom nil
- "If t, make the reconcile window appear along the bottom of the register window and resize."
- :type 'boolean
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-toggle-to-pending t
- "If t, then toggle between uncleared and pending.
-reconcile-finish will mark all pending posting cleared."
- :type 'boolean
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-default-date-format ledger-default-date-format
- "Date format for the reconcile buffer.
-Default is ledger-default-date-format."
- :type 'string
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-target-prompt-string "Target amount for reconciliation "
- "Prompt for recon target."
- :type 'string
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-buffer-header "Reconciling account %s\n\n"
- "Default header string for the reconcile buffer.
-
-If non-nil, the name of the account being reconciled will be substituted
- into the '%s'. If nil, no header will be displayed."
- :type 'string
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-buffer-line-format "%(date)s %-4(code)s %-50(payee)s %-30(account)s %15(amount)s\n"
- "Format string for the ledger reconcile posting format.
-Available fields are date, status, code, payee, account,
-amount. The format for each field is %WIDTH(FIELD), WIDTH can be
-preced by a minus sign which mean to left justify and pad the
-field. WIDTH is the minimum number of characters to display;
-if string is longer, it is not truncated unless
-ledger-reconcile-buffer-payee-max-chars or
-ledger-reconcile-buffer-account-max-chars is defined."
- :type 'string
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-buffer-payee-max-chars -1
- "If positive, truncate payee name right side to max number of characters."
- :type 'integer
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-buffer-account-max-chars -1
- "If positive, truncate account name left side to max number of characters."
- :type 'integer
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-sort-key "(0)"
- "Key for sorting reconcile buffer.
-
-Possible values are '(date)', '(amount)', '(payee)' or '(0)' for no sorting, i.e. using ledger file order."
- :type 'string
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-insert-effective-date nil
- "If t, prompt for effective date when clearing transactions during reconciliation."
- :type 'boolean
- :group 'ledger-reconcile)
-
-(defcustom ledger-reconcile-finish-force-quit nil
- "If t, will force closing reconcile window after \\[ledger-reconcile-finish]."
- :type 'boolean
- :group 'ledger-reconcile)
-
-;; s-functions below are copied from Magnars' s.el
-;; prefix ledger-reconcile- is added to not conflict with s.el
-(defun ledger-reconcile-s-pad-left (len padding s)
- "If S is shorter than LEN, pad it with PADDING on the left."
- (let ((extra (max 0 (- len (length s)))))
- (concat (make-string extra (string-to-char padding))
- s)))
-(defun ledger-reconcile-s-pad-right (len padding s)
- "If S is shorter than LEN, pad it with PADDING on the right."
- (let ((extra (max 0 (- len (length s)))))
- (concat s
- (make-string extra (string-to-char padding)))))
-(defun ledger-reconcile-s-left (len s)
- "Return up to the LEN first chars of S."
- (if (> (length s) len)
- (substring s 0 len)
- s))
-(defun ledger-reconcile-s-right (len s)
- "Return up to the LEN last chars of S."
- (let ((l (length s)))
- (if (> l len)
- (substring s (- l len) l)
- s)))
-
-(defun ledger-reconcile-truncate-right (str len)
- "Truncate STR right side with max LEN characters, and pad with '…' if truncated."
- (if (and (>= len 0) (> (length str) len))
- (ledger-reconcile-s-pad-right len "…" (ledger-reconcile-s-left (- len 1) str))
- str))
-
-(defun ledger-reconcile-truncate-left (str len)
- "Truncate STR left side with max LEN characters, and pad with '…' if truncated."
- (if (and (>= len 0) (> (length str) len))
- (ledger-reconcile-s-pad-left len "…" (ledger-reconcile-s-right (- len 1) str))
- str))
-
-(defun ledger-reconcile-get-cleared-or-pending-balance (buffer account)
- "Use BUFFER to Calculate the cleared or pending balance of the ACCOUNT."
-
- ;; these vars are buffer local, need to hold them for use in the
- ;; temp buffer below
-
- (with-temp-buffer
- ;; note that in the line below, the --format option is
- ;; separated from the actual format string. emacs does not
- ;; split arguments like the shell does, so you need to
- ;; specify the individual fields in the command line.
- (if (ledger-exec-ledger buffer (current-buffer)
- "balance" "--limit" "cleared or pending" "--empty" "--collapse"
- "--format" "%(scrub(display_total))" account)
- (ledger-split-commodity-string
- (buffer-substring-no-properties (point-min) (point-max))))))
-
-(defun ledger-display-balance ()
- "Display the cleared-or-pending balance.
-And calculate the target-delta of the account being reconciled."
- (interactive)
- (let* ((pending (ledger-reconcile-get-cleared-or-pending-balance ledger-buf ledger-acct)))
- (when pending
- (if ledger-target
- (message "Cleared and Pending balance: %s, Difference from target: %s"
- (ledger-commodity-to-string pending)
- (ledger-commodity-to-string (-commodity ledger-target pending)))
- (message "Pending balance: %s"
- (ledger-commodity-to-string pending))))))
-
-(defun ledger-is-stdin (file)
- "True if ledger FILE is standard input."
- (or
- (equal file "")
- (equal file "<stdin>")
- (equal file "/dev/stdin")))
-
-(defun ledger-reconcile-get-buffer (where)
- "Return a buffer from WHERE the transaction is."
- (if (bufferp (car where))
- (car where)
- (error "Function ledger-reconcile-get-buffer: Buffer not set")))
-
-(defun ledger-reconcile-toggle ()
- "Toggle the current transaction, and mark the recon window."
- (interactive)
- (beginning-of-line)
- (let ((where (get-text-property (point) 'where))
- (inhibit-read-only t)
- status)
- (when (ledger-reconcile-get-buffer where)
- (with-current-buffer (ledger-reconcile-get-buffer where)
- (ledger-navigate-to-line (cdr where))
- (forward-char)
- (setq status (ledger-toggle-current (if ledger-reconcile-toggle-to-pending
- 'pending
- 'cleared)))
- (when ledger-reconcile-insert-effective-date
- ;; Ask for effective date & insert it
- (ledger-insert-effective-date)))
- ;; remove the existing face and add the new face
- (remove-text-properties (line-beginning-position)
- (line-end-position)
- (list 'face))
- (cond ((eq status 'pending)
- (add-text-properties (line-beginning-position)
- (line-end-position)
- (list 'face 'ledger-font-reconciler-pending-face )))
- ((eq status 'cleared)
- (add-text-properties (line-beginning-position)
- (line-end-position)
- (list 'face 'ledger-font-reconciler-cleared-face )))
- (t
- (add-text-properties (line-beginning-position)
- (line-end-position)
- (list 'face 'ledger-font-reconciler-uncleared-face )))))
- (forward-line)
- (beginning-of-line)
- (ledger-display-balance)))
-
-(defun ledger-reconcile-refresh ()
- "Force the reconciliation window to refresh.
-Return the number of uncleared xacts found."
- (interactive)
- (let ((inhibit-read-only t))
- (erase-buffer)
- (prog1
- (ledger-do-reconcile ledger-reconcile-sort-key)
- (set-buffer-modified-p t))))
-
-(defun ledger-reconcile-refresh-after-save ()
- "Refresh the recon-window after the ledger buffer is saved."
- (let ((curbufwin (get-buffer-window (current-buffer)))
- (curpoint (point))
- (recon-buf (get-buffer ledger-recon-buffer-name)))
- (when (buffer-live-p recon-buf)
- (with-current-buffer recon-buf
- (ledger-reconcile-refresh)
- (set-buffer-modified-p nil))
- (when curbufwin
- (select-window curbufwin)
- (goto-char curpoint)))))
-
-(defun ledger-reconcile-add ()
- "Use ledger xact to add a new transaction."
- (interactive)
- (with-current-buffer ledger-buf
- (call-interactively #'ledger-add-transaction))
- (ledger-reconcile-refresh))
-
-(defun ledger-reconcile-delete ()
- "Delete the transactions pointed to in the recon window."
- (interactive)
- (let ((where (get-text-property (point) 'where)))
- (when (ledger-reconcile-get-buffer where)
- (with-current-buffer (ledger-reconcile-get-buffer where)
- (ledger-navigate-to-line (cdr where))
- (ledger-delete-current-transaction (point)))
- (let ((inhibit-read-only t))
- (goto-char (line-beginning-position))
- (delete-region (point) (1+ (line-end-position)))
- (set-buffer-modified-p t))
- (ledger-reconcile-refresh))))
-
-(defun ledger-reconcile-visit (&optional come-back)
- "Recenter ledger buffer on transaction and COME-BACK if non-nil."
- (interactive)
- (beginning-of-line)
- (let* ((where (get-text-property (1+ (point)) 'where))
- (target-buffer (if where
- (ledger-reconcile-get-buffer where)
- nil))
- (cur-win (get-buffer-window (get-buffer ledger-recon-buffer-name))))
- (when target-buffer
- (switch-to-buffer-other-window target-buffer)
- (ledger-navigate-to-line (cdr where))
- (forward-char)
- (recenter)
- (ledger-highlight-xact-under-point)
- (forward-char -1)
- (when (and come-back cur-win)
- (select-window cur-win)
- (get-buffer ledger-recon-buffer-name)))))
-
-
-(defun ledger-reconcile-save ()
- "Save the ledger buffer."
- (interactive)
- (let ((cur-buf (current-buffer))
- (cur-point (point)))
- (dolist (buf (cons ledger-buf ledger-bufs))
- (with-current-buffer buf
- (basic-save-buffer)))
- (switch-to-buffer-other-window cur-buf)
- (goto-char cur-point)))
-
-
-(defun ledger-reconcile-finish ()
- "Mark all pending posting or transactions as cleared.
-Depends on ledger-reconcile-clear-whole-transactions, save the buffers
-and exit reconcile mode if `ledger-reconcile-finish-force-quit'"
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (while (not (eobp))
- (let ((where (get-text-property (point) 'where))
- (face (get-text-property (point) 'face)))
- (if (eq face 'ledger-font-reconciler-pending-face)
- (with-current-buffer (ledger-reconcile-get-buffer where)
- (ledger-navigate-to-line (cdr where))
- (ledger-toggle-current 'cleared))))
- (forward-line 1)))
- (ledger-reconcile-save)
- (when ledger-reconcile-finish-force-quit
- (ledger-reconcile-quit)))
-
-
-(defun ledger-reconcile-quit ()
- "Quit the reconcile window without saving ledger buffer."
- (interactive)
- (let ((recon-buf (get-buffer ledger-recon-buffer-name))
- buf)
- (if recon-buf
- (with-current-buffer recon-buf
- (ledger-reconcile-quit-cleanup)
- (setq buf ledger-buf)
- ;; Make sure you delete the window before you delete the buffer,
- ;; otherwise, madness ensues
- (delete-window (get-buffer-window recon-buf))
- (kill-buffer recon-buf)
- (set-window-buffer (selected-window) buf)))))
-
-(defun ledger-reconcile-quit-cleanup ()
- "Cleanup all hooks established by reconcile mode."
- (interactive)
- (let ((buf ledger-buf))
- (if (buffer-live-p buf)
- (with-current-buffer buf
- (remove-hook 'after-save-hook 'ledger-reconcile-refresh-after-save t)
- (when ledger-narrow-on-reconcile
- (ledger-occur-mode -1)
- (ledger-highlight-xact-under-point))))))
-
-(defun ledger-marker-where-xact-is (emacs-xact posting)
- "Find the position of the EMACS-XACT in the `ledger-buf'.
-POSTING is used in `ledger-clear-whole-transactions' is nil."
- (let ((buf (if (ledger-is-stdin (nth 0 emacs-xact))
- ledger-buf
- (find-file-noselect (nth 0 emacs-xact)))))
- (cons
- buf
- (if ledger-clear-whole-transactions
- (nth 1 emacs-xact) ;; return line-no of xact
- (nth 0 posting))))) ;; return line-no of posting
-
-(defun ledger-reconcile-compile-format-string (fstr)
- "Return a function that implements the format string in FSTR."
- (let (fields
- (start 0))
- (while (string-match "(\\(.*?\\))" fstr start)
- (setq fields (cons (intern (match-string 1 fstr)) fields))
- (setq start (match-end 0)))
- (setq fields (list* 'format (replace-regexp-in-string "(.*?)" "" fstr) (nreverse fields)))
- `(lambda (date code status payee account amount)
- ,fields)))
-
-
-
-(defun ledger-reconcile-format-posting (beg where fmt date code status payee account amount)
- "Format posting for the reconcile buffer."
- (insert (funcall fmt date code status payee account amount))
-
- ; Set face depending on cleared status
- (if status
- (if (eq status 'pending)
- (set-text-properties beg (1- (point))
- (list 'face 'ledger-font-reconciler-pending-face
- 'where where))
- (set-text-properties beg (1- (point))
- (list 'face 'ledger-font-reconciler-cleared-face
- 'where where)))
- (set-text-properties beg (1- (point))
- (list 'face 'ledger-font-reconciler-uncleared-face
- 'where where))))
-
-(defun ledger-reconcile-format-xact (xact fmt)
- "Format XACT using FMT."
- (let ((date-format (or (cdr (assoc "date-format" ledger-environment-alist))
- ledger-default-date-format)))
- (dolist (posting (nthcdr 5 xact))
- (let ((beg (point))
- (where (ledger-marker-where-xact-is xact posting)))
- (ledger-reconcile-format-posting beg
- where
- fmt
- (format-time-string date-format (nth 2 xact)) ; date
- (if (nth 3 xact) (nth 3 xact) "") ; code
- (nth 3 posting) ; status
- (ledger-reconcile-truncate-right
- (nth 4 xact) ; payee
- ledger-reconcile-buffer-payee-max-chars)
- (ledger-reconcile-truncate-left
- (nth 1 posting) ; account
- ledger-reconcile-buffer-account-max-chars)
- (nth 2 posting)))))) ; amount
-
-(defun ledger-do-reconcile (&optional sort)
- "SORT the uncleared transactions in the account and display them in the *Reconcile* buffer.
-Return a count of the uncleared transactions."
- (let* ((buf ledger-buf)
- (account ledger-acct)
- (ledger-success nil)
- (sort-by (if sort
- sort
- "(date)"))
- (xacts
- (with-temp-buffer
- (when (ledger-exec-ledger buf (current-buffer)
- "--uncleared" "--real" "emacs" "--sort" sort-by account)
- (setq ledger-success t)
- (goto-char (point-min))
- (unless (eobp)
- (if (looking-at "(")
- (read (current-buffer))))))) ;current-buffer is the *temp* created above
- (fmt (ledger-reconcile-compile-format-string ledger-reconcile-buffer-line-format)))
- (if (and ledger-success (> (length xacts) 0))
- (progn
- (insert (format ledger-reconcile-buffer-header account))
- (dolist (xact xacts)
- (ledger-reconcile-format-xact xact fmt))
- (goto-char (point-max))
- (delete-char -1)) ;gets rid of the extra line feed at the bottom of the list
- (if ledger-success
- (insert (concat "There are no uncleared entries for " account))
- (insert "Ledger has reported a problem. Check *Ledger Error* buffer.")))
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
-
- (ledger-reconcile-ensure-xacts-visible)
- (length xacts)))
-
-(defun ledger-reconcile-ensure-xacts-visible ()
- "Ensure the last of the visible transactions in the ledger buffer is at the bottom of the main window.
-The key to this is to ensure the window is selected when the buffer point is
-moved and recentered. If they aren't strange things happen."
-
- (let ((recon-window (get-buffer-window (get-buffer ledger-recon-buffer-name))))
- (when recon-window
- (fit-window-to-buffer recon-window)
- (with-current-buffer ledger-buf
- (add-hook 'kill-buffer-hook 'ledger-reconcile-quit nil t)
- (if (get-buffer-window ledger-buf)
- (select-window (get-buffer-window ledger-buf)))
- (goto-char (point-max))
- (recenter -1))
- (select-window recon-window)
- (ledger-reconcile-visit t))
- (add-hook 'post-command-hook 'ledger-reconcile-track-xact nil t)))
-
-(defun ledger-reconcile-track-xact ()
- "Force the ledger buffer to recenter on the transaction at point in the reconcile buffer."
- (if (and ledger-buffer-tracks-reconcile-buffer
- (member this-command (list 'next-line
- 'previous-line
- 'mouse-set-point
- 'ledger-reconcile-toggle
- 'end-of-buffer
- 'beginning-of-buffer)))
- (save-excursion
- (ledger-reconcile-visit t))))
-
-(defun ledger-reconcile-open-windows (buf rbuf)
- "Ensure that the ledger buffer BUF is split by RBUF."
- (if ledger-reconcile-force-window-bottom
- ;;create the *Reconcile* window directly below the ledger buffer.
- (set-window-buffer (split-window (get-buffer-window buf) nil nil) rbuf)
- (pop-to-buffer rbuf)))
-
-(defun ledger-reconcile-check-valid-account (account)
- "Check to see if ACCOUNT exists in the ledger file"
- (if (> (length account) 0)
- (save-excursion
- (goto-char (point-min))
- (search-forward account nil t))))
-
-(defun ledger-reconcile ()
- "Start reconciling, prompt for account."
- (interactive)
- (let ((account (ledger-read-account-with-prompt "Account to reconcile"))
- (buf (current-buffer))
- (rbuf (get-buffer ledger-recon-buffer-name)))
-
- (when (ledger-reconcile-check-valid-account account)
- (add-hook 'after-save-hook 'ledger-reconcile-refresh-after-save nil t)
-
- (if rbuf ;; *Reconcile* already exists
- (with-current-buffer rbuf
- (set 'ledger-acct account) ;; already buffer local
- (when (not (eq buf rbuf))
- ;; called from some other ledger-mode buffer
- (ledger-reconcile-quit-cleanup)
- (setq ledger-buf buf)) ;; should already be buffer-local
-
- (unless (get-buffer-window rbuf)
- (ledger-reconcile-open-windows buf rbuf)))
-
- ;; no recon-buffer, starting from scratch.
-
- (with-current-buffer (setq rbuf
- (get-buffer-create ledger-recon-buffer-name))
- (ledger-reconcile-open-windows buf rbuf)
- (ledger-reconcile-mode)
- (make-local-variable 'ledger-target)
- (set (make-local-variable 'ledger-buf) buf)
- (set (make-local-variable 'ledger-acct) account)))
-
- ;; Narrow the ledger buffer
- (with-current-buffer rbuf
- (save-excursion
- (if ledger-narrow-on-reconcile
- (ledger-occur account)))
- (if (> (ledger-reconcile-refresh) 0)
- (ledger-reconcile-change-target))
- (ledger-display-balance)))))
-
-(defvar ledger-reconcile-mode-abbrev-table)
-
-(defun ledger-reconcile-change-target ()
- "Change the target amount for the reconciliation process."
- (interactive)
- (setq ledger-target (ledger-read-commodity-string ledger-reconcile-target-prompt-string)))
-
-(defmacro ledger-reconcile-change-sort-key-and-refresh (sort-by)
- "Set the sort-key to SORT-BY."
- `(lambda ()
- (interactive)
-
- (setq ledger-reconcile-sort-key ,sort-by)
- (ledger-reconcile-refresh)))
-
-(defvar ledger-reconcile-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [(control ?m)] 'ledger-reconcile-visit)
- (define-key map [return] 'ledger-reconcile-visit)
- (define-key map [(control ?x) (control ?s)] 'ledger-reconcile-save)
- (define-key map [(control ?l)] 'ledger-reconcile-refresh)
- (define-key map [(control ?c) (control ?c)] 'ledger-reconcile-finish)
- (define-key map [? ] 'ledger-reconcile-toggle)
- (define-key map [?a] 'ledger-reconcile-add)
- (define-key map [?d] 'ledger-reconcile-delete)
- (define-key map [?g] 'ledger-reconcile);
- (define-key map [?n] 'next-line)
- (define-key map [?p] 'previous-line)
- (define-key map [?t] 'ledger-reconcile-change-target)
- (define-key map [?s] 'ledger-reconcile-save)
- (define-key map [?q] 'ledger-reconcile-quit)
- (define-key map [?b] 'ledger-display-balance)
-
- (define-key map [(control ?c) (control ?o)] (ledger-reconcile-change-sort-key-and-refresh "(0)"))
-
- (define-key map [(control ?c) (control ?a)] (ledger-reconcile-change-sort-key-and-refresh "(amount)"))
-
- (define-key map [(control ?c) (control ?d)] (ledger-reconcile-change-sort-key-and-refresh "(date)"))
-
- (define-key map [(control ?c) (control ?p)] (ledger-reconcile-change-sort-key-and-refresh "(payee)"))
- map)
- "Keymap for `ledger-reconcile-mode'.")
-
-(easy-menu-define ledger-reconcile-mode-menu ledger-reconcile-mode-map
- "Ledger reconcile menu"
- `("Reconcile"
- ["Save" ledger-reconcile-save]
- ["Refresh" ledger-reconcile-refresh]
- ["Finish" ledger-reconcile-finish]
- "---"
- ["Reconcile New Account" ledger-reconcile]
- "---"
- ["Change Target Balance" ledger-reconcile-change-target]
- ["Show Cleared Balance" ledger-display-balance]
- "---"
- ["Sort by payee" ,(ledger-reconcile-change-sort-key-and-refresh "(payee)")]
- ["Sort by date" ,(ledger-reconcile-change-sort-key-and-refresh "(date)")]
- ["Sort by amount" ,(ledger-reconcile-change-sort-key-and-refresh "(amount)")]
- ["Sort by file order" ,(ledger-reconcile-change-sort-key-and-refresh "(0)")]
- "---"
- ["Toggle Entry" ledger-reconcile-toggle]
- ["Add Entry" ledger-reconcile-add]
- ["Delete Entry" ledger-reconcile-delete]
- "---"
- ["Next Entry" next-line]
- ["Visit Source" ledger-reconcile-visit]
- ["Previous Entry" previous-line]
- "---"
- ["Quit" ledger-reconcile-quit]
- ))
-
-(define-derived-mode ledger-reconcile-mode text-mode "Reconcile"
- "A mode for reconciling ledger entries.")
-
-(provide 'ledger-reconcile)
-
-;;; ledger-reconcile.el ends here
diff --git a/lisp/ledger-regex.el b/lisp/ledger-regex.el
deleted file mode 100644
index 83c59feb..00000000
--- a/lisp/ledger-regex.el
+++ /dev/null
@@ -1,383 +0,0 @@
-;;; ledger-regex.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-(require 'rx)
-
-(eval-when-compile
- (require 'cl))
-
-(defconst ledger-amount-regex
- (concat "\\( \\|\t\\| \t\\)[ \t]*-?"
- "\\([A-Z$€£₹_(]+ *\\)?"
- ;; We either match just a number after the commodity with no
- ;; decimal or thousand separators or a number with thousand
- ;; separators. If we have a decimal part starting with `,'
- ;; or `.', because the match is non-greedy, it must leave at
- ;; least one of those symbols for the following capture
- ;; group, which then finishes the decimal part.
- "\\(-?\\(?:[0-9]+\\|[0-9,.]+?\\)\\)"
- "\\([,.][0-9)]+\\)?"
- "\\( *[[:word:]€£₹_\"]+\\)?"
- "\\([ \t]*[@={]@?[^\n;]+?\\)?"
- "\\([ \t]+;.+?\\|[ \t]*\\)?$"))
-
-(defconst ledger-amount-decimal-comma-regex
- "-?[1-9][0-9.]*[,]?[0-9]*")
-
-(defconst ledger-amount-decimal-period-regex
- "-?[1-9][0-9,]*[.]?[0-9]*")
-
-(defconst ledger-other-entries-regex
- "\\(^[~=A-Za-z].+\\)+")
-
-(defconst ledger-comment-regex
- "^[;#|\\*%].*\\|[ \t]+;.*")
-
-(defconst ledger-multiline-comment-start-regex
- "^!comment$")
-(defconst ledger-multiline-comment-end-regex
- "^!end_comment$")
-(defconst ledger-multiline-comment-regex
- "^!comment\n\\(.*\n\\)*?!end_comment$")
-
-(defconst ledger-payee-any-status-regex
- "^[0-9]+[-/][-/.=0-9]+\\(\\s-+\\*\\)?\\(\\s-+(.*?)\\)?\\s-+\\(.+?\\)\\s-*\\(;\\|$\\)")
-
-(defconst ledger-payee-pending-regex
- "^[0-9]+[-/][-/.=0-9]+\\s-\\!\\s-+\\(([^)]+)\\s-+\\)?\\([^*].+?\\)\\s-*\\(;\\|$\\)")
-
-(defconst ledger-payee-cleared-regex
- "^[0-9]+[-/][-/.=0-9]+\\s-\\*\\s-+\\(([^)]+)\\s-+\\)?\\([^*].+?\\)\\s-*\\(;\\|$\\)")
-
-(defconst ledger-payee-uncleared-regex
- "^[0-9]+[-/][-/.=0-9]+\\s-+\\(([^)]+)\\s-+\\)?\\([^*].+?\\)\\s-*\\(;\\|$\\)")
-
-(defconst ledger-init-string-regex
- "^--.+?\\($\\|[ ]\\)")
-
-(defconst ledger-account-any-status-regex
- "^[ \t]+\\([*!]\\s-+\\)?\\([[(]?.+?\\)\\(\t\\|\n\\| [ \t]\\)")
-
-(defun ledger-account-any-status-with-seed-regex (seed)
- (concat "^[ \t]+\\([*!]\\s-+\\)?\\([[(]?" seed ".+?\\)\\(\t\\|\n\\| [ \t]\\)"))
-
-(defconst ledger-account-pending-regex
- "\\(^[ \t]+\\)\\(!\\s-*.*?\\)\\( \\|\t\\|$\\)")
-
-(defconst ledger-account-cleared-regex
- "\\(^[ \t]+\\)\\(*\\s-*.*?\\)\\( \\|\t\\|$\\)")
-
-
-(defmacro ledger-define-regexp (name regex docs &rest args)
- "Simplify the creation of a Ledger regex and helper functions."
- (let ((defs
- (list
- `(defconst
- ,(intern (concat "ledger-" (symbol-name name) "-regexp"))
- ,(eval regex))))
- (addend 0) last-group)
- (if (null args)
- (progn
- (nconc
- defs
- (list
- `(defconst
- ,(intern
- (concat "ledger-regex-" (symbol-name name) "-group"))
- 1)))
- (nconc
- defs
- (list
- `(defconst
- ,(intern (concat "ledger-regex-" (symbol-name name)
- "-group--count"))
- 1)))
- (nconc
- defs
- (list
- `(defmacro
- ,(intern (concat "ledger-regex-" (symbol-name name)))
- (&optional string)
- ,(format "Return the match string for the %s" name)
- (match-string
- ,(intern (concat "ledger-regex-" (symbol-name name)
- "-group"))
- string)))))
-
- (dolist (arg args)
- (let (var grouping target)
- (if (symbolp arg)
- (setq var arg target arg)
- (assert (listp arg))
- (if (= 2 (length arg))
- (setq var (car arg)
- target (cadr arg))
- (setq var (car arg)
- grouping (cadr arg)
- target (caddr arg))))
-
- (if (and last-group
- (not (eq last-group (or grouping target))))
- (incf addend
- (symbol-value
- (intern-soft (concat "ledger-regex-"
- (symbol-name last-group)
- "-group--count")))))
- (nconc
- defs
- (list
- `(defconst
- ,(intern (concat "ledger-regex-" (symbol-name name)
- "-group-" (symbol-name var)))
- ,(+ addend
- (symbol-value
- (intern-soft
- (if grouping
- (concat "ledger-regex-" (symbol-name grouping)
- "-group-" (symbol-name target))
- (concat "ledger-regex-" (symbol-name target)
- "-group"))))))))
- (nconc
- defs
- (list
- `(defmacro
- ,(intern (concat "ledger-regex-" (symbol-name name)
- "-" (symbol-name var)))
- (&optional string)
- ,(format "Return the sub-group match for the %s %s."
- name var)
- (match-string
- ,(intern (concat "ledger-regex-" (symbol-name name)
- "-group-" (symbol-name var)))
- string))))
-
- (setq last-group (or grouping target))))
-
- (nconc defs
- (list
- `(defconst ,(intern (concat "ledger-regex-" (symbol-name name)
- "-group--count"))
- ,(length args)))))
-
- (cons 'progn defs)))
-
-(put 'ledger-define-regexp 'lisp-indent-function 1)
-
-(ledger-define-regexp iso-date
- ( let ((sep '(or ?- ?/)))
- (rx (group
- (and (? (and (group (= 4 num)))
- (eval sep))
- (group (and num (? num)))
- (eval sep)
- (group (and num (? num)))))))
- "Match a single date, in its 'written' form.")
-
-(ledger-define-regexp full-date
- (macroexpand
- `(rx (and (regexp ,ledger-iso-date-regexp)
- (? (and ?= (regexp ,ledger-iso-date-regexp))))))
- "Match a compound date, of the form ACTUAL=EFFECTIVE"
- (actual iso-date)
- (effective iso-date))
-
-(ledger-define-regexp state
- (rx (group (any ?! ?*)))
- "Match a transaction or posting's \"state\" character.")
-
-(ledger-define-regexp code
- (rx (and ?\( (group (+? (not (any ?\))))) ?\)))
- "Match the transaction code.")
-
-(ledger-define-regexp long-space
- (rx (and (*? blank)
- (or (and ? (or ? ?\t)) ?\t)))
- "Match a \"long space\".")
-
-(ledger-define-regexp note
- (rx (group (+ nonl)))
- "")
-
-(ledger-define-regexp end-note
- (macroexpand
- `(rx (and (regexp ,ledger-long-space-regexp) ?\;
- (regexp ,ledger-note-regexp))))
- "")
-
-(ledger-define-regexp full-note
- (macroexpand
- `(rx (and line-start (+ blank)
- ?\; (regexp ,ledger-note-regexp))))
- "")
-
-(ledger-define-regexp xact-line
- (macroexpand
- `(rx (and line-start
- (regexp ,ledger-full-date-regexp)
- (? (and (+ blank) (regexp ,ledger-state-regexp)))
- (? (and (+ blank) (regexp ,ledger-code-regexp)))
- (+ blank) (+? nonl)
- (? (regexp ,ledger-end-note-regexp))
- line-end)))
- "Match a transaction's first line (and optional notes)."
- (actual-date full-date actual)
- (effective-date full-date effective)
- state
- code
- (note end-note))
-
-(ledger-define-regexp recurring-line
- (macroexpand
- `(rx (and line-start
- (regexp "\\[.+/.+/.+\\]")
- (? (and (+ blank) (regexp ,ledger-state-regexp)))
- (? (and (+ blank) (regexp ,ledger-code-regexp)))
- (+ blank) (+? nonl)
- (? (regexp ,ledger-end-note-regexp))
- line-end)))
- "Match a transaction's first line (and optional notes)."
- (actual-date full-date actual)
- (effective-date full-date effective)
- state
- code
- (note end-note))
-
-(ledger-define-regexp account
- (rx (group (and (not (any blank ?\[ ?\( ?: ?\;)) (*? nonl))))
- "")
-
-(ledger-define-regexp account-kind
- (rx (group (? (any ?\[ ?\())))
- "")
-
-(ledger-define-regexp full-account
- (macroexpand
- `(rx (and (regexp ,ledger-account-kind-regexp)
- (regexp ,ledger-account-regexp)
- (? (any ?\] ?\))))))
- ""
- (kind account-kind)
- (name account))
-
-(ledger-define-regexp commodity
- (rx (group
- (or (and ?\" (+ (not (any ?\"))) ?\")
- (not (any blank ?\n
- digit
- ?- ?\[ ?\]
- ?. ?, ?\; ?+ ?* ?/ ?^ ?? ?: ?& ?| ?! ?=
- ?\< ?\> ?\{ ?\} ?\( ?\) ?@)))))
- "")
-
-(ledger-define-regexp amount
- (rx (group
- (and (? ?-)
- (and (+ digit)
- (*? (and (any ?. ?,) (+ digit))))
- (? (and (any ?. ?,) (+ digit))))))
- "")
-
-(ledger-define-regexp commoditized-amount
- (macroexpand
- `(rx (group
- (or (and (regexp ,ledger-commodity-regexp)
- (*? blank)
- (regexp ,ledger-amount-regexp))
- (and (regexp ,ledger-amount-regexp)
- (*? blank)
- (regexp ,ledger-commodity-regexp))))))
- "")
-
-(ledger-define-regexp commodity-annotations
- (macroexpand
- `(rx (* (+ blank)
- (or (and ?\{ (regexp ,ledger-commoditized-amount-regexp) ?\})
- (and ?\[ (regexp ,ledger-iso-date-regexp) ?\])
- (and ?\( (not (any ?\))) ?\))))))
- "")
-
-(ledger-define-regexp cost
- (macroexpand
- `(rx (and (or "@" "@@") (+ blank)
- (regexp ,ledger-commoditized-amount-regexp))))
- "")
-
-(ledger-define-regexp balance-assertion
- (macroexpand
- `(rx (and ?= (+ blank)
- (regexp ,ledger-commoditized-amount-regexp))))
- "")
-
-(ledger-define-regexp full-amount
- (macroexpand `(rx (group (+? (not (any ?\;))))))
- "")
-
-(ledger-define-regexp post-line
- (macroexpand
- `(rx (and line-start (+ blank)
- (? (and (regexp ,ledger-state-regexp) (* blank)))
- (regexp ,ledger-full-account-regexp)
- (? (and (regexp ,ledger-long-space-regexp)
- (regexp ,ledger-full-amount-regexp)))
- (? (regexp ,ledger-end-note-regexp))
- line-end)))
- ""
- state
- (account-kind full-account kind)
- (account full-account name)
- (amount full-amount)
- (note end-note))
-
-(defconst ledger-iterate-regex
- (concat "\\(\\(?:Y\\|year\\)\\s-+\\([0-9]+\\)\\|" ;; Catches a Y/year directive
- ledger-iso-date-regexp
- "\\([ *!]+\\)" ;; mark
- "\\((.*)\\)?" ;; code
- "\\([[:word:] ]+\\)" ;; desc
- "\\)"))
-
-(defconst ledger-xact-start-regex
- (concat "^" ledger-iso-date-regexp ;; subexp 1
- "\\(=" ledger-iso-date-regexp "\\)?"
- ))
-
-(defconst ledger-xact-after-date-regex
- (concat "\\([ \t]+[*!]\\)?" ;; mark, subexp 1
- "\\([ \t]+(.*?)\\)?" ;; code, subexp 2
- "\\([ \t]+[^;\n]+\\)" ;; desc, subexp 3
- "\\(;[^\n]*\\)?" ;; comment, subexp 4
- ))
-
-(defconst ledger-posting-regex
- (concat "^[ \t]+ ?" ;; initial white space
- "\\([*!]\\)? ?" ;; state, subexpr 1
- "\\([[:print:]]+\\([ \t][ \t]\\)\\)" ;; account, subexpr 2
- "\\([^;\n]*\\)" ;; amount, subexpr 4
- "\\(.*\\)" ;; comment, subexpr 5
- ))
-
-
-
-(defconst ledger-directive-start-regex
- "[=~;#%|\\*[A-Za-z]")
-
-
-(provide 'ledger-regex)
diff --git a/lisp/ledger-report.el b/lisp/ledger-report.el
deleted file mode 100644
index 8b6b1c9d..00000000
--- a/lisp/ledger-report.el
+++ /dev/null
@@ -1,462 +0,0 @@
-;;; ledger-report.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-
-;;; Commentary:
-;; Provide facilities for running and saving reports in emacs
-
-;;; Code:
-
-(require 'easymenu)
-(eval-when-compile
- (require 'cl))
-
-(defgroup ledger-report nil
- "Customization option for the Report buffer"
- :group 'ledger)
-
-(defcustom ledger-reports
- '(("bal" "ledger -f %(ledger-file) bal")
- ("reg" "ledger -f %(ledger-file) reg")
- ("payee" "ledger -f %(ledger-file) reg @%(payee)")
- ("account" "ledger -f %(ledger-file) reg %(account)"))
- "Definition of reports to run.
-
-Each element has the form (NAME CMDLINE). The command line can
-contain format specifiers that are replaced with context sensitive
-information. Format specifiers have the format '%(<name>)' where
-<name> is an identifier for the information to be replaced. The
-`ledger-report-format-specifiers' alist variable contains a mapping
-from format specifier identifier to a Lisp function that implements
-the substitution. See the documentation of the individual functions
-in that variable for more information on the behavior of each
-specifier."
- :type '(repeat (list (string :tag "Report Name")
- (string :tag "Command Line")))
- :group 'ledger-report)
-
-(defcustom ledger-report-format-specifiers
- '(("ledger-file" . ledger-report-ledger-file-format-specifier)
- ("payee" . ledger-report-payee-format-specifier)
- ("account" . ledger-report-account-format-specifier)
- ("tagname" . ledger-report-tagname-format-specifier)
- ("tagvalue" . ledger-report-tagvalue-format-specifier))
- "An alist mapping ledger report format specifiers to implementing functions.
-
-The function is called with no parameters and expected to return the
-text that should replace the format specifier."
- :type 'alist
- :group 'ledger-report)
-
-(defcustom ledger-report-auto-refresh t
- "If t then automatically rerun the report when the ledger buffer is saved."
- :type 'boolean
- :group 'ledger-report)
-
-(defcustom ledger-report-auto-refresh-sticky-cursor nil
- "If t then try to place cursor at same relative position as it was before auto-refresh."
- :type 'boolean
- :group 'ledger-report)
-
-(defvar ledger-report-buffer-name "*Ledger Report*")
-
-(defvar ledger-report-name nil)
-(defvar ledger-report-cmd nil)
-(defvar ledger-report-name-prompt-history nil)
-(defvar ledger-report-cmd-prompt-history nil)
-(defvar ledger-original-window-cfg nil)
-(defvar ledger-report-saved nil)
-(defvar ledger-minibuffer-history nil)
-(defvar ledger-report-mode-abbrev-table)
-
-(defvar ledger-report-is-reversed nil)
-(defvar ledger-report-cursor-line-number nil)
-
-(defun ledger-report-reverse-report ()
- "Reverse the order of the report."
- (interactive)
- (ledger-report-reverse-lines)
- (setq ledger-report-is-reversed (not ledger-report-is-reversed)))
-
-(defun ledger-report-reverse-lines ()
- (goto-char (point-min))
- (forward-paragraph)
- (forward-line)
- (save-excursion
- (setq inhibit-read-only t)
- (reverse-region (point) (point-max))))
-
-(defvar ledger-report-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [? ] 'scroll-up)
- (define-key map [backspace] 'scroll-down)
- (define-key map [?r] 'ledger-report-redo)
- (define-key map [(shift ?r)] 'ledger-report-reverse-report)
- (define-key map [?s] 'ledger-report-save)
- (define-key map [?k] 'ledger-report-kill)
- (define-key map [?e] 'ledger-report-edit-report)
- (define-key map [( shift ?e)] 'ledger-report-edit-reports)
- (define-key map [?q] 'ledger-report-quit)
- (define-key map [?g] 'ledger-report-redo)
- (define-key map [(control ?c) (control ?l) (control ?r)]
- 'ledger-report-redo)
- (define-key map [(control ?c) (control ?l) (control ?S)]
- 'ledger-report-save)
- (define-key map [(control ?c) (control ?l) (control ?k)]
- 'ledger-report-kill)
- (define-key map [(control ?c) (control ?l) (control ?e)]
- 'ledger-report-edit)
- (define-key map [return] 'ledger-report-visit-source)
- map)
- "Keymap for `ledger-report-mode'.")
-
-(easy-menu-define ledger-report-mode-menu ledger-report-mode-map
- "Ledger report menu"
- '("Reports"
- ["Save Report" ledger-report-save]
- ["Edit Current Report" ledger-report-edit-report]
- ["Edit All Reports" ledger-report-edit-reports]
- ["Re-run Report" ledger-report-redo]
- "---"
- ["Reverse report order" ledger-report-reverse-report]
- "---"
- ["Scroll Up" scroll-up]
- ["Visit Source" ledger-report-visit-source]
- ["Scroll Down" scroll-down]
- "---"
- ["Quit" ledger-report-quit]
- ))
-
-(define-derived-mode ledger-report-mode text-mode "Ledger-Report"
- "A mode for viewing ledger reports.")
-
-(defun ledger-report-tagname-format-specifier ()
- "Return a valid meta-data tag name"
- ;; It is intended completion should be available on existing account
- ;; names, but it remains to be implemented.
- (ledger-read-string-with-default "Tag Name: " nil))
-
-(defun ledger-report-tagvalue-format-specifier ()
- "Return a valid meta-data tag name"
- ;; It is intended completion should be available on existing account
- ;; names, but it remains to be implemented.
- (ledger-read-string-with-default "Tag Value: " nil))
-
-(defun ledger-report-read-name ()
- "Read the name of a ledger report to use, with completion.
-
-The empty string and unknown names are allowed."
- (completing-read "Report name: "
- ledger-reports nil nil nil
- 'ledger-report-name-prompt-history nil))
-
-(defun ledger-report (report-name edit)
- "Run a user-specified report from `ledger-reports'.
-
-Prompts the user for the REPORT-NAME of the report to run or
-EDIT. If no name is entered, the user will be prompted for a
-command line to run. The command line specified or associated
-with the selected report name is run and the output is made
-available in another buffer for viewing. If a prefix argument is
-given and the user selects a valid report name, the user is
-prompted with the corresponding command line for editing before
-the command is run.
-
-The output buffer will be in `ledger-report-mode', which defines
-commands for saving a new named report based on the command line
-used to generate the buffer, navigating the buffer, etc."
- (interactive
- (progn
- (when (and (buffer-modified-p)
- (y-or-n-p "Buffer modified, save it? "))
- (save-buffer))
- (let ((rname (ledger-report-read-name))
- (edit (not (null current-prefix-arg))))
- (list rname edit))))
- (let ((buf (current-buffer))
- (rbuf (get-buffer ledger-report-buffer-name))
- (wcfg (current-window-configuration)))
- (if rbuf
- (kill-buffer rbuf))
- (with-current-buffer
- (pop-to-buffer (get-buffer-create ledger-report-buffer-name))
- (ledger-report-mode)
- (set (make-local-variable 'ledger-report-saved) nil)
- (set (make-local-variable 'ledger-buf) buf)
- (set (make-local-variable 'ledger-report-name) report-name)
- (set (make-local-variable 'ledger-original-window-cfg) wcfg)
- (set (make-local-variable 'ledger-report-is-reversed) nil)
- (ledger-do-report (ledger-report-cmd report-name edit))
- (shrink-window-if-larger-than-buffer)
- (set-buffer-modified-p nil)
- (setq buffer-read-only t)
- (message "q to quit; r to redo; e to edit; k to kill; s to save; SPC and DEL to scroll"))))
-
-(defun ledger-report-string-empty-p (s)
- "Check S for the empty string."
- (string-equal "" s))
-
-(defun ledger-report-name-exists (name)
- "Check to see if the given report NAME exists.
-
- If name exists, returns the object naming the report,
- otherwise returns nil."
- (unless (ledger-report-string-empty-p name)
- (car (assoc name ledger-reports))))
-
-(defun ledger-reports-add (name cmd)
- "Add a new report NAME and CMD to `ledger-reports'."
- (setq ledger-reports (cons (list name cmd) ledger-reports)))
-
-(defun ledger-reports-custom-save ()
- "Save the `ledger-reports' variable using the customize framework."
- (customize-save-variable 'ledger-reports ledger-reports))
-
-(defun ledger-report-read-command (report-cmd)
- "Read the command line to create a report from REPORT-CMD."
- (read-from-minibuffer "Report command line: "
- (if (null report-cmd) "ledger " report-cmd)
- nil nil 'ledger-report-cmd-prompt-history))
-
-(defun ledger-report-ledger-file-format-specifier ()
- "Substitute the full path to master or current ledger file.
-
- The master file name is determined by the variable `ledger-master-file'
- buffer-local variable which can be set using file variables.
- If it is set, it is used, otherwise the current buffer file is
- used."
- (ledger-master-file))
-
-;; General helper functions
-
-(defvar ledger-master-file nil)
-
-(defun ledger-master-file ()
- "Return the master file for a ledger file.
-
- The master file is either the file for the current ledger buffer or the
- file specified by the buffer-local variable `ledger-master-file'. Typically
- this variable would be set in a file local variable comment block at the
- end of a ledger file which is included in some other file."
- (if ledger-master-file
- (expand-file-name ledger-master-file)
- (buffer-file-name)))
-
-(defun ledger-report-payee-format-specifier ()
- "Substitute a payee name.
-
- The user is prompted to enter a payee and that is substitued. If
- point is in an xact, the payee for that xact is used as the
- default."
- ;; It is intended completion should be available on existing
- ;; payees, but the list of possible completions needs to be
- ;; developed to allow this.
- (ledger-read-string-with-default "Payee" (regexp-quote (ledger-xact-payee))))
-
-(defun ledger-report-account-format-specifier ()
- "Substitute an account name.
-
- The user is prompted to enter an account name, which can be any
- regular expression identifying an account. If point is on an account
- posting line for an xact, the full account name on that line is
- the default."
- ;; It is intended completion should be available on existing account
- ;; names, but it remains to be implemented.
- (ledger-read-account-with-prompt "Account"))
-
-(defun ledger-report-expand-format-specifiers (report-cmd)
- "Expand %(account) and %(payee) appearing in REPORT-CMD with thing under point."
- (save-match-data
- (let ((expanded-cmd report-cmd))
- (set-match-data (list 0 0))
- (while (string-match "%(\\([^)]*\\))" expanded-cmd (if (> (length expanded-cmd) (match-end 0))
- (match-end 0)
- (1- (length expanded-cmd))))
- (let* ((specifier (match-string 1 expanded-cmd))
- (f (cdr (assoc specifier ledger-report-format-specifiers))))
- (if f
- (setq expanded-cmd (replace-match
- (save-match-data
- (with-current-buffer ledger-buf
- (shell-quote-argument (funcall f))))
- t t expanded-cmd)))))
- expanded-cmd)))
-
-(defun ledger-report-cmd (report-name edit)
- "Get the command line to run the report name REPORT-NAME.
-Optional EDIT the command."
- (let ((report-cmd (car (cdr (assoc report-name ledger-reports)))))
- ;; logic for substitution goes here
- (when (or (null report-cmd) edit)
- (setq report-cmd (ledger-report-read-command report-cmd))
- (setq ledger-report-saved nil)) ;; this is a new report, or edited report
- (setq report-cmd (ledger-report-expand-format-specifiers report-cmd))
- (set (make-local-variable 'ledger-report-cmd) report-cmd)
- (or (ledger-report-string-empty-p report-name)
- (ledger-report-name-exists report-name)
- (progn
- (ledger-reports-add report-name report-cmd)
- (ledger-reports-custom-save)))
- report-cmd))
-
-(defun ledger-do-report (cmd)
- "Run a report command line CMD."
- (goto-char (point-min))
- (insert (format "Report: %s\n" ledger-report-name)
- (format "Command: %s\n" cmd)
- (make-string (- (window-width) 1) ?=)
- "\n\n")
- (let ((data-pos (point))
- (register-report (string-match " reg\\(ister\\)? " cmd))
- files-in-report)
- (shell-command
- ;; --subtotal does not produce identifiable transactions, so don't
- ;; prepend location information for them
- (if (and register-report
- (not (string-match "--subtotal" cmd)))
- (concat cmd " --prepend-format='%(filename):%(beg_line):'")
- cmd)
- t nil)
- (when register-report
- (goto-char data-pos)
- (while (re-search-forward "^\\(/[^:]+\\)?:\\([0-9]+\\)?:" nil t)
- (let ((file (match-string 1))
- (line (string-to-number (match-string 2))))
- (delete-region (match-beginning 0) (match-end 0))
- (when file
- (set-text-properties (line-beginning-position) (line-end-position)
- (list 'ledger-source (cons file (save-window-excursion
- (save-excursion
- (find-file file)
- (widen)
- (ledger-navigate-to-line line)
- (point-marker))))))
- (add-text-properties (line-beginning-position) (line-end-position)
- (list 'face 'ledger-font-report-clickable-face))
- (end-of-line)))))
- (goto-char data-pos)))
-
-
-(defun ledger-report-visit-source ()
- "Visit the transaction under point in the report window."
- (interactive)
- (let* ((prop (get-text-property (point) 'ledger-source))
- (file (if prop (car prop)))
- (line-or-marker (if prop (cdr prop))))
- (when (and file line-or-marker)
- (find-file-other-window file)
- (widen)
- (if (markerp line-or-marker)
- (goto-char line-or-marker)
- (goto-char (point-min))
- (forward-line (1- line-or-marker))
- (re-search-backward "^[0-9]+")
- (beginning-of-line)
- (let ((start-of-txn (point)))
- (forward-paragraph)
- (narrow-to-region start-of-txn (point))
- (backward-paragraph))))))
-
-(defun ledger-report-goto ()
- "Goto the ledger report buffer."
- (interactive)
- (let ((rbuf (get-buffer ledger-report-buffer-name)))
- (if (not rbuf)
- (error "There is no ledger report buffer"))
- (pop-to-buffer rbuf)
- (shrink-window-if-larger-than-buffer)))
-
-(defun ledger-report-redo ()
- "Redo the report in the current ledger report buffer."
- (interactive)
- (let ((cur-buf (current-buffer)))
- (if (and ledger-report-auto-refresh
- (or (string= (format-mode-line 'mode-name) "Ledger")
- (string= (format-mode-line 'mode-name) "Ledger-Report"))
- (get-buffer ledger-report-buffer-name))
- (progn
-
- (pop-to-buffer (get-buffer ledger-report-buffer-name))
- (shrink-window-if-larger-than-buffer)
- (setq buffer-read-only nil)
- (setq ledger-report-cursor-line-number (line-number-at-pos))
- (erase-buffer)
- (ledger-do-report ledger-report-cmd)
- (setq buffer-read-only nil)
- (if ledger-report-is-reversed (ledger-report-reverse-lines))
- (if ledger-report-auto-refresh-sticky-cursor (forward-line (- ledger-report-cursor-line-number 5)))
- (pop-to-buffer cur-buf)))))
-
-(defun ledger-report-quit ()
- "Quit the ledger report buffer."
- (interactive)
- (ledger-report-goto)
- (set-window-configuration ledger-original-window-cfg)
- (kill-buffer (get-buffer ledger-report-buffer-name)))
-
-(defun ledger-report-edit-reports ()
- "Edit the defined ledger reports."
- (interactive)
- (customize-variable 'ledger-reports))
-
-(defun ledger-report-edit-report ()
- (interactive)
- "Edit the current report command in the mini buffer and re-run the report"
- (setq ledger-report-cmd (ledger-report-read-command ledger-report-cmd))
- (ledger-report-redo))
-
-(defun ledger-report-read-new-name ()
- "Read the name for a new report from the minibuffer."
- (let ((name ""))
- (while (ledger-report-string-empty-p name)
- (setq name (read-from-minibuffer "Report name: " nil nil nil
- 'ledger-report-name-prompt-history)))
- name))
-
-(defun ledger-report-save ()
- "Save the current report command line as a named report."
- (interactive)
- (ledger-report-goto)
- (let (existing-name)
- (when (ledger-report-string-empty-p ledger-report-name)
- (setq ledger-report-name (ledger-report-read-new-name)))
-
- (if (setq existing-name (ledger-report-name-exists ledger-report-name))
- (cond ((y-or-n-p (format "Overwrite existing report named '%s'? "
- ledger-report-name))
- (if (string-equal
- ledger-report-cmd
- (car (cdr (assq existing-name ledger-reports))))
- (message "Nothing to save. Current command is identical to existing saved one")
- (progn
- (setq ledger-reports
- (assq-delete-all existing-name ledger-reports))
- (ledger-reports-add ledger-report-name ledger-report-cmd)
- (ledger-reports-custom-save))))
- (t
- (progn
- (setq ledger-report-name (ledger-report-read-new-name))
- (ledger-reports-add ledger-report-name ledger-report-cmd)
- (ledger-reports-custom-save)))))))
-
-(provide 'ledger-report)
-
-;;; ledger-report.el ends here
diff --git a/lisp/ledger-schedule.el b/lisp/ledger-schedule.el
deleted file mode 100644
index 1fbbcb59..00000000
--- a/lisp/ledger-schedule.el
+++ /dev/null
@@ -1,327 +0,0 @@
-;;; ledger-schedule.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2013 Craig Earls (enderw88 at gmail dot com)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-;; License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-;;; Commentary:
-;;
-;; This module provides for automatically adding transactions to a
-;; ledger buffer on a periodic basis. Recurrence expressions are
-;; inspired by Martin Fowler's "Recurring Events for Calendars",
-;; martinfowler.com/apsupp/recurring.pdf
-
-;; use (fset 'VARNAME (macro args)) to put the macro definition in the
-;; function slot of the symbol VARNAME. Then use VARNAME as the
-;; function without have to use funcall.
-
-(require 'ledger-init)
-(require 'cl)
-
-;;; Code:
-
-(defgroup ledger-schedule nil
- "Support for automatically recommendation transactions."
- :group 'ledger)
-
-(defcustom ledger-schedule-buffer-name "*Ledger Schedule*"
- "Name for the schedule buffer."
- :type 'string
- :group 'ledger-schedule)
-
-(defcustom ledger-schedule-look-backward 7
- "Number of days to look back in time for transactions."
- :type 'integer
- :group 'ledger-schedule)
-
-(defcustom ledger-schedule-look-forward 14
- "Number of days auto look forward to recommend transactions."
- :type 'integer
- :group 'ledger-schedule)
-
-(defcustom ledger-schedule-file "~/ledger-schedule.ledger"
- "File to find scheduled transactions."
- :type 'file
- :group 'ledger-schedule)
-
-(defcustom ledger-schedule-week-days '(("Mo" 1)
- ("Tu" 2)
- ("We" 3)
- ("Th" 4)
- ("Fr" 5)
- ("Sa" 6)
- ("Su" 7))
- "List of weekday abbreviations. There must be exactly seven
-entries each with a two character abbreviation for a day and the
-number of that day in the week. "
- :type '(alist :value-type (group integer))
- :group 'ledger-schedule)
-
-(defsubst between (val low high)
- "Return TRUE if VAL > LOW and < HIGH."
- (and (>= val low) (<= val high)))
-
-(defun ledger-schedule-days-in-month (month year)
- "Return number of days in the MONTH, MONTH is from 1 to 12.
-If YEAR is nil, assume it is not a leap year"
- (if (between month 1 12)
- (if (and year (date-leap-year-p year) (= 2 month))
- 29
- (nth (1- month) '(31 28 31 30 31 30 31 31 30 31 30 31)))
- (error "Month out of range, MONTH=%S" month)))
-
-(defun ledger-schedule-encode-day-of-week (day-string)
- "Return the numerical day of week corresponding to DAY-STRING."
- (cadr (assoc day-string ledger-schedule-week-days)))
-
-;; Macros to handle date expressions
-
-(defun ledger-schedule-constrain-day-in-month (count day-of-week)
- "Return a form that returns TRUE for the the COUNT DAY-OF-WEEK.
-For example, return true if date is the 3rd Thursday of the
-month. Negative COUNT starts from the end of the month. (EQ
-COUNT 0) means EVERY day-of-week (eg. every Saturday)"
- (if (and (between count -6 6) (between day-of-week 0 6))
- (cond ((zerop count) ;; Return true if day-of-week matches
- `(eq (nth 6 (decode-time date)) ,day-of-week))
- ((> count 0) ;; Positive count
- (let ((decoded (gensym)))
- `(let ((,decoded (decode-time date)))
- (and (eq (nth 6 ,decoded) ,day-of-week)
- (between (nth 3 ,decoded)
- ,(* (1- count) 7)
- ,(* count 7))))))
- ((< count 0)
- (let ((days-in-month (gensym))
- (decoded (gensym)))
- `(let* ((,decoded (decode-time date))
- (,days-in-month (ledger-schedule-days-in-month
- (nth 4 ,decoded)
- (nth 5 ,decoded))))
- (and (eq (nth 6 ,decoded) ,day-of-week)
- (between (nth 3 ,decoded)
- (+ ,days-in-month ,(* count 7))
- (+ ,days-in-month ,(* (1+ count) 7)))))))
- (t
- (error "COUNT out of range, COUNT=%S" count)))
- (error "Invalid argument to ledger-schedule-day-in-month-macro %S %S"
- count
- day-of-week)))
-
-(defun ledger-schedule-constrain-every-count-day (day-of-week skip start-date)
- "Return a form that is true for every DAY-OF-WEEK skipping SKIP, starting on START-DATE.
-For example every second Friday, regardless of month."
- (let ((start-day (nth 6 (decode-time start-date))))
- (if (eq start-day day-of-week) ;; good, can proceed
- `(zerop (mod (- (time-to-days date) ,(time-to-days start-date)) ,(* skip 7)))
- (error "START-DATE day of week doesn't match DAY-OF-WEEK"))))
-
-(defun ledger-schedule-constrain-date-range (month1 day1 month2 day2)
- "Return a form of DATE that is true if DATE falls between MONTH1 DAY1 and MONTH2 DAY2."
- (let ((decoded (gensym))
- (target-month (gensym))
- (target-day (gensym)))
- `(let* ((,decoded (decode-time date))
- (,target-month (nth 4 decoded))
- (,target-day (nth 3 decoded)))
- (and (and (> ,target-month ,month1)
- (< ,target-month ,month2))
- (and (> ,target-day ,day1)
- (< ,target-day ,day2))))))
-
-
-
-(defun ledger-schedule-scan-transactions (schedule-file)
- "Scan SCHEDULE-FILE and return a list of transactions with date predicates.
-The car of each item is a function of date that returns true if
-the transaction should be logged for that day."
- (interactive "fFile name: ")
- (let ((xact-list (list)))
- (with-current-buffer
- (find-file-noselect schedule-file)
- (goto-char (point-min))
- (while (re-search-forward "^\\[\\(.*\\)\\] " nil t)
- (let ((date-descriptor "")
- (transaction nil)
- (xact-start (match-end 0)))
- (setq date-descriptor
- (ledger-schedule-read-descriptor-tree
- (buffer-substring-no-properties
- (match-beginning 0)
- (match-end 0))))
- (forward-paragraph)
- (setq transaction (list date-descriptor
- (buffer-substring-no-properties
- xact-start
- (point))))
- (setq xact-list (cons transaction xact-list))))
- xact-list)))
-
-(defun ledger-schedule-read-descriptor-tree (descriptor-string)
- "Read DESCRIPTOR-STRING and return a form that evaluates dates."
- (ledger-schedule-transform-auto-tree
- (split-string
- (substring descriptor-string 1 (string-match "]" descriptor-string)) " ")))
-
-(defun ledger-schedule-transform-auto-tree (descriptor-string-list)
- "Take DESCRIPTOR-STRING-LIST, and return a string with a lambda function of date."
- ;; use funcall to use the lambda function spit out here
- (if (consp descriptor-string-list)
- (let (result)
- (while (consp descriptor-string-list)
- (let ((newcar (car descriptor-string-list)))
- (if (consp newcar)
- (setq newcar (ledger-schedule-transform-auto-tree (car descriptor-string-list))))
- ;; newcar may be a cons now, after ledger-schedule-transfrom-auto-tree
- (if (consp newcar)
- (push newcar result)
- ;; this is where we actually turn the string descriptor into useful lisp
- (push (ledger-schedule-compile-constraints newcar) result)) )
- (setq descriptor-string-list (cdr descriptor-string-list)))
-
- ;; tie up all the clauses in a big or lambda, and return
- ;; the lambda function as list to be executed by funcall
- `(lambda (date)
- ,(nconc (list 'or) (nreverse result) descriptor-string-list)))))
-
-(defun ledger-schedule-compile-constraints (descriptor-string)
- "Return a list with the year, month and day fields split."
- (let ((fields (split-string descriptor-string "[/\\-]" t)))
- (if (string-match "[A-Za-z]" descriptor-string)
- (ledger-schedule-constrain-day (nth 0 fields) (nth 1 fields) (nth 2 fields))
- (list 'and
- (ledger-schedule-constrain-day (nth 0 fields) (nth 1 fields) (nth 2 fields))
- (ledger-schedule-constrain-year (nth 0 fields) (nth 1 fields) (nth 2 fields))
- (ledger-schedule-constrain-month (nth 0 fields) (nth 1 fields) (nth 2 fields))))))
-
-(defun ledger-schedule-constrain-year (year-desc month-desc day-desc)
- "Return a form that constrains the year.
-
-YEAR-DESC, MONT-DESC, and DAY-DESC are the string portions of the
-date descriptor."
- (cond ((string= year-desc "*") t)
- ((/= 0 (string-to-number year-desc))
- `(memq (nth 5 (decode-time date)) ',(mapcar 'string-to-number (split-string year-desc ","))))
- (t
- (error "Improperly specified year constraint: %s %s %s" year-desc month-desc day-desc))))
-
-(defun ledger-schedule-constrain-month (year-desc month-desc day-desc)
- "Return a form that constrains the month.
-
-YEAR-DESC, MONT-DESC, and DAY-DESC are the string portions of the
-date descriptor."
- (cond ((string= month-desc "*")
- t) ;; always match
- ((string= month-desc "E") ;; Even
- `(evenp (nth 4 (decode-time date))))
- ((string= month-desc "O") ;; Odd
- `(oddp (nth 4 (decode-time date))))
- ((/= 0 (string-to-number month-desc)) ;; Starts with number
- `(memq (nth 4 (decode-time date)) ',(mapcar 'string-to-number (split-string month-desc ","))))
- (t
- (error "Improperly specified month constraint: %s %s %s" year-desc month-desc day-desc))))
-
-(defun ledger-schedule-constrain-day (year-desc month-desc day-desc)
- "Return a form that constrains the day.
-
-YEAR-DESC, MONT-DESC, and DAY-DESC are the string portions of the
-date descriptor."
- (cond ((string= day-desc "*")
- t)
- ((string-match "[A-Za-z]" day-desc) ;; There is something other than digits and commas
- (ledger-schedule-parse-complex-date year-desc month-desc day-desc))
- ((/= 0 (string-to-number day-desc))
- `(memq (nth 3 (decode-time date)) ',(mapcar 'string-to-number (split-string day-desc ","))))
- (t
- (error "Improperly specified day constraint: %s %s %s" year-desc month-desc day-desc))))
-
-
-
-(defun ledger-schedule-parse-complex-date (year-desc month-desc day-desc)
- "Parse day descriptors that have repeats."
- (let ((years (mapcar 'string-to-number (split-string year-desc ",")))
- (months (mapcar 'string-to-number (split-string month-desc ",")))
- (day-parts (split-string day-desc "+"))
- (every-nth (string-match "+" day-desc)))
- (if every-nth
- (let ((base-day (string-to-number (car day-parts)))
- (increment (string-to-number (substring (cadr day-parts) 0
- (string-match "[A-Za-z]" (cadr day-parts)))))
- (day-of-week (ledger-schedule-encode-day-of-week
- (substring (cadr day-parts) (string-match "[A-Za-z]" (cadr day-parts))))))
- (ledger-schedule-constrain-every-count-day day-of-week increment (encode-time 0 0 0 base-day (car months) (car years))))
- (let ((count (string-to-number (substring (car day-parts) 0 1)))
- (day-of-week (ledger-schedule-encode-day-of-week
- (substring (car day-parts) (string-match "[A-Za-z]" (car day-parts))))))
- (ledger-schedule-constrain-day-in-month count day-of-week)))))
-
-(defun ledger-schedule-list-upcoming-xacts (candidate-items early horizon)
- "Search CANDIDATE-ITEMS for xacts that occur within the period today - EARLY to today + HORIZON."
- (let ((start-date (time-subtract (current-time) (days-to-time early)))
- test-date items)
- (loop for day from 0 to (+ early horizon) by 1 do
- (setq test-date (time-add start-date (days-to-time day)))
- (dolist (candidate candidate-items items)
- (if (funcall (car candidate) test-date)
- (setq items (append items (list (list test-date (cadr candidate))))))))
- items))
-
-(defun ledger-schedule-create-auto-buffer (candidate-items early horizon ledger-buf)
- "Format CANDIDATE-ITEMS for display."
- (let ((candidates (ledger-schedule-list-upcoming-xacts candidate-items early horizon))
- (schedule-buf (get-buffer-create ledger-schedule-buffer-name))
- (date-format (or (cdr (assoc "date-format" ledger-environment-alist))
- ledger-default-date-format)))
- (with-current-buffer schedule-buf
- (erase-buffer)
- (dolist (candidate candidates)
- (insert (format-time-string date-format (car candidate) ) " " (cadr candidate) "\n"))
- (ledger-mode))
- (length candidates)))
-
-(defun ledger-schedule-upcoming (file look-backward look-forward)
- "Generate upcoming transactions.
-
-FILE is the file containing the scheduled transaction,
-default to `ledger-schedule-file'.
-LOOK-BACKWARD is the number of day in the past to look at
-default to `ledger-schedule-look-backward'
-LOOK-FORWARD is the number of day in the futur to look at
-default to `ledger-schedule-look-forward'
-
-Use a prefix arg to change the default value"
- (interactive (if current-prefix-arg
- (list (read-file-name "Schedule File: " () ledger-schedule-file t)
- (read-number "Look backward: " ledger-schedule-look-backward)
- (read-number "Look forward: " ledger-schedule-look-forward))
- (list ledger-schedule-file ledger-schedule-look-backward ledger-schedule-look-forward)))
- (if (and file
- (file-exists-p file))
- (progn
- (ledger-schedule-create-auto-buffer
- (ledger-schedule-scan-transactions file)
- look-backward
- look-forward
- (current-buffer))
- (pop-to-buffer ledger-schedule-buffer-name))
- (error "Could not find ledger schedule file at %s" file)))
-
-
-(provide 'ledger-schedule)
-
-;;; ledger-schedule.el ends here
diff --git a/lisp/ledger-sort.el b/lisp/ledger-sort.el
deleted file mode 100644
index 4306a6ca..00000000
--- a/lisp/ledger-sort.el
+++ /dev/null
@@ -1,123 +0,0 @@
-;;; ledger-xact.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-
-
-;;; Commentary:
-;;
-
-;;; Code:
-
-
-(defun ledger-sort-find-start ()
- "Find the beginning of a sort region"
- (if (re-search-forward ";.*Ledger-mode:.*Start sort" nil t)
- (match-end 0)))
-
-(defun ledger-sort-find-end ()
- "Find the end of a sort region"
- (if (re-search-forward ";.*Ledger-mode:.*End sort" nil t)
- (match-end 0)))
-
-(defun ledger-sort-insert-start-mark ()
- "Insert a marker to start a sort region"
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (if (ledger-sort-find-start)
- (delete-region (match-beginning 0) (match-end 0))))
- (beginning-of-line)
- (insert "\n; Ledger-mode: Start sort\n\n"))
-
-(defun ledger-sort-insert-end-mark ()
- "Insert a marker to end a sort region"
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (if (ledger-sort-find-end)
- (delete-region (match-beginning 0) (match-end 0))))
- (beginning-of-line)
- (insert "\n; Ledger-mode: End sort\n\n"))
-
-(defun ledger-sort-startkey ()
- "Return the actual date so the sort-subr doesn't sort onthe entire first line."
- (buffer-substring-no-properties (point) (+ 10 (point))))
-
-(defun ledger-sort-region (beg end)
- "Sort the region from BEG to END in chronological order."
- (interactive "r") ;; load beg and end from point and mark
- ;; automagically
- (let ((new-beg beg)
- (new-end end)
- point-delta
- (bounds (ledger-navigate-find-xact-extents (point)))
- target-xact)
-
- (setq point-delta (- (point) (car bounds)))
- (setq target-xact (buffer-substring (car bounds) (cadr bounds)))
- (setq inhibit-modification-hooks t)
- (save-excursion
- (save-restriction
- (goto-char beg)
- ;; make sure point is at the beginning of a xact
- (ledger-navigate-next-xact)
- (unless (looking-at ledger-payee-any-status-regex)
- (ledger-navigate-next-xact))
- (setq new-beg (point))
- (goto-char end)
- (ledger-navigate-next-xact)
- ;; make sure end of region is at the beginning of next record
- ;; after the region
- (setq new-end (point))
- (narrow-to-region new-beg new-end)
- (goto-char new-beg)
-
- (let ((inhibit-field-text-motion t))
- (sort-subr
- nil
- 'ledger-navigate-next-xact
- 'ledger-navigate-end-of-xact
- 'ledger-sort-startkey))))
-
- (goto-char (point-min))
- (re-search-forward (regexp-quote target-xact))
- (goto-char (+ (match-beginning 0) point-delta))
- (setq inhibit-modification-hooks nil)))
-
-(defun ledger-sort-buffer ()
- "Sort the entire buffer."
- (interactive)
- (let (sort-start
- sort-end)
- (save-excursion
- (goto-char (point-min))
- (setq sort-start (ledger-sort-find-start)
- sort-end (ledger-sort-find-end)))
- (ledger-sort-region (if sort-start
- sort-start
- (point-min))
- (if sort-end
- sort-end
- (point-max)))))
-
-(provide 'ledger-sort)
-
-;;; ledger-sort.el ends here
diff --git a/lisp/ledger-state.el b/lisp/ledger-state.el
deleted file mode 100644
index 61a9375e..00000000
--- a/lisp/ledger-state.el
+++ /dev/null
@@ -1,257 +0,0 @@
-;;; ledger-state.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-
-;;; Commentary:
-;; Utilities for dealing with transaction and posting status.
-
-;;; Code:
-
-(defcustom ledger-clear-whole-transactions nil
- "If non-nil, clear whole transactions, not individual postings."
- :type 'boolean
- :group 'ledger)
-
-(defun ledger-transaction-state ()
- "Return the state of the transaction at point."
- (save-excursion
- (when (or (looking-at "^[0-9]")
- (re-search-backward "^[0-9]" nil t))
- (skip-chars-forward "0-9./=\\-")
- (skip-syntax-forward " ")
- (cond ((looking-at "!\\s-*") 'pending)
- ((looking-at "\\*\\s-*") 'cleared)
- (t nil)))))
-
-(defun ledger-posting-state ()
- "Return the state of the posting."
- (save-excursion
- (goto-char (line-beginning-position))
- (skip-syntax-forward " ")
- (cond ((looking-at "!\\s-*") 'pending)
- ((looking-at "\\*\\s-*") 'cleared)
- (t (ledger-transaction-state)))))
-
-(defun ledger-char-from-state (state)
- "Return the char representation of STATE."
- (if state
- (if (eq state 'pending)
- "!"
- "*")
- ""))
-
-(defun ledger-state-from-char (state-char)
- "Get state from STATE-CHAR."
- (cond ((eql state-char ?\!) 'pending)
- ((eql state-char ?\*) 'cleared)
- ((eql state-char ?\;) 'comment)
- (t nil)))
-
-
-(defun ledger-state-from-string (state-string)
- "Get state from STATE-CHAR."
- (when state-string
- (cond
- ((string-match "\\!" state-string) 'pending)
- ((string-match "\\*" state-string) 'cleared)
- ((string-match ";" state-string) 'comment)
- (t nil))))
-
-(defun ledger-toggle-current-posting (&optional style)
- "Toggle the cleared status of the transaction under point.
-Optional argument STYLE may be `pending' or `cleared', depending
-on which type of status the caller wishes to indicate (default is
-`cleared'). Returns the new status as 'pending 'cleared or nil.
-This function is rather complicated because it must preserve both
-the overall formatting of the ledger xact, as well as ensuring
-that the most minimal display format is used. This could be
-achieved more certainly by passing the xact to ledger for
-formatting, but doing so causes inline math expressions to be
-dropped."
- (interactive)
- (let ((bounds (ledger-navigate-find-xact-extents (point)))
- new-status cur-status)
- ;; Uncompact the xact, to make it easier to toggle the
- ;; transaction
- (save-excursion ;; this excursion checks state of entire
- ;; transaction and unclears if marked
- (goto-char (car bounds)) ;; beginning of xact
- (skip-chars-forward "0-9./=\\-") ;; skip the date
- (skip-chars-forward " \t") ;; skip the white space after the date
- (setq cur-status (and (member (char-after) '(?\* ?\!))
- (ledger-state-from-char (char-after))))
- ;;if cur-status if !, or * then delete the marker
- (when cur-status
- (let ((here (point)))
- (skip-chars-forward "*! ")
- (let ((width (- (point) here)))
- (when (> width 0)
- (delete-region here (point))
- (if (search-forward " " (line-end-position) t)
- (insert (make-string width ? ))))))
- (forward-line)
- ;; Shift the cleared/pending status to the postings
- (while (looking-at "[ \t]")
- (skip-chars-forward " \t")
- (when (not (eq (ledger-state-from-char (char-after)) 'comment))
- (insert (ledger-char-from-state cur-status) " ")
- (if (and (search-forward " " (line-end-position) t)
- (looking-at " "))
- (delete-char 2)))
- (forward-line))
- (setq new-status nil)))
-
- ;;this excursion toggles the posting status
- (save-excursion
- (setq inhibit-modification-hooks t)
-
- (goto-char (line-beginning-position))
- (when (looking-at "[ \t]")
- (skip-chars-forward " \t")
- (let ((here (point))
- (cur-status (ledger-state-from-char (char-after))))
- (skip-chars-forward "*! ")
- (let ((width (- (point) here)))
- (when (> width 0)
- (delete-region here (point))
- (save-excursion
- (if (search-forward " " (line-end-position) t)
- (insert (make-string width ? ))))))
- (let (inserted)
- (if cur-status
- (if (and style (eq style 'cleared))
- (progn
- (insert "* ")
- (setq inserted 'cleared)))
- (if (and style (eq style 'pending))
- (progn
- (insert "! ")
- (setq inserted 'pending))
- (progn
- (insert "* ")
- (setq inserted 'cleared))))
- (if (and inserted
- (re-search-forward "\\(\t\\| [ \t]\\)"
- (line-end-position) t))
- (cond
- ((looking-at "\t")
- (delete-char 1))
- ((looking-at " [ \t]")
- (delete-char 2))
- ((looking-at " ")
- (delete-char 1))))
- (setq new-status inserted))))
- (setq inhibit-modification-hooks nil))
-
- ;; This excursion cleans up the xact so that it displays
- ;; minimally. This means that if all posts are cleared, remove
- ;; the marks and clear the entire transaction.
- (save-excursion
- (goto-char (car bounds))
- (forward-line)
- (let ((first t)
- (state nil)
- (hetero nil))
- (while (and (not hetero) (looking-at "[ \t]"))
- (skip-chars-forward " \t")
- (let ((cur-status (ledger-state-from-char (char-after))))
- (if (not (eq cur-status 'comment))
- (if first
- (setq state cur-status
- first nil)
- (if (not (eq state cur-status))
- (setq hetero t)))))
- (forward-line))
- (when (and (not hetero) (not (eq state nil)))
- (goto-char (car bounds))
- (forward-line)
- (while (looking-at "[ \t]")
- (skip-chars-forward " \t")
- (let ((here (point)))
- (skip-chars-forward "*! ")
- (let ((width (- (point) here)))
- (when (> width 0)
- (delete-region here (point))
- (if (re-search-forward "\\(\t\\| [ \t]\\)"
- (line-end-position) t)
- (insert (make-string width ? ))))))
- (forward-line))
- (goto-char (car bounds))
- (skip-chars-forward "0-9./=\\-") ;; Skip the date
- (skip-chars-forward " \t") ;; Skip the white space
- (insert (ledger-char-from-state state) " ")
- (setq new-status state)
- (if (re-search-forward "\\(\t\\| [ \t]\\)"
- (line-end-position) t)
- (cond
- ((looking-at "\t")
- (delete-char 1))
- ((looking-at " [ \t]")
- (delete-char 2))
- ((looking-at " ")
- (delete-char 1)))))))
- new-status))
-
-(defun ledger-toggle-current (&optional style)
- "Toggle the current thing at point with optional STYLE."
- (interactive)
- (if (or ledger-clear-whole-transactions
- (eq 'transaction (ledger-thing-at-point)))
- (progn
- (save-excursion
- (forward-line)
- (goto-char (line-beginning-position))
- (while (and (not (eolp))
- (save-excursion
- (not (eq 'transaction (ledger-thing-at-point)))))
- (if (looking-at "\\s-+[*!]")
- (ledger-toggle-current-posting style))
- (forward-line)
- (goto-char (line-beginning-position))))
- (ledger-toggle-current-transaction style))
- (ledger-toggle-current-posting style)))
-
-(defun ledger-toggle-current-transaction (&optional style)
- "Toggle the transaction at point using optional STYLE."
- (interactive)
- (save-excursion
- (when (or (looking-at "^[0-9]")
- (re-search-backward "^[0-9]" nil t))
- (skip-chars-forward "0-9./=\\-")
- (delete-horizontal-space)
- (if (or (eq (ledger-state-from-char (char-after)) 'pending)
- (eq (ledger-state-from-char (char-after)) 'cleared))
- (progn
- (delete-char 1)
- (when (and style (eq style 'cleared))
- (insert " *")
- 'cleared))
- (if (and style (eq style 'pending))
- (progn
- (insert " ! ")
- 'pending)
- (progn
- (insert " * ")
- 'cleared))))))
-
-(provide 'ledger-state)
-
-;;; ledger-state.el ends here
diff --git a/lisp/ledger-test.el b/lisp/ledger-test.el
deleted file mode 100644
index 26811bb3..00000000
--- a/lisp/ledger-test.el
+++ /dev/null
@@ -1,139 +0,0 @@
-;;; ledger-test.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(declare-function ledger-mode "ledger-mode") ; TODO: fix this cyclic dependency
-(declare-function org-narrow-to-subtree "org")
-(declare-function org-entry-get "org")
-(declare-function outline-back-to-heading "outline")
-(declare-function outline-next-heading "outline")
-
-(defgroup ledger-test nil
- "Definitions for the Ledger testing framework"
- :group 'ledger)
-
-(defcustom ledger-source-directory "~/ledger/"
- "Directory where the Ledger sources are located."
- :type 'directory
- :group 'ledger-test)
-
-(defcustom ledger-test-binary "/Products/ledger/debug/ledger"
- "Directory where the Ledger debug binary is located."
- :type 'file
- :group 'ledger-test)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun ledger-create-test ()
- "Create a regression test."
- (interactive)
- (save-restriction
- (org-narrow-to-subtree)
- (save-excursion
- (let (text beg)
- (goto-char (point-min))
- (forward-line 1)
- (setq beg (point))
- (search-forward ":PROPERTIES:")
- (goto-char (line-beginning-position))
- (setq text (buffer-substring-no-properties beg (point)))
- (goto-char (point-min))
- (re-search-forward ":ID:\\s-+\\([^-]+\\)")
- (find-file-other-window
- (format "~/src/ledger/test/regress/%s.test" (match-string 1)))
- (sit-for 0)
- (insert text)
- (goto-char (point-min))
- (while (not (eobp))
- (goto-char (line-beginning-position))
- (delete-char 3)
- (forward-line 1))))))
-
-(defun ledger-test-org-narrow-to-entry ()
- (outline-back-to-heading)
- (narrow-to-region (point) (progn (outline-next-heading) (point)))
- (goto-char (point-min)))
-
-(defun ledger-test-create ()
- (interactive)
- (let ((uuid (org-entry-get (point) "ID")))
- (when (string-match "\\`\\([^-]+\\)-" uuid)
- (let ((prefix (match-string 1 uuid))
- input output)
- (save-restriction
- (ledger-test-org-narrow-to-entry)
- (goto-char (point-min))
- (while (re-search-forward "#\\+begin_src ledger" nil t)
- (goto-char (match-end 0))
- (forward-line 1)
- (let ((beg (point)))
- (re-search-forward "#\\+end_src")
- (setq input
- (concat (or input "")
- (buffer-substring beg (match-beginning 0))))))
- (goto-char (point-min))
- (while (re-search-forward ":OUTPUT:" nil t)
- (goto-char (match-end 0))
- (forward-line 1)
- (let ((beg (point)))
- (re-search-forward ":END:")
- (setq output
- (concat (or output "")
- (buffer-substring beg (match-beginning 0)))))))
- (find-file-other-window
- (expand-file-name (concat prefix ".test")
- (expand-file-name "test/regress"
- ledger-source-directory)))
- (ledger-mode)
- (if input
- (insert input)
- (insert "2012-03-17 Payee\n")
- (insert " Expenses:Food $20\n")
- (insert " Assets:Cash\n"))
- (insert "\ntest reg\n")
- (if output
- (insert output))
- (insert "end test\n")))))
-
-(defun ledger-test-run ()
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (when (re-search-forward "^test \\(.+?\\)\\( ->.*\\)?$" nil t)
- (let ((command (expand-file-name ledger-test-binary))
- (args (format "--args-only --columns=80 --no-color -f \"%s\" %s"
- buffer-file-name (match-string 1))))
- (setq args (replace-regexp-in-string "\\$sourcepath"
- ledger-source-directory args))
- (kill-new args)
- (message "Testing: ledger %s" args)
- (let ((prev-directory default-directory))
- (cd ledger-source-directory)
- (unwind-protect
- (async-shell-command (format "\"%s\" %s" command args))
- (cd prev-directory)))))))
-
-(provide 'ledger-test)
-
-;;; ledger-test.el ends here
diff --git a/lisp/ledger-texi.el b/lisp/ledger-texi.el
deleted file mode 100644
index 0ceef477..00000000
--- a/lisp/ledger-texi.el
+++ /dev/null
@@ -1,172 +0,0 @@
-;;; ledger-texi.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-(defgroup ledger-texi nil
- "Options for working on Ledger texi documentation"
- :group 'ledger)
-
-(defcustom ledger-texi-sample-doc-path "~/ledger/doc/sample.dat"
- "Location for sample data to be used in texi tests"
- :type 'file
- :group 'ledger-texi)
-
-(defcustom ledger-texi-normalization-args "--args-only --columns 80"
- "texi normalization for producing ledger output"
- :type 'string
- :group 'ledger-texi)
-
-(defun ledger-update-test ()
- (interactive)
- (goto-char (point-min))
- (let ((command (buffer-substring (point-min) (line-end-position)))
- input)
- (re-search-forward "^<<<\n")
- (let ((beg (point)) end)
- (re-search-forward "^>>>")
- (setq end (match-beginning 0))
- (forward-line 1)
- (let ((output-beg (point)))
- (re-search-forward "^>>>")
- (goto-char (match-beginning 0))
- (delete-region output-beg (point))
- (apply #'call-process-region
- beg end (expand-file-name "~/Products/ledger/debug/ledger")
- nil t nil
- "-f" "-" "--args-only" "--columns=80" "--no-color"
- (split-string command " "))))))
-
-(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-binary-path
- data-file ledger-texi-normalization-args) t t command)
- (concat (format "%s -f \"%s\" %s " ledger-binary-path
- data-file ledger-texi-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-texi-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 'ledger-texi)
diff --git a/lisp/ledger-xact.el b/lisp/ledger-xact.el
deleted file mode 100644
index 5286d784..00000000
--- a/lisp/ledger-xact.el
+++ /dev/null
@@ -1,196 +0,0 @@
-;;; ledger-xact.el --- Helper code for use with the "ledger" command-line tool
-
-;; Copyright (C) 2003-2016 John Wiegley (johnw AT gnu DOT org)
-
-;; This file is not part of GNU Emacs.
-
-;; This is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 2, or (at your option) any later
-;; version.
-;;
-;; This is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-;; MA 02110-1301 USA.
-
-
-;;; Commentary:
-;; Utilities for running ledger synchronously.
-
-;;; Code:
-
-(require 'eshell)
-(require 'ledger-regex)
-(require 'ledger-navigate)
-;; TODO: This file depends on code in ledger-mode.el, which depends on this.
-
-(defcustom ledger-highlight-xact-under-point t
- "If t highlight xact under point."
- :type 'boolean
- :group 'ledger)
-
-(defcustom ledger-use-iso-dates nil
- "If non-nil, use the iso-8601 format for dates (YYYY-MM-DD)."
- :type 'boolean
- :group 'ledger
- :safe t)
-
-(defvar ledger-xact-highlight-overlay (list))
-(make-variable-buffer-local 'ledger-xact-highlight-overlay)
-
-(defun ledger-highlight-xact-under-point ()
- "Move the highlight overlay to the current transaction."
- (if ledger-highlight-xact-under-point
- (let ((exts (ledger-navigate-find-element-extents (point)))
- (ovl ledger-xact-highlight-overlay))
- (if (not ledger-xact-highlight-overlay)
- (setq ovl
- (setq ledger-xact-highlight-overlay
- (make-overlay (car exts)
- (cadr exts)
- (current-buffer) t nil)))
- (move-overlay ovl (car exts) (cadr exts)))
- (overlay-put ovl 'face 'ledger-font-xact-highlight-face)
- (overlay-put ovl 'priority '(nil . 99)))))
-
-(defun ledger-xact-payee ()
- "Return the payee of the transaction containing point or nil."
- (let ((i 0))
- (while (eq (ledger-context-line-type (ledger-context-other-line i)) 'acct-transaction)
- (setq i (- i 1)))
- (let ((context-info (ledger-context-other-line i)))
- (if (eq (ledger-context-line-type context-info) 'xact)
- (ledger-context-field-value context-info 'payee)
- nil))))
-
-(defun ledger-time-less-p (t1 t2)
- "Say whether time value T1 is less than time value T2."
- (or (< (car t1) (car t2))
- (and (= (car t1) (car t2))
- (< (nth 1 t1) (nth 1 t2)))))
-
-(defun ledger-xact-find-slot (moment)
- "Find the right place in the buffer for a transaction at MOMENT.
-MOMENT is an encoded date"
- (let (last-xact-start)
- (catch 'found
- (ledger-xact-iterate-transactions
- (function
- (lambda (start date mark desc)
- (setq last-xact-start start)
- (if (ledger-time-less-p moment date)
- (throw 'found t))))))
- (when (and (eobp) last-xact-start)
- (let ((end (cadr (ledger-navigate-find-xact-extents last-xact-start))))
- (goto-char end)
- (insert "\n")
- (forward-line)))))
-
-(defun ledger-xact-iterate-transactions (callback)
- "Iterate through each transaction call CALLBACK for each."
- (goto-char (point-min))
- (let* ((now (current-time))
- (current-year (nth 5 (decode-time now))))
- (while (not (eobp))
- (when (looking-at ledger-iterate-regex)
- (let ((found-y-p (match-string 2)))
- (if found-y-p
- (setq current-year (string-to-number found-y-p)) ;; a Y directive was found
- (let ((start (match-beginning 0))
- (year (match-string 4))
- (month (string-to-number (match-string 5)))
- (day (string-to-number (match-string 6)))
- (mark (match-string 7))
- (code (match-string 8))
- (desc (match-string 9)))
- (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-year-and-month ()
- (let ((sep (if ledger-use-iso-dates
- "-"
- "/")))
- (concat ledger-year sep ledger-month sep)))
-
-(defun ledger-copy-transaction-at-point (date)
- "Ask for a new DATE and copy the transaction under point to that date. Leave point on the first amount."
- (interactive (list
- (ledger-read-date "Copy to date: ")))
- (let* ((here (point))
- (extents (ledger-navigate-find-xact-extents (point)))
- (transaction (buffer-substring-no-properties (car extents) (cadr extents)))
- encoded-date)
- (if (string-match ledger-iso-date-regexp date)
- (setq encoded-date
- (encode-time 0 0 0 (string-to-number (match-string 4 date))
- (string-to-number (match-string 3 date))
- (string-to-number (match-string 2 date)))))
- (ledger-xact-find-slot encoded-date)
- (insert transaction "\n")
- (beginning-of-line -1)
- (ledger-navigate-beginning-of-xact)
- (re-search-forward ledger-iso-date-regexp)
- (replace-match date)
- (ledger-next-amount)
- (if (re-search-forward "[-0-9]")
- (goto-char (match-beginning 0)))))
-
-(defun ledger-delete-current-transaction (pos)
- "Delete the transaction surrounging POS."
- (interactive "d")
- (let ((bounds (ledger-navigate-find-xact-extents pos)))
- (delete-region (car bounds) (cadr bounds))))
-
-(defun ledger-add-transaction (transaction-text &optional insert-at-point)
- "Use ledger xact TRANSACTION-TEXT to add a transaction to the buffer.
-If INSERT-AT-POINT is non-nil insert the transaction there,
-otherwise call `ledger-xact-find-slot' to insert it at the
-correct chronological place in the buffer."
- (interactive (list
- ;; Note: This isn't "just" the date - it can contain
- ;; other text too
- (ledger-read-date "Transaction: ")))
- (let* ((args (with-temp-buffer
- (insert transaction-text)
- (eshell-parse-arguments (point-min) (point-max))))
- (ledger-buf (current-buffer))
- exit-code)
- (unless insert-at-point
- (let ((date (car args)))
- (if (string-match ledger-iso-date-regexp date)
- (setq date
- (encode-time 0 0 0 (string-to-number (match-string 4 date))
- (string-to-number (match-string 3 date))
- (string-to-number (match-string 2 date)))))
- (ledger-xact-find-slot date)))
- (if (> (length args) 1)
- (save-excursion
- (insert
- (with-temp-buffer
- (setq exit-code
- (apply #'ledger-exec-ledger ledger-buf (current-buffer) "xact"
- (mapcar 'eval args)))
- (goto-char (point-min))
- (if (looking-at "Error: ")
- (error (concat "Error in ledger-add-transaction: " (buffer-string)))
- (ledger-post-align-postings (point-min) (point-max))
- (buffer-string)))
- "\n"))
- (progn
- (insert (car args) " \n\n")
- (end-of-line -1)))))
-
-(provide 'ledger-xact)
-
-;;; ledger-xact.el ends here
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 65e58edb..71d9478a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -138,20 +138,24 @@ set(LEDGER_INCLUDES
${PROJECT_BINARY_DIR}/system.hh)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
- if ((CMAKE_CXX_COMPILER MATCHES "clang") OR (CMAKE_CXX_COMPILER MATCHES "cxx"))
+ if (CMAKE_CXX_COMPILER MATCHES "clang\\+\\+")
add_definitions(
- -Weverything
- -Wno-disabled-macro-expansion
- -Wno-padded
- -Wno-weak-vtables
- -Wno-exit-time-destructors
- -Wno-global-constructors
- -Wno-switch-enum
- -Wno-missing-prototypes
- -Wno-missing-noreturn
- -Wno-unused-parameter
- -Wno-c++98-compat
- -fno-limit-debug-info)
+ # -Weverything
+ # -Wno-disabled-macro-expansion
+ # -Wno-padded
+ # -Wno-weak-vtables
+ # -Wno-exit-time-destructors
+ # -Wno-global-constructors
+ # -Wno-switch-enum
+ # -Wno-missing-prototypes
+ # -Wno-missing-noreturn
+ # -Wno-unused-parameter
+ # -Wno-c++98-compat
+ # -fno-limit-debug-info
+ -Wno-\#pragma-messages
+ -Wno-unused-local-typedef
+ --system-header-prefix=include/boost/
+ --system-header-prefix=boost/)
macro(ADD_PCH_RULE _header_filename _src_list _other_srcs)
set(_pch_filename "${_header_filename}.pch")
@@ -189,7 +193,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
DEPENDS ${_header_filename})
endmacro(ADD_PCH_RULE _header_filename _src_list _other_srcs)
- elseif(CMAKE_CXX_COMPILER MATCHES "g\\+\\+")
+ elseif (CMAKE_CXX_COMPILER MATCHES "g\\+\\+")
set(GXX_WARNING_FLAGS
-pedantic
-Wall
@@ -237,7 +241,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
get_directory_property(DIRINC INCLUDE_DIRECTORIES)
foreach(_inc ${DIRINC})
- list(APPEND _args "-isystem " ${_inc})
+ list(APPEND _args "-I" ${_inc})
endforeach(_inc ${DIRINC})
separate_arguments(_args)
diff --git a/src/account.cc b/src/account.cc
index 2a48eaf5..29c28866 100644
--- a/src/account.cc
+++ b/src/account.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -136,6 +136,19 @@ void account_t::add_post(post_t * post)
xdata_->self_details.calculated = false;
xdata_->family_details.gathered = false;
xdata_->family_details.calculated = false;
+ if (! xdata_->family_details.total.is_null()) {
+ xdata_->family_details.total = ledger::value_t();
+ }
+ account_t *ancestor = this;
+ while (ancestor->parent) {
+ ancestor = ancestor->parent;
+ if (ancestor->has_xdata()) {
+ xdata_t &xdata = ancestor->xdata();
+ xdata.family_details.gathered = false;
+ xdata.family_details.calculated = false;
+ xdata.family_details.total = ledger::value_t();
+ }
+ }
}
}
@@ -296,6 +309,20 @@ namespace {
return long(&account);
}
+ value_t get_depth_parent(account_t& account)
+ {
+ std::size_t depth = 0;
+ for (const account_t * acct = account.parent;
+ acct && acct->parent;
+ acct = acct->parent) {
+ std::size_t count = acct->children_with_flags(ACCOUNT_EXT_TO_DISPLAY);
+ assert(count > 0);
+ if (count > 1 || acct->has_xflags(ACCOUNT_EXT_TO_DISPLAY))
+ depth++;
+ }
+ return long(depth);
+ }
+
value_t get_depth_spacer(account_t& account)
{
std::size_t depth = 0;
@@ -412,6 +439,8 @@ expr_t::ptr_op_t account_t::lookup(const symbol_t::kind_t kind,
case 'd':
if (fn_name == "depth")
return WRAP_FUNCTOR(get_wrapper<&get_depth>);
+ else if (fn_name == "depth_parent")
+ return WRAP_FUNCTOR(get_wrapper<&get_depth_parent>);
else if (fn_name == "depth_spacer")
return WRAP_FUNCTOR(get_wrapper<&get_depth_spacer>);
break;
diff --git a/src/account.h b/src/account.h
index 4a4e859d..0abbd87a 100644
--- a/src/account.h
+++ b/src/account.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -205,7 +205,9 @@ public:
posts_cleared_count(0),
posts_last_7_count(0),
posts_last_30_count(0),
- posts_this_month_count(0) {
+ posts_this_month_count(0),
+ latest_checkout_cleared(false)
+ {
TRACE_CTOR(account_t::xdata_t::details_t, "");
}
// A copy copies nothing
@@ -218,7 +220,8 @@ public:
posts_cleared_count(0),
posts_last_7_count(0),
posts_last_30_count(0),
- posts_this_month_count(0)
+ posts_this_month_count(0),
+ latest_checkout_cleared(false)
{
TRACE_CTOR(account_t::xdata_t::details_t, "copy");
}
diff --git a/src/amount.cc b/src/amount.cc
index 52ccbc88..05145f87 100644
--- a/src/amount.cc
+++ b/src/amount.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -1090,6 +1090,8 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
bool no_more_commas = false;
bool no_more_periods = false;
+ bool no_migrate_style
+ = commodity().has_flags(COMMODITY_STYLE_NO_MIGRATE);
bool decimal_comma_style
= (commodity_t::decimal_comma_by_default ||
commodity().has_flags(COMMODITY_STYLE_DECIMAL_COMMA));
@@ -1173,7 +1175,7 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
// is non-NULL.
new_quantity->add_flags(BIGINT_KEEP_PREC);
}
- else if (commodity_) {
+ else if (commodity_ && ! no_migrate_style) {
commodity().add_flags(comm_flags);
if (new_quantity->prec > commodity().precision())
diff --git a/src/amount.h b/src/amount.h
index 8885a69d..fed9a467 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/annotate.cc b/src/annotate.cc
index e953f441..ab81d412 100644
--- a/src/annotate.cc
+++ b/src/annotate.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/annotate.h b/src/annotate.h
index 0ea2561b..75d42589 100644
--- a/src/annotate.h
+++ b/src/annotate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/balance.cc b/src/balance.cc
index ca14c7ff..fa1bc20c 100644
--- a/src/balance.cc
+++ b/src/balance.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/balance.h b/src/balance.h
index d68fccc8..8e773fc5 100644
--- a/src/balance.h
+++ b/src/balance.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/chain.cc b/src/chain.cc
index 94afc0fa..d508dd3e 100644
--- a/src/chain.cc
+++ b/src/chain.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -186,9 +186,9 @@ post_handler_ptr chain_post_handlers(post_handler_ptr base_handler,
// value expression.
if (report.HANDLED(sort_)) {
if (report.HANDLED(sort_xacts_))
- handler.reset(new sort_xacts(handler, report.HANDLER(sort_).str()));
+ handler.reset(new sort_xacts(handler, expr_t(report.HANDLER(sort_).str()), report));
else
- handler.reset(new sort_posts(handler, report.HANDLER(sort_).str()));
+ handler.reset(new sort_posts(handler, report.HANDLER(sort_).str(), report));
}
// collapse_posts causes xacts with multiple posts to appear as xacts
diff --git a/src/chain.h b/src/chain.h
index 16fb4400..ff891238 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/commodity.cc b/src/commodity.cc
index 1475f52e..a8520ca1 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/commodity.h b/src/commodity.h
index 1741bfaf..c25ccaf2 100644
--- a/src/commodity.h
+++ b/src/commodity.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -95,6 +95,7 @@ protected:
#define COMMODITY_SAW_ANN_PRICE_FLOAT 0x400
#define COMMODITY_SAW_ANN_PRICE_FIXATED 0x800
#define COMMODITY_STYLE_TIME_COLON 0x1000
+#define COMMODITY_STYLE_NO_MIGRATE 0x2000
string symbol;
optional<std::size_t> graph_index;
diff --git a/src/compare.cc b/src/compare.cc
index 547acc18..63b85154 100644
--- a/src/compare.cc
+++ b/src/compare.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -33,8 +33,10 @@
#include "compare.h"
#include "op.h"
+#include "scope.h"
#include "post.h"
#include "account.h"
+#include "report.h"
namespace ledger {
@@ -65,6 +67,20 @@ void push_sort_value(std::list<sort_value_t>& sort_values,
}
template <>
+void compare_items<post_t>::find_sort_values(
+ std::list<sort_value_t>& sort_values, scope_t& scope) {
+ bind_scope_t bound_scope(report, scope);
+ push_sort_value(sort_values, sort_order.get_op(), bound_scope);
+}
+
+template <>
+void compare_items<account_t>::find_sort_values(
+ std::list<sort_value_t>& sort_values, scope_t& scope) {
+ bind_scope_t bound_scope(report, scope);
+ push_sort_value(sort_values, sort_order.get_op(), bound_scope);
+}
+
+template <>
bool compare_items<post_t>::operator()(post_t * left, post_t * right)
{
assert(left);
diff --git a/src/compare.h b/src/compare.h
index baee6075..f1b6b9b3 100644
--- a/src/compare.h
+++ b/src/compare.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -48,6 +48,7 @@ namespace ledger {
class post_t;
class account_t;
+class report_t;
void push_sort_value(std::list<sort_value_t>& sort_values,
expr_t::ptr_op_t node, scope_t& scope);
@@ -56,23 +57,24 @@ template <typename T>
class compare_items
{
expr_t sort_order;
+ report_t& report;
compare_items();
public:
- compare_items(const compare_items& other) : sort_order(other.sort_order) {
- TRACE_CTOR(compare_items, "copy");
+ compare_items(const expr_t& _sort_order, report_t& _report) :
+ sort_order(_sort_order), report(_report) {
+ TRACE_CTOR(compare_items, "const value_expr&, report_t&");
}
- compare_items(const expr_t& _sort_order) : sort_order(_sort_order) {
- TRACE_CTOR(compare_items, "const value_expr&");
+ compare_items(const compare_items& other) :
+ sort_order(other.sort_order), report(other.report) {
+ TRACE_CTOR(compare_items, "copy");
}
~compare_items() throw() {
TRACE_DTOR(compare_items);
}
- void find_sort_values(std::list<sort_value_t>& sort_values, scope_t& scope) {
- push_sort_value(sort_values, sort_order.get_op(), scope);
- }
+ void find_sort_values(std::list<sort_value_t>& sort_values, scope_t& scope);
bool operator()(T * left, T * right);
};
diff --git a/src/context.h b/src/context.h
index 603898f4..0af59930 100644
--- a/src/context.h
+++ b/src/context.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/convert.cc b/src/convert.cc
index d0a0dc39..cea2a130 100644
--- a/src/convert.cc
+++ b/src/convert.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/convert.h b/src/convert.h
index cb6bcd71..e27b5872 100644
--- a/src/convert.h
+++ b/src/convert.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/csv.cc b/src/csv.cc
index 85e41057..40b8e01b 100644
--- a/src/csv.cc
+++ b/src/csv.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/csv.h b/src/csv.h
index a294a865..274ecc7e 100644
--- a/src/csv.h
+++ b/src/csv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/draft.cc b/src/draft.cc
index f7557373..424b7a9a 100644
--- a/src/draft.cc
+++ b/src/draft.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/draft.h b/src/draft.h
index f4c24c26..44c3bf3d 100644
--- a/src/draft.h
+++ b/src/draft.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/emacs.cc b/src/emacs.cc
index 9f2626a3..52389316 100644
--- a/src/emacs.cc
+++ b/src/emacs.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/emacs.h b/src/emacs.h
index 52b7bd37..6e428613 100644
--- a/src/emacs.h
+++ b/src/emacs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/error.cc b/src/error.cc
index 4b3565a3..7e49645b 100644
--- a/src/error.cc
+++ b/src/error.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/error.h b/src/error.h
index 26cbfafb..ba278519 100644
--- a/src/error.h
+++ b/src/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/expr.cc b/src/expr.cc
index bc877c1a..85818e4b 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/expr.h b/src/expr.h
index bbe4bf74..b3806bc1 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/exprbase.h b/src/exprbase.h
index 6d13c429..9c28dca3 100644
--- a/src/exprbase.h
+++ b/src/exprbase.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/filters.cc b/src/filters.cc
index 1d7832ca..3dfd2327 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -154,7 +154,7 @@ void truncate_xacts::operator()(post_t& post)
void sort_posts::post_accumulated_posts()
{
std::stable_sort(posts.begin(), posts.end(),
- compare_items<post_t>(sort_order));
+ compare_items<post_t>(sort_order, report));
foreach (post_t * post, posts) {
post->xdata().drop_flags(POST_EXT_SORT_CALC);
@@ -982,10 +982,12 @@ void interval_posts::flush()
std::stable_sort(all_posts.begin(), all_posts.end(),
sort_posts_by_date());
- // Determine the beginning interval by using the earliest post
- if (all_posts.size() > 0 && all_posts.front() &&
- ! interval.find_period(all_posts.front()->date()))
- throw_(std::logic_error, _("Failed to find period for interval report"));
+ // only if the interval has no start use the earliest post
+ if (!(interval.begin() && interval.find_period(*interval.begin())))
+ // Determine the beginning interval by using the earliest post
+ if (all_posts.size() > 0 && all_posts.front()
+ && !interval.find_period(all_posts.front()->date()))
+ throw_(std::logic_error, _("Failed to find period for interval report"));
// Walk the interval forward reporting all posts within each one
// before moving on, until we reach the end of all_posts
@@ -1243,19 +1245,34 @@ void generate_posts::add_post(const date_interval_t& period, post_t& post)
void budget_posts::report_budget_items(const date_t& date)
{
+ { // Cleanup pending items that finished before date
+ // We have to keep them until the last day they apply because operator() needs them to see if a
+ // posting is budgeted or not
+ std::list<pending_posts_list::iterator> posts_to_erase;
+ for (pending_posts_list::iterator i = pending_posts.begin(); i != pending_posts.end(); i++) {
+ pending_posts_list::value_type& pair(*i);
+ if (pair.first.finish && ! pair.first.start && pair.first.finish < date) {
+ posts_to_erase.push_back(i);
+ }
+ }
+ foreach (pending_posts_list::iterator& i, posts_to_erase)
+ pending_posts.erase(i);
+ }
+
if (pending_posts.size() == 0)
return;
bool reported;
do {
- std::list<pending_posts_list::iterator> posts_to_erase;
-
reported = false;
for (pending_posts_list::iterator i = pending_posts.begin();
i != pending_posts.end();
i++) {
pending_posts_list::value_type& pair(*i);
+ if (pair.first.finish && ! pair.first.start)
+ continue; // skip expired posts
+
optional<date_t> begin = pair.first.start;
if (! begin) {
optional<date_t> range_begin;
@@ -1283,9 +1300,6 @@ void budget_posts::report_budget_items(const date_t& date)
post_t& post = *pair.second;
++pair.first;
- if (! pair.first.start)
- posts_to_erase.push_back(i);
-
DEBUG("budget.generate", "Reporting budget for "
<< post.reported_account()->fullname());
@@ -1310,9 +1324,6 @@ void budget_posts::report_budget_items(const date_t& date)
reported = true;
}
}
-
- foreach (pending_posts_list::iterator& i, posts_to_erase)
- pending_posts.erase(i);
} while (reported);
}
diff --git a/src/filters.h b/src/filters.h
index 4aa8af7a..c1dc2e04 100644
--- a/src/filters.h
+++ b/src/filters.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -237,17 +237,20 @@ class sort_posts : public item_handler<post_t>
posts_deque posts;
expr_t sort_order;
+ report_t& report;
sort_posts();
public:
- sort_posts(post_handler_ptr handler, const expr_t& _sort_order)
- : item_handler<post_t>(handler), sort_order(_sort_order) {
- TRACE_CTOR(sort_posts, "post_handler_ptr, const value_expr&");
+ sort_posts(post_handler_ptr handler, const expr_t& _sort_order,
+ report_t& _report)
+ : item_handler<post_t>(handler), sort_order(_sort_order), report(_report) {
+ TRACE_CTOR(sort_posts, "post_handler_ptr, const value_expr&, report_t&");
}
- sort_posts(post_handler_ptr handler, const string& _sort_order)
- : item_handler<post_t>(handler), sort_order(_sort_order) {
- TRACE_CTOR(sort_posts, "post_handler_ptr, const string&");
+ sort_posts(post_handler_ptr handler, const string& _sort_order,
+ report_t& _report)
+ : item_handler<post_t>(handler), sort_order(_sort_order), report(_report) {
+ TRACE_CTOR(sort_posts, "post_handler_ptr, const string&, report_t&");
}
virtual ~sort_posts() {
TRACE_DTOR(sort_posts);
@@ -280,15 +283,17 @@ class sort_xacts : public item_handler<post_t>
sort_xacts();
public:
- sort_xacts(post_handler_ptr handler, const expr_t& _sort_order)
- : sorter(handler, _sort_order) {
+ sort_xacts(post_handler_ptr handler, const expr_t& _sort_order,
+ report_t& _report)
+ : sorter(handler, _sort_order, _report) {
TRACE_CTOR(sort_xacts,
- "post_handler_ptr, const value_expr&");
+ "post_handler_ptr, const value_expr&, report_t&");
}
- sort_xacts(post_handler_ptr handler, const string& _sort_order)
- : sorter(handler, _sort_order) {
+ sort_xacts(post_handler_ptr handler, const string& _sort_order,
+ report_t& _report)
+ : sorter(handler, _sort_order, _report) {
TRACE_CTOR(sort_xacts,
- "post_handler_ptr, const string&");
+ "post_handler_ptr, const string&, report_t&");
}
virtual ~sort_xacts() {
TRACE_DTOR(sort_xacts);
@@ -560,9 +565,9 @@ public:
last_display_total = value_t();
temps.clear();
- create_accounts();
-
item_handler<post_t>::clear();
+
+ create_accounts();
}
};
@@ -622,9 +627,9 @@ public:
last_total = value_t();
temps.clear();
- create_accounts();
-
item_handler<post_t>::clear();
+
+ create_accounts();
}
};
diff --git a/src/flags.h b/src/flags.h
index e6b66470..42e2719a 100644
--- a/src/flags.h
+++ b/src/flags.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/format.cc b/src/format.cc
index b6f0d5ae..bb578141 100644
--- a/src/format.cc
+++ b/src/format.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/format.h b/src/format.h
index 8856905d..15431cf1 100644
--- a/src/format.h
+++ b/src/format.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/generate.cc b/src/generate.cc
index c1ecb007..95cdfa2e 100644
--- a/src/generate.cc
+++ b/src/generate.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/generate.h b/src/generate.h
index d4f13070..5272c7db 100644
--- a/src/generate.h
+++ b/src/generate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/global.cc b/src/global.cc
index 6edc69ca..32d3cc5a 100644
--- a/src/global.cc
+++ b/src/global.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -136,9 +136,7 @@ void global_scope_t::read_init()
path init_file;
if (HANDLED(init_file_)) {
init_file=HANDLER(init_file_).str();
- if (exists(init_file)) {
- parse_init(init_file);
- } else {
+ if (!exists(init_file)) {
throw_(parse_error, _f("Could not find specified init file %1%") % init_file);
}
} else {
@@ -451,7 +449,7 @@ expr_t::func_t global_scope_t::look_for_command(scope_t& scope,
void global_scope_t::visit_man_page() const
{
-#ifndef WIN32
+#if !defined(_WIN32) && !defined(__CYGWIN__)
int pid = fork();
if (pid < 0) {
throw std::logic_error(_("Failed to fork child process"));
diff --git a/src/global.h b/src/global.h
index 42464e35..8f8266ac 100644
--- a/src/global.h
+++ b/src/global.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -129,7 +129,7 @@ public:
out << '-' << Ledger_VERSION_DATE;
out << _(", the command-line accounting tool");
out <<
- _("\n\nCopyright (c) 2003-2016, John Wiegley. All rights reserved.\n\n\
+ _("\n\nCopyright (c) 2003-2018, John Wiegley. All rights reserved.\n\n\
This program is made available under the terms of the BSD Public License.\n\
See LICENSE file included with the distribution for details and disclaimer.");
out << std::endl;
diff --git a/src/history.cc b/src/history.cc
index 25d42b06..7c98182c 100644
--- a/src/history.cc
+++ b/src/history.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/history.h b/src/history.h
index 37efb068..11e29bd7 100644
--- a/src/history.h
+++ b/src/history.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/item.cc b/src/item.cc
index 0402f467..bd025c52 100644
--- a/src/item.cc
+++ b/src/item.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/item.h b/src/item.h
index ca16d87b..a28bf59e 100644
--- a/src/item.h
+++ b/src/item.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -92,7 +92,7 @@ public:
typedef std::pair<optional<value_t>, bool> tag_data_t;
typedef std::map<string, tag_data_t,
- function<bool(string, string)> > string_map;
+ std::function<bool(string, string)> > string_map;
state_t _state;
optional<date_t> _date;
diff --git a/src/iterators.cc b/src/iterators.cc
index 88233ea1..0a20eac6 100644
--- a/src/iterators.cc
+++ b/src/iterators.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -201,7 +201,7 @@ void sorted_accounts_iterator::push_back(account_t& account)
std::stable_sort(accounts_list.back().begin(),
accounts_list.back().end(),
- compare_items<account_t>(sort_cmp));
+ compare_items<account_t>(sort_cmp, report));
#if DEBUG_ON
if (SHOW_DEBUG("account.sorted")) {
@@ -234,7 +234,7 @@ void sorted_accounts_iterator::sort_accounts(account_t& account,
deque.push_back(pair.second);
std::stable_sort(deque.begin(), deque.end(),
- compare_items<account_t>(sort_cmp));
+ compare_items<account_t>(sort_cmp, report));
#if DEBUG_ON
if (SHOW_DEBUG("account.sorted")) {
diff --git a/src/iterators.h b/src/iterators.h
index a3f535b1..0eaa3cc2 100644
--- a/src/iterators.h
+++ b/src/iterators.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -50,6 +50,7 @@
namespace ledger {
class journal_t;
+class report_t;
template <typename Derived, typename Value, typename CategoryOrTraversal>
class iterator_facade_base
@@ -279,8 +280,9 @@ class sorted_accounts_iterator
: public iterator_facade_base<sorted_accounts_iterator, account_t *,
boost::forward_traversal_tag>
{
- expr_t sort_cmp;
- bool flatten_all;
+ expr_t sort_cmp;
+ report_t& report;
+ bool flatten_all;
typedef std::deque<account_t *> accounts_deque_t;
@@ -290,16 +292,21 @@ class sorted_accounts_iterator
public:
sorted_accounts_iterator(account_t& account,
- const expr_t& _sort_cmp, bool _flatten_all)
- : sort_cmp(_sort_cmp), flatten_all(_flatten_all) {
+ const expr_t& _sort_cmp,
+ report_t& _report,
+ bool _flatten_all)
+ : sort_cmp(_sort_cmp), report(_report),
+ flatten_all(_flatten_all) {
push_back(account);
increment();
- TRACE_CTOR(sorted_accounts_iterator, "account_t&, expr_t, bool");
+ TRACE_CTOR(sorted_accounts_iterator,
+ "account_t&, expr_t, report_t&, bool");
}
sorted_accounts_iterator(const sorted_accounts_iterator& i)
: iterator_facade_base<sorted_accounts_iterator, account_t *,
boost::forward_traversal_tag>(i),
- sort_cmp(i.sort_cmp), flatten_all(i.flatten_all),
+ sort_cmp(i.sort_cmp), report(i.report),
+ flatten_all(i.flatten_all),
accounts_list(i.accounts_list),
sorted_accounts_i(i.sorted_accounts_i),
sorted_accounts_end(i.sorted_accounts_end) {
diff --git a/src/journal.cc b/src/journal.cc
index 36fe5fc0..1df7a114 100644
--- a/src/journal.cc
+++ b/src/journal.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/journal.h b/src/journal.h
index 76e1735d..3fefe4e1 100644
--- a/src/journal.h
+++ b/src/journal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/lookup.cc b/src/lookup.cc
index 11b7db61..a88752f5 100644
--- a/src/lookup.cc
+++ b/src/lookup.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/lookup.h b/src/lookup.h
index 2c4e6575..a357cafe 100644
--- a/src/lookup.h
+++ b/src/lookup.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/main.cc b/src/main.cc
index 3a36280a..c8b9ec3a 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -74,7 +74,7 @@ int main(int argc, char * argv[], char * envp[])
#endif
std::signal(SIGINT, sigint_handler);
-#ifndef WIN32
+#if !defined(_WIN32) && !defined(__CYGWIN__)
std::signal(SIGPIPE, sigpipe_handler);
#endif
diff --git a/src/mask.cc b/src/mask.cc
index c6868dde..434acad6 100644
--- a/src/mask.cc
+++ b/src/mask.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/mask.h b/src/mask.h
index f416611f..4e44b76b 100644
--- a/src/mask.h
+++ b/src/mask.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/op.cc b/src/op.cc
index 97437ce3..00b84459 100644
--- a/src/op.cc
+++ b/src/op.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/op.h b/src/op.h
index 937b321d..bbbb5d81 100644
--- a/src/op.h
+++ b/src/op.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/option.cc b/src/option.cc
index 7c5c5e07..ab6c37e0 100644
--- a/src/option.cc
+++ b/src/option.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/option.h b/src/option.h
index b06c1754..c9759924 100644
--- a/src/option.h
+++ b/src/option.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/org.cc b/src/org.cc
index 4d572415..c5a1aac3 100644
--- a/src/org.cc
+++ b/src/org.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/org.h b/src/org.h
index da28c772..9702297c 100644
--- a/src/org.h
+++ b/src/org.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/output.cc b/src/output.cc
index 77083450..c2fa83ac 100644
--- a/src/output.cc
+++ b/src/output.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -34,6 +34,7 @@
#include "output.h"
#include "xact.h"
#include "post.h"
+#include "item.h"
#include "account.h"
#include "session.h"
#include "report.h"
@@ -281,8 +282,23 @@ void format_accounts::operator()(account_t& account)
void report_accounts::flush()
{
std::ostream& out(report.output_stream);
+ format_t prepend_format;
+ std::size_t prepend_width;
+
+ if (report.HANDLED(prepend_format_)) {
+ prepend_format.parse_format(report.HANDLER(prepend_format_).str());
+ prepend_width = report.HANDLED(prepend_width_)
+ ? lexical_cast<std::size_t>(report.HANDLER(prepend_width_).str())
+ : 0;
+ }
foreach (accounts_pair& entry, accounts) {
+ if (prepend_format) {
+ bind_scope_t bound_scope(report, *entry.first);
+ out.width(static_cast<std::streamsize>(prepend_width));
+ out << prepend_format(bound_scope);
+ }
+
if (report.HANDLED(count))
out << entry.second << ' ';
out << *entry.first << '\n';
@@ -329,23 +345,29 @@ void report_tags::flush()
}
}
-void report_tags::operator()(post_t& post)
+void report_tags::gather_metadata(item_t& item)
{
- if (post.metadata) {
- foreach (const item_t::string_map::value_type& data, *post.metadata) {
- string tag=data.first;
- if (report.HANDLED(values) && (data.second).first) {
- tag+=": "+ (data.second).first.get().to_string();
- }
- std::map<string, std::size_t>::iterator i = tags.find(tag);
- if (i == tags.end())
- tags.insert(tags_pair(tag, 1));
- else
- (*i).second++;
- }
+ if (! item.metadata)
+ return;
+ foreach (const item_t::string_map::value_type& data, *item.metadata) {
+ string tag(data.first);
+ if (report.HANDLED(values) && data.second.first)
+ tag += ": " + data.second.first.get().to_string();
+
+ std::map<string, std::size_t>::iterator i = tags.find(tag);
+ if (i == tags.end())
+ tags.insert(tags_pair(tag, 1));
+ else
+ (*i).second++;
}
}
+void report_tags::operator()(post_t& post)
+{
+ gather_metadata(*post.xact);
+ gather_metadata(post);
+}
+
void report_commodities::flush()
{
std::ostream& out(report.output_stream);
diff --git a/src/output.h b/src/output.h
index e8c45337..f7dd98b8 100644
--- a/src/output.h
+++ b/src/output.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -51,6 +51,7 @@ namespace ledger {
class xact_t;
class post_t;
+class item_t;
class report_t;
class format_posts : public item_handler<post_t>
@@ -208,6 +209,7 @@ public:
}
virtual void flush();
+ virtual void gather_metadata(item_t& item);
virtual void operator()(post_t& post);
virtual void clear() {
diff --git a/src/parser.cc b/src/parser.cc
index 53b03a0c..5675aef8 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/parser.h b/src/parser.h
index 913179a1..5f5bfd2c 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pool.cc b/src/pool.cc
index dff02df8..c04d00b7 100644
--- a/src/pool.cc
+++ b/src/pool.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -262,6 +262,9 @@ commodity_pool_t::exchange(const amount_t& amount,
if (! cost.has_commodity())
per_unit_cost.clear_commodity();
+ if (cost.has_annotation())
+ per_unit_cost = per_unit_cost.strip_annotations(keep_details_t());
+
DEBUG("commodity.prices.add", "exchange: per-unit-cost = " << per_unit_cost);
// Do not record commodity exchanges where amount's commodity has a
diff --git a/src/pool.h b/src/pool.h
index 945fd083..b89789f4 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/post.cc b/src/post.cc
index 8d2693c7..97f6b6d4 100644
--- a/src/post.cc
+++ b/src/post.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/post.h b/src/post.h
index d7d8f7c4..aaf7ec64 100644
--- a/src/post.h
+++ b/src/post.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/precmd.cc b/src/precmd.cc
index af8c5ee0..7c2a791d 100644
--- a/src/precmd.cc
+++ b/src/precmd.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/precmd.h b/src/precmd.h
index 365cc1ba..41fab617 100644
--- a/src/precmd.h
+++ b/src/precmd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/predicate.h b/src/predicate.h
index aca44452..cf41ffe6 100644
--- a/src/predicate.h
+++ b/src/predicate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/print.cc b/src/print.cc
index 0cc23275..92323777 100644
--- a/src/print.cc
+++ b/src/print.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -103,11 +103,13 @@ namespace {
void print_xact(report_t& report, std::ostream& out, xact_t& xact)
{
format_type_t format_type = FMT_WRITTEN;
+ string format_str;
optional<const char *> format;
if (report.HANDLED(date_format_)) {
format_type = FMT_CUSTOM;
- format = report.HANDLER(date_format_).str().c_str();
+ format_str = report.HANDLER(date_format_).str();
+ format = format_str.c_str();
}
std::ostringstream buf;
diff --git a/src/print.h b/src/print.h
index 70b26d65..902fcd9a 100644
--- a/src/print.h
+++ b/src/print.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pstream.h b/src/pstream.h
index fc7fc8ca..6b12dcf0 100644
--- a/src/pstream.h
+++ b/src/pstream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/ptree.cc b/src/ptree.cc
index 534db003..1be6dec5 100644
--- a/src/ptree.cc
+++ b/src/ptree.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/ptree.h b/src/ptree.h
index ca7b46e2..9044f13b 100644
--- a/src/ptree.h
+++ b/src/ptree.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_account.cc b/src/py_account.cc
index c4a9ae07..59680a23 100644
--- a/src/py_account.cc
+++ b/src/py_account.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_amount.cc b/src/py_amount.cc
index 8a8ea871..2d99ddec 100644
--- a/src/py_amount.cc
+++ b/src/py_amount.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_balance.cc b/src/py_balance.cc
index 6a6c59fb..dc9975cf 100644
--- a/src/py_balance.cc
+++ b/src/py_balance.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_commodity.cc b/src/py_commodity.cc
index 5aafa6ce..c98a0def 100644
--- a/src/py_commodity.cc
+++ b/src/py_commodity.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -243,9 +243,6 @@ namespace {
void export_commodity()
{
-#if BOOST_VERSION >= 106000
- python::register_ptr_to_python< shared_ptr<commodity_pool_t> >();
-#endif
class_< commodity_pool_t, shared_ptr<commodity_pool_t>,
boost::noncopyable > ("CommodityPool", no_init)
.add_property("null_commodity",
diff --git a/src/py_expr.cc b/src/py_expr.cc
index de3ac925..c4891ac9 100644
--- a/src/py_expr.cc
+++ b/src/py_expr.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_format.cc b/src/py_format.cc
index 4dcd4ba3..57100290 100644
--- a/src/py_format.cc
+++ b/src/py_format.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_item.cc b/src/py_item.cc
index 644b11f1..6207f69c 100644
--- a/src/py_item.cc
+++ b/src/py_item.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_journal.cc b/src/py_journal.cc
index c1c38a90..08e9902e 100644
--- a/src/py_journal.cc
+++ b/src/py_journal.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -135,6 +135,11 @@ namespace {
return journal.find_account(name, auto_create);
}
+ account_t * py_register_account(journal_t& journal, const string& name, post_t* post)
+ {
+ return journal.register_account(name, post, journal.master);
+ }
+
#if 0
std::size_t py_read(journal_t& journal, const string& pathname)
{
@@ -232,9 +237,6 @@ void export_journal()
boost::noncopyable >("PostHandler")
;
-#if BOOST_VERSION >= 106000
- python::register_ptr_to_python< shared_ptr<collector_wrapper> >();
-#endif
class_< collector_wrapper, shared_ptr<collector_wrapper>,
boost::noncopyable >("PostCollectorWrapper", no_init)
.def("__len__", &collector_wrapper::length)
@@ -289,6 +291,14 @@ void export_journal()
return_internal_reference<1,
with_custodian_and_ward_postcall<1, 0> >())
+ .def("register_account", py_register_account,
+ return_internal_reference<1,
+ with_custodian_and_ward_postcall<1, 0> >())
+
+ .def("expand_aliases", &journal_t::expand_aliases,
+ return_internal_reference<1,
+ with_custodian_and_ward_postcall<1, 0> >())
+
.def("add_xact", &journal_t::add_xact)
.def("remove_xact", &journal_t::remove_xact)
diff --git a/src/py_post.cc b/src/py_post.cc
index 85d4701a..6195570b 100644
--- a/src/py_post.cc
+++ b/src/py_post.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_session.cc b/src/py_session.cc
index 0ddf66d2..1825fc14 100644
--- a/src/py_session.cc
+++ b/src/py_session.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_times.cc b/src/py_times.cc
index be3e4f31..bbd6f69a 100644
--- a/src/py_times.cc
+++ b/src/py_times.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_utils.cc b/src/py_utils.cc
index 731294b2..c2f84f55 100644
--- a/src/py_utils.cc
+++ b/src/py_utils.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/py_value.cc b/src/py_value.cc
index 60ba4cf2..f4f63946 100644
--- a/src/py_value.cc
+++ b/src/py_value.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -325,7 +325,6 @@ void export_value()
.def("to_mask", &value_t::to_mask)
.def("to_sequence", &value_t::to_sequence)
- .def("__unicode__", py_dump_relaxed)
.def("__repr__", py_dump)
.def("casted", &value_t::casted)
@@ -372,6 +371,7 @@ void export_value()
register_optional_to_python<value_t>();
+ implicitly_convertible<bool, value_t>();
implicitly_convertible<long, value_t>();
implicitly_convertible<string, value_t>();
implicitly_convertible<amount_t, value_t>();
diff --git a/src/py_xact.cc b/src/py_xact.cc
index f7283989..70dba5a0 100644
--- a/src/py_xact.cc
+++ b/src/py_xact.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pyfstream.h b/src/pyfstream.h
index a90b121c..5be3a1c4 100644
--- a/src/pyfstream.h
+++ b/src/pyfstream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
index 81924c86..19430bef 100644
--- a/src/pyinterp.cc
+++ b/src/pyinterp.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pyinterp.h b/src/pyinterp.h
index 9c24b0cf..51d6c8ec 100644
--- a/src/pyinterp.h
+++ b/src/pyinterp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pyledger.cc b/src/pyledger.cc
index a516f66d..d8832220 100644
--- a/src/pyledger.cc
+++ b/src/pyledger.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/pyutils.h b/src/pyutils.h
index 07ce7bdd..641dbd3b 100644
--- a/src/pyutils.h
+++ b/src/pyutils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/query.cc b/src/query.cc
index a2117cfe..fc1d4ff0 100644
--- a/src/query.cc
+++ b/src/query.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/query.h b/src/query.h
index cbfac6bc..f7d48d32 100644
--- a/src/query.h
+++ b/src/query.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/quotes.cc b/src/quotes.cc
index 2777974e..50791560 100644
--- a/src/quotes.cc
+++ b/src/quotes.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -62,7 +62,7 @@ commodity_quote_from_script(commodity_t& commodity,
DEBUG("commodity.download", "invoking command: " << getquote_cmd);
bool success = true;
-#ifndef WIN32
+#if !defined(_WIN32) && !defined(__CYGWIN__)
if (FILE * fp = popen(getquote_cmd.c_str(), "r")) {
if (std::feof(fp) || ! std::fgets(buf, 255, fp))
success = false;
diff --git a/src/quotes.h b/src/quotes.h
index b3978171..f1b347de 100644
--- a/src/quotes.h
+++ b/src/quotes.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/report.cc b/src/report.cc
index 9e480ea5..13e6a61f 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -57,13 +57,16 @@ void report_t::normalize_options(const string& verb)
// Patch up some of the reporting options based on what kind of
// command it was.
-#if HAVE_ISATTY
+#ifdef HAVE_ISATTY
if (! HANDLED(force_color)) {
if (! HANDLED(no_color) && isatty(STDOUT_FILENO))
HANDLER(color).on("?normalize");
if (HANDLED(color) && ! isatty(STDOUT_FILENO))
HANDLER(color).off();
}
+ else {
+ HANDLER(color).on("?normalize");
+ }
if (! HANDLED(force_pager)) {
if (HANDLED(pager_) && ! isatty(STDOUT_FILENO))
HANDLER(pager_).off();
@@ -181,14 +184,14 @@ void report_t::normalize_options(const string& verb)
}
long cols = 0;
-#if HAVE_IOCTL
+#ifdef HAVE_IOCTL
struct winsize ws;
#endif
if (HANDLED(columns_))
cols = lexical_cast<long>(HANDLER(columns_).value);
else if (const char * columns = std::getenv("COLUMNS"))
cols = lexical_cast<long>(columns);
-#if HAVE_IOCTL
+#ifdef HAVE_IOCTL
else if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != -1)
cols = ws.ws_col;
#endif
@@ -428,8 +431,9 @@ namespace {
} else {
expr_t sort_expr(report.HANDLER(sort_).str());
sort_expr.set_context(&report);
- sorted_accounts_iterator iter(*report.session.journal->master,
- sort_expr, report.HANDLED(flat));
+ sorted_accounts_iterator iter(
+ *report.session.journal->master, sort_expr, report,
+ report.HANDLED(flat));
pass_down_accounts<sorted_accounts_iterator>
(handler, iter, predicate_t(report.HANDLER(display_).str(),
report.what_to_keep()), report);
@@ -441,8 +445,9 @@ namespace {
} else {
expr_t sort_expr(report.HANDLER(sort_).str());
sort_expr.set_context(&report);
- sorted_accounts_iterator iter(*report.session.journal->master,
- sort_expr, report.HANDLED(flat));
+ sorted_accounts_iterator iter(
+ *report.session.journal->master, sort_expr, report,
+ report.HANDLED(flat));
pass_down_accounts<sorted_accounts_iterator>(handler, iter);
}
}
@@ -628,18 +633,15 @@ value_t report_t::fn_trim(call_scope_t& args)
std::strcpy(buf.get(), temp.c_str());
const char * p = buf.get();
- while (*p && std::isspace(*p))
+ const char * e = buf.get() + temp.length() - 1;
+
+ while (p <= e && std::isspace(*p))
p++;
- const char * e = buf.get() + temp.length() - 1;
while (e > p && std::isspace(*e))
e--;
- if (e == p) {
- return string_value(empty_string);
- }
- else if (e < p) {
- assert(false);
+ if (p > e) {
return string_value(empty_string);
}
else {
@@ -756,6 +758,23 @@ value_t report_t::fn_quoted(call_scope_t& args)
return string_value(out.str());
}
+value_t report_t::fn_quoted_rfc4180(call_scope_t& args)
+{
+ std::ostringstream out;
+
+ out << '"';
+ string arg(args.get<string>(0));
+ foreach (const char ch, arg) {
+ if (ch == '"')
+ out << '"' << '"';
+ else
+ out << ch;
+ }
+ out << '"';
+
+ return string_value(out.str());
+}
+
value_t report_t::fn_join(call_scope_t& args)
{
std::ostringstream out;
@@ -822,6 +841,13 @@ value_t report_t::fn_commodity(call_scope_t& args)
return string_value(args.get<amount_t>(0).commodity().symbol());
}
+value_t report_t::fn_clear_commodity(call_scope_t& args)
+{
+ amount_t amt(args.get<amount_t>(0));
+ amt.clear_commodity();
+ return amt;
+}
+
value_t report_t::fn_nail_down(call_scope_t& args)
{
value_t arg0(args[0]);
@@ -1365,6 +1391,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
return MAKE_FUNCTOR(report_t::fn_commodity);
else if (is_eq(p, "ceiling"))
return MAKE_FUNCTOR(report_t::fn_ceiling);
+ else if (is_eq(p, "clear_commodity"))
+ return MAKE_FUNCTOR(report_t::fn_clear_commodity);
break;
case 'd':
@@ -1439,6 +1467,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
case 'q':
if (is_eq(p, "quoted"))
return MAKE_FUNCTOR(report_t::fn_quoted);
+ else if (is_eq(p, "quoted_rfc4180"))
+ return MAKE_FUNCTOR(report_t::fn_quoted_rfc4180);
else if (is_eq(p, "quantity"))
return MAKE_FUNCTOR(report_t::fn_quantity);
break;
diff --git a/src/report.h b/src/report.h
index 9110c5b0..1bda0407 100644
--- a/src/report.h
+++ b/src/report.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -175,12 +175,14 @@ public:
value_t fn_truncated(call_scope_t& scope);
value_t fn_floor(call_scope_t& scope);
value_t fn_ceiling(call_scope_t& scope);
+ value_t fn_clear_commodity(call_scope_t& scope);
value_t fn_round(call_scope_t& scope);
value_t fn_roundto(call_scope_t& scope);
value_t fn_unround(call_scope_t& scope);
value_t fn_abs(call_scope_t& scope);
value_t fn_justify(call_scope_t& scope);
value_t fn_quoted(call_scope_t& scope);
+ value_t fn_quoted_rfc4180(call_scope_t& scope);
value_t fn_join(call_scope_t& scope);
value_t fn_format_date(call_scope_t& scope);
value_t fn_format_datetime(call_scope_t& scope);
@@ -403,6 +405,7 @@ public:
OPTION(report_t, auto_match);
OPTION_(report_t, average, DO() { // -A
+ OTHER(empty).on(whence);
OTHER(display_total_)
.on(whence, "count>0?(display_total/count):0");
});
@@ -457,12 +460,12 @@ public:
(report_t, budget_format_,
CTOR(report_t, budget_format_) {
on(none,
- "%(justify(scrub(get_at(display_total, 0)), 12, -1, true, color))"
- " %(justify(-scrub(get_at(display_total, 1)), 12, "
- " 12 + 1 + 12, true, color))"
- " %(justify(scrub(get_at(display_total, 1) + "
- " get_at(display_total, 0)), 12, "
- " 12 + 1 + 12 + 1 + 12, true, color))"
+ "%(justify(scrub(get_at(display_total, 0)), int(amount_width), -1, true, color))"
+ " %(justify(-scrub(get_at(display_total, 1)), int(amount_width), "
+ " int(amount_width) + 1 + int(amount_width), true, color))"
+ " %(justify(scrub((get_at(display_total, 1) || 0) + "
+ " (get_at(display_total, 0) || 0)), int(amount_width), "
+ " int(amount_width) + 1 + int(amount_width) + 1 + int(amount_width), true, color))"
" %(ansify_if("
" justify((get_at(display_total, 1) ? "
" (100% * quantity(scrub(get_at(display_total, 0)))) / "
@@ -792,7 +795,8 @@ public:
OPTION(report_t, output_); // -o
-#if HAVE_ISATTY
+// setenv() is not available on WIN32
+#if defined(HAVE_ISATTY) and !defined(_WIN32) and !defined(__CYGWIN__)
OPTION__
(report_t, pager_,
CTOR(report_t, pager_) {
diff --git a/src/scope.cc b/src/scope.cc
index 03387549..281d843b 100644
--- a/src/scope.cc
+++ b/src/scope.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/scope.h b/src/scope.h
index 147b400f..8ec1a44f 100644
--- a/src/scope.h
+++ b/src/scope.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/select.cc b/src/select.cc
index 1c69b2bf..187387d8 100644
--- a/src/select.cc
+++ b/src/select.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -145,14 +145,14 @@ value_t select_command(call_scope_t& args)
string thus_far = "";
std::size_t cols = 0;
-#if HAVE_IOCTL
+#ifdef HAVE_IOCTL
struct winsize ws;
#endif
if (report.HANDLED(columns_))
cols = lexical_cast<std::size_t>(report.HANDLER(columns_).value);
else if (const char * columns_env = std::getenv("COLUMNS"))
cols = lexical_cast<std::size_t>(columns_env);
-#if HAVE_IOCTL
+#ifdef HAVE_IOCTL
else if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != -1)
cols = ws.ws_col;
#endif
diff --git a/src/select.h b/src/select.h
index 89d7c989..ea2e3708 100644
--- a/src/select.h
+++ b/src/select.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/session.cc b/src/session.cc
index 8d03431f..427850d9 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -284,7 +284,7 @@ value_t session_t::fn_str(call_scope_t& args)
value_t session_t::fn_lot_price(call_scope_t& args)
{
- amount_t amt(args.get<amount_t>(1, false));
+ amount_t amt(args.get<amount_t>(0, false));
if (amt.has_annotation() && amt.annotation().price)
return *amt.annotation().price;
else
@@ -292,7 +292,7 @@ value_t session_t::fn_lot_price(call_scope_t& args)
}
value_t session_t::fn_lot_date(call_scope_t& args)
{
- amount_t amt(args.get<amount_t>(1, false));
+ amount_t amt(args.get<amount_t>(0, false));
if (amt.has_annotation() && amt.annotation().date)
return *amt.annotation().date;
else
@@ -300,7 +300,7 @@ value_t session_t::fn_lot_date(call_scope_t& args)
}
value_t session_t::fn_lot_tag(call_scope_t& args)
{
- amount_t amt(args.get<amount_t>(1, false));
+ amount_t amt(args.get<amount_t>(0, false));
if (amt.has_annotation() && amt.annotation().tag)
return string_value(*amt.annotation().tag);
else
diff --git a/src/session.h b/src/session.h
index 3d35a93e..4dce3816 100644
--- a/src/session.h
+++ b/src/session.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -52,6 +52,16 @@ namespace ledger {
class xact_t;
+struct ComparePaths
+{
+ bool operator()(const path& p1, const path& p2) const
+ {
+ return p1 < p2 && !boost::filesystem::equivalent(p1, p2);
+ }
+};
+
+#define COMMA ,
+
class session_t : public symbol_scope_t
{
friend void set_session_context(session_t * session);
diff --git a/src/stats.cc b/src/stats.cc
index 2d1f8dc7..2c6d9069 100644
--- a/src/stats.cc
+++ b/src/stats.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/stats.h b/src/stats.h
index dfb9e796..c8d7ee4c 100644
--- a/src/stats.h
+++ b/src/stats.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/stream.cc b/src/stream.cc
index 60b0dc55..c4bbb42e 100644
--- a/src/stream.cc
+++ b/src/stream.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -58,7 +58,7 @@ namespace {
*/
int do_fork(std::ostream ** os, const path& pager_path)
{
-#ifndef WIN32
+#if !defined(_WIN32) && !defined(__CYGWIN__)
int pfd[2];
int status = pipe(pfd);
@@ -115,7 +115,7 @@ void output_stream_t::initialize(const optional<path>& output_file,
void output_stream_t::close()
{
-#ifndef WIN32
+#if !defined(_WIN32) && !defined(__CYGWIN__)
if (os != &std::cout) {
checked_delete(os);
os = &std::cout;
diff --git a/src/stream.h b/src/stream.h
index 996cffb1..dd171284 100644
--- a/src/stream.h
+++ b/src/stream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/strptime.cc b/src/strptime.cc
index b31954f4..069b9267 100644
--- a/src/strptime.cc
+++ b/src/strptime.cc
@@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-
-#ifdef WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
// Implement strptime under windows
#include "strptime.h"
@@ -22,6 +21,22 @@
#include <ctype.h>
#include <string.h>
+#if defined(__CYGWIN__)
+// Define strnicmp for Cygwin.
+#ifndef strcmpi
+#define strcmpi strcasecmp
+#endif
+#ifndef stricmp
+#define stricmp strcasecmp
+#endif
+#ifndef strncmpi
+#define strncmpi strncasecmp
+#endif
+#ifndef strnicmp
+#define strnicmp strncasecmp
+#endif
+#endif
+
static const char* kWeekFull[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
@@ -70,14 +85,14 @@ static char* _strptime(const char *s, const char *format, struct tm *tm) {
case 'A':
tm->tm_wday = -1;
for (int i = 0; i < 7; ++i) {
- len = static_cast<int>(strlen(kWeekAbbr[i]));
- if (strnicmp(kWeekAbbr[i], s, len) == 0) {
+ len = static_cast<int>(strlen(kWeekFull[i]));
+ if (strnicmp(kWeekFull[i], s, len) == 0) {
tm->tm_wday = i;
break;
}
- len = static_cast<int>(strlen(kWeekFull[i]));
- if (strnicmp(kWeekFull[i], s, len) == 0) {
+ len = static_cast<int>(strlen(kWeekAbbr[i]));
+ if (strnicmp(kWeekAbbr[i], s, len) == 0) {
tm->tm_wday = i;
break;
}
@@ -92,14 +107,14 @@ static char* _strptime(const char *s, const char *format, struct tm *tm) {
case 'h':
tm->tm_mon = -1;
for (int i = 0; i < 12; ++i) {
- len = static_cast<int>(strlen(kMonthAbbr[i]));
- if (strnicmp(kMonthAbbr[i], s, len) == 0) {
+ len = static_cast<int>(strlen(kMonthFull[i]));
+ if (strnicmp(kMonthFull[i], s, len) == 0) {
tm->tm_mon = i;
break;
}
- len = static_cast<int>(strlen(kMonthFull[i]));
- if (strnicmp(kMonthFull[i], s, len) == 0) {
+ len = static_cast<int>(strlen(kMonthAbbr[i]));
+ if (strnicmp(kMonthAbbr[i], s, len) == 0) {
tm->tm_mon = i;
break;
}
@@ -186,4 +201,4 @@ char* strptime(const char *buf, const char *fmt, struct tm *tm) {
return _strptime(buf, fmt, tm);
}
-#endif // WIN32
+#endif // _WIN32
diff --git a/src/system.hh.in b/src/system.hh.in
index 54bcf7a9..38ac1e63 100644
--- a/src/system.hh.in
+++ b/src/system.hh.in
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -60,12 +60,12 @@
#define HAVE_EDIT @HAVE_EDIT@
#define HAVE_GETTEXT @HAVE_GETTEXT@
-#define HAVE_ACCESS @HAVE_ACCESS@
-#define HAVE_REALPATH @HAVE_REALPATH@
-#define HAVE_GETPWUID @HAVE_GETPWUID@
-#define HAVE_GETPWNAM @HAVE_GETPWNAM@
-#define HAVE_IOCTL @HAVE_IOCTL@
-#define HAVE_ISATTY @HAVE_ISATTY@
+#cmakedefine HAVE_ACCESS
+#cmakedefine HAVE_REALPATH
+#cmakedefine HAVE_GETPWUID
+#cmakedefine HAVE_GETPWNAM
+#cmakedefine HAVE_IOCTL
+#cmakedefine HAVE_ISATTY
#define HAVE_UNIX_PIPES @HAVE_UNIX_PIPES@
@@ -144,16 +144,16 @@ typedef std::ostream::pos_type ostream_pos_type;
#endif
#include <sys/stat.h>
-#if defined(WIN32)
+#if defined(_WIN32) || defined(__CYGWIN__)
#include <io.h>
#else
#include <unistd.h>
#endif
-#if HAVE_GETPWUID || HAVE_GETPWNAM
+#if defined(HAVE_GETPWUID) || defined(HAVE_GETPWNAM)
#include <pwd.h>
#endif
-#if HAVE_IOCTL
+#ifdef HAVE_IOCTL
#include <sys/ioctl.h>
#endif
diff --git a/src/temps.cc b/src/temps.cc
index b8e7bfb6..7ff5ec94 100644
--- a/src/temps.cc
+++ b/src/temps.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/temps.h b/src/temps.h
index eb2b9b23..a28966fe 100644
--- a/src/temps.h
+++ b/src/temps.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/textual.cc b/src/textual.cc
index c97b8b01..3416073b 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -567,6 +567,9 @@ void instance_t::automated_xact_directive(char * line)
expr_t::ptr_op_t expr =
query.parse_args(string_value(skip_ws(line + 1)).to_sequence(),
keeper, false, true);
+ if (!expr) {
+ throw parse_error(_("Expected predicate after '='"));
+ }
unique_ptr<auto_xact_t> ae(new auto_xact_t(predicate_t(expr, keeper)));
ae->pos = position_t();
@@ -725,15 +728,12 @@ void instance_t::include_directive(char * line)
if (line[0] != '/' && line[0] != '\\' && line[0] != '~') {
DEBUG("textual.include", "received a relative path");
DEBUG("textual.include", "parent file path: " << context.pathname);
- string pathstr(context.pathname.string());
- string::size_type pos = pathstr.rfind('/');
- if (pos == string::npos)
- pos = pathstr.rfind('\\');
- if (pos != string::npos) {
- filename = path(string(pathstr, 0, pos + 1)) / line;
- DEBUG("textual.include", "normalized path: " << filename.string());
- } else {
+ path parent_path = context.pathname.parent_path();
+ if (parent_path.empty()) {
filename = path(string(".")) / line;
+ } else {
+ filename = parent_path / line;
+ DEBUG("textual.include", "normalized path: " << filename.string());
}
} else {
filename = line;
@@ -1132,6 +1132,7 @@ void instance_t::commodity_format_directive(commodity_t&, string format)
trim(format);
amount_t amt;
amt.parse(format);
+ amt.commodity().add_flags(COMMODITY_STYLE_NO_MIGRATE);
VERIFY(amt.valid());
}
@@ -1647,53 +1648,84 @@ post_t * instance_t::parse_post(char * line,
}
DEBUG("textual.parse", "line " << context.linenum << ": "
- << "POST assign: parsed amt = " << *post->assigned_amount);
+ << "POST assign: parsed balance amount = " << *post->assigned_amount);
- amount_t& amt(*post->assigned_amount);
+ const amount_t& amt(*post->assigned_amount);
value_t account_total
(post->account->amount().strip_annotations(keep_details_t()));
DEBUG("post.assign", "line " << context.linenum << ": "
<< "account balance = " << account_total);
- DEBUG("post.assign",
- "line " << context.linenum << ": " << "post amount = " << amt);
+ DEBUG("post.assign", "line " << context.linenum << ": "
+ << "post amount = " << amt << " (is_zero = " << amt.is_zero() << ")");
- amount_t diff = amt;
+ balance_t diff = amt;
switch (account_total.type()) {
case value_t::AMOUNT:
diff -= account_total.as_amount();
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Subtracting amount " << account_total.as_amount() << " from diff, yielding " << diff);
break;
case value_t::BALANCE:
- if (optional<amount_t> comm_bal =
- account_total.as_balance().commodity_amount(amt.commodity()))
- diff -= *comm_bal;
+ diff -= account_total.as_balance();
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Subtracting balance " << account_total.as_balance() << " from diff, yielding " << diff);
break;
default:
break;
}
- amount_t tot = amt - diff;
-
DEBUG("post.assign",
"line " << context.linenum << ": " << "diff = " << diff);
DEBUG("textual.parse", "line " << context.linenum << ": "
<< "POST assign: diff = " << diff);
- if (! diff.is_zero()) {
- if (! post->amount.is_null()) {
- diff -= post->amount;
- if (! no_assertions && ! diff.is_zero())
- throw_(parse_error,
- _f("Balance assertion off by %1% (expected to see %2%)")
- % diff % tot);
+ // Subtract amounts from previous posts to this account in the xact.
+ for (post_t* p : xact->posts) {
+ if (p->account == post->account) {
+ diff -= p->amount;
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Subtracting " << p->amount << ", diff = " << diff);
+ }
+ }
+
+ // If amt has a commodity, restrict balancing to that. Otherwise, it's the blanket '0' and
+ // check that all of them are zero.
+ if (amt.has_commodity()) {
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Finding commodity " << amt.commodity() << " (" << amt << ") in balance " << diff);
+ optional<amount_t> wanted_commodity = diff.commodity_amount(amt.commodity());
+ if (!wanted_commodity) {
+ diff = amt - amt; // this is '0' with the correct commodity.
} else {
- post->amount = diff;
+ diff = *wanted_commodity;
+ }
+ DEBUG("textual.parse", "line " << context.linenum << ": "
+ << "Diff is now " << diff);
+ }
+
+ if (post->amount.is_null()) {
+ // balance assignment
+ if (! diff.is_zero()) {
+ // This will fail if there are more than 1 commodity in diff, which is wanted,
+ // as amount cannot store more than 1 commodity.
+ post->amount = diff.to_amount();
DEBUG("textual.parse", "line " << context.linenum << ": "
<< "Overwrite null posting");
}
+ } else {
+ // balance assertion
+ diff -= post->amount;
+ if (! no_assertions && ! diff.is_zero()) {
+ balance_t tot = -diff + amt;
+ DEBUG("textual.parse", "Balance assertion: off by " << diff << " (expected to see " << tot << ")");
+ throw_(parse_error,
+ _f("Balance assertion off by %1% (expected to see %2%)")
+ % diff.to_string() % tot.to_string());
+ }
}
if (stream.eof())
diff --git a/src/timelog.cc b/src/timelog.cc
index 870a4b4b..2a618afd 100644
--- a/src/timelog.cc
+++ b/src/timelog.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/timelog.h b/src/timelog.h
index 95a87eae..4e7d2bb4 100644
--- a/src/timelog.h
+++ b/src/timelog.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/times.cc b/src/times.cc
index b9c8fc01..eda71ae7 100644
--- a/src/times.cc
+++ b/src/times.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -33,7 +33,7 @@
#include "times.h"
-#ifdef WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
#include "strptime.h"
#endif
@@ -420,7 +420,6 @@ class date_parser_t
TOK_DASH,
TOK_DOT,
- TOK_A_YEAR,
TOK_A_MONTH,
TOK_A_WDAY,
@@ -512,9 +511,6 @@ class date_parser_t
case TOK_SLASH: return "/";
case TOK_DASH: return "-";
case TOK_DOT: return ".";
- case TOK_A_YEAR:
- out << boost::get<date_specifier_t::year_type>(*value);
- break;
case TOK_A_MONTH:
out << date_specifier_t::month_type
(boost::get<date_time::months_of_year>(*value));
@@ -566,7 +562,6 @@ class date_parser_t
case TOK_SLASH: out << "TOK_SLASH"; break;
case TOK_DASH: out << "TOK_DASH"; break;
case TOK_DOT: out << "TOK_DOT"; break;
- case TOK_A_YEAR: out << "TOK_A_YEAR"; break;
case TOK_A_MONTH: out << "TOK_A_MONTH"; break;
case TOK_A_WDAY: out << "TOK_A_WDAY"; break;
case TOK_AGO: out << "TOK_AGO"; break;
@@ -727,7 +722,11 @@ void date_parser_t::determine_when(date_parser_t::lexer_t::token_t& tok,
when += gregorian::days(amount * adjust);
break;
default:
- specifier.day = date_specifier_t::day_type(amount);
+ if (amount > 31) {
+ specifier.year = date_specifier_t::year_type(amount);
+ } else {
+ specifier.day = date_specifier_t::day_type(amount);
+ }
break;
}
@@ -832,16 +831,13 @@ void date_parser_t::determine_when(date_parser_t::lexer_t::token_t& tok,
break;
}
- case lexer_t::token_t::TOK_A_YEAR:
- specifier.year = boost::get<date_specifier_t::year_type>(*tok.value);
- break;
case lexer_t::token_t::TOK_A_MONTH:
specifier.month =
date_specifier_t::month_type
(boost::get<date_time::months_of_year>(*tok.value));
tok = lexer.peek_token();
switch (tok.kind) {
- case lexer_t::token_t::TOK_A_YEAR:
+ case lexer_t::token_t::TOK_INT:
specifier.year = boost::get<date_specifier_t::year_type>(*tok.value);
break;
case lexer_t::token_t::END_REACHED:
@@ -898,12 +894,6 @@ date_interval_t date_parser_t::parse()
determine_when(tok, *inclusion_specifier);
break;
- case lexer_t::token_t::TOK_A_YEAR:
- if (! inclusion_specifier)
- inclusion_specifier = date_specifier_t();
- determine_when(tok, *inclusion_specifier);
- break;
-
case lexer_t::token_t::TOK_A_MONTH:
if (! inclusion_specifier)
inclusion_specifier = date_specifier_t();
@@ -1304,21 +1294,35 @@ void date_interval_t::stabilize(const optional<date_t>& date)
#endif
date_t when = start ? *start : *date;
-
- if (duration->quantum == date_duration_t::MONTHS ||
- duration->quantum == date_duration_t::QUARTERS ||
- duration->quantum == date_duration_t::YEARS) {
+ switch (duration->quantum) {
+ case date_duration_t::MONTHS:
+ case date_duration_t::QUARTERS:
+ case date_duration_t::YEARS:
+ // These start on most recent period start quantum before when
DEBUG("times.interval",
- "stabilize: monthly, quarterly or yearly duration");
+ "stabilize: monthly, quarterly or yearly duration");
start = date_duration_t::find_nearest(when, duration->quantum);
- } else {
- DEBUG("times.interval", "stabilize: daily or weekly duration");
- start = date_duration_t::find_nearest(when - gregorian::days(400),
- duration->quantum);
+ break;
+ case date_duration_t::WEEKS:
+ // Weeks start on the beginning of week prior to 400 remainder period length
+ // Either the first quanta of the period or the last quanta of the period seems more sensible
+ // implies period is never less than 400 days not too unreasonable
+ DEBUG("times.interval", "stabilize: weekly duration");
+ {
+ int period = duration->length * 7;
+ start = date_duration_t::find_nearest(
+ when - gregorian::days(period + 400 % period), duration->quantum);
+ }
+ break;
+ default:
+ // multiples of days have a quanta of 1 day so should not have the start date adjusted to a quanta
+ DEBUG("times.interval",
+ "stabilize: daily duration - stable by definition");
+ start = when;
+ break;
}
- DEBUG("times.interval",
- "stabilize: beginning start date = " << *start);
+ DEBUG("times.interval", "stabilize: beginning start date = " << *start);
while (*start < *date) {
date_interval_t next_interval(*this);
@@ -1328,7 +1332,7 @@ void date_interval_t::stabilize(const optional<date_t>& date)
*this = next_interval;
} else {
end_of_duration = none;
- next = none;
+ next = none;
break;
}
}
@@ -1598,13 +1602,8 @@ date_parser_t::lexer_t::token_t date_parser_t::lexer_t::next_token()
if (! term.empty()) {
if (std::isdigit(term[0])) {
- if (term.length() == 4)
- return token_t(token_t::TOK_A_YEAR,
- token_t::content_t
- (lexical_cast<date_specifier_t::year_type>(term)));
- else
- return token_t(token_t::TOK_INT,
- token_t::content_t(lexical_cast<unsigned short>(term)));
+ return token_t(token_t::TOK_INT,
+ token_t::content_t(lexical_cast<unsigned short>(term)));
}
else if (std::isalpha(term[0])) {
to_lower(term);
diff --git a/src/times.h b/src/times.h
index df833958..71ad6e3e 100644
--- a/src/times.h
+++ b/src/times.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/token.cc b/src/token.cc
index 0bbff6ea..1ec052ed 100644
--- a/src/token.cc
+++ b/src/token.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -303,8 +303,8 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags)
kind = SLASH;
} else { // terminal context
// Read in the regexp
- char buf[256];
- READ_INTO_(in, buf, 255, c, length, c != '/');
+ char buf[4096];
+ READ_INTO_(in, buf, 4095, c, length, c != '/');
if (c != '/')
expected('/', c);
in.get(c);
diff --git a/src/token.h b/src/token.h
index b9ccde86..5d9f1fac 100644
--- a/src/token.h
+++ b/src/token.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/unistring.h b/src/unistring.h
index fc37c9f2..8cc4a9cd 100644
--- a/src/unistring.h
+++ b/src/unistring.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/utils.cc b/src/utils.cc
index 947f2408..23dc7205 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -807,7 +807,7 @@ path expand_path(const path& pathname)
if (path_string.length() == 1 || pos == 1) {
pfx = std::getenv("HOME");
-#if HAVE_GETPWUID
+#ifdef HAVE_GETPWUID
if (! pfx) {
// Punt. We're trying to expand ~/, but HOME isn't set
struct passwd * pw = getpwuid(getuid());
@@ -816,7 +816,7 @@ path expand_path(const path& pathname)
}
#endif
}
-#if HAVE_GETPWNAM
+#ifdef HAVE_GETPWNAM
else {
string user(path_string, 1, pos == string::npos ?
string::npos : pos - 1);
diff --git a/src/utils.h b/src/utils.h
index 42ea2ae9..857b8289 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -44,7 +44,11 @@
#ifndef _UTILS_H
#define _UTILS_H
+#if (BOOST_VERSION >= 106600)
+#include <boost/uuid/detail/sha1.hpp>
+#else
#include <boost/uuid/sha1.hpp>
+#endif
/**
* @name Default values
@@ -496,7 +500,7 @@ inline T& downcast(U& object) {
path resolve_path(const path& pathname);
-#if HAVE_REALPATH
+#ifdef HAVE_REALPATH
extern "C" char * realpath(const char *, char resolved_path[]);
#endif
diff --git a/src/value.cc b/src/value.cc
index 878d7349..1841505d 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/value.h b/src/value.h
index eb0c7c76..35581bfb 100644
--- a/src/value.h
+++ b/src/value.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/views.cc b/src/views.cc
index 65d21a9a..85128307 100644
--- a/src/views.cc
+++ b/src/views.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/views.h b/src/views.h
index 070ac22d..61929dcf 100644
--- a/src/views.h
+++ b/src/views.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/src/xact.cc b/src/xact.cc
index 2524889d..5df9ebc5 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, 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
@@ -145,7 +145,7 @@ namespace {
first = false;
} else {
unique_ptr<post_t> p(new post_t(null_post->account, amount.negated(),
- ITEM_GENERATED | POST_CALCULATED));
+ null_post->flags() | ITEM_GENERATED | POST_CALCULATED));
p->set_state(null_post->state());
xact.add_post(p.release());
}
@@ -396,9 +396,9 @@ bool xact_base_t::finalize()
}
if (post->has_flags(POST_DEFERRED))
- post->account->add_deferred_post(id(), post);
- else
- post->account->add_post(post);
+ post->account->add_deferred_post(id(), post);
+ else
+ post->account->add_post(post);
post->xdata().add_flags(POST_EXT_VISITED);
post->account->xdata().add_flags(ACCOUNT_EXT_VISITED);
@@ -806,6 +806,10 @@ void auto_xact_t::extend_xact(xact_base_t& xact, parse_context_t& context)
xact.add_post(new_post);
new_post->account->add_post(new_post);
+ // Add flags so this post updates the account balance
+ new_post->xdata().add_flags(POST_EXT_VISITED);
+ new_post->account->xdata().add_flags(ACCOUNT_EXT_VISITED);
+
if (new_post->must_balance())
needs_further_verification = true;
}
diff --git a/src/xact.h b/src/xact.h
index a43246ee..b0a4417e 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/test/CheckBaselineTests.py b/test/CheckBaselineTests.py
index 8659d1b5..f53c59a2 100755
--- a/test/CheckBaselineTests.py
+++ b/test/CheckBaselineTests.py
@@ -23,7 +23,6 @@ class CheckBaselineTests (CheckOptions):
'args-only',
'debug',
'download',
- 'force-color',
'force-pager',
'generated',
'help',
diff --git a/test/DocTests.py b/test/DocTests.py
index 7af7abc3..52632a7b 100755
--- a/test/DocTests.py
+++ b/test/DocTests.py
@@ -192,6 +192,8 @@ class DocTests:
error = None
try:
verify = subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if sys.platform == 'win32':
+ verify = verify.replace('\r\n', '\n')
valid = (output == verify) or (not error and validation)
except subprocess.CalledProcessError, e:
error = e.output
diff --git a/test/LedgerHarness.py b/test/LedgerHarness.py
index 39a31286..63d6a0ec 100755
--- a/test/LedgerHarness.py
+++ b/test/LedgerHarness.py
@@ -86,6 +86,13 @@ class LedgerHarness:
if os.path.isfile(valgrind) and '--verify' in insert:
command = valgrind + ' -q ' + command
+ # If we are running under msys2, use bash to execute the test commands
+ if 'MSYSTEM' in os.environ:
+ bash_path = os.environ['MINGW_PREFIX'] + '/../usr/bin/bash.exe'
+ return Popen([bash_path, '-c', command], shell=False,
+ close_fds=False, env=env, stdin=PIPE, stdout=PIPE,
+ stderr=PIPE, cwd=self.sourcepath)
+
return Popen(command, shell=True, close_fds=True, env=env,
stdin=PIPE, stdout=PIPE, stderr=PIPE,
cwd=self.sourcepath)
diff --git a/test/RegressTests.py b/test/RegressTests.py
index a5bab42d..58869edc 100755
--- a/test/RegressTests.py
+++ b/test/RegressTests.py
@@ -98,6 +98,13 @@ class RegressFile(object):
def run_test(self, test):
use_stdin = False
+ if sys.platform == 'win32':
+ test['command'] = test['command'].replace('/dev/null', 'nul')
+ # There is no equivalent to /dev/stdout, /dev/stderr, /dev/stdin
+ # on Windows, so skip tests that require them.
+ if '/dev/std' in test['command']:
+ harness.success()
+ return
if test['command'].find("-f ") != -1:
test['command'] = '$ledger ' + test['command']
if re.search("-f (-|/dev/stdin)(\s|$)", test['command']):
@@ -122,7 +129,16 @@ class RegressFile(object):
printed = False
index = 0
if test['output'] is not None:
- for line in unified_diff(test['output'], harness.readlines(p.stdout)):
+ process_output = harness.readlines(p.stdout)
+ expected_output = test['output']
+ if sys.platform == 'win32':
+ process_output = [l.replace('\r\n', '\n').replace('\\', '/')
+ for l in process_output]
+ # Replace \ with / in the expected output because the line above
+ # makes it impossible for the process output to have a \.
+ expected_output = [l.replace('\\', '/') for l in expected_output]
+
+ for line in unified_diff(expected_output, process_output):
index += 1
if index < 3:
continue
@@ -135,8 +151,14 @@ class RegressFile(object):
printed = False
index = 0
- if test['error'] is not None:
- for line in unified_diff(test['error'], harness.readlines(p.stderr)):
+ process_error = harness.readlines(p.stderr)
+ if test['error'] is not None or process_error is not None:
+ if test['error'] is None:
+ test['error'] = []
+ if sys.platform == 'win32':
+ process_error = [l.replace('\r\n', '\n').replace('\\', '/')
+ for l in process_error]
+ for line in unified_diff(test['error'], process_error):
index += 1
if index < 3:
continue
diff --git a/test/baseline/cmd-tags.test b/test/baseline/cmd-tags.test
index bfff763a..926bdbfd 100644
--- a/test/baseline/cmd-tags.test
+++ b/test/baseline/cmd-tags.test
@@ -33,6 +33,7 @@ a
b
bar
foo
+xxx
end test
test tags --values
@@ -42,6 +43,7 @@ b
b: bbb
bar
foo
+xxx
end test
test tags --values --count
@@ -51,5 +53,6 @@ test tags --values --count
1 b: bbb
1 bar
1 foo
+2 xxx
end test
diff --git a/test/baseline/feat-balance_assert-off.test b/test/baseline/feat-balance_assert-off.test
index fed24d4a..d1da753e 100644
--- a/test/baseline/feat-balance_assert-off.test
+++ b/test/baseline/feat-balance_assert-off.test
@@ -13,6 +13,6 @@ While parsing file "$FILE", line 8:
While parsing posting:
Assets:Cash -$10 = $80
^^^
-Error: Balance assertion off by $-10 (expected to see $100)
+Error: Balance assertion off by $-10 (expected to see $90)
end test
diff --git a/test/baseline/feat-balance_assert_split.test b/test/baseline/feat-balance_assert_split.test
index 2d9cce9f..ad299325 100644
--- a/test/baseline/feat-balance_assert_split.test
+++ b/test/baseline/feat-balance_assert_split.test
@@ -14,7 +14,7 @@
2012-01-04 Test
; UUID: foo
- Liabilities:MasterCard $150.00 = $-300
+ Liabilities:MasterCard $150.00 = $-150
<Assets:Checking>
2012-01-04 Test
@@ -24,7 +24,7 @@
2012-01-04 Test
; UUID: baz
- Liabilities:MasterCard $150.00 = $0
+ Liabilities:MasterCard $150.00 = $150
<Assets:Checking>
;; b.dat
diff --git a/test/baseline/feat-value-expr.test b/test/baseline/feat-value-expr.test
index 01f9780b..885fd194 100644
--- a/test/baseline/feat-value-expr.test
+++ b/test/baseline/feat-value-expr.test
@@ -77,7 +77,7 @@ account Expenses:Food5
2012-03-07 KFC
Expenses:Food7 1 CAD
- Assets:Cas7
+ Assets:Cash7
2012-03-08 XACT
Expenses:Food8 $1
diff --git a/test/baseline/opt-color.test b/test/baseline/opt-color.test
index a7d702bd..a0abdffc 100644
--- a/test/baseline/opt-color.test
+++ b/test/baseline/opt-color.test
@@ -2,10 +2,10 @@
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
Income:Dividends:Vanguard:VMMXX $-0.35
-test bal --color --force-color
- 0.350 VMMXX Assets:Investments:Vanguard:VMMXX
- $-0.35 Income:Dividends:Vanguard:VMMXX
+test bal --color
+ 0.350 VMMXX Assets:Investments:Vanguard:VMMXX
+ $-0.35 Income:Dividends:Vanguard:VMMXX
--------------------
- $-0.35
+ $-0.35
0.350 VMMXX
end test
diff --git a/test/baseline/opt-force-color.test b/test/baseline/opt-force-color.test
new file mode 100644
index 00000000..536c3834
--- /dev/null
+++ b/test/baseline/opt-force-color.test
@@ -0,0 +1,19 @@
+2007/02/02 RD VMMXX
+ Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
+ Income:Dividends:Vanguard:VMMXX $-0.35
+
+test bal --force-color
+ 0.350 VMMXX Assets:Investments:Vanguard:VMMXX
+ $-0.35 Income:Dividends:Vanguard:VMMXX
+--------------------
+ $-0.35
+ 0.350 VMMXX
+end test
+
+test bal
+ 0.350 VMMXX Assets:Investments:Vanguard:VMMXX
+ $-0.35 Income:Dividends:Vanguard:VMMXX
+--------------------
+ $-0.35
+ 0.350 VMMXX
+end test
diff --git a/test/baseline/opt-prepend-format.test b/test/baseline/opt-prepend-format.test
index 105930f1..de79d72e 100644
--- a/test/baseline/opt-prepend-format.test
+++ b/test/baseline/opt-prepend-format.test
@@ -15,3 +15,8 @@ VMMXX07-Feb-02 RD VMMXX As:Inves:Vanguar:VMMXX 0.350 VMMXX 0.350
VMMXX In:Divid:Vanguar:VMMXX $-0.35 $-0.35
0.350 VMMXX
end test
+
+test accounts --prepend-format "%(account_base) "
+VMMXX Assets:Investments:Vanguard:VMMXX
+VMMXX Income:Dividends:Vanguard:VMMXX
+end test
diff --git a/test/baseline/opt-prepend-width.test b/test/baseline/opt-prepend-width.test
index c20baeb4..0efd220f 100644
--- a/test/baseline/opt-prepend-width.test
+++ b/test/baseline/opt-prepend-width.test
@@ -15,3 +15,8 @@ test reg --prepend-format "%(account_base) " --prepend-width=10
VMMXX In:Divid:Vanguar:VMMXX $-0.35 $-0.35
0.350 VMMXX
end test
+
+test accounts --prepend-format "%(account_base) " --prepend-width=10
+ VMMXX Assets:Investments:Vanguard:VMMXX
+ VMMXX Income:Dividends:Vanguard:VMMXX
+end test
diff --git a/test/convert.py b/test/convert.py
index 857d4d30..2ac7a21b 100755
--- a/test/convert.py
+++ b/test/convert.py
@@ -3,7 +3,7 @@
# convert.py: This script converts a Boost.Test unit test into an
# equivalent Python unit test.
#
-# Copyright (c) 2003-2016, John Wiegley. All rights reserved.
+# Copyright (c) 2003-2018, John Wiegley. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
diff --git a/test/regress/1055.test b/test/regress/1055.test
new file mode 100644
index 00000000..e3e997fa
--- /dev/null
+++ b/test/regress/1055.test
@@ -0,0 +1,26 @@
+2011-01-01 * Opening balance
+ Assets:Broker 250.00 GBP = 250.00 GBP
+ Equity:Opening balance -250.00 GBP
+
+2011-02-01 * Buy 1 AAA for 10.00 GBP
+ Assets:Broker 1 AAA = 1 AAA
+ Assets:Broker -10.00 GBP
+
+2011-03-01 * Buy 1 AAA for 10.00 GBP
+ Assets:Broker 1 AAA = 2 AAA
+ Assets:Broker -10.00 GBP
+
+2011-04-01 * Buy 1 BBB for 15.00 GBP
+ Assets:Broker 1 BBB = 1 BBB
+ Assets:Broker -15.00 GBP
+
+test bal
+ 2 AAA
+ 1 BBB
+ 215.00 GBP Assets:Broker
+ -250.00 GBP Equity:Opening balance
+--------------------
+ 2 AAA
+ 1 BBB
+ -35.00 GBP
+end test
diff --git a/test/regress/1057.test b/test/regress/1057.test
index 1cd91ee7..07eb2dbf 100644
--- a/test/regress/1057.test
+++ b/test/regress/1057.test
@@ -3,7 +3,7 @@
Dépense:Maison:Service:Poste
* Passif:Crédit:BanqueAccord -171,63 €
-test -f test/regress/1057.test --now=2014/06/27 emacs
+test --now=2014/06/27 emacs
(("$sourcepath/test/regress/1057.test" 1 (21308 60112 0) nil "www.amazon.fr"
(2 "Dépense:Loisir:Ordi:Matériel" "101,50 €" nil " disque dur portable 2,5\" 2000 Go")
(3 "Dépense:Maison:Service:Poste" "70,13 €" nil)
diff --git a/test/regress/1127.test b/test/regress/1127.test
new file mode 100644
index 00000000..905401f8
--- /dev/null
+++ b/test/regress/1127.test
@@ -0,0 +1,15 @@
+; Test that automated transactions are added to accounts soon enough
+; for assertions to work.
+
+= expr account =~ /^Assets/
+ (Foo) 1
+
+2018-06-09 Something
+ Assets $100
+ Equity
+
+2018-06-09 Assert amount added by automated transaction
+ [Foo] = $100
+test bal Foo
+ $100 Foo
+end test
diff --git a/test/regress/1132.test b/test/regress/1132.test
new file mode 100644
index 00000000..d912ddcf
--- /dev/null
+++ b/test/regress/1132.test
@@ -0,0 +1,16 @@
+1994/09/02=1994/08/25 * Joe
+ Actif:Courant:BnpCc 126,00 F
+ Actif:Remboursement:Autre -126,00 F = 0,00 F
+
+1994/10/20=1994/08/25 * (3551465) Bill
+ Actif:Remboursement:Autre 126,00 F
+ Actif:Courant:BnpCc
+
+test bal -> 1
+__ERROR__
+While parsing file "$FILE", line 3:
+While parsing posting:
+ Actif:Remboursement:Autre -126,00 F = 0,00 F
+ ^^^^^^
+Error: Balance assertion off by 126,00 F (expected to see -126,00 F)
+end test
diff --git a/test/regress/1147-a.test b/test/regress/1147-a.test
new file mode 100644
index 00000000..e999c312
--- /dev/null
+++ b/test/regress/1147-a.test
@@ -0,0 +1,12 @@
+2000/01/01 Pre-transaction balance
+ A $5.00 = $0.00
+ B
+
+test bal -> 1
+__ERROR__
+While parsing file "$FILE", line 2:
+While parsing posting:
+ A $5.00 = $0.00
+ ^^^^^
+Error: Balance assertion off by $-5.00 (expected to see $5.00)
+end test
diff --git a/test/regress/1147-b.test b/test/regress/1147-b.test
new file mode 100644
index 00000000..d3a1cffc
--- /dev/null
+++ b/test/regress/1147-b.test
@@ -0,0 +1,10 @@
+2000/01/01 Post-transaction balance
+ A $5.00 = $5.00
+ B
+
+test bal
+ $5.00 A
+ $-5.00 B
+--------------------
+ 0
+end test
diff --git a/test/regress/1159.test b/test/regress/1159.test
new file mode 100644
index 00000000..72da771a
--- /dev/null
+++ b/test/regress/1159.test
@@ -0,0 +1,29 @@
+2003/09/13 a payee ; sat
+ A $100.00
+ B
+
+2003/09/14 a payee ; mon
+ A $100.00
+ B
+
+2004/10/15 a payee ; fri
+ A $50.00
+ B
+
+2004/10/19 a payee ; tue
+ A $50.00
+ B
+
+;sun first day of month
+test reg -p "every 12 months from 2001/04/01"
+03-Apr-01 - 04-Mar-31 A $200.00 $200.00
+ B $-200.00 0
+04-Apr-01 - 05-Mar-31 A $100.00 $100.00
+ B $-100.00 0
+end test
+test reg -p 'every 12 months'
+03-Sep-01 - 04-Aug-31 A $200.00 $200.00
+ B $-200.00 0
+04-Sep-01 - 05-Aug-31 A $100.00 $100.00
+ B $-100.00 0
+end test
diff --git a/test/regress/1182_1.test b/test/regress/1182_1.test
new file mode 100644
index 00000000..e9c399e6
--- /dev/null
+++ b/test/regress/1182_1.test
@@ -0,0 +1,12 @@
+=
+2000/01/01 Test
+ A $1.00
+ B
+
+test bal -> 1
+__ERROR__
+While parsing file "$FILE", line 1:
+While parsing automated transaction:
+> =
+Error: Expected predicate after '='
+end test
diff --git a/test/regress/1182_2.test b/test/regress/1182_2.test
new file mode 100644
index 00000000..d3c88dd8
--- /dev/null
+++ b/test/regress/1182_2.test
@@ -0,0 +1,17 @@
+2000/01/01 Test
+ A $1.00
+ B
+
+============
+
+2000/01/02 Test
+ A $1.00
+ B
+
+test bal -> 1
+__ERROR__
+While parsing file "$FILE", line 5:
+While parsing automated transaction:
+> ============
+Error: Expected predicate after '='
+end test
diff --git a/test/regress/1187_1.test b/test/regress/1187_1.test
new file mode 100644
index 00000000..484146ce
--- /dev/null
+++ b/test/regress/1187_1.test
@@ -0,0 +1,19 @@
+2006/08/17 * Au Bon Bec
+ Dépense:Alimentation:Restaurant 100,00 €
+ Passif:Crédit:Banque
+
+2006/08/20 * Retrait
+ Dépense:Liquide 60,00 €
+ Passif:Crédit:Banque -60,00 €
+ Passif:Crédit:Banque 60,00 € = -100,00 €
+ Actif:Courant:Cc -60,00 €
+
+test bal
+ -60,00 € Actif:Courant:Cc
+ 160,00 € Dépense
+ 100,00 € Alimentation:Restaurant
+ 60,00 € Liquide
+ -100,00 € Passif:Crédit:Banque
+--------------------
+ 0
+end test
diff --git a/test/regress/1187_2.test b/test/regress/1187_2.test
new file mode 100644
index 00000000..432a40f2
--- /dev/null
+++ b/test/regress/1187_2.test
@@ -0,0 +1,18 @@
+2001/01/01 * Balance
+ Actif:Courant:Cc 10000,00 F = 10000,00 F
+ Equity
+
+2002/01/11 * Passage à l'euro
+ Actif:Courant:Cc -10000,00 F = 0,00 F
+ Actif:Courant:Cc 1524,49 € = 1524,49 €
+ Revenu:Devise 10000,00 F
+ Revenu:Devise -1524,49 €
+
+test bal
+ 1524,49 € Actif:Courant:Cc
+ -10000,00 F Equity
+ 10000,00 F
+ -1524,49 € Revenu:Devise
+--------------------
+ 0
+end test
diff --git a/test/regress/1187_3.test b/test/regress/1187_3.test
new file mode 100644
index 00000000..2c6d7452
--- /dev/null
+++ b/test/regress/1187_3.test
@@ -0,0 +1,36 @@
+2000/01/01 Multiple posts
+ A $5.00
+ B $7.20
+ C $-114.99
+ D
+
+2000/01/02 Many assertions
+ A $2.00
+ A $3.00 = $10.00
+ B $0.80 = $8.00
+ C $-0.01 = $-115.00
+ B $1.00
+ C $1
+ C $4 = $-110
+ D
+
+2000/01/03 Incremental
+ A $1.00 = $11.00
+ A $1.00 = $12.00
+ A $1.00 = $13.00
+ D
+
+2000/01/04 Assignment
+ A $2
+ A = $25
+ D $-10
+ D $-2
+
+test bal
+ $25.00 A
+ $9.00 B
+ $-110.00 C
+ $76.00 D
+--------------------
+ 0
+end test
diff --git a/test/regress/1187_4.test b/test/regress/1187_4.test
new file mode 100644
index 00000000..4804d5c6
--- /dev/null
+++ b/test/regress/1187_4.test
@@ -0,0 +1,32 @@
+2000/01/01 Multiple commodities
+ A $5.00
+ A 32 F
+ B $-12
+ C
+
+2000/01/02 Assertions
+ A $1 = $6
+ A 1 F = 33 F
+ A $1 = $7
+ A 1 F = 34 F
+ B 3 F = 3 F
+ B $12 = $0
+ B 1 F = 4 F
+ C
+
+2000/01/03 Assignments
+ A = $0
+ A -4 F = 30 F
+ B $-7 = $-7
+ B = 0 F
+ C $14
+ C 8 F
+
+test bal
+ 30 F A
+ $-7.00 B
+ $7.00
+ -30 F C
+--------------------
+ 0
+end test
diff --git a/test/regress/1187_5.test b/test/regress/1187_5.test
new file mode 100644
index 00000000..4aa5fdd8
--- /dev/null
+++ b/test/regress/1187_5.test
@@ -0,0 +1,36 @@
+2013/12/01 * Initial State
+ Crédit:Viseca:MasterCard P1 -618.50 CHF
+ Crédit:Viseca:MasterCard P2 -52.10 CHF
+ Equity:Opening Balances
+
+2013/12/15 * Buy Some Chocolate
+ Dépenses:Nourriture 19.00 EUR ; #1
+ Crédit:Viseca:MasterCard P1
+
+2013/12/15 * Buy Some Chocolate
+ Crédit:Viseca:MasterCard P1 18.00 EUR ; #2
+ Recettes:Erreurs
+
+2013/12/23 * Facture Viseca
+ Crédit:Viseca:MasterCard P2 52.10 CHF = 0 ; #3
+ Crédit:Viseca:MasterCard P1 618.50 CHF = 0 CHF ; #4
+ Dépenses:Frais:Gestion Comptes 1.50 CHF
+ Crédit:Viseca -672.10 CHF
+
+2014/01/03 * Facture Viseca
+ Crédit:Viseca 672.10 CHF = 0
+ Actif:Comptes:CP courant
+
+test bal
+ -672.10 CHF Actif:Comptes:CP courant
+ -1.00 EUR Crédit:Viseca
+ -1.00 EUR MasterCard P1
+ 1.50 CHF
+ 19.00 EUR Dépenses
+ 1.50 CHF Frais:Gestion Comptes
+ 19.00 EUR Nourriture
+ 670.60 CHF Equity:Opening Balances
+ -18.00 EUR Recettes:Erreurs
+--------------------
+ 0
+end test
diff --git a/test/regress/1626.test b/test/regress/1626.test
new file mode 100644
index 00000000..89ae80f8
--- /dev/null
+++ b/test/regress/1626.test
@@ -0,0 +1,28 @@
+test period every 1000 years from 1 Sep 2011 to 30 May 2012 --now=2018-06-10
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 1000
+TOK_YEARS: years
+TOK_SINCE: since
+TOK_INT: 1
+TOK_A_MONTH: Sep
+TOK_INT: 2011
+TOK_UNTIL: until
+TOK_INT: 30
+TOK_A_MONTH: May
+TOK_INT: 2012
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from day 1 to day 30
+duration: 1000 years
+
+--- After stabilization ---
+ range: from day 1 to day 30
+ start: 18-Jan-01
+ finish: 18-Jan-30
+duration: 1000 years
+
+--- Sample dates in range (max. 20) ---
+ 1: 18-Jan-01 -- 18-Jan-29
+end test
diff --git a/test/regress/370-budget_period_days.test b/test/regress/370-budget_period_days.test
new file mode 100644
index 00000000..459c5071
--- /dev/null
+++ b/test/regress/370-budget_period_days.test
@@ -0,0 +1,27 @@
+;budgets care about start dates
+~ every 14 days from 2010/02/23
+ Expenses:Bills:Housecleaning $85.00
+ Assets:Bank:Checking
+
+;before Sun aug 01 2010
+;now is Mon jun 21 2010
+;a Tuesday?
+;
+test reg --budget --now=2010/06/13
+10-Feb-23 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Feb-23 Budget transaction Assets:Bank:Checking $85.00 0
+10-Mar-09 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Mar-09 Budget transaction Assets:Bank:Checking $85.00 0
+10-Mar-23 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Mar-23 Budget transaction Assets:Bank:Checking $85.00 0
+10-Apr-06 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Apr-06 Budget transaction Assets:Bank:Checking $85.00 0
+10-Apr-20 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Apr-20 Budget transaction Assets:Bank:Checking $85.00 0
+10-May-04 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-May-04 Budget transaction Assets:Bank:Checking $85.00 0
+10-May-18 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-May-18 Budget transaction Assets:Bank:Checking $85.00 0
+10-Jun-01 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Jun-01 Budget transaction Assets:Bank:Checking $85.00 0
+end test
diff --git a/test/regress/370-budget_period_weeks.test b/test/regress/370-budget_period_weeks.test
new file mode 100644
index 00000000..8d4801a6
--- /dev/null
+++ b/test/regress/370-budget_period_weeks.test
@@ -0,0 +1,29 @@
+;budgets care about start dates
+~ every 2 weeks from 2010/02/23
+ Expenses:Bills:Housecleaning $85.00
+ Assets:Bank:Checking
+
+;before Sun aug 01 2010
+;now is Mon jun 21 2010
+;a Tuesday?
+;
+test reg --budget --now=2010/06/13
+10-Feb-23 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Feb-23 Budget transaction Assets:Bank:Checking $85.00 0
+10-Feb-28 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Feb-28 Budget transaction Assets:Bank:Checking $85.00 0
+10-Mar-14 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Mar-14 Budget transaction Assets:Bank:Checking $85.00 0
+10-Mar-28 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Mar-28 Budget transaction Assets:Bank:Checking $85.00 0
+10-Apr-11 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Apr-11 Budget transaction Assets:Bank:Checking $85.00 0
+10-Apr-25 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Apr-25 Budget transaction Assets:Bank:Checking $85.00 0
+10-May-09 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-May-09 Budget transaction Assets:Bank:Checking $85.00 0
+10-May-23 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-May-23 Budget transaction Assets:Bank:Checking $85.00 0
+10-Jun-06 Budget transaction Ex:Bills:Housecleaning $-85.00 $-85.00
+10-Jun-06 Budget transaction Assets:Bank:Checking $85.00 0
+end test
diff --git a/test/regress/370-forecast_period_days.test b/test/regress/370-forecast_period_days.test
new file mode 100644
index 00000000..faf9d47b
--- /dev/null
+++ b/test/regress/370-forecast_period_days.test
@@ -0,0 +1,17 @@
+;does not care about start date
+~ every 14 days from 2010/02/23
+ Expenses:Bills:Housecleaning $85.00
+ Assets:Bank:Checking
+
+;before Sun aug 01 2010
+;now is Mon jun 21 2010
+;a Tuesday?
+;forecasts period start is now first forecast transaction is now + 1 'tomorrow'
+test reg --forecast 'date <[2010/08/01]' --now=2010/06/13
+10-Jun-27 Forecast transaction Ex:Bills:Housecleaning $85.00 $85.00
+10-Jun-27 Forecast transaction Assets:Bank:Checking $-85.00 0
+10-Jul-11 Forecast transaction Ex:Bills:Housecleaning $85.00 $85.00
+10-Jul-11 Forecast transaction Assets:Bank:Checking $-85.00 0
+10-Jul-25 Forecast transaction Ex:Bills:Housecleaning $85.00 $85.00
+10-Jul-25 Forecast transaction Assets:Bank:Checking $-85.00 0
+end test
diff --git a/test/regress/370-forecast_period_weeks.test b/test/regress/370-forecast_period_weeks.test
new file mode 100644
index 00000000..3927a48d
--- /dev/null
+++ b/test/regress/370-forecast_period_weeks.test
@@ -0,0 +1,16 @@
+;Tuesday
+~ every 2 weeks from 2010/02/23
+ Expenses:Bills:Housecleaning $85.00
+ Assets:Bank:Checking
+
+;before Sun aug 01 2010
+;now is Mon jun 21 2010
+;a Sunday
+test reg --forecast 'date <[2010/08/01]' --now=2010/06/21
+10-Jun-27 Forecast transaction Ex:Bills:Housecleaning $85.00 $85.00
+10-Jun-27 Forecast transaction Assets:Bank:Checking $-85.00 0
+10-Jul-11 Forecast transaction Ex:Bills:Housecleaning $85.00 $85.00
+10-Jul-11 Forecast transaction Assets:Bank:Checking $-85.00 0
+10-Jul-25 Forecast transaction Ex:Bills:Housecleaning $85.00 $85.00
+10-Jul-25 Forecast transaction Assets:Bank:Checking $-85.00 0
+end test
diff --git a/test/regress/370-period.test b/test/regress/370-period.test
new file mode 100644
index 00000000..81275da6
--- /dev/null
+++ b/test/regress/370-period.test
@@ -0,0 +1,443 @@
+;period days should not be alligned
+
+test period 'every 14 days from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 14
+TOK_DAYS: days
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 14 days
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 14 days
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Oct-16
+ 2: 11-Oct-17 -- 11-Oct-30
+ 3: 11-Oct-31 -- 11-Nov-13
+ 4: 11-Nov-14 -- 11-Nov-27
+ 5: 11-Nov-28 -- 11-Dec-11
+ 6: 11-Dec-12 -- 11-Dec-25
+ 7: 11-Dec-26 -- 12-Jan-08
+ 8: 12-Jan-09 -- 12-Jan-22
+ 9: 12-Jan-23 -- 12-Feb-05
+10: 12-Feb-06 -- 12-Feb-19
+11: 12-Feb-20 -- 12-Mar-04
+12: 12-Mar-05 -- 12-Mar-18
+13: 12-Mar-19 -- 12-Apr-01
+14: 12-Apr-02 -- 12-Apr-15
+15: 12-Apr-16 -- 12-Apr-29
+16: 12-Apr-30 -- 12-May-13
+17: 12-May-14 -- 12-May-27
+18: 12-May-28 -- 12-Jun-10
+19: 12-Jun-11 -- 12-Jun-24
+20: 12-Jun-25 -- 12-Jul-08
+end test
+;ensure weeks behave as before
+test period 'every 1 weeks from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 1
+TOK_WEEKS: weeks
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 1 week
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 1 week
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Oct-08
+ 2: 11-Oct-09 -- 11-Oct-15
+ 3: 11-Oct-16 -- 11-Oct-22
+ 4: 11-Oct-23 -- 11-Oct-29
+ 5: 11-Oct-30 -- 11-Nov-05
+ 6: 11-Nov-06 -- 11-Nov-12
+ 7: 11-Nov-13 -- 11-Nov-19
+ 8: 11-Nov-20 -- 11-Nov-26
+ 9: 11-Nov-27 -- 11-Dec-03
+10: 11-Dec-04 -- 11-Dec-10
+11: 11-Dec-11 -- 11-Dec-17
+12: 11-Dec-18 -- 11-Dec-24
+13: 11-Dec-25 -- 11-Dec-31
+14: 12-Jan-01 -- 12-Jan-07
+15: 12-Jan-08 -- 12-Jan-14
+16: 12-Jan-15 -- 12-Jan-21
+17: 12-Jan-22 -- 12-Jan-28
+18: 12-Jan-29 -- 12-Feb-04
+19: 12-Feb-05 -- 12-Feb-11
+20: 12-Feb-12 -- 12-Feb-18
+end test
+test period 'every 2 weeks from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 2
+TOK_WEEKS: weeks
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 2 weeks
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 2 weeks
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Oct-08
+ 2: 11-Oct-09 -- 11-Oct-22
+ 3: 11-Oct-23 -- 11-Nov-05
+ 4: 11-Nov-06 -- 11-Nov-19
+ 5: 11-Nov-20 -- 11-Dec-03
+ 6: 11-Dec-04 -- 11-Dec-17
+ 7: 11-Dec-18 -- 11-Dec-31
+ 8: 12-Jan-01 -- 12-Jan-14
+ 9: 12-Jan-15 -- 12-Jan-28
+10: 12-Jan-29 -- 12-Feb-11
+11: 12-Feb-12 -- 12-Feb-25
+12: 12-Feb-26 -- 12-Mar-10
+13: 12-Mar-11 -- 12-Mar-24
+14: 12-Mar-25 -- 12-Apr-07
+15: 12-Apr-08 -- 12-Apr-21
+16: 12-Apr-22 -- 12-May-05
+17: 12-May-06 -- 12-May-19
+18: 12-May-20 -- 12-Jun-02
+19: 12-Jun-03 -- 12-Jun-16
+20: 12-Jun-17 -- 12-Jun-30
+end test
+test period 'every 3 weeks from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 3
+TOK_WEEKS: weeks
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 3 weeks
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 3 weeks
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Oct-22
+ 2: 11-Oct-23 -- 11-Nov-12
+ 3: 11-Nov-13 -- 11-Dec-03
+ 4: 11-Dec-04 -- 11-Dec-24
+ 5: 11-Dec-25 -- 12-Jan-14
+ 6: 12-Jan-15 -- 12-Feb-04
+ 7: 12-Feb-05 -- 12-Feb-25
+ 8: 12-Feb-26 -- 12-Mar-17
+ 9: 12-Mar-18 -- 12-Apr-07
+10: 12-Apr-08 -- 12-Apr-28
+11: 12-Apr-29 -- 12-May-19
+12: 12-May-20 -- 12-Jun-09
+13: 12-Jun-10 -- 12-Jun-30
+14: 12-Jul-01 -- 12-Jul-21
+15: 12-Jul-22 -- 12-Aug-11
+16: 12-Aug-12 -- 12-Sep-01
+17: 12-Sep-02 -- 12-Sep-22
+18: 12-Sep-23 -- 12-Oct-13
+19: 12-Oct-14 -- 12-Nov-03
+20: 12-Nov-04 -- 12-Nov-24
+end test
+test period 'every 4 weeks from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 4
+TOK_WEEKS: weeks
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 4 weeks
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 4 weeks
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Oct-22
+ 2: 11-Oct-23 -- 11-Nov-19
+ 3: 11-Nov-20 -- 11-Dec-17
+ 4: 11-Dec-18 -- 12-Jan-14
+ 5: 12-Jan-15 -- 12-Feb-11
+ 6: 12-Feb-12 -- 12-Mar-10
+ 7: 12-Mar-11 -- 12-Apr-07
+ 8: 12-Apr-08 -- 12-May-05
+ 9: 12-May-06 -- 12-Jun-02
+10: 12-Jun-03 -- 12-Jun-30
+11: 12-Jul-01 -- 12-Jul-28
+12: 12-Jul-29 -- 12-Aug-25
+13: 12-Aug-26 -- 12-Sep-22
+14: 12-Sep-23 -- 12-Oct-20
+15: 12-Oct-21 -- 12-Nov-17
+16: 12-Nov-18 -- 12-Dec-15
+17: 12-Dec-16 -- 13-Jan-12
+18: 13-Jan-13 -- 13-Feb-09
+19: 13-Feb-10 -- 13-Mar-09
+20: 13-Mar-10 -- 13-Apr-06
+end test
+test period 'every 5 weeks from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 5
+TOK_WEEKS: weeks
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 5 weeks
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 5 weeks
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Oct-22
+ 2: 11-Oct-23 -- 11-Nov-26
+ 3: 11-Nov-27 -- 11-Dec-31
+ 4: 12-Jan-01 -- 12-Feb-04
+ 5: 12-Feb-05 -- 12-Mar-10
+ 6: 12-Mar-11 -- 12-Apr-14
+ 7: 12-Apr-15 -- 12-May-19
+ 8: 12-May-20 -- 12-Jun-23
+ 9: 12-Jun-24 -- 12-Jul-28
+10: 12-Jul-29 -- 12-Sep-01
+11: 12-Sep-02 -- 12-Oct-06
+12: 12-Oct-07 -- 12-Nov-10
+13: 12-Nov-11 -- 12-Dec-15
+14: 12-Dec-16 -- 13-Jan-19
+15: 13-Jan-20 -- 13-Feb-23
+16: 13-Feb-24 -- 13-Mar-30
+17: 13-Mar-31 -- 13-May-04
+18: 13-May-05 -- 13-Jun-08
+19: 13-Jun-09 -- 13-Jul-13
+20: 13-Jul-14 -- 13-Aug-17
+end test
+test period 'every 6 weeks from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 6
+TOK_WEEKS: weeks
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 6 weeks
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 6 weeks
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Oct-22
+ 2: 11-Oct-23 -- 11-Dec-03
+ 3: 11-Dec-04 -- 12-Jan-14
+ 4: 12-Jan-15 -- 12-Feb-25
+ 5: 12-Feb-26 -- 12-Apr-07
+ 6: 12-Apr-08 -- 12-May-19
+ 7: 12-May-20 -- 12-Jun-30
+ 8: 12-Jul-01 -- 12-Aug-11
+ 9: 12-Aug-12 -- 12-Sep-22
+10: 12-Sep-23 -- 12-Nov-03
+11: 12-Nov-04 -- 12-Dec-15
+12: 12-Dec-16 -- 13-Jan-26
+13: 13-Jan-27 -- 13-Mar-09
+14: 13-Mar-10 -- 13-Apr-20
+15: 13-Apr-21 -- 13-Jun-01
+16: 13-Jun-02 -- 13-Jul-13
+17: 13-Jul-14 -- 13-Aug-24
+18: 13-Aug-25 -- 13-Oct-05
+19: 13-Oct-06 -- 13-Nov-16
+20: 13-Nov-17 -- 13-Dec-28
+end test
+test period 'every 7 weeks from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 7
+TOK_WEEKS: weeks
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 7 weeks
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 7 weeks
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Nov-12
+ 2: 11-Nov-13 -- 11-Dec-31
+ 3: 12-Jan-01 -- 12-Feb-18
+ 4: 12-Feb-19 -- 12-Apr-07
+ 5: 12-Apr-08 -- 12-May-26
+ 6: 12-May-27 -- 12-Jul-14
+ 7: 12-Jul-15 -- 12-Sep-01
+ 8: 12-Sep-02 -- 12-Oct-20
+ 9: 12-Oct-21 -- 12-Dec-08
+10: 12-Dec-09 -- 13-Jan-26
+11: 13-Jan-27 -- 13-Mar-16
+12: 13-Mar-17 -- 13-May-04
+13: 13-May-05 -- 13-Jun-22
+14: 13-Jun-23 -- 13-Aug-10
+15: 13-Aug-11 -- 13-Sep-28
+16: 13-Sep-29 -- 13-Nov-16
+17: 13-Nov-17 -- 14-Jan-04
+18: 14-Jan-05 -- 14-Feb-22
+19: 14-Feb-23 -- 14-Apr-12
+20: 14-Apr-13 -- 14-May-31
+end test
+test period 'every 8 weeks from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 8
+TOK_WEEKS: weeks
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 8 weeks
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 8 weeks
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Nov-19
+ 2: 11-Nov-20 -- 12-Jan-14
+ 3: 12-Jan-15 -- 12-Mar-10
+ 4: 12-Mar-11 -- 12-May-05
+ 5: 12-May-06 -- 12-Jun-30
+ 6: 12-Jul-01 -- 12-Aug-25
+ 7: 12-Aug-26 -- 12-Oct-20
+ 8: 12-Oct-21 -- 12-Dec-15
+ 9: 12-Dec-16 -- 13-Feb-09
+10: 13-Feb-10 -- 13-Apr-06
+11: 13-Apr-07 -- 13-Jun-01
+12: 13-Jun-02 -- 13-Jul-27
+13: 13-Jul-28 -- 13-Sep-21
+14: 13-Sep-22 -- 13-Nov-16
+15: 13-Nov-17 -- 14-Jan-11
+16: 14-Jan-12 -- 14-Mar-08
+17: 14-Mar-09 -- 14-May-03
+18: 14-May-04 -- 14-Jun-28
+19: 14-Jun-29 -- 14-Aug-23
+20: 14-Aug-24 -- 14-Oct-18
+end test
+test period 'every 9 weeks from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 9
+TOK_WEEKS: weeks
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 9 weeks
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 9 weeks
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Nov-12
+ 2: 11-Nov-13 -- 12-Jan-14
+ 3: 12-Jan-15 -- 12-Mar-17
+ 4: 12-Mar-18 -- 12-May-19
+ 5: 12-May-20 -- 12-Jul-21
+ 6: 12-Jul-22 -- 12-Sep-22
+ 7: 12-Sep-23 -- 12-Nov-24
+ 8: 12-Nov-25 -- 13-Jan-26
+ 9: 13-Jan-27 -- 13-Mar-30
+10: 13-Mar-31 -- 13-Jun-01
+11: 13-Jun-02 -- 13-Aug-03
+12: 13-Aug-04 -- 13-Oct-05
+13: 13-Oct-06 -- 13-Dec-07
+14: 13-Dec-08 -- 14-Feb-08
+15: 14-Feb-09 -- 14-Apr-12
+16: 14-Apr-13 -- 14-Jun-14
+17: 14-Jun-15 -- 14-Aug-16
+18: 14-Aug-17 -- 14-Oct-18
+19: 14-Oct-19 -- 14-Dec-20
+20: 14-Dec-21 -- 15-Feb-21
+end test
+test period 'every 10 weeks from 2011/10/03'
+--- Period expression tokens ---
+TOK_EVERY: every
+TOK_INT: 10
+TOK_WEEKS: weeks
+TOK_SINCE: since
+TOK_DATE: year 2011 month Oct day 3
+END_REACHED: <EOF>
+
+--- Before stabilization ---
+ range: from year 2011 month Oct day 3
+duration: 10 weeks
+
+--- After stabilization ---
+ range: from year 2011 month Oct day 3
+ start: 11-Oct-03
+duration: 10 weeks
+
+--- Sample dates in range (max. 20) ---
+ 1: 11-Oct-03 -- 11-Oct-22
+ 2: 11-Oct-23 -- 11-Dec-31
+ 3: 12-Jan-01 -- 12-Mar-10
+ 4: 12-Mar-11 -- 12-May-19
+ 5: 12-May-20 -- 12-Jul-28
+ 6: 12-Jul-29 -- 12-Oct-06
+ 7: 12-Oct-07 -- 12-Dec-15
+ 8: 12-Dec-16 -- 13-Feb-23
+ 9: 13-Feb-24 -- 13-May-04
+10: 13-May-05 -- 13-Jul-13
+11: 13-Jul-14 -- 13-Sep-21
+12: 13-Sep-22 -- 13-Nov-30
+13: 13-Dec-01 -- 14-Feb-08
+14: 14-Feb-09 -- 14-Apr-19
+15: 14-Apr-20 -- 14-Jun-28
+16: 14-Jun-29 -- 14-Sep-06
+17: 14-Sep-07 -- 14-Nov-15
+18: 14-Nov-16 -- 15-Jan-24
+19: 15-Jan-25 -- 15-Apr-04
+20: 15-Apr-05 -- 15-Jun-13
+end test
diff --git a/test/regress/383.test b/test/regress/383.test
index ab4372fd..019c91eb 100644
--- a/test/regress/383.test
+++ b/test/regress/383.test
@@ -23,7 +23,7 @@ test bal Assets:Investments --lots --date-format %Y-%m-%d
100 AA {2.00 GBP} [2014-01-01] Assets:Investments
end test
-test bal Assets:Investments --lots --date-format %g-%b-%d
+test bal Assets:Investments --lots --date-format %y-%b-%d
100 AA {2.00 GBP} [14-Jan-01] Assets:Investments
end test
diff --git a/test/input/spaces.dat b/test/regress/550-584.test
index 1ada1b61..1c3be3b8 100644
--- a/test/input/spaces.dat
+++ b/test/regress/550-584.test
@@ -53,3 +53,21 @@
; COM commodity has three spaces after
Expenses:misc 1 COM
Assets:checking
+
+test payees
+test
+testcommodity
+end test
+
+test reg --group-by "tag('test')"
+spaces
+11-Nov-28 test Expenses:misc $1 $1
+11-Nov-28 test Expenses:misc $2 $3
+11-Nov-28 test Expenses:misc $4 $7
+11-Nov-28 test Expenses:misc $8 $15
+end test
+
+test commodities
+$
+COM
+end test
diff --git a/test/regress/727B2DF8.test b/test/regress/727B2DF8.test
index 0c32d660..ad2b903f 100644
--- a/test/regress/727B2DF8.test
+++ b/test/regress/727B2DF8.test
@@ -43,7 +43,7 @@ N $
Assets:Bank:Checking
; :AnotherTag:
-test reg --color --force-color
+test reg --force-color
04-May-01 Checking balance Assets:Bank:Checking  $1,000.00 $1,000.00
Equit:Opening Balances $-1,000.00 0
04-May-03 Investment balance Assets:Brokerage  50 AAPL 50 AAPL
diff --git a/test/regress/7F3650FD.test b/test/regress/7F3650FD.test
index f0498ddb..0ccfe644 100644
--- a/test/regress/7F3650FD.test
+++ b/test/regress/7F3650FD.test
@@ -68,7 +68,7 @@ end test
test period --now=2010/11/01 2009
--- Period expression tokens ---
-TOK_A_YEAR: 2009
+TOK_INT: 2009
END_REACHED: <EOF>
--- Before stabilization ---
diff --git a/test/regress/981.test b/test/regress/981.test
new file mode 100644
index 00000000..2338b82a
--- /dev/null
+++ b/test/regress/981.test
@@ -0,0 +1,29 @@
+
+; Test a regex longer than 255 char
+
+tag Project
+ check value =~ /^(0ad|ankur|aptosid|archlinux|chakra|debian|debconf14|debconf15|debconf16|drizzle|ffmpeg|ffmpeg|fluxbox|freedesktop|freedombox|gallery|texmacs|haskell|jenkins|libreoffice|madwifi|mingw|openvas|openwrt|openbioinformatics|openembedded|openvoting|osunix|path64|plan9|postgresql|privoxy|smc|helios|tidesdk|tux4kids|yafaray|spi)$/
+
+2016-01-01 * Test - correct tag
+ Expenses:Hosting 20.00 USD
+ ; Project: debian
+ Assets:Cash -20.00 USD
+
+2016-02-01 * Test - wrong tag
+ Expenses:Hosting 20.00 USD
+ ; Project: foo
+ Assets:Cash -20.00 USD
+
+test bal
+ -40.00 USD Assets:Cash
+ 40.00 USD Expenses:Hosting
+--------------------
+ 0
+__ERROR__
+Warning: "$FILE", line 15: Metadata check failed for (Project: foo): (value =~ /^(0ad|ankur|aptosid|archlinux|chakra|debian|debconf14|debconf15|debconf16|drizzle|ffmpeg|ffmpeg|fluxbox|freedesktop|freedombox|gallery|texmacs|haskell|jenkins|libreoffice|madwifi|mingw|openvas|openwrt|openbioinformatics|openembedded|openvoting|osunix|path64|plan9|postgresql|privoxy|smc|helios|tidesdk|tux4kids|yafaray|spi)$/)
+end test
+
+test reg --limit 'payee =~ /XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/'
+__ERROR__
+Warning: "$FILE", line 15: Metadata check failed for (Project: foo): (value =~ /^(0ad|ankur|aptosid|archlinux|chakra|debian|debconf14|debconf15|debconf16|drizzle|ffmpeg|ffmpeg|fluxbox|freedesktop|freedombox|gallery|texmacs|haskell|jenkins|libreoffice|madwifi|mingw|openvas|openwrt|openbioinformatics|openembedded|openvoting|osunix|path64|plan9|postgresql|privoxy|smc|helios|tidesdk|tux4kids|yafaray|spi)$/)
+end test
diff --git a/test/regress/B21BF389.py b/test/regress/B21BF389.py
new file mode 100644
index 00000000..707ce340
--- /dev/null
+++ b/test/regress/B21BF389.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import print_function, unicode_literals
+
+import ledger
+
+for post in ledger.read_journal(__file__.replace(".py", "_py.test")).query("income"):
+ print(unicode(post.tag("Reference")))
diff --git a/test/regress/B21BF389_py.test b/test/regress/B21BF389_py.test
new file mode 100644
index 00000000..c0a2166a
--- /dev/null
+++ b/test/regress/B21BF389_py.test
@@ -0,0 +1,8 @@
+2016/01/11 * Employer
+ Assets:Checking
+ Income:Salary € 1.500,00
+ ; Reference: Christmas bonus
+
+test python test/regress/B21BF389.py
+Christmas bonus
+end test
diff --git a/test/regress/BBFA1759.test b/test/regress/BBFA1759.test
index 7a402d0c..5df7ecb2 100644
--- a/test/regress/BBFA1759.test
+++ b/test/regress/BBFA1759.test
@@ -2,7 +2,7 @@
test period june 2008
--- Period expression tokens ---
TOK_A_MONTH: Jun
-TOK_A_YEAR: 2008
+TOK_INT: 2008
END_REACHED: <EOF>
--- Before stabilization ---
diff --git a/test/regress/GH520.test b/test/regress/GH520.test
new file mode 100644
index 00000000..54dd2299
--- /dev/null
+++ b/test/regress/GH520.test
@@ -0,0 +1,33 @@
+2009-01-01 * Jan 09
+ A 100.00 EUR
+ B
+
+test reg --format '%(trim(""))\n'
+
+
+end test
+
+test reg --format '%(trim("a"))\n'
+a
+a
+end test
+
+test reg --format '%(trim(" a"))\n'
+a
+a
+end test
+
+test reg --format '%(trim("a "))\n'
+a
+a
+end test
+
+test reg --format '%(trim(" a "))\n'
+a
+a
+end test
+
+test reg --format '%(trim(" aa "))\n'
+aa
+aa
+end test
diff --git a/test/regress/fix-missing-trans-in-last-budget-period.test b/test/regress/fix-missing-trans-in-last-budget-period.test
new file mode 100644
index 00000000..163a0540
--- /dev/null
+++ b/test/regress/fix-missing-trans-in-last-budget-period.test
@@ -0,0 +1,79 @@
+= ~ ^A
+ [Balance] 1
+ [Budget:$account] -1
+
+~ Monthly from 2014/01 to 2014/12/31
+ [Budget:A] 100.00 USD
+ [Balance]
+
+~ Monthly from 2014/01 to 2014/12/31
+ [Budget:Z] 100.00 USD
+ [Balance]
+
+2014/10/01 toto0
+ [Budget:A:B] 0.01 USD
+ [Balance]
+
+2014/11/01 toto1
+ A:B 51.00 USD
+ Cash
+
+2014/11/02 toto2
+ A:B 52.00 USD
+ Cash
+
+2014/11/03 toto3
+ A:B 53.00 USD
+ Cash
+
+2014/11/04 toto4
+ A:B 54.00 USD
+ Cash
+
+2014/12/08 toto5
+ A:B 55.00 USD
+ Cash
+
+2014/12/09 toto6
+ A:B 56.00 USD
+ Cash
+
+2014/12/10 toto7
+ A:B 57.00 USD
+ Cash
+
+2014/12/11 toto8
+ A:B 58.00 USD
+ Cash
+
+2014/12/12 toto9
+ A:B 59.00 USD
+ Cash
+
+2014/12/12 toto9
+ C 59.00 USD
+ Cash
+
+2015/01/12 toto10
+ A:B 59.00 USD
+ Cash
+
+test reg --budget -b 2014/10 -e 2015/02 --columns 80 --date-format "%F" reg ^Bu
+2014-10-01 Budget transaction [Budget:A] -100.00 USD -100.00 USD
+2014-10-01 Budget transaction [Budget:Z] -100.00 USD -200.00 USD
+2014-10-01 toto0 [Budget:A] 0.01 USD -199.99 USD
+2014-11-01 Budget transaction [Budget:A] -100.00 USD -299.99 USD
+2014-11-01 Budget transaction [Budget:Z] -100.00 USD -399.99 USD
+2014-11-01 toto1 [Budget:A] -51.00 USD -450.99 USD
+2014-11-02 toto2 [Budget:A] -52.00 USD -502.99 USD
+2014-11-03 toto3 [Budget:A] -53.00 USD -555.99 USD
+2014-11-04 toto4 [Budget:A] -54.00 USD -609.99 USD
+2014-12-01 Budget transaction [Budget:A] -100.00 USD -709.99 USD
+2014-12-01 Budget transaction [Budget:Z] -100.00 USD -809.99 USD
+2014-12-08 toto5 [Budget:A] -55.00 USD -864.99 USD
+2014-12-09 toto6 [Budget:A] -56.00 USD -920.99 USD
+2014-12-10 toto7 [Budget:A] -57.00 USD -977.99 USD
+2014-12-11 toto8 [Budget:A] -58.00 USD -1035.99 USD
+2014-12-12 toto9 [Budget:A] -59.00 USD -1094.99 USD
+2015-01-12 toto10 [Budget:A] -59.00 USD -1153.99 USD
+end test
diff --git a/test/regress/market-group-by.test b/test/regress/market-group-by.test
new file mode 100644
index 00000000..a0d204aa
--- /dev/null
+++ b/test/regress/market-group-by.test
@@ -0,0 +1,26 @@
+D 1000.00 EUR
+
+2008/04/15 * Paid expenses back from cie.
+ Expenses:Cie-Reimbursements 2000 CAD @ 1.10 EUR
+ Assets:Checking
+
+2008/04/15 * Paid expenses back from cie.
+ Expenses:Cie-Reimbursements 2000 USD @ 1.10 EUR
+ Assets:Checking
+
+P 2008/04/20 00:00:00 CAD 1.20 EUR
+P 2008/04/20 00:00:00 USD 1.20 EUR
+
+test reg -V --group-by commodity
+CAD
+08-Apr-15 Paid expenses back .. Exp:Cie-Reimbursements 2200.00 EUR 2200.00 EUR
+08-Apr-20 Commodities revalued <Revalued> 200.00 EUR 2400.00 EUR
+
+EUR
+08-Apr-15 Paid expenses back .. Assets:Checking -2200.00 EUR -2200.00 EUR
+08-Apr-15 Paid expenses back .. Assets:Checking -2200.00 EUR -4400.00 EUR
+
+USD
+08-Apr-15 Paid expenses back .. Exp:Cie-Reimbursements 2200.00 EUR 2200.00 EUR
+08-Apr-20 Commodities revalued <Revalued> 200.00 EUR 2400.00 EUR
+end test
diff --git a/test/regress/total-1.test b/test/regress/total-1.test
new file mode 100644
index 00000000..51448dd2
--- /dev/null
+++ b/test/regress/total-1.test
@@ -0,0 +1,28 @@
+; Test that calling total does not affect future calls to that function via a
+; stale cache entry for the totalled account, because of a change to that same
+; account
+
+2017-10-01 * Opening Balance
+ Assets:Current Account $1000.00
+ Equity:Opening Balances
+
+2017-10-02 * Savings
+ Assets:Savings $100.00
+ Assets:Current Account
+
+assert account("Assets:Current Account").total == $900.00
+
+2017-10-03 * Savings
+ Assets:Savings $100.00
+ Assets:Current Account
+
+assert account("Assets:Current Account").total == $800.00
+
+test bal
+ $1000.00 Assets
+ $800.00 Current Account
+ $200.00 Savings
+ $-1000.00 Equity:Opening Balances
+--------------------
+ 0
+end test
diff --git a/test/regress/total-2.test b/test/regress/total-2.test
new file mode 100644
index 00000000..2b15650f
--- /dev/null
+++ b/test/regress/total-2.test
@@ -0,0 +1,30 @@
+; Test that calling total does not affect future calls to that function via a
+; stale cache entry for the totalled account, because of a change to an
+; descendant (Assets:Current:Unallocated) of that account (Assets:Current)
+
+2017-10-01 * Opening entry
+ Assets:Current:Unallocated $2000.00
+ Equity:Opening Balances
+
+2017-10-02 * Initial savings
+ Assets:Current:Savings $1000.00
+ Assets:Current:Unallocated
+
+assert account("Assets:Current").total == $2000.00
+
+2017-10-03 * Balance
+ Assets:Current:Unallocated $1.00
+ Equity:Adjustments
+
+assert account("Assets:Current").total == $2001.00
+
+test bal
+ $2001.00 Assets:Current
+ $1000.00 Savings
+ $1001.00 Unallocated
+ $-2001.00 Equity
+ $-1.00 Adjustments
+ $-2000.00 Opening Balances
+--------------------
+ 0
+end test
diff --git a/test/unit/t_value.cc b/test/unit/t_value.cc
index 2daedcb1..a31c84c8 100644
--- a/test/unit/t_value.cc
+++ b/test/unit/t_value.cc
@@ -6,6 +6,10 @@
#include "value.h"
+#if defined(_WIN32) || defined(__CYGWIN__)
+#include "strptime.h"
+#endif
+
using namespace ledger;
struct value_fixture {
diff --git a/tools/excludes b/tools/excludes
index 762a27c9..f758854e 100644
--- a/tools/excludes
+++ b/tools/excludes
@@ -24,7 +24,6 @@ data_tests
depcomp
doc/.dirstamp
doc/ledger.info
-elisp-comp
expr_tests
install-sh
intl/
diff --git a/tools/nix-build.sh b/tools/nix-build.sh
new file mode 100755
index 00000000..4712dbea
--- /dev/null
+++ b/tools/nix-build.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+flavor=$1
+shift 1
+
+JOBS=-j$(sysctl -n hw.activecpu)
+
+OPTIONS="$flavor --debug --python --ninja $JOBS"
+#OPTIONS="$flavor --debug --python --ninja --doxygen $JOBS"
+
+time nice -n 20 nix-shell -p \
+ cmake boost gmp mpfr libedit python texinfo gnused \
+ ninja doxygen \
+ --command "./acprep $OPTIONS make $JOBS $@" && \
+
+time nice -n 20 nix-shell -p \
+ cmake boost gmp mpfr libedit python texinfo gnused \
+ ninja doxygen \
+ --command "./acprep $OPTIONS check $JOBS $@" \
+ \
diff --git a/tools/update_copyright_year.sh b/tools/update_copyright_year.sh
index ea0a5d35..db9541d4 100755
--- a/tools/update_copyright_year.sh
+++ b/tools/update_copyright_year.sh
@@ -30,7 +30,7 @@ YEAR=${1:-$(date +%Y)}
# is not generally installed
GREP=${2:-egrep}
-${GREP} -Rl 'Copyright.*Wiegley' . \
+${GREP} -Rl 'Copyright.*Wiegley' $(git ls-files | cut -d / -f1 | uniq) \
| ${GREP} -v "(test/garbage-input.dat|$(basename $0))" \
| xargs sed -i '' -e "s/\(Copyright.*\)-20[0-9]\{2\}/\1-${YEAR}/"