summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README-1ST1
-rwxr-xr-xacprep70
-rw-r--r--contrib/vim/ftplugin/ledger.vim85
-rw-r--r--doc/ledger.texi5
-rw-r--r--doc/ledger3.texi21
-rw-r--r--lib/Makefile17
-rw-r--r--lisp/ldg-mode.el4
-rw-r--r--src/amount.cc23
-rw-r--r--src/report.cc14
-rw-r--r--src/report.h2
-rw-r--r--src/stats.cc3
-rwxr-xr-xtools/genuuid28
12 files changed, 199 insertions, 74 deletions
diff --git a/README-1ST b/README-1ST
index 88174308..4643d655 100644
--- a/README-1ST
+++ b/README-1ST
@@ -101,6 +101,7 @@ it's usually fairly obvious where things have gone astray.
exact same Python as the Ledger executable. In particular I see this
bug on OS X systems where boost_python is linked against the default
Python, while Ledger is linked against the version provided by MacPorts.
+ Or vice versa.
Solution: Use one or the other. If you prefer the system Python, run
"port deactivate -f python26", to get MacPorts' version out of the way.
diff --git a/acprep b/acprep
index 1d0fa795..f260edcb 100755
--- a/acprep
+++ b/acprep
@@ -209,7 +209,7 @@ class BoostInfo(object):
def dependencies(self, system):
if system == 'darwin':
- return [ 'boost-jam', 'boost', '+icu+python26+st+universal' ]
+ return [ 'boost-jam', 'boost', '+icu+python27+st+universal' ]
if system == 'centos':
return [ 'boost-devel' ]
@@ -239,6 +239,15 @@ class BoostInfo(object):
'libboost-filesystem-dev',
'libboost-iostreams-dev' ]
+ elif system == 'ubuntu-oneiric':
+ return [ 'libboost-dev',
+ 'libboost-python-dev',
+ 'libboost-regex-dev',
+ 'libboost-date-time-dev',
+ 'libboost-filesystem-dev',
+ 'libboost-iostreams-dev' ]
+
+
class CommandLineApp(object):
"Base class for building command line applications."
@@ -400,8 +409,9 @@ class PrepareBuild(CommandLineApp):
self.LDFLAGS = []
self.envvars = {
+ 'PYTHON': '/usr/bin/python',
'PYTHON_HOME': '/usr',
- 'PYTHON_VERSION': '2.6',
+ 'PYTHON_VERSION': '2.7',
'LEDGER_PRODUCTS': None,
'CC': 'gcc',
'CPPFLAGS': '',
@@ -817,7 +827,7 @@ class PrepareBuild(CommandLineApp):
packages = [
'sudo', 'port', 'install', '-f',
'automake', 'autoconf', 'libtool',
- 'python26', '+universal',
+ 'python27', '+universal',
'libiconv', '+universal',
'zlib', '+universal',
'gmp' ,'+universal', 'mpfr', '+universal',
@@ -864,7 +874,7 @@ class PrepareBuild(CommandLineApp):
'lcov',
'sloccount'
] + self.boost_info.dependencies('ubuntu-karmic')
- else:
+ elif re.search('hardy', info):
self.log.info('Looks like you are using APT on Ubuntu Hardy')
packages = [
'sudo', 'apt-get', 'install',
@@ -888,6 +898,30 @@ class PrepareBuild(CommandLineApp):
'lcov',
'sloccount'
] + self.boost_info.dependencies('ubuntu-hardy')
+ elif re.search('oeneric', info):
+ self.log.info('Looks like you are using APT on Ubuntu Oeneric')
+ packages = [
+ 'sudo', 'apt-get', 'install',
+ 'build-essential',
+ 'libtool',
+ 'autoconf',
+ 'automake',
+ 'autopoint',
+ 'zlib1g-dev',
+ 'libbz2-dev',
+ 'python-dev',
+ 'cvs',
+ 'gettext',
+ 'libgmp3-dev',
+ 'libmpfr-dev',
+ 'libedit-dev',
+ #'texlive-full',
+ #'doxygen',
+ #'graphviz',
+ 'texinfo',
+ 'lcov',
+ 'sloccount'
+ ] + self.boost_info.dependencies('ubuntu-oeneric')
self.log.info('Executing: ' + string.join(packages, ' '))
self.execute(*packages)
@@ -929,7 +963,7 @@ class PrepareBuild(CommandLineApp):
boost_include = self.boost_info.include_directory()
boost_library = self.boost_info.library_directory()
- if re.match('/opt/local', self.boost_info.home_path):
+ if re.match('/(usr|opt)/local', self.boost_info.home_path):
self.log.debug("Setting Python home to /opt/local based on Boost's location")
self.envvars['PYTHON_HOME'] = '/opt/local'
@@ -946,6 +980,13 @@ class PrepareBuild(CommandLineApp):
self.log.info('Noticing include directory => ' + path)
self.sys_include_dirs.append(path)
+ includes = string.split(self.get_stdout('python-config',
+ '--includes'), '-I')
+ for include in includes:
+ include = include.strip()
+ if include and include not in self.sys_include_dirs:
+ self.sys_include_dirs.append(include)
+
# Each of these becomes '-L<name>'
for path in ['/usr/local/lib',
'%s/lib' % self.envvars['PYTHON_HOME'],
@@ -961,12 +1002,14 @@ class PrepareBuild(CommandLineApp):
self.sys_library_dirs.append(path)
def setup_for_johnw(self):
+ self.envvars['PYTHON'] = '/opt/local/bin/python'
+ self.envvars['PYTHON_HOME'] = '/opt/local'
+
if self.options.use_clang:
self.boost_inc_ident = "clang"
self.boost_lib_ident = "clang-darwin28"
self.log.debug("Setting Python home to /opt/local")
- self.envvars['PYTHON_HOME'] = '/opt/local'
self.log.debug('Using Clang ident: %s/%s' %
(self.boost_inc_ident, self.boost_lib_ident))
@@ -1040,28 +1083,21 @@ class PrepareBuild(CommandLineApp):
self.envvars['LD'] = '/usr/bin/g++-4.2'
self.darwin_gcc = True
elif exists('/opt/local/bin/g++-mp-4.6') and \
- not self.options.gcc45:
+ self.options.gcc46:
self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.6'
#if exists('/Users/johnw/bin/gfilt'):
# self.envvars['CXX'] = '/Users/johnw/bin/gfilt'
#else:
self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.6'
self.envvars['LD'] = '/opt/local/bin/g++-mp-4.6'
- elif exists('/opt/local/bin/g++-mp-4.5'):
+ elif exists('/opt/local/bin/g++-mp-4.5') and \
+ self.options.gcc45:
self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.5'
if exists('/Users/johnw/bin/gfilt'):
self.envvars['CXX'] = '/Users/johnw/bin/gfilt'
else:
self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.5'
self.envvars['LD'] = '/opt/local/bin/g++-mp-4.5'
- elif exists('/opt/local/bin/g++-mp-4.4'):
- self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.4'
- self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.4'
- self.envvars['LD'] = '/opt/local/bin/g++-mp-4.4'
- elif exists('/opt/local/bin/g++-mp-4.3'):
- self.envvars['CC'] = '/opt/local/bin/gcc-mp-4.3'
- self.envvars['CXX'] = '/opt/local/bin/g++-mp-4.3'
- self.envvars['LD'] = '/opt/local/bin/g++-mp-4.3'
elif exists('/usr/bin/g++-4.2'):
self.envvars['CC'] = '/usr/bin/gcc-4.2'
self.envvars['CXX'] = '/usr/bin/g++-4.2'
@@ -1296,7 +1332,9 @@ class PrepareBuild(CommandLineApp):
if self.options.gcc45 or self.options.gcc46:
self.CXXFLAGS.append('-g2')
+ self.CXXFLAGS.append('-ggdb')
self.LDFLAGS.append('-g2')
+ self.LDFLAGS.append('-ggdb')
else:
self.CXXFLAGS.append('-g')
self.LDFLAGS.append('-g')
diff --git a/contrib/vim/ftplugin/ledger.vim b/contrib/vim/ftplugin/ledger.vim
index 9cc4ed91..63de88b5 100644
--- a/contrib/vim/ftplugin/ledger.vim
+++ b/contrib/vim/ftplugin/ledger.vim
@@ -69,7 +69,17 @@ endif
" A
" }}}
if !exists('g:ledger_detailed_first')
- let g:ledger_detailed_first = 0
+ let g:ledger_detailed_first = 1
+endif
+
+" only display exact matches (no parent accounts etc.)
+if !exists('g:ledger_exact_only')
+ let g:ledger_exact_only = 0
+endif
+
+" display original text / account name as completion
+if !exists('g:ledger_include_original')
+ let g:ledger_include_original = 0
endif
let s:rx_amount = '\('.
@@ -141,10 +151,10 @@ function! LedgerComplete(findstart, base) "{{{1
" only allow completion when in or at end of account name
if matchend(line, '^\s\+\%(\S \S\|\S\)\+') >= col('.') - 1
" the start of the first non-blank character
- " (excluding virtual-transaction-marks)
+ " (excluding virtual-transaction and 'cleared' marks)
" is the beginning of the account name
let b:compl_context = 'account'
- return matchend(line, '^\s\+[\[(]\?')
+ return matchend(line, '^\s\+[*!]\?\s*[\[(]\?')
endif
elseif line =~ '^\d' "{{{2 (description)
let pre = matchend(line, '^\d\S\+\%(([^)]*)\|[*?!]\|\s\)\+')
@@ -161,31 +171,51 @@ function! LedgerComplete(findstart, base) "{{{1
let b:compl_cache = s:collect_completion_data()
let b:compl_cache['#'] = changenr()
endif
+ let update_cache = 0
let results = []
if b:compl_context == 'account' "{{{2 (account)
- unlet! b:compl_context
let hierarchy = split(a:base, ':')
if a:base =~ ':$'
call add(hierarchy, '')
endif
let results = LedgerFindInTree(b:compl_cache.accounts, hierarchy)
- " sort by alphabet and reverse because it will get reversed one more time
+ let exacts = filter(copy(results), 'v:val[1]')
+
+ if len(exacts) < 1
+ " update cache if we have no exact matches
+ let update_cache = 1
+ endif
+
+ if g:ledger_exact_only
+ let results = exacts
+ endif
+
+ call map(results, 'v:val[0]')
+
if g:ledger_detailed_first
let results = reverse(sort(results, 's:sort_accounts_by_depth'))
else
let results = sort(results)
endif
- call insert(results, a:base)
elseif b:compl_context == 'description' "{{{2 (description)
- let results = [a:base] + s:filter_items(b:compl_cache.descriptions, a:base)
+ let results = s:filter_items(b:compl_cache.descriptions, a:base)
+
+ if len(results) < 1
+ let update_cache = 1
+ endif
elseif b:compl_context == 'new' "{{{2 (new line)
return [strftime('%Y/%m/%d')]
endif "}}}
+
+ if g:ledger_include_original
+ call insert(results, a:base)
+ endif
+
" no completion (apart from a:base) found. update cache if file has changed
- if len(results) <= 1 && b:compl_cache['#'] != changenr()
+ if update_cache && b:compl_cache['#'] != changenr()
unlet b:compl_cache
return LedgerComplete(a:findstart, a:base)
else
@@ -203,11 +233,12 @@ function! LedgerFindInTree(tree, levels) "{{{1
let currentlvl = a:levels[0]
let nextlvls = a:levels[1:]
let branches = s:filter_items(keys(a:tree), currentlvl)
+ let exact = empty(nextlvls)
for branch in branches
- call add(results, branch)
- if !empty(nextlvls)
- for result in LedgerFindInTree(a:tree[branch], nextlvls)
- call add(results, branch.':'.result)
+ call add(results, [branch, exact])
+ if ! empty(nextlvls)
+ for [result, exact] in LedgerFindInTree(a:tree[branch], nextlvls)
+ call add(results, [branch.':'.result, exact])
endfor
endif
endfor
@@ -221,7 +252,7 @@ function! LedgerToggleTransactionState(lnum, ...)
let chars = ' *'
endif
let trans = s:transaction.from_lnum(a:lnum)
- if empty(trans)
+ if empty(trans) || has_key(trans, 'expr')
return
endif
@@ -238,7 +269,7 @@ function! LedgerSetTransactionState(lnum, char) "{{{1
" modifies or sets the state of the transaction at the cursor,
" removing the state alltogether if a:char is empty
let trans = s:transaction.from_lnum(a:lnum)
- if empty(trans)
+ if empty(trans) || has_key(trans, 'expr')
return
endif
@@ -250,7 +281,7 @@ endf "}}}
function! LedgerSetDate(lnum, type, ...) "{{{1
let time = a:0 == 1 ? a:1 : localtime()
let trans = s:transaction.from_lnum(a:lnum)
- if empty(trans)
+ if empty(trans) || has_key(trans, 'expr')
return
endif
@@ -288,7 +319,7 @@ function! s:collect_completion_data() "{{{1
let accounts = []
for xact in transactions
" collect descriptions
- if index(cache.descriptions, xact['description']) < 0
+ if has_key(xact, 'description') && index(cache.descriptions, xact['description']) < 0
call add(cache.descriptions, xact['description'])
endif
let [t, postings] = xact.parse_body()
@@ -354,6 +385,9 @@ function! s:transaction.from_lnum(lnum) dict "{{{2
if parts[0] ==# '~'
let trans['expr'] = join(parts[1:])
return trans
+ elseif parts[0] ==# '='
+ let trans['auto'] = join(parts[1:])
+ return trans
elseif parts[0] !~ '^\d'
" this case is avoided in s:get_transaction_extents(),
" but we'll check anyway.
@@ -411,9 +445,14 @@ function! s:transaction.parse_body(...) dict "{{{2
if line[0] =~ '^\s\+[^[:blank:];]'
" posting
- " FIXME: replaces original spacing in amount with single spaces
- let parts = split(line[0], '\%(\t\| \)\s*')
- call add(postings, {'account': parts[0], 'amount': join(parts[1:], ' ')})
+ let [state, rest] = matchlist(line[0], '^\s\+\([*!]\?\)\s*\(.*\)$')[1:2]
+ if rest =~ '\t\| '
+ let [account, amount] = matchlist(rest, '^\(.\{-}\)\%(\t\| \)\s*\(.\{-}\)\s*$')[1:2]
+ else
+ let amount = ''
+ let account = matchstr(rest, '^\s*\zs.\{-}\ze\s*$')
+ endif
+ call add(postings, {'account': account, 'amount': amount, 'state': state})
end
" where are tags to be stored?
@@ -450,6 +489,8 @@ endf "}}}
function! s:transaction.format_head() dict "{{{2
if has_key(self, 'expr')
return '~ '.self['expr']
+ elseif has_key(self, 'auto')
+ return '= '.self['auto']
endif
let parts = []
@@ -492,7 +533,7 @@ function! s:get_transactions(...) "{{{2
call add(transactions, trans)
call cursor(trans['tail'], 0)
endif
- let lnum = search('^[~[:digit:]]\S\+', 'cW')
+ let lnum = search('^[~=[:digit:]]', 'cW')
endw
" restore view / position
@@ -503,7 +544,7 @@ function! s:get_transactions(...) "{{{2
endf "}}}
function! s:get_transaction_extents(lnum) "{{{2
- if ! (indent(a:lnum) || getline(a:lnum) =~ '^[~[:digit:]]\S\+')
+ if ! (indent(a:lnum) || getline(a:lnum) =~ '^[~=[:digit:]]')
" only do something if lnum is in a transaction
return [0, 0]
endif
@@ -514,7 +555,7 @@ function! s:get_transaction_extents(lnum) "{{{2
set nofoldenable
call cursor(a:lnum, 0)
- let head = search('^[~[:digit:]]\S\+', 'bcnW')
+ let head = search('^[~=[:digit:]]', 'bcnW')
let tail = search('^[^;[:blank:]]\S\+', 'nW')
let tail = tail > head ? tail - 1 : line('$')
diff --git a/doc/ledger.texi b/doc/ledger.texi
index ac7bfc5f..8389c383 100644
--- a/doc/ledger.texi
+++ b/doc/ledger.texi
@@ -1305,8 +1305,9 @@ The format of each following posting is:
ACCOUNT AMOUNT [; NOTE]
@end example
-The @samp{ACCOUNT} may be surrounded by parentheses if it is a virtual
-postings, or square brackets if it is a virtual postings that
+Note that there must be at least two spaces between @samp{ACCOUNT} and
+@samp{AMOUNT}. The @samp{ACCOUNT} may be surrounded by parentheses if it
+is a virtual posting or square brackets if it is a virtual posting that
must balance. The @samp{AMOUNT} can be followed by a per-unit
posting cost, by specifying @samp{@@ AMOUNT}, or a complete
posting cost with @samp{@@@@ AMOUNT}. Lastly, the @samp{NOTE} may
diff --git a/doc/ledger3.texi b/doc/ledger3.texi
index 3fce78e2..da63dd98 100644
--- a/doc/ledger3.texi
+++ b/doc/ledger3.texi
@@ -4223,7 +4223,7 @@ associated commodity. This commodity can appear before or after the
amount, and may or may not be separated from it by a space. Most
characters are allowed in a commodity name, except for the following:
-@itemize
+@itemize @bullet
@item Any kind of whitespace
@item Numerical digits
@item Punctuation: @samp{.,;:?!}
@@ -4249,18 +4249,17 @@ in the same form as parsed. If you specify dollar amounts using
@samp{$100.000}. You may even use decimal commas, such as
@samp{$100,00}, or thousand-marks, as in @samp{$10,000.00}.
-These display characteristics become associated with the commodity,
-with the result being that all amounts of the same commodity are
-reported consistently. Where this is most noticeable is the
-@dfn{display precision}, which is determined by the most precise value
-seen for a given commodity. In most cases.
+These display characteristics become associated with the commodity, with
+the result being that all amounts of the same commodity are reported
+consistently. Where this is most noticeable is the @dfn{display
+precision}, which is determined by the most precise value seen for a
+given commodity---in most cases.
-Ledger makes a distinction by @dfn{observed amounts} and unobserved
+Ledger makes a distinction between @dfn{observed amounts} and unobserved
amounts. An observed amount is critiqued by Ledger to determine how
-amounts using that commodity should be displayed; unobserved amounts
-are significant in their value only---no matter how they are
-specified, it does not change how other amounts in that commodity will
-be displayed.
+amounts using that commodity should be displayed; unobserved amounts are
+significant in their value only---no matter how they are specified, it
+does not change how other amounts in that commodity will be displayed.
An example of this is found in cost expressions, covered next.
diff --git a/lib/Makefile b/lib/Makefile
index 734816af..bc9611f0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,7 +5,7 @@
STOW_ROOT = /usr/local/stow
PRODUCTS = $(HOME)/Products
-GCC_VERSION = 4.5
+GCC_VERSION = 4.6
BOOST_VERSION = 1_47_0
CC = gcc-mp-$(GCC_VERSION)
@@ -13,19 +13,19 @@ ifeq ($(CC),clang)
CXX = clang++
LD = llvm-ld
DIR_SUFFIX = clang
-OPTJ =
+OPTJ =
else
CXX = g++-mp-$(GCC_VERSION)
LD = gcc-mp-$(GCC_VERSION)
DIR_SUFFIX = gcc$(subst .,,$(GCC_VERSION))
-OPTJ = #-j8
+OPTJ = #-j8
endif
CPPFLAGS = -D_GLIBCXX_FULLY_DYNAMIC_STRING=1
ifneq ($(CC),clang)
CPPFLAGS += -D_GLIBCXX_DEBUG=1
endif
-CFLAGS = $(CPPFLAGS) -g
-LDFLAGS = -g
+CFLAGS = $(CPPFLAGS) -g2 -ggdb
+LDFLAGS = -g2 -ggdb
BOOST_SOURCE = boost-release
BOOST_DEFINES = define=_GLIBCXX_FULLY_DYNAMIC_STRING=1
@@ -36,9 +36,8 @@ BOOST_TOOLSET = darwin
BOOST_DEFINES += define=_GLIBCXX_DEBUG=1
endif
#BOOST_FLAGS = --architecture=x86 --address_model=32_64
-BOOST_FLAGS = toolset=$(BOOST_TOOLSET) \
- --build-type=complete --layout=versioned \
- $(BOOST_DEFINES)
+BOOST_FLAGS = toolset=$(BOOST_TOOLSET) --layout=versioned \
+ link=shared threading=single $(BOOST_DEFINES)
BOOST_DIR = boost_$(BOOST_VERSION)-$(DIR_SUFFIX)
BOOST_STOW = $(STOW_ROOT)/$(BOOST_DIR)
BOOST_BUILD = $(PRODUCTS)/$(BOOST_DIR)
@@ -56,7 +55,7 @@ prepare-boost:
boost-build: prepare-boost
(cd $(BOOST_SOURCE) && \
sh bootstrap.sh && \
- ./bjam $(OPTJ) debug --prefix=$(BOOST_STOW) \
+ ./b2 $(OPTJ) debug --prefix=$(BOOST_STOW) \
--build-dir=$(BOOST_BUILD) \
$(BOOST_FLAGS) install)
diff --git a/lisp/ldg-mode.el b/lisp/ldg-mode.el
index 3e9a9106..cc9e8d92 100644
--- a/lisp/ldg-mode.el
+++ b/lisp/ldg-mode.el
@@ -10,8 +10,8 @@
;;("^[0-9]+[-/.=][-/.=0-9]+\\s-+\\(([^)]+)\\s-+\\)?\\([*].+?\\)\\(\\( ;\\| ;\\|$\\)\\)"
;; 2 font-lock-type-face)
("^\\s-+\\([*]\\s-*\\)?\\(\\([[(]\\)?[^*:
- ]+?:[^]);
- ]+?\\([])]\\)?\\)\\( \\| \\|$\\)"
+ ]+?:\\([^]);
+ ]\\|\\s-\\)+?\\([])]\\)?\\)\\( \\| \\|$\\)"
2 font-lock-keyword-face)
("^\\([~=].+\\)" 1 font-lock-function-name-face)
("^\\([A-Za-z]+ .+\\)" 1 font-lock-function-name-face))
diff --git a/src/amount.cc b/src/amount.cc
index 808f118d..99e346b7 100644
--- a/src/amount.cc
+++ b/src/amount.cc
@@ -115,6 +115,7 @@ namespace {
mpq_t quant,
amount_t::precision_t precision,
int zeros_prec = -1,
+ mpfr_rnd_t rnd = MPFR_RNDN,
const optional<commodity_t&>& comm = none)
{
char * buf = NULL;
@@ -135,7 +136,7 @@ namespace {
DEBUG("amount.convert", "num prec = " << num_prec);
mpfr_set_prec(tempfnum, num_prec);
- mpfr_set_z(tempfnum, mpq_numref(quant), GMP_RNDN);
+ mpfr_set_z(tempfnum, mpq_numref(quant), rnd);
mp_prec_t den_prec = mpz_sizeinbase(mpq_denref(quant), 2);
den_prec += amount_t::extend_by_digits*64;
@@ -144,10 +145,10 @@ namespace {
DEBUG("amount.convert", "den prec = " << den_prec);
mpfr_set_prec(tempfden, den_prec);
- mpfr_set_z(tempfden, mpq_denref(quant), GMP_RNDN);
+ mpfr_set_z(tempfden, mpq_denref(quant), rnd);
mpfr_set_prec(tempfb, num_prec + den_prec);
- mpfr_div(tempfb, tempfnum, tempfden, GMP_RNDN);
+ mpfr_div(tempfb, tempfnum, tempfden, rnd);
if (mpfr_asprintf(&buf, "%.*RNf", precision, tempfb) < 0)
throw_(amount_error,
@@ -669,7 +670,7 @@ void amount_t::in_place_floor()
_dup();
std::ostringstream out;
- stream_out_mpq(out, MP(quantity), precision_t(0));
+ stream_out_mpq(out, MP(quantity), precision_t(0), -1, MPFR_RNDZ);
mpq_set_str(MP(quantity), out.str().c_str(), 10);
}
@@ -844,8 +845,8 @@ double amount_t::to_double() const
if (! quantity)
throw_(amount_error, _("Cannot convert an uninitialized amount to a double"));
- mpfr_set_q(tempf, MP(quantity), GMP_RNDN);
- return mpfr_get_d(tempf, GMP_RNDN);
+ mpfr_set_q(tempf, MP(quantity), MPFR_RNDN);
+ return mpfr_get_d(tempf, MPFR_RNDN);
}
long amount_t::to_long() const
@@ -853,14 +854,14 @@ long amount_t::to_long() const
if (! quantity)
throw_(amount_error, _("Cannot convert an uninitialized amount to a long"));
- mpfr_set_q(tempf, MP(quantity), GMP_RNDN);
- return mpfr_get_si(tempf, GMP_RNDN);
+ mpfr_set_q(tempf, MP(quantity), MPFR_RNDN);
+ return mpfr_get_si(tempf, MPFR_RNDN);
}
bool amount_t::fits_in_long() const
{
- mpfr_set_q(tempf, MP(quantity), GMP_RNDN);
- return mpfr_fits_slong_p(tempf, GMP_RNDN);
+ mpfr_set_q(tempf, MP(quantity), MPFR_RNDN);
+ return mpfr_fits_slong_p(tempf, MPFR_RNDN);
}
commodity_t& amount_t::commodity() const
@@ -1239,7 +1240,7 @@ void amount_t::print(std::ostream& _out, const uint_least8_t flags) const
}
stream_out_mpq(out, MP(quantity), display_precision(),
- comm ? commodity().precision() : 0, comm);
+ comm ? commodity().precision() : 0, MPFR_RNDN, comm);
if (comm.has_flags(COMMODITY_STYLE_SUFFIXED)) {
if (comm.has_flags(COMMODITY_STYLE_SEPARATED))
diff --git a/src/report.cc b/src/report.cc
index d3a219a0..548d39df 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -622,6 +622,16 @@ value_t report_t::fn_floor(call_scope_t& args)
return args[0].floored();
}
+value_t report_t::fn_round(call_scope_t& args)
+{
+ return args[0].rounded();
+}
+
+value_t report_t::fn_unround(call_scope_t& args)
+{
+ return args[0].unrounded();
+}
+
value_t report_t::fn_abs(call_scope_t& args)
{
return args[0].abs();
@@ -1281,6 +1291,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
return MAKE_FUNCTOR(report_t::fn_rounded);
else if (is_eq(p, "red"))
return WRAP_FUNCTOR(fn_red);
+ else if (is_eq(p, "round"))
+ return MAKE_FUNCTOR(report_t::fn_round);
break;
case 's':
@@ -1333,6 +1345,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
case 'u':
if (is_eq(p, "underline"))
return WRAP_FUNCTOR(fn_underline);
+ else if (is_eq(p, "unround"))
+ return MAKE_FUNCTOR(report_t::fn_unround);
else if (is_eq(p, "unrounded"))
return MAKE_FUNCTOR(report_t::fn_unrounded);
break;
diff --git a/src/report.h b/src/report.h
index e142b0dc..58c12f24 100644
--- a/src/report.h
+++ b/src/report.h
@@ -160,6 +160,8 @@ public:
value_t fn_unrounded(call_scope_t& scope);
value_t fn_truncated(call_scope_t& scope);
value_t fn_floor(call_scope_t& scope);
+ value_t fn_round(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);
diff --git a/src/stats.cc b/src/stats.cc
index 8899ddf5..524f5a87 100644
--- a/src/stats.cc
+++ b/src/stats.cc
@@ -89,7 +89,8 @@ value_t report_statistics(call_scope_t& args)
out << " (";
out.precision(2);
out << (double(statistics.posts_count)/
- double((statistics.latest_post - statistics.earliest_post).days())) << _(" per day)") << std::endl;
+ double((statistics.latest_post - statistics.earliest_post).days()))
+ << _(" per day)") << std::endl;
out << _(" Uncleared postings: ");
out.width(6);
diff --git a/tools/genuuid b/tools/genuuid
new file mode 100755
index 00000000..53fb7a0a
--- /dev/null
+++ b/tools/genuuid
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+import re
+import sys
+
+def scan_path(path):
+ bug = uuid = None
+ with open(path, 'r') as fd:
+ for line in fd:
+ match = re.match('\*', line)
+ if match:
+ bug = uuid = None
+
+ match = re.search('\[\[bug:([0-9]+)\]\[#[0-9]+\]\]', line)
+ if match:
+ bug = match.group(1)
+ elif bug:
+ match = re.search(':ID:\s+(.+?)\s*$', line)
+ if match:
+ uuid = match.group(1)
+ print "UPDATE bugs SET cf_uuid='%s' WHERE bug_id=%s;" % (uuid, bug)
+
+scan_path('/Users/johnw/src/ledger/plan/TODO')
+scan_path('/Users/johnw/src/ledger/plan/TODO-3.0')
+scan_path('/Users/johnw/src/ledger/plan/TODO-2.6.2')
+scan_path('/Users/johnw/src/ledger/plan/TODO-2.6.1')
+
+### genuuid ends here