Merge branch 'master' into fix-matchgroups

This commit is contained in:
Simon Michael 2024-03-02 12:15:52 -10:00 committed by GitHub
commit 169198ff55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 1169 additions and 1072 deletions

488
Justfile
View File

@ -1,5 +1,5 @@
#!/usr/bin/env just #!/usr/bin/env just
# * Project scripts, using https://github.com/casey/just (last tested with 1.16.0) # * Project scripts, using https://github.com/casey/just (last tested with 1.24.0)
# Usage: alias j=just, run j to list available scripts. # Usage: alias j=just, run j to list available scripts.
# #
# After many years with make and plain shell and haskell for # After many years with make and plain shell and haskell for
@ -22,7 +22,7 @@
# (highlight-lines-matching-regexp "^@?\\w.*\\w:$" 'hi-pink) ; recipe headings (misses recipes with dependencies) # (highlight-lines-matching-regexp "^@?\\w.*\\w:$" 'hi-pink) ; recipe headings (misses recipes with dependencies)
# )) # ))
# #
# This file is formatted by `just _fmt`, which currently eats blank lines a bit (and commits). # This file is formatted by `just format`, which currently eats blank lines a bit (and commits).
# #
# 'set export' makes constants and arguments available as $VAR as well as {{ VAR }}. # 'set export' makes constants and arguments available as $VAR as well as {{ VAR }}.
# $ makes just code more like shell code. # $ makes just code more like shell code.
@ -59,9 +59,9 @@ alias h := help
@check: @check:
just --fmt --unstable --check just --fmt --unstable --check
# if this justfile is error free but in non-standard format, reformat and commit it # if this justfile is error free but in non-standard format, reformat it, and if it has changes, commit it
@format: @format:
just -q chk || just --fmt --unstable && git commit -m ';just: format' -- {{ justfile() }} just -q chk || just -q --fmt --unstable && git diff --quiet || git commit -m ';just: format' -- {{ justfile() }}
# rerun RECIPE when any watched-by-default file changes # rerun RECIPE when any watched-by-default file changes
watch RECIPE *JOPTS: watch RECIPE *JOPTS:
@ -87,13 +87,14 @@ _watchgitdbg *WOPTS:
BROWSE := 'open' BROWSE := 'open'
# XXX These often don't work well interpolated as $CMD or {{ CMD }}, not sure why # XXX These often don't work well interpolated as $CMD or {{ CMD }}, not sure why
# find GNU tools, eg on mac # find GNU tools, eg on mac
GDATE := `type -P gdate || echo date`
GTAR := `type -P gtar || echo tar`
#GNUTAR := `which gtar >/dev/null && echo gtar || echo tar`
GDATE := `type -P gdate || echo date`
GTAR := `type -P gtar || echo tar`
#GNUTAR := `which gtar >/dev/null && echo gtar || echo tar`
# make ghc usable for scripting with -e # make ghc usable for scripting with -e
GHC := 'ghc -ignore-dot-ghci -package-env -' GHC := 'ghc -ignore-dot-ghci -package-env -'
GHCI := 'ghci' GHCI := 'ghci'
@ -204,8 +205,8 @@ DOCSOURCEFILES := '
CONTRIBUTING.md CONTRIBUTING.md
' + MANUALSOURCEFILES + COMMANDHELPFILES ' + MANUALSOURCEFILES + COMMANDHELPFILES
TESTFILES := `fd '\.test$' --exclude ledger-compat` TESTFILES := `fd '\.test$' --exclude ledger-compat`
# XXX it's fd-find on gnu/linux ?
# XXX it's fd-find on gnu/linux ?
# # file(s) which require recompilation for a build to have an up-to-date version string # # file(s) which require recompilation for a build to have an up-to-date version string
# VERSIONSOURCEFILE := 'hledger/Hledger/Cli/Version.hs' # VERSIONSOURCEFILE := 'hledger/Hledger/Cli/Version.hs'
# Two or three-part version string, set as program version in builds made by this makefile. # Two or three-part version string, set as program version in builds made by this makefile.
@ -246,55 +247,30 @@ BUILDFLAGS := '-rtsopts ' + WARNINGS + GHCLOWMEMFLAGS + CABALMACROSFLAGS + ' -DD
TIME := "{{ shell date +'%Y%m%d%H%M' }}" TIME := "{{ shell date +'%Y%m%d%H%M' }}"
MONTHYEAR := "{{ shell date +'%B %Y' }}" MONTHYEAR := "{{ shell date +'%B %Y' }}"
# ** ghci ------------------------------------------------------------ # ** Building ------------------------------------------------------------
GHCI: BUILDING:
# run ghci on hledger-lib + hledger # build the hledger package showing ghc codegen times/allocations
@ghci: @buildtimes:
$STACKGHCI exec -- $GHCI $BUILDFLAGS hledger/Hledger/Cli.hs time ($STACK build hledger --force-dirty --ghc-options='-fforce-recomp -ddump-timings' 2>&1 | grep -E '\bCodeGen \[.*time=')
# run ghci on hledger-lib + hledger with profiling/call stack information # # build an unoptimised hledger at bin/hledger.EXT.unopt (default: git describe)
@ghci-prof: # build-unopt *EXT:
stack build --profile hledger --only-dependencies # #!/usr/bin/env bash
$STACKGHCI exec -- $GHCI $BUILDFLAGS -fexternal-interpreter -prof -fprof-auto hledger/Hledger/Cli.hs # ext={{ if EXT == '' { `git describe --tags` } else { EXT } }}
# exe="bin/hledger.$ext.unopt"
# # run ghci on hledger-lib + hledger + dev.hs script # $STACK --verbosity=error install --ghc-options=-O0 hledger --local-bin-path=bin
# @ghci-dev: # mv bin/hledger "$exe"
# $STACKGHCI exec -- $GHCI $BUILDFLAGS -fno-warn-unused-imports -fno-warn-unused-binds dev.hs # echo "$exe"
# # build hledger with profiling enabled at bin/hledgerprof
# run ghci on hledger-lib + hledger + hledger-ui # hledgerprof:
@ghci-ui: # # $STACK --verbosity=error install --local-bin-path=bin hledger
$STACKGHCI exec -- $GHCI $BUILDFLAGS hledger-ui/Hledger/UI/Main.hs # $STACK build --profile hledger
# # hledger-lib --ghc-options=-fprof-auto
# run ghci on hledger-lib + hledger + hledger-web # # @echo "to profile, use $STACK exec --profile -- hledger ..."
@ghci-web: # # build "bin/hledgercov" for coverage reports (with ghc)
$STACKGHCI exec -- $GHCI $BUILDFLAGS hledger-web/app/main.hs # hledgercov:
# $STACK ghc {{ MAIN }} -fhpc -o bin/hledgercov -outputdir .hledgercovobjs $BUILDFLAGS
# run ghci on hledger-lib + hledger + hledger-web + hledger-web test suite
@ghci-web-test:
$STACKGHCI exec -- $GHCI $BUILDFLAGS hledger-web/test/test.hs
# # better than stack exec ?
# # XXX does not see changes to files
# # run ghci on hledger-lib + test runner
# ghci-lib-test:
# $STACKGHCI ghci --ghc-options="\'-rtsopts {{ WARNINGS }} -ihledger-lib -DDEVELOPMENT -DVERSION=\"1.26.99\"\'" hledger-lib/test/unittest.hs
# run ghci on all the hledger
# ghci-all:
# $STACK exec -- $GHCI $BUILDFLAGS \
# hledger-ui/Hledger/UI/Main.hs \
# hledger-web/app/main.hs \
# run ghci on hledger-lib doctests
@ghci-doctest:
cd hledger-lib; $STACKGHCI ghci hledger-lib:test:doctest
# run ghci on Shake.hs
@ghci-shake:
$STACK exec {{ SHAKEDEPS }} -- ghci Shake.hs
# ** ghcid ------------------------------------------------------------
GHCID:
# run ghcid on hledger-lib + hledger # run ghcid on hledger-lib + hledger
@ghcid: @ghcid:
@ -349,7 +325,53 @@ SHAKEDEPS := '\
ghcid-shake: ghcid-shake:
stack exec {{ SHAKEDEPS }} -- ghcid Shake.hs stack exec {{ SHAKEDEPS }} -- ghcid Shake.hs
# ** dev.hs script ------------------------------------------------------------ # ** Testing ------------------------------------------------------------
TESTING:
# run ghci on hledger-lib + hledger
@ghci:
$STACKGHCI exec -- $GHCI $BUILDFLAGS hledger/Hledger/Cli.hs
# run ghci on hledger-lib + hledger with profiling/call stack information
@ghci-prof:
stack build --profile hledger --only-dependencies
$STACKGHCI exec -- $GHCI $BUILDFLAGS -fexternal-interpreter -prof -fprof-auto hledger/Hledger/Cli.hs
# # run ghci on hledger-lib + hledger + dev.hs script
# @ghci-dev:
# $STACKGHCI exec -- $GHCI $BUILDFLAGS -fno-warn-unused-imports -fno-warn-unused-binds dev.hs
# run ghci on hledger-lib + hledger + hledger-ui
@ghci-ui:
$STACKGHCI exec -- $GHCI $BUILDFLAGS hledger-ui/Hledger/UI/Main.hs
# run ghci on hledger-lib + hledger + hledger-web
@ghci-web:
$STACKGHCI exec -- $GHCI $BUILDFLAGS hledger-web/app/main.hs
# run ghci on hledger-lib + hledger + hledger-web + hledger-web test suite
@ghci-web-test:
$STACKGHCI exec -- $GHCI $BUILDFLAGS hledger-web/test/test.hs
# # better than stack exec ?
# # XXX does not see changes to files
# # run ghci on hledger-lib + test runner
# ghci-lib-test:
# $STACKGHCI ghci --ghc-options="\'-rtsopts {{ WARNINGS }} -ihledger-lib -DDEVELOPMENT -DVERSION=\"1.26.99\"\'" hledger-lib/test/unittest.hs
# run ghci on all the hledger
# ghci-all:
# $STACK exec -- $GHCI $BUILDFLAGS \
# hledger-ui/Hledger/UI/Main.hs \
# hledger-web/app/main.hs \
# run ghci on hledger-lib doctests
@ghci-doctest:
cd hledger-lib; $STACKGHCI ghci hledger-lib:test:doctest
# run ghci on Shake.hs
@ghci-shake:
$STACK exec {{ SHAKEDEPS }} -- ghci Shake.hs
# # hledger-lib/Hledger/Read/TimeclockReaderPP.hs # # hledger-lib/Hledger/Read/TimeclockReaderPP.hs
# # build the dev.hs script for quick experiments (with ghc) # # build the dev.hs script for quick experiments (with ghc)
# dev: # dev:
@ -372,34 +394,6 @@ ghcid-shake:
# curl -F "file=@devprof-hc.hp" -F "title='hledger parser'" http://heap.ezyang.com/upload # curl -F "file=@devprof-hc.hp" -F "title='hledger parser'" http://heap.ezyang.com/upload
# curl -F "file=@devprof-hr.hp" -F "title='hledger parser'" http://heap.ezyang.com/upload # curl -F "file=@devprof-hr.hp" -F "title='hledger parser'" http://heap.ezyang.com/upload
# ** Building ------------------------------------------------------------
BUILDING:
# build the hledger package showing ghc codegen times/allocations
@buildtimes:
time ($STACK build hledger --force-dirty --ghc-options='-fforce-recomp -ddump-timings' 2>&1 | grep -E '\bCodeGen \[.*time=')
# # build an unoptimised hledger at bin/hledger.EXT.unopt (default: git describe)
# build-unopt *EXT:
# #!/usr/bin/env bash
# ext={{ if EXT == '' { `git describe --tags` } else { EXT } }}
# exe="bin/hledger.$ext.unopt"
# $STACK --verbosity=error install --ghc-options=-O0 hledger --local-bin-path=bin
# mv bin/hledger "$exe"
# echo "$exe"
# # build hledger with profiling enabled at bin/hledgerprof
# hledgerprof:
# # $STACK --verbosity=error install --local-bin-path=bin hledger
# $STACK build --profile hledger
# # hledger-lib --ghc-options=-fprof-auto
# # @echo "to profile, use $STACK exec --profile -- hledger ..."
# # build "bin/hledgercov" for coverage reports (with ghc)
# hledgercov:
# $STACK ghc {{ MAIN }} -fhpc -o bin/hledgercov -outputdir .hledgercovobjs $BUILDFLAGS
# ** Testing ------------------------------------------------------------
TESTING:
# run tests that are reasonably quick (files, unit, functional) and benchmarks # run tests that are reasonably quick (files, unit, functional) and benchmarks
test: filestest functest test: filestest functest
@ -492,6 +486,18 @@ ADDONEXTS := 'pl py rb sh hs lhs rkt exe com bat'
mkdir hledger/test/addons/hledger-addondir mkdir hledger/test/addons/hledger-addondir
chmod +x hledger/test/addons/hledger-* chmod +x hledger/test/addons/hledger-*
# compare hledger's and ledger's balance report
compare-balance:
#!/usr/bin/env bash
for f in examples/1txns-1accts.journal \
examples/10txns-10accts.journal \
; do \
(export f=$f; \
printf "\n-------------------------------------------------------------------------------\n"; \
echo "comparing hledger -f $f balance and ledger -f $f balance --flat"; \
difft --color=always --display side-by-side-show-both <(hledger -f $f balance) <(ledger -f $f balance --flat) ) | tail +2; \
done
# generate a hlint report # generate a hlint report
# hlinttest hlint: # hlinttest hlint:
# hlint --hint=hlint --report=hlint.html {{ SOURCEFILES }} # hlint --hint=hlint --report=hlint.html {{ SOURCEFILES }}
@ -513,6 +519,53 @@ ADDONEXTS := 'pl py rb sh hs lhs rkt exe com bat'
installtest: installtest:
cd; {{ justfile_directory() }}/hledger-install/hledger-install.sh cd; {{ justfile_directory() }}/hledger-install/hledger-install.sh
# ** Installing ------------------------------------------------------------
INSTALLING:
# # copy the current ~/.local/bin/hledger to bin/old/hledger-VER
# @copy-as VER:
# cp ~/.local/bin/hledger bin/old/hledger-{{ VER }}; echo "bin/hledger-{{ VER }}"
# stack install, then copy the hledger executables to bin/old/hledger*-VER
@installas VER:
$STACK install --local-bin-path bin/old
for e in hledger hledger-ui hledger-web ; do cp bin/old/$e bin/old/$e-{{ VER }}; echo "bin/$e-{{ VER }}"; done
# # make must be GNU Make 4.3+
# .PHONY: shellcompletions
# # update shell completions in hledger package
# shellcompletions:
# make -C hledger/shell-completion/ clean-all all
# download a recent set of hledger versions from github releases to bin/hledger-VER
get-binaries:
for V in 1.32.2 1.31 1.30 1.29.2 1.28 1.27.1; do just get-binary $OS x64 $V; done
just symlink-binaries
# download hledger version VER for OS (linux, mac windows) and ARCH (x64) from github releases to bin/hledger-VER
# On gnu/linux: can't interpolate GTAR here for some reason, and need the shebang line.
get-binary OS ARCH VER:
#!/usr/bin/env bash
cd bin && curl -Ls https://github.com/simonmichael/hledger/releases/download/{{ VER }}/hledger-{{ OS }}-{{ ARCH }}.zip | funzip | `type -P gtar || echo tar` xf - hledger --transform 's/$/-{{ VER }}/'
# add easier symlinks for all the minor hledger releases downloaded by get-binaries.
symlink-binaries:
just symlink-binary 1.32.2
just symlink-binary 1.29.2
just symlink-binary 1.27.1
# add an easier symlink for this minor hledger release (hledger-1.29 -> hledger-1.29.2, etc.)
@symlink-binary MINORVER:
cd bin && ln -sf hledger-$MINORVER hledger-`echo $MINORVER | sed -E 's/\.[0-9]+$//'`
# sym-link some directories required by hledger-web dev builds
symlink-web-dirs:
echo "#ln -sf hledger-web/config # disabled, causes makeinfo warnings"
ln -sf hledger-web/messages
ln -sf hledger-web/static
ln -sf hledger-web/templates
# ** Benchmarking ------------------------------------------------------------ # ** Benchmarking ------------------------------------------------------------
BENCHMARKING: BENCHMARKING:
@ -571,29 +624,9 @@ samplejournals:
# The current OS name, in the form used for hledger release binaries: linux, mac, windows or other. # The current OS name, in the form used for hledger release binaries: linux, mac, windows or other.
# can't use $GHC or {{GHC}} here for some reason # can't use $GHC or {{GHC}} here for some reason
OS := `ghc -ignore-dot-ghci -package-env - -e 'import System.Info' -e 'putStrLn $ case os of "darwin"->"mac"; "mingw32"->"windows"; "linux"->"linux"; _->"other"'` OS := `ghc -ignore-dot-ghci -package-env - -e 'import System.Info' -e 'putStrLn $ case os of "darwin"->"mac"; "mingw32"->"windows"; "linux"->"linux"; _->"other"'`
# download a recent set of hledger versions from github releases to bin/hledger-VER
get-binaries:
for V in 1.32.2 1.31 1.30 1.29.2 1.28 1.27.1; do just get-binary $OS x64 $V; done
just symlink-binaries
# download hledger version VER for OS (linux, mac windows) and ARCH (x64) from github releases to bin/hledger-VER
# On gnu/linux: can't interpolate GTAR here for some reason, and need the shebang line.
get-binary OS ARCH VER:
#!/usr/bin/env bash
cd bin && curl -Ls https://github.com/simonmichael/hledger/releases/download/{{ VER }}/hledger-{{ OS }}-{{ ARCH }}.zip | funzip | `type -P gtar || echo tar` xf - hledger --transform 's/$/-{{ VER }}/'
# add easier symlinks for all the minor hledger releases downloaded by get-binaries.
symlink-binaries:
just symlink-binary 1.32.2
just symlink-binary 1.29.2
just symlink-binary 1.27.1
# add an easier symlink for this minor hledger release (hledger-1.29 -> hledger-1.29.2, etc.)
@symlink-binary MINORVER:
cd bin && ln -sf hledger-$MINORVER hledger-`echo $MINORVER | sed -E 's/\.[0-9]+$//'`
# tools/generatejournal.hs 3 5 5 --chinese > examples/chinese.journal # don't regenerate, keep the simple version # tools/generatejournal.hs 3 5 5 --chinese > examples/chinese.journal # don't regenerate, keep the simple version
# $ just --set BENCHEXES ledger,hledger bench # $ just --set BENCHEXES ledger,hledger bench
@ -602,20 +635,14 @@ symlink-binaries:
printf "Running quick benchmarks (times are approximate, can be skewed):\n" printf "Running quick benchmarks (times are approximate, can be skewed):\n"
which quickbench >/dev/null && quickbench {{ ARGS }} || echo "quickbench not installed (see bench.sh), skipping" which quickbench >/dev/null && quickbench {{ ARGS }} || echo "quickbench not installed (see bench.sh), skipping"
@bench-quick8: # @bench-gtime:
quickbench -w hledger-1.23,hledger-1.24,hledger-1.25,hledger-1.26,hledger-1.28,hledger-1.29,hledger-21ad,ledger # for args in '-f examples/10ktxns-1kaccts.journal print' '-f examples/100ktxns-1kaccts.journal register' '-f examples/100ktxns-1kaccts.journal balance'; do \
# echo; \
@bench-quick3: # for app in hledger-1.26 hledger-21ad ledger; do \
quickbench -w hledger-1.26,hledger-21ad,ledger '_ -f examples/10ktxns-1kaccts.journal print' '_ -f examples/10ktxns-1kaccts.journal register' '_ -f examples/10ktxns-1kaccts.journal balance' # echo; echo $app $args:; \
# gtime $app $args >/dev/null; \
@bench-gtime: # done; \
for args in '-f examples/10ktxns-1kaccts.journal print' '-f examples/100ktxns-1kaccts.journal register' '-f examples/100ktxns-1kaccts.journal balance'; do \ # done
echo; \
for app in hledger-1.26 hledger-21ad ledger; do \
echo; echo $app $args:; \
gtime $app $args >/dev/null; \
done; \
done
# show throughput at various data sizes with the given hledger executable (requires samplejournals) # show throughput at various data sizes with the given hledger executable (requires samplejournals)
@bench-throughput EXE: @bench-throughput EXE:
@ -633,28 +660,15 @@ symlink-binaries:
stack build hledger stack build hledger
stack exec -- just throughput hledger stack exec -- just throughput hledger
# show throughput of recent hledger versions (requires samplejournals)
@bench-throughput-recent: @bench-throughput-recent:
for v in 1.25 1.28 1.29 1.32 21ad; do printf "\nhledger-$v:\n"; for i in `seq 1 3`; do hledger-$v -f examples/10ktxns-10kaccts.journal stats | grep throughput; done; done for v in 1.25 1.28 1.29 1.32 1.32.3; do printf "\nhledger-$v:\n"; for i in `seq 1 3`; do hledger-$v -f examples/10ktxns-10kaccts.journal stats | grep throughput; done; done
@bench-balance-many-accts:
quickbench -w hledger-1.26,hledger-21ad,ledger -f bench-many-accts.sh -N2
#quickbench -w hledger-1.25,hledger-1.28,hledger-1.29,hledger-1.30,hledger-1.31,hledger-1.32,hledger-21ad,ledger -f bench-many-accts.sh -N2
@bench-balance-many-txns:
quickbench -w hledger-21ad,ledger -f bench-many-txns.sh -N2
# examples/100txns-100accts.journal \
compare-balance:
#!/usr/bin/env bash
for f in examples/1txns-1accts.journal \
examples/10txns-10accts.journal \
; do \
(export f=$f; \
printf "\n-------------------------------------------------------------------------------\n"; \
echo "comparing hledger -f $f balance and ledger -f $f balance --flat"; \
difft --color=always --display side-by-side-show-both <(hledger -f $f balance) <(ledger -f $f balance --flat) ) | tail +2; \
done
# @bench-balance-many-accts:
# quickbench -w hledger-1.26,hledger-21ad,ledger -f bench-many-accts.sh -N2
# #quickbench -w hledger-1.25,hledger-1.28,hledger-1.29,hledger-1.30,hledger-1.31,hledger-1.32,hledger-21ad,ledger -f bench-many-accts.sh -N2
# @bench-balance-many-txns:
# quickbench -w hledger-21ad,ledger -f bench-many-txns.sh -N2
# samplejournals bench.sh # samplejournals bench.sh
# bench: samplejournals tests/bench.tests tools/simplebench \ # bench: samplejournals tests/bench.tests tools/simplebench \
# $(call def-help,bench,\ # $(call def-help,bench,\
@ -674,7 +688,6 @@ compare-balance:
# run progression benchmark tests and save graphical results\ # run progression benchmark tests and save graphical results\
# ) # )
# tools/progressionbench -- -t png -k png # tools/progressionbench -- -t png -k png
# # prof: samplejournals \ # # prof: samplejournals \
# # $(call def-help,prof,\ # # $(call def-help,prof,\
# # generate and archive an execution profile\ # # generate and archive an execution profile\
@ -745,12 +758,6 @@ DOCUMENTING:
# see also Shake.hs # see also Shake.hs
# http://www.haskell.org/haddock/doc/html/invoking.html # http://www.haskell.org/haddock/doc/html/invoking.html
# optimise and commit RELEASING value map diagram
@releasediag:
pngquant doc/HledgerReleaseValueMap.png -f -o doc/HledgerReleaseValueMap.png
git add doc/HledgerReleaseValueMap.png
git commit -m ';doc: RELEASING: update value map' -- doc/HledgerReleaseValueMap.png
STACKHADDOCK := 'time ' + STACK + ' --verbosity=error haddock --fast --no-keep-going \ STACKHADDOCK := 'time ' + STACK + ' --verbosity=error haddock --fast --no-keep-going \
--only-locals --no-haddock-deps --no-haddock-hyperlink-source \ --only-locals --no-haddock-deps --no-haddock-hyperlink-source \
--haddock-arguments="--no-warnings" \ --haddock-arguments="--no-warnings" \
@ -832,95 +839,20 @@ haddock-open:
# @(printf "\nbrowser will open in $(BROWSEDELAY)s (adjust BROWSE in Makefile if needed)...\n\n"; sleep $(BROWSEDELAY); $(BROWSE) $(LOCALSITEURL)) & # @(printf "\nbrowser will open in $(BROWSEDELAY)s (adjust BROWSE in Makefile if needed)...\n\n"; sleep $(BROWSEDELAY); $(BROWSE) $(LOCALSITEURL)) &
# @$(WATCHEXEC) --print-events -e md,m4 -i hledger.md -i hledger-ui.md -i hledger-web.md -r './Shake webmanuals && ./Shake orgfiles && make -sC site serve' # @$(WATCHEXEC) --print-events -e md,m4 -i hledger.md -i hledger-ui.md -i hledger-web.md -r './Shake webmanuals && ./Shake orgfiles && make -sC site serve'
# ** Installing ------------------------------------------------------------ # optimise and commit RELEASING value map diagram
INSTALLING: @releasediag:
pngquant doc/HledgerReleaseValueMap.png -f -o doc/HledgerReleaseValueMap.png
# # copy the current ~/.local/bin/hledger to bin/old/hledger-VER git add doc/HledgerReleaseValueMap.png
# @copy-as VER: git commit -m ';doc: RELEASING: update value map' -- doc/HledgerReleaseValueMap.png
# cp ~/.local/bin/hledger bin/old/hledger-{{ VER }}; echo "bin/hledger-{{ VER }}"
# stack install, then copy the hledger executables to bin/old/hledger*-VER
@installas VER:
$STACK install --local-bin-path bin/old
for e in hledger hledger-ui hledger-web ; do cp bin/old/$e bin/old/$e-{{ VER }}; echo "bin/$e-{{ VER }}"; done
# # make must be GNU Make 4.3+
# .PHONY: shellcompletions
# # update shell completions in hledger package
# shellcompletions:
# make -C hledger/shell-completion/ clean-all all
# ** Releasing ------------------------------------------------------------
RELEASING:
# Symlink/copy important files temporarily in .relfiles/.
relfiles:
#!/usr/bin/env bash
echo "linking/copying important release files in .relfiles/ for convenient access..."
mkdir -p .relfiles
cd .relfiles
for f in \
../stack.yaml \
../Shake.hs \
../hledger-install/hledger-install.sh \
../CHANGES.md \
../hledger/CHANGES.md \
../hledger-ui/CHANGES.md \
../hledger-web/CHANGES.md \
../hledger-lib/CHANGES.md \
../doc/github-release.md \
../doc/ANNOUNCE \
../doc/ANNOUNCE.masto \
../site/src/release-notes.md \
../site/src/install.md \
; do ln -sf $f .; done
cp ../doc/RELEASING.md ./RELEASING2.md # temp copy which can be edited without disruption
# Prepare to release today, creating/switching to release branch, updating versions, dates, manuals, changelogs etc.
relprep VER:
#!/usr/bin/env bash
set -euo pipefail
[[ -z {{ VER }} ]] && usage
BRANCH=$(just _versionReleaseBranch {{ VER }})
COMMIT="-c"
echo "Switching to $BRANCH, auto-creating it if needed..."
just _gitSwitchAutoCreate "$BRANCH"
echo "Bumping all version strings to {{ VER }} ..."
./Shake setversion {{ VER }} $COMMIT
echo "Updating all command help texts for embedding..."
./Shake cmdhelp $COMMIT
echo "Updating all dates in man pages..."
./Shake mandates
echo "Generating all the manuals in all formats...."
./Shake manuals $COMMIT
echo "Updating CHANGES.md files with latest commits..."
./Shake changelogs $COMMIT
# Push the current branch to github to generate release binaries.
@relbin:
# assumes the github remote is named "github"
git push -f github HEAD:binaries
# Show last release date (of hledger package).
@reldate:
awk '/^#+ +[0-9]+\.[0-9].*([0-9]{4}-[0-9]{2}-[0-9]{2})/{print $3;exit}' hledger/CHANGES.md
# Show last release date and version (of hledger package).
@rel:
just rels | head -1
# Show all release dates and versions (of hledger package).
@rels:
awk '/^#+ +[0-9]+\.[0-9].*([0-9]{4}-[0-9]{2}-[0-9]{2})/{printf "%s %s\n",$3,$2}' hledger/CHANGES.md
# Convert DATEARG to an ISO date. It can be an ISO date, number of recent days, or nothing (meaning last release date). # Convert DATEARG to an ISO date. It can be an ISO date, number of recent days, or nothing (meaning last release date).
@datearg *DATEARG: @_datearg *DATEARG:
echo {{ if DATEARG == '' { `just reldate` } else { if DATEARG =~ '^\d+$' { `dateadd $(date +%Y-%m-%d) -$DATEARG` } else { DATEARG } } }} echo {{ if DATEARG == '' { `just reldate` } else { if DATEARG =~ '^\d+$' { `dateadd $(date +%Y-%m-%d) -$DATEARG` } else { DATEARG } } }}
# Show activity since (mostly) this date or days ago or last release. Eg: just log > log.org # Show activity since (mostly) this date or days ago or last release. Eg: just log > log.org
log *DATEARG: log *DATEARG:
#!/usr/bin/env osh #!/usr/bin/env osh
DATE=`just datearg $DATEARG` DATE=`just _datearg $DATEARG`
printf "* Activity since $DATE:\n\n" printf "* Activity since $DATE:\n\n"
printf "Last release: `just rel`\n\n" printf "Last release: `just rel`\n\n"
just chlog just chlog
@ -954,7 +886,7 @@ GITLG := "git log --format='%ad %h %s' --date=short"
# Show commits in the three repos since this date or days ago or last release, briefly. # Show commits in the three repos since this date or days ago or last release, briefly.
commitlog *DATEARG: commitlog *DATEARG:
#!/usr/bin/env osh #!/usr/bin/env osh
DATE=`just datearg $DATEARG` DATE=`just _datearg $DATEARG`
printf "** hledger commits\n\n" printf "** hledger commits\n\n"
{{ GITLG }} --since $DATE {{ GITLG }} --since $DATE
echo echo
@ -1037,16 +969,79 @@ bloglog:
echo "** pta.o: https://plaintextaccounting.org/#`date +%Y`" echo "** pta.o: https://plaintextaccounting.org/#`date +%Y`"
echo echo
# Some evil works against this.. # # Some evil works against this..
# echo "open https://www.reddit.com/r/plaintextaccounting/new, copy links since $DAYS days ago ($DATE), paste into obsidian, select, cut, and paste here for cleaning (in emacs shell use C-c C-d, C-c C-r)" # # echo "open https://www.reddit.com/r/plaintextaccounting/new, copy links since $DAYS days ago ($DATE), paste into obsidian, select, cut, and paste here for cleaning (in emacs shell use C-c C-d, C-c C-r)"
# just redditclean > $$.tmp # # just redditclean > $$.tmp
# printf "\n\n\n\n\n" # # printf "\n\n\n\n\n"
# cat $$.tmp # # cat $$.tmp
# rm -f $$.tmp # # rm -f $$.tmp
# # #
# Clean links copied from old.reddit.com. # # Clean links copied from old.reddit.com.
@redditclean: # @redditclean:
rg '^(\[.*?]\([^\)]+\)).*self.plaintextaccounting' -or '- $1\n' - # rg '^(\[.*?]\([^\)]+\)).*self.plaintextaccounting' -or '- $1\n' -
# ** Releasing ------------------------------------------------------------
RELEASING:
# Symlink/copy important files temporarily in .relfiles/.
relfiles:
#!/usr/bin/env bash
echo "linking/copying important release files in .relfiles/ for convenient access..."
mkdir -p .relfiles
cd .relfiles
for f in \
../stack.yaml \
../Shake.hs \
../hledger-install/hledger-install.sh \
../CHANGES.md \
../hledger/CHANGES.md \
../hledger-ui/CHANGES.md \
../hledger-web/CHANGES.md \
../hledger-lib/CHANGES.md \
../doc/github-release.md \
../doc/ANNOUNCE \
../doc/ANNOUNCE.masto \
../site/src/release-notes.md \
../site/src/install.md \
; do ln -sf $f .; done
cp ../doc/RELEASING.md ./RELEASING2.md # temp copy which can be edited without disruption
# Prepare to release today, creating/switching to release branch, updating versions, dates, manuals, changelogs etc.
relprep VER:
#!/usr/bin/env bash
set -euo pipefail
[[ -z {{ VER }} ]] && usage
BRANCH=$(just _versionReleaseBranch {{ VER }})
COMMIT="-c"
echo "Switching to $BRANCH, auto-creating it if needed..."
just _gitSwitchAutoCreate "$BRANCH"
echo "Bumping all version strings to {{ VER }} ..."
./Shake setversion {{ VER }} $COMMIT
echo "Updating all command help texts for embedding..."
./Shake cmdhelp $COMMIT
echo "Updating all dates in man pages..."
./Shake mandates
echo "Generating all the manuals in all formats...."
./Shake manuals $COMMIT
echo "Updating CHANGES.md files with latest commits..."
./Shake changelogs $COMMIT
# Push the current branch to github to generate release binaries.
@relbin:
# assumes the github remote is named "github"
git push -f github HEAD:binaries
# Show last release date (of hledger package).
@reldate:
awk '/^#+ +[0-9]+\.[0-9].*([0-9]{4}-[0-9]{2}-[0-9]{2})/{print $3;exit}' hledger/CHANGES.md
# Show last release date and version (of hledger package).
@rel:
just rels | head -1
# Show all release dates and versions (of hledger package).
@rels:
awk '/^#+ +[0-9]+\.[0-9].*([0-9]{4}-[0-9]{2}-[0-9]{2})/{printf "%s %s\n",$3,$2}' hledger/CHANGES.md
# *** hledger version number helpers # *** hledger version number helpers
# (as hidden recipes, since just doesn't support global custom functions) # (as hidden recipes, since just doesn't support global custom functions)
@ -1288,9 +1283,9 @@ sccv:
# ** Misc ------------------------------------------------------------ # ** Misc ------------------------------------------------------------
MISC: MISC:
# push to github CI, wait for tests to pass, then push to master # push to github CI, wait for tests to pass, refreshing every INTERVAL (default:10s), then push to master.
@push: @push *INTERVAL:
tools/push tools/push {{ INTERVAL }}
# run some tests to validate the development environment # run some tests to validate the development environment
# check-setup: # check-setup:
@ -1300,13 +1295,6 @@ MISC:
# @({{ SHELLTEST }} checks \ # @({{ SHELLTEST }} checks \
# && echo $@ PASSED) || echo $@ FAILED # && echo $@ PASSED) || echo $@ FAILED
# sym-link some directories required by hledger-web dev builds
mkwebdirs:
echo "#ln -sf hledger-web/config # disabled, causes makeinfo warnings"
ln -sf hledger-web/messages
ln -sf hledger-web/static
ln -sf hledger-web/templates
# Show activity over the last N days (eg 7), for This Week In Hledger. # Show activity over the last N days (eg 7), for This Week In Hledger.
@_lastweek DAYS: @_lastweek DAYS:
echo "hledger time last $DAYS days including today (this should be run on a Friday):" echo "hledger time last $DAYS days including today (this should be run on a Friday):"

View File

@ -1,5 +1,5 @@
#!/usr/bin/env stack #!/usr/bin/env stack
{- stack script --resolver nightly-2023-10-13 --compile {- stack script --resolver nightly-2024-02-28 --compile
--extra-include-dirs /Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/usr/include/ffi --extra-include-dirs /Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/usr/include/ffi
--package base-prelude --package base-prelude
--package directory --package directory

View File

@ -97,7 +97,7 @@ module Hledger.Data.Amount (
amountSetPrecisionMax, amountSetPrecisionMax,
withPrecision, withPrecision,
amountSetFullPrecision, amountSetFullPrecision,
amountSetFullPrecisionOr, amountSetFullPrecisionUpTo,
amountInternalPrecision, amountInternalPrecision,
amountDisplayPrecision, amountDisplayPrecision,
defaultMaxPrecision, defaultMaxPrecision,
@ -159,6 +159,7 @@ module Hledger.Data.Amount (
wbUnpack, wbUnpack,
mixedAmountSetPrecision, mixedAmountSetPrecision,
mixedAmountSetFullPrecision, mixedAmountSetFullPrecision,
mixedAmountSetFullPrecisionUpTo,
mixedAmountSetPrecisionMin, mixedAmountSetPrecisionMin,
mixedAmountSetPrecisionMax, mixedAmountSetPrecisionMax,
@ -453,24 +454,26 @@ amountSetFullPrecision a = amountSetPrecision p a
-- | We often want to display "infinite decimal" amounts rounded to some readable -- | We often want to display "infinite decimal" amounts rounded to some readable
-- number of digits, while still displaying amounts with a large "non infinite" number -- number of digits, while still displaying amounts with a large but "non infinite"
-- of decimal digits (eg, 100 or 200 digits) in full. -- number of decimal digits (eg 10 or 100 or 200 digits) in full.
-- This helper is like amountSetFullPrecision, but with some refinements: -- This helper is like amountSetFullPrecision, but with some refinements:
-- 1. If the internal precision is the maximum (255), indicating an infinite decimal, --
-- the display precision is set to a smaller hard-coded default (8). -- 1. A maximum display precision can be specified, setting a hard upper limit.
-- 2. A maximum display precision can be specified, setting a hard upper limit. --
-- 2. If no limit is specified, and the internal precision is the maximum (255),
-- indicating an infinite decimal, display precision is set to a smaller default (8).
--
-- This function always sets an explicit display precision (ie, Precision n). -- This function always sets an explicit display precision (ie, Precision n).
amountSetFullPrecisionOr :: Maybe Word8 -> Amount -> Amount --
amountSetFullPrecisionOr mmaxp a = amountSetPrecision (Precision p2) a amountSetFullPrecisionUpTo :: Maybe Word8 -> Amount -> Amount
amountSetFullPrecisionUpTo mmaxp a = amountSetPrecision (Precision p) a
where where
p1 = if -- dbg0 "maxdigits" $ p = case mmaxp of
amountHasMaxDigits a then defaultMaxPrecision else max disp intp Just maxp -> min maxp $ max disp intp
-- & dbg0 "p1" Nothing -> if amountHasMaxDigits a then defaultMaxPrecision else max disp intp
where where
intp = amountInternalPrecision a
disp = amountDisplayPrecision a disp = amountDisplayPrecision a
p2 = maybe p1 (min p1) mmaxp intp = amountInternalPrecision a
-- & dbg0 "p2"
-- | The fallback display precision used when showing amounts -- | The fallback display precision used when showing amounts
-- representing an infinite decimal. -- representing an infinite decimal.
@ -1228,6 +1231,14 @@ mixedAmountSetPrecision p = mapMixedAmountUnsafe (amountSetPrecision p)
mixedAmountSetFullPrecision :: MixedAmount -> MixedAmount mixedAmountSetFullPrecision :: MixedAmount -> MixedAmount
mixedAmountSetFullPrecision = mapMixedAmountUnsafe amountSetFullPrecision mixedAmountSetFullPrecision = mapMixedAmountUnsafe amountSetFullPrecision
-- | In each component amount, increase the display precision sufficiently
-- to render it exactly if possible, but not more than the given max precision,
-- and if no max precision is given and the amount has infinite decimals,
-- limit display precision to a hard-coded smaller number (8).
-- See amountSetFullPrecisionUpTo.
mixedAmountSetFullPrecisionUpTo :: Maybe Word8 -> MixedAmount -> MixedAmount
mixedAmountSetFullPrecisionUpTo mmaxp = mapMixedAmountUnsafe (amountSetFullPrecisionUpTo mmaxp)
-- | In each component amount, ensure the display precision is at least the given value. -- | In each component amount, ensure the display precision is at least the given value.
-- Makes all amounts have an explicit Precision. -- Makes all amounts have an explicit Precision.
mixedAmountSetPrecisionMin :: Word8 -> MixedAmount -> MixedAmount mixedAmountSetPrecisionMin :: Word8 -> MixedAmount -> MixedAmount

View File

@ -131,11 +131,17 @@ transactionCheckBalanced BalancingOpts{commodity_styles_} t = errs
rmsg rmsg
| rsumok = "" | rsumok = ""
| not rsignsok = "The real postings all have the same sign. Consider negating some of them." | not rsignsok = "The real postings all have the same sign. Consider negating some of them."
| otherwise = "The real postings' sum should be 0 but is: " ++ showMixedAmountOneLineWithoutCost False rsumcost | otherwise = "The real postings' sum should be 0 but is: " ++
(showMixedAmountWith oneLineNoCostFmt{displayCost=True, displayZeroCommodity=True} $
mixedAmountSetFullPrecisionUpTo Nothing $ mixedAmountSetFullPrecision
rsumcost)
bvmsg bvmsg
| bvsumok = "" | bvsumok = ""
| not bvsignsok = "The balanced virtual postings all have the same sign. Consider negating some of them." | not bvsignsok = "The balanced virtual postings all have the same sign. Consider negating some of them."
| otherwise = "The balanced virtual postings' sum should be 0 but is: " ++ showMixedAmountOneLineWithoutCost False bvsumcost | otherwise = "The balanced virtual postings' sum should be 0 but is: " ++
(showMixedAmountWith oneLineNoCostFmt{displayCost=True, displayZeroCommodity=True} $
mixedAmountSetFullPrecisionUpTo Nothing $ mixedAmountSetFullPrecision
bvsumcost)
-- | Legacy form of transactionCheckBalanced. -- | Legacy form of transactionCheckBalanced.
isTransactionBalanced :: BalancingOpts -> Transaction -> Bool isTransactionBalanced :: BalancingOpts -> Transaction -> Bool

View File

@ -63,6 +63,7 @@ module Hledger.Data.Dates (
spanIntersect, spanIntersect,
spansIntersect, spansIntersect,
spanDefaultsFrom, spanDefaultsFrom,
spanExtend,
spanUnion, spanUnion,
spansUnion, spansUnion,
daysSpan, daysSpan,
@ -314,8 +315,8 @@ groupByDateSpan showempty date colspans =
where where
groupByCols [] _ = [] groupByCols [] _ = []
groupByCols (c:cs) [] = if showempty then (c, []) : groupByCols cs [] else [] groupByCols (c:cs) [] = if showempty then (c, []) : groupByCols cs [] else []
groupByCols (c:cs) ps = (c, map snd matches) : groupByCols cs later groupByCols (c:cs) ps = (c, map snd colps) : groupByCols cs laterps
where (matches, later) = span ((spanEnd c >) . Just . fst) ps where (colps, laterps) = span ((spanEnd c >) . Just . fst) ps
beforeStart = maybe (const False) (>) $ spanStart =<< headMay colspans beforeStart = maybe (const False) (>) $ spanStart =<< headMay colspans
@ -324,40 +325,82 @@ spansIntersect [] = nulldatespan
spansIntersect [d] = d spansIntersect [d] = d
spansIntersect (d:ds) = d `spanIntersect` (spansIntersect ds) spansIntersect (d:ds) = d `spanIntersect` (spansIntersect ds)
-- | Calculate the intersection of two datespans.
--
-- For non-intersecting spans, gives an empty span beginning on the second's start date:
-- >>> DateSpan (Just $ Flex $ fromGregorian 2018 01 01) (Just $ Flex $ fromGregorian 2018 01 03) `spanIntersect` DateSpan (Just $ Flex $ fromGregorian 2018 01 03) (Just $ Flex $ fromGregorian 2018 01 05)
-- DateSpan 2018-01-03..2018-01-02
spanIntersect (DateSpan b1 e1) (DateSpan b2 e2) = DateSpan b e
where
b = latest b1 b2
e = earliest e1 e2
-- | Fill any unspecified dates in the first span with the dates from
-- the second one. Sort of a one-way spanIntersect.
spanDefaultsFrom (DateSpan a1 b1) (DateSpan a2 b2) = DateSpan a b
where a = if isJust a1 then a1 else a2
b = if isJust b1 then b1 else b2
-- | Calculate the union of a number of datespans. -- | Calculate the union of a number of datespans.
spansUnion [] = nulldatespan spansUnion [] = nulldatespan
spansUnion [d] = d spansUnion [d] = d
spansUnion (d:ds) = d `spanUnion` (spansUnion ds) spansUnion (d:ds) = d `spanUnion` (spansUnion ds)
-- | Calculate the intersection of two datespans.
--
-- For non-intersecting spans, gives an empty span beginning on the second's start date:
-- >>> DateSpan (Just $ Flex $ fromGregorian 2018 01 01) (Just $ Flex $ fromGregorian 2018 01 03) `spanIntersect` DateSpan (Just $ Flex $ fromGregorian 2018 01 03) (Just $ Flex $ fromGregorian 2018 01 05)
-- DateSpan 2018-01-03..2018-01-02
spanIntersect (DateSpan b1 e1) (DateSpan b2 e2) = DateSpan (laterDefinite b1 b2) (earlierDefinite e1 e2)
-- | Fill any unspecified dates in the first span with the dates from
-- the second one (if specified there). Sort of a one-way spanIntersect.
spanDefaultsFrom (DateSpan a1 b1) (DateSpan a2 b2) = DateSpan a b
where a = if isJust a1 then a1 else a2
b = if isJust b1 then b1 else b2
-- | Calculate the union of two datespans. -- | Calculate the union of two datespans.
spanUnion (DateSpan b1 e1) (DateSpan b2 e2) = DateSpan b e -- If either span is open-ended, the union will be too.
where --
b = earliest b1 b2 -- >>> ys2024 = fromGregorian 2024 01 01
e = latest e1 e2 -- >>> ys2025 = fromGregorian 2025 01 01
-- >>> to2024 = DateSpan Nothing (Just $ Exact ys2024)
-- >>> in2024 = DateSpan (Just $ Exact ys2024) (Just $ Exact ys2025)
-- >>> spanUnion to2024 in2024
-- DateSpan ..2024-12-31
-- >>> spanUnion in2024 to2024
-- DateSpan ..2024-12-31
spanUnion (DateSpan b1 e1) (DateSpan b2 e2) = DateSpan (earlier b1 b2) (later e1 e2)
latest d Nothing = d -- | Extend the first span to include any definite end dates of the second.
latest Nothing d = d -- Unlike spanUnion, open ends in the second are ignored.
latest (Just d1) (Just d2) = Just $ max d1 d2 -- If the first span was open-ended, it still will be after being extended.
--
-- >>> ys2024 = fromGregorian 2024 01 01
-- >>> ys2025 = fromGregorian 2025 01 01
-- >>> to2024 = DateSpan Nothing (Just $ Exact ys2024)
-- >>> all2024 = DateSpan (Just $ Exact ys2024) (Just $ Exact ys2025)
-- >>> partof2024 = DateSpan (Just $ Exact $ fromGregorian 2024 03 01) (Just $ Exact $ fromGregorian 2024 09 01)
-- >>> spanExtend to2024 all2024
-- DateSpan 2024
-- >>> spanExtend all2024 to2024
-- DateSpan 2024
-- >>> spanExtend partof2024 all2024
-- DateSpan 2024
-- >>> spanExtend all2024 partof2024
-- DateSpan 2024
--
spanExtend (DateSpan b1 e1) (DateSpan b2 e2) = DateSpan (earlierDefinite b1 b2) (laterDefinite e1 e2)
earliest d Nothing = d -- | Pick the earlier of two DateSpan starts, treating Nothing as infinitely early.
earliest Nothing d = d -- An Exact and Flex with the same date are considered equal; the first argument wins.
earliest (Just d1) (Just d2) = Just $ min d1 d2 earlier :: Maybe EFDay -> Maybe EFDay -> Maybe EFDay
earlier = min
-- | Pick the later of two DateSpan starts, treating Nothing as infinitely late.
-- An Exact and Flex with the same date are considered equal; the second argument wins.
later :: Maybe EFDay -> Maybe EFDay -> Maybe EFDay
later _ Nothing = Nothing
later Nothing _ = Nothing
later d1 d2 = max d1 d2
-- | Pick the earlier of two DateSpan ends that is a definite date (if any).
-- An Exact and Flex with the same date are considered equal; the first argument wins.
earlierDefinite :: Maybe EFDay -> Maybe EFDay -> Maybe EFDay
earlierDefinite d1 Nothing = d1
earlierDefinite Nothing d2 = d2
earlierDefinite d1 d2 = min d1 d2
-- | Pick the later of two DateSpan ends that is a definite date (if any).
-- An Exact and Flex with the same date are considered equal; the second argument wins.
laterDefinite :: Maybe EFDay -> Maybe EFDay -> Maybe EFDay
laterDefinite d1 Nothing = d1
laterDefinite Nothing d2 = d2
laterDefinite d1 d2 = max d1 d2
-- | Calculate the minimal DateSpan containing all of the given Days (in the -- | Calculate the minimal DateSpan containing all of the given Days (in the
-- usual exclusive-end-date sense: beginning on the earliest, and ending on -- usual exclusive-end-date sense: beginning on the earliest, and ending on

View File

@ -115,7 +115,7 @@ amountPriceDirectiveFromCost :: Day -> Amount -> Maybe PriceDirective
amountPriceDirectiveFromCost d amt@Amount{acommodity=fromcomm, aquantity=n} = case acost amt of amountPriceDirectiveFromCost d amt@Amount{acommodity=fromcomm, aquantity=n} = case acost amt of
Just (UnitCost u) -> Just $ pd{pdamount=u} Just (UnitCost u) -> Just $ pd{pdamount=u}
Just (TotalCost t) | n /= 0 -> Just $ pd{pdamount=u} Just (TotalCost t) | n /= 0 -> Just $ pd{pdamount=u}
where u = amountSetFullPrecisionOr Nothing $ divideAmount n t where u = amountSetFullPrecisionUpTo Nothing $ divideAmount n t
_ -> Nothing _ -> Nothing
where where
pd = PriceDirective{pddate = d, pdcommodity = fromcomm, pdamount = nullamt} pd = PriceDirective{pddate = d, pdcommodity = fromcomm, pdamount = nullamt}
@ -209,7 +209,7 @@ amountValueAtDate priceoracle styles mto d a =
-- set the display precision to match the internal precision (showing all digits), -- set the display precision to match the internal precision (showing all digits),
-- unnormalised (don't strip trailing zeros); -- unnormalised (don't strip trailing zeros);
-- but if it looks like an infinite decimal, limit the precision to 8. -- but if it looks like an infinite decimal, limit the precision to 8.
& amountSetFullPrecisionOr Nothing & amountSetFullPrecisionUpTo Nothing
& dbg9With (lbl "calculated value".showAmount) & dbg9With (lbl "calculated value".showAmount)
-- | Calculate the gain of each component amount, that is the difference -- | Calculate the gain of each component amount, that is the difference

View File

@ -696,7 +696,7 @@ reportSpanHelper bothdates j ReportSpec{_rsQuery=query, _rsReportOpts=ropts} =
_ -> Nothing _ -> Nothing
-- If the requested span is open-ended, close it using the journal's start and end dates. -- If the requested span is open-ended, close it using the journal's start and end dates.
-- This can still be the null (open) span if the journal is empty. -- This can still be the null (open) span if the journal is empty.
requestedspan' = dbg3 "requestedspan'" $ requestedspan `spanDefaultsFrom` (journalspan `spanUnion` pricespan) requestedspan' = dbg3 "requestedspan'" $ requestedspan `spanDefaultsFrom` (journalspan `spanExtend` pricespan)
-- The list of interval spans enclosing the requested span. -- The list of interval spans enclosing the requested span.
-- This list can be empty if the journal was empty, -- This list can be empty if the journal was empty,
-- or if hledger-ui has added its special date:-tomorrow to the query -- or if hledger-ui has added its special date:-tomorrow to the query

View File

@ -341,9 +341,11 @@ This is very useful when reconciling. A good workflow is to have
your bank's online register open in a browser window, for reference; your bank's online register open in a browser window, for reference;
the journal file open in an editor window; the journal file open in an editor window;
and hledger-ui in watch mode in a terminal window, eg: and hledger-ui in watch mode in a terminal window, eg:
```cli ```cli
$ hledger-ui --watch --register checking -C $ hledger-ui --watch --register checking -C
``` ```
As you mark things cleared in the editor, As you mark things cleared in the editor,
you can see the effect immediately without having to context switch. you can see the effect immediately without having to context switch.
This leaves more mental bandwidth for your accounting. This leaves more mental bandwidth for your accounting.

View File

@ -95,7 +95,7 @@ accountOnlyQuery = ("inacctonly:" <>) . quoteIfSpaced
mixedAmountAsHtml :: MixedAmount -> HtmlUrl a mixedAmountAsHtml :: MixedAmount -> HtmlUrl a
mixedAmountAsHtml b _ = mixedAmountAsHtml b _ =
for_ (lines (showMixedAmountWithoutCost False b)) $ \t -> do for_ (lines (showMixedAmountWith noCostFmt{displayZeroCommodity=True} b)) $ \t -> do
H.span ! A.class_ c $ toHtml t H.span ! A.class_ c $ toHtml t
H.br H.br
where where

View File

@ -129,6 +129,12 @@ Query options and arguments may be used to set an initial filter,
which although not shown in the UI, will restrict the data shown, which although not shown in the UI, will restrict the data shown,
in addition to any search query entered in the UI. in addition to any search query entered in the UI.
Note that hledger-web shows accounts with zero balances by default, like `hledger-ui` (and unlike `hledger`).
Using the `-E/--empty` flag at startup will hide them.
If you see accounts which appear to have a zero balance, but cannot be hidden with `-E`:
these have a mixed-cost balance which looks like zero when costs are hidden.
Currently hledger-web does not show costs at all.
## General help options ## General help options

View File

@ -17,9 +17,9 @@ $forall (acct, adisplay, aindent, abal) <- items
$if hasSubAccounts acct $if hasSubAccounts acct
<a href="@?{(registerR, [("q", replaceInacct qparam $ accountOnlyQuery acct)])}" .only.hidden-sm.hidden-xs <a href="@?{(registerR, [("q", replaceInacct qparam $ accountOnlyQuery acct)])}" .only.hidden-sm.hidden-xs
title="Show transactions affecting this account but not subaccounts">only title="Show transactions affecting this account but not subaccounts">only
<td> <td .amount>
^{mixedAmountAsHtml abal} ^{mixedAmountAsHtml abal}
<tr .total> <tr .total>
<td> <td>
<td> <td .amount>
^{mixedAmountAsHtml total} ^{mixedAmountAsHtml total}

View File

@ -33,9 +33,9 @@ Features:
- If you make a mistake, enter `<` at any prompt to go one step backward. - If you make a mistake, enter `<` at any prompt to go one step backward.
- Input prompts are displayed in a different colour when the terminal supports it. - Input prompts are displayed in a different colour when the terminal supports it.
Example (see https://hledger.org/add.html for a detailed tutorial): Example (see <https://hledger.org/add.html> for a detailed tutorial):
``` shell ```cli
$ hledger add $ hledger add
Adding transactions to journal file /src/hledger/examples/sample.journal Adding transactions to journal file /src/hledger/examples/sample.journal
Any command line arguments will be used as defaults. Any command line arguments will be used as defaults.

View File

@ -39,6 +39,7 @@ Many of these work with the higher-level commands as well.
- or value of balance changes ([`-V`](#valuation-type)) - or value of balance changes ([`-V`](#valuation-type))
- or change of balance values ([`--valuechange`](#balance-report-types)) - or change of balance values ([`--valuechange`](#balance-report-types))
- or unrealised capital gain/loss ([`--gain`](#balance-report-types)) - or unrealised capital gain/loss ([`--gain`](#balance-report-types))
- or balance changes from sibling postings (`--related`/`-r`)
- or postings count ([`--count`](#balance-report-types)) - or postings count ([`--count`](#balance-report-types))
..in.. ..in..
@ -77,9 +78,6 @@ This command supports the
with output formats `txt`, `csv`, `tsv` (*Added in 1.32*), `json`, and (multi-period reports only:) `html`. with output formats `txt`, `csv`, `tsv` (*Added in 1.32*), `json`, and (multi-period reports only:) `html`.
In `txt` output in a colour-supporting terminal, negative amounts are shown in red. In `txt` output in a colour-supporting terminal, negative amounts are shown in red.
The `--related`/`-r` flag shows the balance of the *other* postings in the
transactions of the postings which would normally be shown.
### Simple balance report ### Simple balance report
With no arguments, `balance` shows a list of all accounts and their With no arguments, `balance` shows a list of all accounts and their
@ -189,6 +187,7 @@ Some example formats:
[valuation]: #valuation [valuation]: #valuation
[valuation date(s)]: #valuation-date [valuation date(s)]: #valuation-date
[valuation commodity]: #valuation-commodity [valuation commodity]: #valuation-commodity
### Filtered balance report ### Filtered balance report
You can show fewer accounts, a different time period, totals from You can show fewer accounts, a different time period, totals from
@ -371,7 +370,9 @@ Multi-period reports with many periods can be too wide for easy viewing in the t
Here are some ways to handle that: Here are some ways to handle that:
- Hide the totals row with `-N/--no-total` - Hide the totals row with `-N/--no-total`
- Convert to a single currency with `-V` - Filter to a single currency with `cur:`
- Convert to a single currency with `-V [--infer-market-price]`
- Use a more compact layout like `--layout=bare`
- Maximize the terminal window - Maximize the terminal window
- Reduce the terminal's font size - Reduce the terminal's font size
- View with a pager like less, eg: `hledger bal -D --color=yes | less -RS` - View with a pager like less, eg: `hledger bal -D --color=yes | less -RS`
@ -440,13 +441,13 @@ It is one of:
#### Accumulation type #### Accumulation type
How amounts should accumulate across report periods. How amounts should accumulate across a report's subperiods/columns.
Another way to say it: which time period's postings should contribute to each cell's calculation. Another way to say it: which time period's postings should contribute to each cell's calculation.
It is one of: It is one of:
- `--change` : calculate with postings from column start to column end, ie "just this column". - `--change` : calculate with postings from column start to column end, ie "just this column".
Typically used to see revenues/expenses. Typically used to see revenues/expenses.
(**default for balance, incomestatement**) (**default for balance, cashflow, incomestatement**)
- `--cumulative` : calculate with postings from report start to column end, ie "previous columns plus this column". - `--cumulative` : calculate with postings from report start to column end, ie "previous columns plus this column".
Typically used to show changes accumulated since the report's start date. Typically used to show changes accumulated since the report's start date.
@ -455,7 +456,7 @@ It is one of:
- `--historical/-H` : calculate with postings from journal start to column end, - `--historical/-H` : calculate with postings from journal start to column end,
ie "all postings from before report start date until this column's end". ie "all postings from before report start date until this column's end".
Typically used to see historical end balances of assets/liabilities/equity. Typically used to see historical end balances of assets/liabilities/equity.
(**default for balancesheet, balancesheetequity, cashflow**) (**default for balancesheet, balancesheetequity**)
#### Valuation type #### Valuation type
@ -658,30 +659,16 @@ and then select from multiple budgets defined in your journal.
#### Budgeting vs forecasting #### Budgeting vs forecasting
`--budget` and `--forecast` both use the periodic transaction rules in the journal to generate temporary transactions for reporting purposes. `--forecast` and `--budget` both use the periodic transaction rules in the journal to generate temporary transactions for reporting purposes.
However they are separate features - though you can use both at the same time if you want. However they are separate features - though you can use both at the same time if you want.
Here are some differences between them: Here are some differences between them:
1. `--budget` is a command-specific option; it selects the **budget report**. | --forecast | --budget |
|------------|----------|
`--forecast` is a general option; **forecasting works with all reports**. | is a general option; it enables forecasting with all reports | is a balance command option; it selects the balance report's budget mode |
| generates visible transactions which appear in reports | generates invisible transactions which produce goal amounts |
2. `--budget` uses **all periodic rules**; `--budget=DESCPAT` uses **just the rules matched** by DESCPAT. | generates forecast transactions from after the last regular transaction, to the end of the report period; or with an argument `--forecast=PERIODEXPR` generates them throughout the specified period, both optionally restricted by periods specified in the periodic transaction rules | generates budget goal transactions throughout the report period, optionally restricted by periods specified in the periodic transaction rules |
| uses all periodic rules | uses all periodic rules; or with an argument `--budget=DESCPAT` uses just the rules matched by DESCPAT |
`--forecast` uses **all periodic rules**.
3. `--budget`'s budget goal transactions are invisible, except that they produce **goal amounts**.
`--forecast`'s forecast transactions are visible, and **appear in reports**.
4. `--budget` generates budget goal transactions **throughout the report period**,
optionally restricted by periods specified in the periodic transaction rules.
`--forecast` generates forecast transactions
from **after the last regular transaction**, to the end of the report period;
while `--forecast=PERIODEXPR` generates them **throughout the specified period**;
both optionally restricted by periods specified in the periodic transaction rules.
### Balance report layout ### Balance report layout
@ -695,8 +682,8 @@ It has four possible values:
- `--layout=bare`: commodity symbols are in their own column, amounts are bare numbers - `--layout=bare`: commodity symbols are in their own column, amounts are bare numbers
- `--layout=tidy`: data is normalised to easily-consumed "tidy" form, with one row per data value - `--layout=tidy`: data is normalised to easily-consumed "tidy" form, with one row per data value
Here are the `--layout` modes supported by each [output format](#output-format); Here are the `--layout` modes supported by each [output format](#output-format)
note only CSV output supports all of them: Only CSV output supports all of them:
| - | txt | csv | html | json | sql | | - | txt | csv | html | json | sql |
|------|-----|-----|------|------|-----| |------|-----|-----|------|------|-----|
@ -707,119 +694,122 @@ note only CSV output supports all of them:
Examples: Examples:
- Wide layout. With many commodities, reports can be very wide: #### Wide layout
```cli With many commodities, reports can be very wide:
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=wide ```cli
Balance changes in 2012-01-01..2014-12-31: $ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=wide
Balance changes in 2012-01-01..2014-12-31:
|| 2012 2013 2014 Total
==================++====================================================================================================================================================================================================================
Assets:US:ETrade || 10.00 ITOT, 337.18 USD, 12.00 VEA, 106.00 VHT 70.00 GLD, 18.00 ITOT, -98.12 USD, 10.00 VEA, 18.00 VHT -11.00 ITOT, 4881.44 USD, 14.00 VEA, 170.00 VHT 70.00 GLD, 17.00 ITOT, 5120.50 USD, 36.00 VEA, 294.00 VHT
------------------++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|| 10.00 ITOT, 337.18 USD, 12.00 VEA, 106.00 VHT 70.00 GLD, 18.00 ITOT, -98.12 USD, 10.00 VEA, 18.00 VHT -11.00 ITOT, 4881.44 USD, 14.00 VEA, 170.00 VHT 70.00 GLD, 17.00 ITOT, 5120.50 USD, 36.00 VEA, 294.00 VHT
```
- Limited wide layout. A width limit reduces the width, but some commodities will be hidden: || 2012 2013 2014 Total
```cli ==================++====================================================================================================================================================================================================================
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=wide,32 Assets:US:ETrade || 10.00 ITOT, 337.18 USD, 12.00 VEA, 106.00 VHT 70.00 GLD, 18.00 ITOT, -98.12 USD, 10.00 VEA, 18.00 VHT -11.00 ITOT, 4881.44 USD, 14.00 VEA, 170.00 VHT 70.00 GLD, 17.00 ITOT, 5120.50 USD, 36.00 VEA, 294.00 VHT
Balance changes in 2012-01-01..2014-12-31: ------------------++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|| 10.00 ITOT, 337.18 USD, 12.00 VEA, 106.00 VHT 70.00 GLD, 18.00 ITOT, -98.12 USD, 10.00 VEA, 18.00 VHT -11.00 ITOT, 4881.44 USD, 14.00 VEA, 170.00 VHT 70.00 GLD, 17.00 ITOT, 5120.50 USD, 36.00 VEA, 294.00 VHT
|| 2012 2013 2014 Total ```
==================++===========================================================================================================================
Assets:US:ETrade || 10.00 ITOT, 337.18 USD, 2 more.. 70.00 GLD, 18.00 ITOT, 3 more.. -11.00 ITOT, 3 more.. 70.00 GLD, 17.00 ITOT, 3 more..
------------------++---------------------------------------------------------------------------------------------------------------------------
|| 10.00 ITOT, 337.18 USD, 2 more.. 70.00 GLD, 18.00 ITOT, 3 more.. -11.00 ITOT, 3 more.. 70.00 GLD, 17.00 ITOT, 3 more..
```
- Tall layout. Each commodity gets a new line (may be different in each column), and account names are repeated: A width limit reduces the width, but some commodities will be hidden:
```cli ```cli
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=tall $ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=wide,32
Balance changes in 2012-01-01..2014-12-31: Balance changes in 2012-01-01..2014-12-31:
|| 2012 2013 2014 Total
==================++==================================================
Assets:US:ETrade || 10.00 ITOT 70.00 GLD -11.00 ITOT 70.00 GLD
Assets:US:ETrade || 337.18 USD 18.00 ITOT 4881.44 USD 17.00 ITOT
Assets:US:ETrade || 12.00 VEA -98.12 USD 14.00 VEA 5120.50 USD
Assets:US:ETrade || 106.00 VHT 10.00 VEA 170.00 VHT 36.00 VEA
Assets:US:ETrade || 18.00 VHT 294.00 VHT
------------------++--------------------------------------------------
|| 10.00 ITOT 70.00 GLD -11.00 ITOT 70.00 GLD
|| 337.18 USD 18.00 ITOT 4881.44 USD 17.00 ITOT
|| 12.00 VEA -98.12 USD 14.00 VEA 5120.50 USD
|| 106.00 VHT 10.00 VEA 170.00 VHT 36.00 VEA
|| 18.00 VHT 294.00 VHT
```
- Bare layout. Commodity symbols are kept in one column, each commodity gets its own report row, account names are repeated: || 2012 2013 2014 Total
```cli ==================++===========================================================================================================================
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=bare Assets:US:ETrade || 10.00 ITOT, 337.18 USD, 2 more.. 70.00 GLD, 18.00 ITOT, 3 more.. -11.00 ITOT, 3 more.. 70.00 GLD, 17.00 ITOT, 3 more..
Balance changes in 2012-01-01..2014-12-31: ------------------++---------------------------------------------------------------------------------------------------------------------------
|| 10.00 ITOT, 337.18 USD, 2 more.. 70.00 GLD, 18.00 ITOT, 3 more.. -11.00 ITOT, 3 more.. 70.00 GLD, 17.00 ITOT, 3 more..
|| Commodity 2012 2013 2014 Total ```
==================++=============================================
Assets:US:ETrade || GLD 0 70.00 0 70.00
Assets:US:ETrade || ITOT 10.00 18.00 -11.00 17.00
Assets:US:ETrade || USD 337.18 -98.12 4881.44 5120.50
Assets:US:ETrade || VEA 12.00 10.00 14.00 36.00
Assets:US:ETrade || VHT 106.00 18.00 170.00 294.00
------------------++---------------------------------------------
|| GLD 0 70.00 0 70.00
|| ITOT 10.00 18.00 -11.00 17.00
|| USD 337.18 -98.12 4881.44 5120.50
|| VEA 12.00 10.00 14.00 36.00
|| VHT 106.00 18.00 170.00 294.00
```
- Bare layout also affects [CSV output](#output-format), #### Tall layout
which is useful for producing data that is easier to consume, eg for making charts: Each commodity gets a new line (may be different in each column), and account names are repeated:
```cli ```cli
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -O csv --layout=bare $ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=tall
"account","commodity","balance" Balance changes in 2012-01-01..2014-12-31:
"Assets:US:ETrade","GLD","70.00"
"Assets:US:ETrade","ITOT","17.00"
"Assets:US:ETrade","USD","5120.50"
"Assets:US:ETrade","VEA","36.00"
"Assets:US:ETrade","VHT","294.00"
"total","GLD","70.00"
"total","ITOT","17.00"
"total","USD","5120.50"
"total","VEA","36.00"
"total","VHT","294.00"
```
- Note: bare layout will sometimes display an extra row for the no-symbol commodity, || 2012 2013 2014 Total
because of zero amounts (hledger treats zeroes as commodity-less, usually). ==================++==================================================
This can break `hledger-bar` confusingly (workaround: add a `cur:` query to exclude Assets:US:ETrade || 10.00 ITOT 70.00 GLD -11.00 ITOT 70.00 GLD
the no-symbol row). Assets:US:ETrade || 337.18 USD 18.00 ITOT 4881.44 USD 17.00 ITOT
Assets:US:ETrade || 12.00 VEA -98.12 USD 14.00 VEA 5120.50 USD
Assets:US:ETrade || 106.00 VHT 10.00 VEA 170.00 VHT 36.00 VEA
Assets:US:ETrade || 18.00 VHT 294.00 VHT
------------------++--------------------------------------------------
|| 10.00 ITOT 70.00 GLD -11.00 ITOT 70.00 GLD
|| 337.18 USD 18.00 ITOT 4881.44 USD 17.00 ITOT
|| 12.00 VEA -98.12 USD 14.00 VEA 5120.50 USD
|| 106.00 VHT 10.00 VEA 170.00 VHT 36.00 VEA
|| 18.00 VHT 294.00 VHT
```
- Tidy layout produces normalised "tidy data", where every variable #### Bare layout
has its own column and each row represents a single data point. Commodity symbols are kept in one column, each commodity has its own row,
See <https://cran.r-project.org/web/packages/tidyr/vignettes/tidy-data.html> for more. amounts are bare numbers, account names are repeated:
This is the easiest kind of data for other software to consume. ```cli
Here's how it looks: $ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=bare
Balance changes in 2012-01-01..2014-12-31:
```cli
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -Y -O csv --layout=tidy
"account","period","start_date","end_date","commodity","value"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","GLD","0"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","ITOT","10.00"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","USD","337.18"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","VEA","12.00"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","VHT","106.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","GLD","70.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","ITOT","18.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","USD","-98.12"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","VEA","10.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","VHT","18.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","GLD","0"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","ITOT","-11.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","USD","4881.44"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","VEA","14.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","VHT","170.00"
```
### Useful balance reports || Commodity 2012 2013 2014 Total
==================++=============================================
Assets:US:ETrade || GLD 0 70.00 0 70.00
Assets:US:ETrade || ITOT 10.00 18.00 -11.00 17.00
Assets:US:ETrade || USD 337.18 -98.12 4881.44 5120.50
Assets:US:ETrade || VEA 12.00 10.00 14.00 36.00
Assets:US:ETrade || VHT 106.00 18.00 170.00 294.00
------------------++---------------------------------------------
|| GLD 0 70.00 0 70.00
|| ITOT 10.00 18.00 -11.00 17.00
|| USD 337.18 -98.12 4881.44 5120.50
|| VEA 12.00 10.00 14.00 36.00
|| VHT 106.00 18.00 170.00 294.00
```
Bare layout also affects [CSV output](#output-format),
which is useful for producing data that is easier to consume, eg for making charts:
```cli
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -O csv --layout=bare
"account","commodity","balance"
"Assets:US:ETrade","GLD","70.00"
"Assets:US:ETrade","ITOT","17.00"
"Assets:US:ETrade","USD","5120.50"
"Assets:US:ETrade","VEA","36.00"
"Assets:US:ETrade","VHT","294.00"
"total","GLD","70.00"
"total","ITOT","17.00"
"total","USD","5120.50"
"total","VEA","36.00"
"total","VHT","294.00"
```
Bare layout will sometimes display an extra row for the no-symbol commodity,
because of zero amounts (hledger treats zeroes as commodity-less, usually).
This can break `hledger-bar` confusingly (workaround: add a `cur:` query to exclude
the no-symbol row).
#### Tidy layout
This produces normalised "tidy data" (see <https://cran.r-project.org/web/packages/tidyr/vignettes/tidy-data.html>)
where every variable has its own column and each row represents a single data point.
This is the easiest kind of data for other software to consume:
```cli
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -Y -O csv --layout=tidy
"account","period","start_date","end_date","commodity","value"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","GLD","0"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","ITOT","10.00"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","USD","337.18"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","VEA","12.00"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","VHT","106.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","GLD","70.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","ITOT","18.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","USD","-98.12"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","VEA","10.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","VHT","18.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","GLD","0"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","ITOT","-11.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","USD","4881.44"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","VEA","14.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","VHT","170.00"
```
### Some useful balance reports
Some frequently used `balance` options/reports are: Some frequently used `balance` options/reports are:

View File

@ -35,6 +35,7 @@ balance can show..
- or value of balance changes (-V) - or value of balance changes (-V)
- or change of balance values (--valuechange) - or change of balance values (--valuechange)
- or unrealised capital gain/loss (--gain) - or unrealised capital gain/loss (--gain)
- or balance changes from sibling postings (--related/-r)
- or postings count (--count) - or postings count (--count)
..in.. ..in..
@ -70,9 +71,6 @@ with output formats txt, csv, tsv (Added in 1.32), json, and
(multi-period reports only:) html. In txt output in a colour-supporting (multi-period reports only:) html. In txt output in a colour-supporting
terminal, negative amounts are shown in red. terminal, negative amounts are shown in red.
The --related/-r flag shows the balance of the other postings in the
transactions of the postings which would normally be shown.
Simple balance report Simple balance report
With no arguments, balance shows a list of all accounts and their change With no arguments, balance shows a list of all accounts and their change
@ -343,7 +341,9 @@ Multi-period reports with many periods can be too wide for easy viewing
in the terminal. Here are some ways to handle that: in the terminal. Here are some ways to handle that:
- Hide the totals row with -N/--no-total - Hide the totals row with -N/--no-total
- Convert to a single currency with -V - Filter to a single currency with cur:
- Convert to a single currency with -V [--infer-market-price]
- Use a more compact layout like --layout=bare
- Maximize the terminal window - Maximize the terminal window
- Reduce the terminal's font size - Reduce the terminal's font size
- View with a pager like less, eg: - View with a pager like less, eg:
@ -415,13 +415,13 @@ The basic calculation to perform for each table cell. It is one of:
Accumulation type Accumulation type
How amounts should accumulate across report periods. Another way to say How amounts should accumulate across a report's subperiods/columns.
it: which time period's postings should contribute to each cell's Another way to say it: which time period's postings should contribute to
calculation. It is one of: each cell's calculation. It is one of:
- --change : calculate with postings from column start to column end, - --change : calculate with postings from column start to column end,
ie "just this column". Typically used to see revenues/expenses. ie "just this column". Typically used to see revenues/expenses.
(default for balance, incomestatement) (default for balance, cashflow, incomestatement)
- --cumulative : calculate with postings from report start to column - --cumulative : calculate with postings from report start to column
end, ie "previous columns plus this column". Typically used to show end, ie "previous columns plus this column". Typically used to show
@ -431,7 +431,7 @@ calculation. It is one of:
column end, ie "all postings from before report start date until column end, ie "all postings from before report start date until
this column's end". Typically used to see historical end balances of this column's end". Typically used to see historical end balances of
assets/liabilities/equity. (default for balancesheet, assets/liabilities/equity. (default for balancesheet,
balancesheetequity, cashflow) balancesheetequity)
Valuation type Valuation type
@ -659,35 +659,35 @@ defined in your journal.
Budgeting vs forecasting Budgeting vs forecasting
--budget and --forecast both use the periodic transaction rules in the --forecast and --budget both use the periodic transaction rules in the
journal to generate temporary transactions for reporting purposes. journal to generate temporary transactions for reporting purposes.
However they are separate features - though you can use both at the same However they are separate features - though you can use both at the same
time if you want. Here are some differences between them: time if you want. Here are some differences between them:
1. --budget is a command-specific option; it selects the budget report. -----------------------------------------------------------------------
--forecast --budget
-------------------------------------- --------------------------------
is a general option; it enables is a balance command option; it
forecasting with all reports selects the balance report's
budget mode
--forecast is a general option; forecasting works with all reports. generates visible transactions which generates invisible transactions
appear in reports which produce goal amounts
2. --budget uses all periodic rules; --budget=DESCPAT uses just the generates forecast transactions from generates budget goal
rules matched by DESCPAT. after the last regular transaction, to transactions throughout the
the end of the report period; or with report period, optionally
an argument --forecast=PERIODEXPR restricted by periods specified
generates them throughout the in the periodic transaction
specified period, both optionally rules
restricted by periods specified in the
periodic transaction rules
--forecast uses all periodic rules. uses all periodic rules uses all periodic rules; or with
an argument --budget=DESCPAT
3. --budget's budget goal transactions are invisible, except that they uses just the rules matched by
produce goal amounts. DESCPAT
-----------------------------------------------------------------------
--forecast's forecast transactions are visible, and appear in
reports.
4. --budget generates budget goal transactions throughout the report
period, optionally restricted by periods specified in the periodic
transaction rules.
--forecast generates forecast transactions from after the last
regular transaction, to the end of the report period; while
--forecast=PERIODEXPR generates them throughout the specified
period; both optionally restricted by periods specified in the
periodic transaction rules.
Balance report layout Balance report layout
@ -704,8 +704,8 @@ four possible values:
- --layout=tidy: data is normalised to easily-consumed "tidy" form, - --layout=tidy: data is normalised to easily-consumed "tidy" form,
with one row per data value with one row per data value
Here are the --layout modes supported by each output format; note only Here are the --layout modes supported by each output format Only CSV
CSV output supports all of them: output supports all of them:
- txt csv html json sql - txt csv html json sql
------ ----- ----- ------ ------ ----- ------ ----- ----- ------ ------ -----
@ -716,115 +716,122 @@ CSV output supports all of them:
Examples: Examples:
- Wide layout. With many commodities, reports can be very wide: Wide layout
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=wide With many commodities, reports can be very wide:
Balance changes in 2012-01-01..2014-12-31:
|| 2012 2013 2014 Total $ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=wide
==================++==================================================================================================================================================================================================================== Balance changes in 2012-01-01..2014-12-31:
Assets:US:ETrade || 10.00 ITOT, 337.18 USD, 12.00 VEA, 106.00 VHT 70.00 GLD, 18.00 ITOT, -98.12 USD, 10.00 VEA, 18.00 VHT -11.00 ITOT, 4881.44 USD, 14.00 VEA, 170.00 VHT 70.00 GLD, 17.00 ITOT, 5120.50 USD, 36.00 VEA, 294.00 VHT
------------------++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|| 10.00 ITOT, 337.18 USD, 12.00 VEA, 106.00 VHT 70.00 GLD, 18.00 ITOT, -98.12 USD, 10.00 VEA, 18.00 VHT -11.00 ITOT, 4881.44 USD, 14.00 VEA, 170.00 VHT 70.00 GLD, 17.00 ITOT, 5120.50 USD, 36.00 VEA, 294.00 VHT
- Limited wide layout. A width limit reduces the width, but some || 2012 2013 2014 Total
commodities will be hidden: ==================++====================================================================================================================================================================================================================
Assets:US:ETrade || 10.00 ITOT, 337.18 USD, 12.00 VEA, 106.00 VHT 70.00 GLD, 18.00 ITOT, -98.12 USD, 10.00 VEA, 18.00 VHT -11.00 ITOT, 4881.44 USD, 14.00 VEA, 170.00 VHT 70.00 GLD, 17.00 ITOT, 5120.50 USD, 36.00 VEA, 294.00 VHT
------------------++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|| 10.00 ITOT, 337.18 USD, 12.00 VEA, 106.00 VHT 70.00 GLD, 18.00 ITOT, -98.12 USD, 10.00 VEA, 18.00 VHT -11.00 ITOT, 4881.44 USD, 14.00 VEA, 170.00 VHT 70.00 GLD, 17.00 ITOT, 5120.50 USD, 36.00 VEA, 294.00 VHT
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=wide,32 A width limit reduces the width, but some commodities will be hidden:
Balance changes in 2012-01-01..2014-12-31:
|| 2012 2013 2014 Total $ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=wide,32
==================++=========================================================================================================================== Balance changes in 2012-01-01..2014-12-31:
Assets:US:ETrade || 10.00 ITOT, 337.18 USD, 2 more.. 70.00 GLD, 18.00 ITOT, 3 more.. -11.00 ITOT, 3 more.. 70.00 GLD, 17.00 ITOT, 3 more..
------------------++---------------------------------------------------------------------------------------------------------------------------
|| 10.00 ITOT, 337.18 USD, 2 more.. 70.00 GLD, 18.00 ITOT, 3 more.. -11.00 ITOT, 3 more.. 70.00 GLD, 17.00 ITOT, 3 more..
- Tall layout. Each commodity gets a new line (may be different in || 2012 2013 2014 Total
each column), and account names are repeated: ==================++===========================================================================================================================
Assets:US:ETrade || 10.00 ITOT, 337.18 USD, 2 more.. 70.00 GLD, 18.00 ITOT, 3 more.. -11.00 ITOT, 3 more.. 70.00 GLD, 17.00 ITOT, 3 more..
------------------++---------------------------------------------------------------------------------------------------------------------------
|| 10.00 ITOT, 337.18 USD, 2 more.. 70.00 GLD, 18.00 ITOT, 3 more.. -11.00 ITOT, 3 more.. 70.00 GLD, 17.00 ITOT, 3 more..
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=tall Tall layout
Balance changes in 2012-01-01..2014-12-31:
|| 2012 2013 2014 Total Each commodity gets a new line (may be different in each column), and
==================++================================================== account names are repeated:
Assets:US:ETrade || 10.00 ITOT 70.00 GLD -11.00 ITOT 70.00 GLD
Assets:US:ETrade || 337.18 USD 18.00 ITOT 4881.44 USD 17.00 ITOT
Assets:US:ETrade || 12.00 VEA -98.12 USD 14.00 VEA 5120.50 USD
Assets:US:ETrade || 106.00 VHT 10.00 VEA 170.00 VHT 36.00 VEA
Assets:US:ETrade || 18.00 VHT 294.00 VHT
------------------++--------------------------------------------------
|| 10.00 ITOT 70.00 GLD -11.00 ITOT 70.00 GLD
|| 337.18 USD 18.00 ITOT 4881.44 USD 17.00 ITOT
|| 12.00 VEA -98.12 USD 14.00 VEA 5120.50 USD
|| 106.00 VHT 10.00 VEA 170.00 VHT 36.00 VEA
|| 18.00 VHT 294.00 VHT
- Bare layout. Commodity symbols are kept in one column, each $ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=tall
commodity gets its own report row, account names are repeated: Balance changes in 2012-01-01..2014-12-31:
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=bare || 2012 2013 2014 Total
Balance changes in 2012-01-01..2014-12-31: ==================++==================================================
Assets:US:ETrade || 10.00 ITOT 70.00 GLD -11.00 ITOT 70.00 GLD
Assets:US:ETrade || 337.18 USD 18.00 ITOT 4881.44 USD 17.00 ITOT
Assets:US:ETrade || 12.00 VEA -98.12 USD 14.00 VEA 5120.50 USD
Assets:US:ETrade || 106.00 VHT 10.00 VEA 170.00 VHT 36.00 VEA
Assets:US:ETrade || 18.00 VHT 294.00 VHT
------------------++--------------------------------------------------
|| 10.00 ITOT 70.00 GLD -11.00 ITOT 70.00 GLD
|| 337.18 USD 18.00 ITOT 4881.44 USD 17.00 ITOT
|| 12.00 VEA -98.12 USD 14.00 VEA 5120.50 USD
|| 106.00 VHT 10.00 VEA 170.00 VHT 36.00 VEA
|| 18.00 VHT 294.00 VHT
|| Commodity 2012 2013 2014 Total Bare layout
==================++=============================================
Assets:US:ETrade || GLD 0 70.00 0 70.00
Assets:US:ETrade || ITOT 10.00 18.00 -11.00 17.00
Assets:US:ETrade || USD 337.18 -98.12 4881.44 5120.50
Assets:US:ETrade || VEA 12.00 10.00 14.00 36.00
Assets:US:ETrade || VHT 106.00 18.00 170.00 294.00
------------------++---------------------------------------------
|| GLD 0 70.00 0 70.00
|| ITOT 10.00 18.00 -11.00 17.00
|| USD 337.18 -98.12 4881.44 5120.50
|| VEA 12.00 10.00 14.00 36.00
|| VHT 106.00 18.00 170.00 294.00
- Bare layout also affects CSV output, which is useful for producing Commodity symbols are kept in one column, each commodity has its own
data that is easier to consume, eg for making charts: row, amounts are bare numbers, account names are repeated:
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -O csv --layout=bare $ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=bare
"account","commodity","balance" Balance changes in 2012-01-01..2014-12-31:
"Assets:US:ETrade","GLD","70.00"
"Assets:US:ETrade","ITOT","17.00"
"Assets:US:ETrade","USD","5120.50"
"Assets:US:ETrade","VEA","36.00"
"Assets:US:ETrade","VHT","294.00"
"total","GLD","70.00"
"total","ITOT","17.00"
"total","USD","5120.50"
"total","VEA","36.00"
"total","VHT","294.00"
- Note: bare layout will sometimes display an extra row for the || Commodity 2012 2013 2014 Total
no-symbol commodity, because of zero amounts (hledger treats zeroes ==================++=============================================
as commodity-less, usually). This can break hledger-bar confusingly Assets:US:ETrade || GLD 0 70.00 0 70.00
(workaround: add a cur: query to exclude the no-symbol row). Assets:US:ETrade || ITOT 10.00 18.00 -11.00 17.00
Assets:US:ETrade || USD 337.18 -98.12 4881.44 5120.50
Assets:US:ETrade || VEA 12.00 10.00 14.00 36.00
Assets:US:ETrade || VHT 106.00 18.00 170.00 294.00
------------------++---------------------------------------------
|| GLD 0 70.00 0 70.00
|| ITOT 10.00 18.00 -11.00 17.00
|| USD 337.18 -98.12 4881.44 5120.50
|| VEA 12.00 10.00 14.00 36.00
|| VHT 106.00 18.00 170.00 294.00
- Tidy layout produces normalised "tidy data", where every variable Bare layout also affects CSV output, which is useful for producing data
has its own column and each row represents a single data point. See that is easier to consume, eg for making charts:
https://cran.r-project.org/web/packages/tidyr/vignettes/tidy-data.html
for more. This is the easiest kind of data for other software to
consume. Here's how it looks:
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -Y -O csv --layout=tidy $ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -O csv --layout=bare
"account","period","start_date","end_date","commodity","value" "account","commodity","balance"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","GLD","0" "Assets:US:ETrade","GLD","70.00"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","ITOT","10.00" "Assets:US:ETrade","ITOT","17.00"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","USD","337.18" "Assets:US:ETrade","USD","5120.50"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","VEA","12.00" "Assets:US:ETrade","VEA","36.00"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","VHT","106.00" "Assets:US:ETrade","VHT","294.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","GLD","70.00" "total","GLD","70.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","ITOT","18.00" "total","ITOT","17.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","USD","-98.12" "total","USD","5120.50"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","VEA","10.00" "total","VEA","36.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","VHT","18.00" "total","VHT","294.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","GLD","0"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","ITOT","-11.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","USD","4881.44"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","VEA","14.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","VHT","170.00"
Useful balance reports Bare layout will sometimes display an extra row for the no-symbol
commodity, because of zero amounts (hledger treats zeroes as
commodity-less, usually). This can break hledger-bar confusingly
(workaround: add a cur: query to exclude the no-symbol row).
Tidy layout
This produces normalised "tidy data" (see
https://cran.r-project.org/web/packages/tidyr/vignettes/tidy-data.html)
where every variable has its own column and each row represents a single
data point. This is the easiest kind of data for other software to
consume:
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -Y -O csv --layout=tidy
"account","period","start_date","end_date","commodity","value"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","GLD","0"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","ITOT","10.00"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","USD","337.18"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","VEA","12.00"
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","VHT","106.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","GLD","70.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","ITOT","18.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","USD","-98.12"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","VEA","10.00"
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","VHT","18.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","GLD","0"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","ITOT","-11.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","USD","4881.44"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","VEA","14.00"
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","VHT","170.00"
Some useful balance reports
Some frequently used balance options/reports are: Some frequently used balance options/reports are:

View File

@ -132,6 +132,10 @@ balances in an opening transaction. These provide useful error checking,
but you can ignore them temporarily with -I, or remove them if you but you can ignore them temporarily with -I, or remove them if you
prefer. prefer.
Single-commodity, subaccount-exclusive balance assertions (=) are
generated by default. This can be changed with --assertion-type='==*'
(eg).
When running close you should probably avoid using -C, -R, status: When running close you should probably avoid using -C, -R, status:
(filtering by status or realness) or --auto (generating postings), since (filtering by status or realness) or --auto (generating postings), since
the generated balance assertions would then require these. the generated balance assertions would then require these.

View File

@ -107,7 +107,7 @@ reversePriceDirective pd@PriceDirective{pdcommodity=c, pdamount=a}
where where
lbl = lbl_ "reversePriceDirective" lbl = lbl_ "reversePriceDirective"
a' = a' =
amountSetFullPrecisionOr (Just defaultMaxPrecision) $ amountSetFullPrecisionUpTo (Just defaultMaxPrecision) $
invertAmount a{acommodity=c} invertAmount a{acommodity=c}
& dbg9With (lbl "calculated reverse price".showAmount) & dbg9With (lbl "calculated reverse price".showAmount)
-- & dbg9With (lbl "precision of reverse price".show.amountDisplayPrecision) -- & dbg9With (lbl "precision of reverse price".show.amountDisplayPrecision)

View File

@ -147,7 +147,7 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{_rsReportOpts=ReportO
, T.pack $ showMixedAmount $ styleAmounts styles $ cashFlowAmt , T.pack $ showMixedAmount $ styleAmounts styles $ cashFlowAmt
-- , T.pack $ showMixedAmount $ -- , T.pack $ showMixedAmount $
-- -- dbg0With (lbl "cashflow after styling".showMixedAmountOneLine) $ -- -- dbg0With (lbl "cashflow after styling".showMixedAmountOneLine) $
-- mapMixedAmount (amountSetFullPrecisionOr (Just defaultMaxPrecision)) $ -- mapMixedAmount (amountSetFullPrecisionUpTo (Just defaultMaxPrecision)) $
-- styleAmounts (styles -- styleAmounts (styles
-- -- & dbg0With (lbl "styles".show)) -- -- & dbg0With (lbl "styles".show))
-- cashFlowAmt -- cashFlowAmt

View File

@ -72,7 +72,7 @@ contributions and which is due to the return on investment.
assets, or otherwise converting between your investment commodity and assets, or otherwise converting between your investment commodity and
any other commodity. Example: any other commodity. Example:
``` ```journal
2019-01-01 Investing in Snake Oil 2019-01-01 Investing in Snake Oil
assets:cash -$100 assets:cash -$100
investment:snake oil investment:snake oil
@ -84,7 +84,7 @@ any other commodity. Example:
- "Profit and loss" is change in the value of your investment: - "Profit and loss" is change in the value of your investment:
``` ```journal
2019-06-01 Snake Oil falls in value 2019-06-01 Snake Oil falls in value
investment:snake oil = $57 investment:snake oil = $57
equity:unrealized profit or loss equity:unrealized profit or loss
@ -98,7 +98,7 @@ investment return.
Example: if you use `--inv snake --pnl equity:unrealized`, then Example: if you use `--inv snake --pnl equity:unrealized`, then
postings in the example below would be classifed as: postings in the example below would be classifed as:
``` ```journal
2019-01-01 Snake Oil #1 2019-01-01 Snake Oil #1
assets:cash -$100 ; cash flow posting assets:cash -$100 ; cash flow posting
investment:snake oil ; investment posting investment:snake oil ; investment posting

View File

@ -16,6 +16,7 @@ module Hledger.Cli.Commands.Stats (
where where
import Data.Default (def) import Data.Default (def)
import System.FilePath (takeFileName)
import Data.List (intercalate, nub, sortOn) import Data.List (intercalate, nub, sortOn)
import Data.List.Extra (nubSort) import Data.List.Extra (nubSort)
import qualified Data.Map as Map import qualified Data.Map as Map
@ -39,7 +40,8 @@ import Hledger.Cli.Utils (writeOutputLazyText)
statsmode = hledgerCommandMode statsmode = hledgerCommandMode
$(embedFileRelative "Hledger/Cli/Commands/Stats.txt") $(embedFileRelative "Hledger/Cli/Commands/Stats.txt")
[flagReq ["output-file","o"] (\s opts -> Right $ setopt "output-file" s opts) "FILE" "write output to FILE." [ flagNone ["verbose","v"] (setboolopt "verbose") "show more detailed output"
,flagReq ["output-file","o"] (\s opts -> Right $ setopt "output-file" s opts) "FILE" "write output to FILE."
] ]
[generalflagsgroup1] [generalflagsgroup1]
hiddenflags hiddenflags
@ -48,16 +50,17 @@ statsmode = hledgerCommandMode
-- like Register.summarisePostings -- like Register.summarisePostings
-- | Print various statistics for the journal. -- | Print various statistics for the journal.
stats :: CliOpts -> Journal -> IO () stats :: CliOpts -> Journal -> IO ()
stats opts@CliOpts{reportspec_=rspec, progstarttime_} j = do stats opts@CliOpts{rawopts_=rawopts, reportspec_=rspec, progstarttime_} j = do
let today = _rsDay rspec let today = _rsDay rspec
verbose = boolopt "verbose" rawopts
q = _rsQuery rspec q = _rsQuery rspec
l = ledgerFromJournal q j l = ledgerFromJournal q j
intervalspans = snd $ reportSpanBothDates j rspec intervalspans = snd $ reportSpanBothDates j rspec
showstats = showLedgerStats l today ismultiperiod = length intervalspans > 1
(ls, txncounts) = unzip $ map showstats intervalspans (ls, txncounts) = unzip $ map (showLedgerStats verbose l today) intervalspans
numtxns = sum txncounts numtxns = sum txncounts
b = unlinesB ls txt = (if ismultiperiod then id else TL.init) $ TB.toLazyText $ unlinesB ls
writeOutputLazyText opts $ TL.init $ TB.toLazyText b writeOutputLazyText opts txt
t <- getPOSIXTime t <- getPOSIXTime
let dt = t - progstarttime_ let dt = t - progstarttime_
rtsStatsEnabled <- getRTSStatsEnabled rtsStatsEnabled <- getRTSStatsEnabled
@ -68,11 +71,11 @@ stats opts@CliOpts{reportspec_=rspec, progstarttime_} j = do
RTSStats{..} <- getRTSStats RTSStats{..} <- getRTSStats
printf printf
(intercalate ", " (intercalate ", "
["Runtime stats : %.2f s elapsed" ["Runtime stats : %.2f s elapsed" -- keep synced
,"%.0f txns/s" ,"%.0f txns/s" --
-- ,"%0.0f MB avg live" -- ,"%0.0f MB avg live"
,"%0.0f MB max live" ,"%0.0f MB live"
,"%0.0f MB peak allocation" ,"%0.0f MB alloc"
-- ,"(%0.0f MiB" -- ,"(%0.0f MiB"
-- ,"%0.0f MiB)" -- ,"%0.0f MiB)"
] ++ "\n") ] ++ "\n")
@ -84,7 +87,7 @@ stats opts@CliOpts{reportspec_=rspec, progstarttime_} j = do
else else
printf printf
(intercalate ", " (intercalate ", "
["Runtime stats : %.2f s elapsed" ["Runtime stats : %.2f s elapsed" -- keep
,"%.0f txns/s" ,"%.0f txns/s"
] ++ "\n(add +RTS -T -RTS for more)\n") ] ++ "\n(add +RTS -T -RTS for more)\n")
(realToFrac dt :: Float) (realToFrac dt :: Float)
@ -93,36 +96,37 @@ stats opts@CliOpts{reportspec_=rspec, progstarttime_} j = do
toMegabytes n = realToFrac n / 1000000 ::Float -- SI preferred definition, 10^6 toMegabytes n = realToFrac n / 1000000 ::Float -- SI preferred definition, 10^6
-- toMebibytes n = realToFrac n / 1048576 ::Float -- traditional computing definition, 2^20 -- toMebibytes n = realToFrac n / 1048576 ::Float -- traditional computing definition, 2^20
showLedgerStats :: Ledger -> Day -> DateSpan -> (TB.Builder, Int) showLedgerStats :: Bool -> Ledger -> Day -> DateSpan -> (TB.Builder, Int)
showLedgerStats l today spn = showLedgerStats verbose l today spn =
(unlinesB $ map (renderRowB def{tableBorders=False, borderSpaces=False} . showRow) stts (unlinesB $ map (renderRowB def{tableBorders=False, borderSpaces=False} . showRow) stts
,tnum) ,tnum)
where where
showRow (label, val) = Group NoLine $ map (Header . textCell TopLeft) showRow (label, val) = Group NoLine $ map (Header . textCell TopLeft)
[fitText (Just w) (Just w) False True label `T.append` ": ", T.pack val] [fitText (Just w) (Just w) False True label `T.append` ": ", T.pack val]
w = 25 -- keep synced with labels above w = 20 -- keep synced with labels above
-- w = maximum $ map (T.length . fst) stts -- w = maximum $ map (T.length . fst) stts
(stts, tnum) = ([ (stts, tnum) = ([
("Main file", path) -- ++ " (from " ++ source ++ ")") ("Main file", path') -- ++ " (from " ++ source ++ ")")
,("Included files", unlines $ drop 1 $ journalFilePaths j) ,("Included files", if verbose then unlines includedpaths else show (length includedpaths))
,("Transactions span", printf "%s to %s (%d days)" (showstart spn) (showend spn) days) ,("Txns span", printf "%s to %s (%d days)" (showstart spn) (showend spn) days)
,("Last transaction", maybe "none" show lastdate ++ showelapsed lastelapsed) ,("Last txn", maybe "none" show lastdate ++ showelapsed lastelapsed)
,("Transactions", printf "%d (%0.1f per day)" tnum txnrate) ,("Txns", printf "%d (%0.1f per day)" tnum txnrate)
,("Transactions last 30 days", printf "%d (%0.1f per day)" tnum30 txnrate30) ,("Txns last 30 days", printf "%d (%0.1f per day)" tnum30 txnrate30)
,("Transactions last 7 days", printf "%d (%0.1f per day)" tnum7 txnrate7) ,("Txns last 7 days", printf "%d (%0.1f per day)" tnum7 txnrate7)
,("Payees/descriptions", show $ size $ fromList $ map (tdescription) ts) ,("Payees/descriptions", show $ size $ fromList $ map (tdescription) ts)
,("Accounts", printf "%d (depth %d)" acctnum acctdepth) ,("Accounts", printf "%d (depth %d)" acctnum acctdepth)
,("Commodities", printf "%s (%s)" (show $ length cs) (T.intercalate ", " cs)) ,("Commodities", printf "%s%s" (show $ length cs) (if verbose then " (" <> T.intercalate ", " cs <> ")" else ""))
,("Market prices", printf "%s (%s)" (show $ length mktprices) (T.intercalate ", " mktpricecommodities)) ,("Market prices", printf "%s%s" (show $ length mktprices) (if verbose then " (" <> T.intercalate ", " mktpricecommodities <> ")" else ""))
-- Transactions this month : %(monthtxns)s (last month in the same period: %(lastmonthtxns)s) -- Txns this month : %(monthtxns)s (last month in the same period: %(lastmonthtxns)s)
-- Unmarked transactions : %(unmarked)s -- Unmarked txns : %(unmarked)s
-- Days since reconciliation : %(reconcileelapsed)s -- Days since reconciliation : %(reconcileelapsed)s
-- Days since last transaction : %(recentelapsed)s -- Days since last txn : %(recentelapsed)s
] ]
,tnum1) ,tnum1)
where where
j = ljournal l j = ljournal l
path = journalFilePath j path' = if verbose then path else ".../" <> takeFileName path where path = journalFilePath j
includedpaths = drop 1 $ journalFilePaths j
ts = sortOn tdate $ filter (spanContainsDate spn . tdate) $ jtxns j ts = sortOn tdate $ filter (spanContainsDate spn . tdate) $ jtxns j
as = nub $ map paccount $ concatMap tpostings ts as = nub $ map paccount $ concatMap tpostings ts
cs = either error' Map.keys $ commodityStylesFromAmounts $ concatMap (amountsRaw . pamount) $ concatMap tpostings ts -- PARTIAL: cs = either error' Map.keys $ commodityStylesFromAmounts $ concatMap (amountsRaw . pamount) $ concatMap tpostings ts -- PARTIAL:

View File

@ -4,36 +4,43 @@ Show journal and performance statistics.
_FLAGS _FLAGS
The stats command displays summary information for the whole journal, or The stats command shows summary information for the whole journal, or
a matched part of it. With a [reporting interval](#reporting-interval), a matched part of it. With a [reporting interval](#reporting-interval),
it shows a report for each report period. it shows a report for each report period.
At the end, it shows (in the terminal) the overall run time and number of The default output is fairly impersonal, though it reveals the main file name.
transactions processed per second. Note these are approximate and will vary With `-v/--verbose`, more details are shown, like file paths, included files,
based on machine, current load, data size, hledger version, haskell lib and commodity names.
versions, GHC version.. but they may be of interest. The `stats` command's
run time is similar to that of a single-column balance report. It also shows some run time statistics:
- elapsed time
- throughput: the number of transactions processed per second
- live: the peak memory in use by the program to do its work
- alloc: the peak memory allocation from the OS as seen by GHC.
Measuring this externally, eg with GNU time, is more accurate;
usually that will be a larger number; sometimes (with swapping?) smaller.
The `stats` command's run time is similar to that of a balance report.
Example: Example:
```cli ```cli
$ hledger stats -f examples/1000x1000x10.journal $ hledger stats -f examples/1ktxns-1kaccts.journal
Main file : /Users/simon/src/hledger/examples/1000x1000x10.journal Main file : .../1ktxns-1kaccts.journal
Included files : Included files : 0
Transactions span : 2000-01-01 to 2002-09-27 (1000 days) Txns span : 2000-01-01 to 2002-09-27 (1000 days)
Last transaction : 2002-09-26 (6995 days ago) Last txn : 2002-09-26 (7827 days ago)
Transactions : 1000 (1.0 per day) Txns : 1000 (1.0 per day)
Transactions last 30 days: 0 (0.0 per day) Txns last 30 days : 0 (0.0 per day)
Transactions last 7 days : 0 (0.0 per day) Txns last 7 days : 0 (0.0 per day)
Payees/descriptions : 1000 Payees/descriptions : 1000
Accounts : 1000 (depth 10) Accounts : 1000 (depth 10)
Commodities : 26 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) Commodities : 26
Market prices : 1000 (A) Market prices : 1000
Runtime stats : 0.12 s elapsed, 8266 txns/s, 4 MB live, 16 MB alloc
Run time : 0.12 s
Throughput : 8342 txns/s
``` ```
This command supports This command supports
the [-o/--output-file](hledger.html#output-destination) option the [-o/--output-file](hledger.html#output-destination) option
(but not [-O/--output-format](hledger.html#output-format) selection). (but not [-O/--output-format](hledger.html#output-format)).

View File

@ -4,34 +4,41 @@ Show journal and performance statistics.
_FLAGS _FLAGS
The stats command displays summary information for the whole journal, or The stats command shows summary information for the whole journal, or a
a matched part of it. With a reporting interval, it shows a report for matched part of it. With a reporting interval, it shows a report for
each report period. each report period.
At the end, it shows (in the terminal) the overall run time and number The default output is fairly impersonal, though it reveals the main file
of transactions processed per second. Note these are approximate and name. With -v/--verbose, more details are shown, like file paths,
will vary based on machine, current load, data size, hledger version, included files, and commodity names.
haskell lib versions, GHC version.. but they may be of interest. The
stats command's run time is similar to that of a single-column balance It also shows some run time statistics:
report.
- elapsed time
- throughput: the number of transactions processed per second
- live: the peak memory in use by the program to do its work
- alloc: the peak memory allocation from the OS as seen by GHC.
Measuring this externally, eg with GNU time, is more accurate;
usually that will be a larger number; sometimes (with swapping?)
smaller.
The stats command's run time is similar to that of a balance report.
Example: Example:
$ hledger stats -f examples/1000x1000x10.journal $ hledger stats -f examples/1ktxns-1kaccts.journal
Main file : /Users/simon/src/hledger/examples/1000x1000x10.journal Main file : .../1ktxns-1kaccts.journal
Included files : Included files : 0
Transactions span : 2000-01-01 to 2002-09-27 (1000 days) Txns span : 2000-01-01 to 2002-09-27 (1000 days)
Last transaction : 2002-09-26 (6995 days ago) Last txn : 2002-09-26 (7827 days ago)
Transactions : 1000 (1.0 per day) Txns : 1000 (1.0 per day)
Transactions last 30 days: 0 (0.0 per day) Txns last 30 days : 0 (0.0 per day)
Transactions last 7 days : 0 (0.0 per day) Txns last 7 days : 0 (0.0 per day)
Payees/descriptions : 1000 Payees/descriptions : 1000
Accounts : 1000 (depth 10) Accounts : 1000 (depth 10)
Commodities : 26 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) Commodities : 26
Market prices : 1000 (A) Market prices : 1000
Runtime stats : 0.12 s elapsed, 8266 txns/s, 4 MB live, 16 MB alloc
Run time : 0.12 s
Throughput : 8342 txns/s
This command supports the -o/--output-file option (but not This command supports the -o/--output-file option (but not
-O/--output-format selection). -O/--output-format).

File diff suppressed because it is too large Load Diff

View File

@ -15,9 +15,7 @@
b $-1 = $-3 b $-1 = $-3
(b) $1 = $-2 (b) $1 = $-2
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 2. same entries as 1 but different parse order, assertion should still pass based on date # ** 2. same entries as 1 but different parse order, assertion should still pass based on date
< <
@ -34,9 +32,7 @@ $ hledger -f - stats
a $1 =$2 a $1 =$2
b $-1 =$-2 b $-1 =$-2
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 3. like 1 but switch order of postings in last entry, # ** 3. like 1 but switch order of postings in last entry,
# assertion should fail and exit code should be non zero # assertion should fail and exit code should be non zero
@ -54,7 +50,7 @@ $ hledger -f - stats
(b) $1 = $-2 (b) $1 = $-2
b $-1 = $-3 b $-1 = $-3
$ hledger -f - stats $ hledger -f - check
>2 /Error: -:11:12/ >2 /Error: -:11:12/
>=1 >=1
@ -63,9 +59,7 @@ $ hledger -f - stats
2013/1/1 2013/1/1
(a) 1 =1 (a) 1 =1
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 5. should work for fractional amount with trailing zeros # ** 5. should work for fractional amount with trailing zeros
< <
@ -81,9 +75,7 @@ $ hledger -f - stats
a $0.7 =$2 a $0.7 =$2
b =-$2 b =-$2
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 6. assertions currently check only a single commodity's balance, like Ledger # ** 6. assertions currently check only a single commodity's balance, like Ledger
< <
@ -93,9 +85,7 @@ $ hledger -f - stats
(a) 0 = A1 (a) 0 = A1
(a) C0 = D0 (a) C0 = D0
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 7. balances should accumulate (#195) # ** 7. balances should accumulate (#195)
< <
@ -106,9 +96,7 @@ $ hledger -f - stats
1/2 1/2
(a) 3F = 4F (a) 3F = 4F
$ hledger -f - stats $ hledger -f - check
> !/assertion failed/
>=0
# ** 8. what should happen here ? Currently, # ** 8. what should happen here ? Currently,
# in a, 3.4 EUR @@ $5.6 and -3.4 EUR cancel out (wrong ?) # in a, 3.4 EUR @@ $5.6 and -3.4 EUR cancel out (wrong ?)
@ -128,9 +116,7 @@ $ hledger -f - stats
# a $0.1 =$1.30 # a $0.1 =$1.30
# b =-$1.30 # b =-$1.30
# $ hledger -f - stats # $ hledger -f - check
# > /Transactions/
# >=0
# ** 8. Using balance assignment to set balances. # ** 8. Using balance assignment to set balances.
< <
@ -146,9 +132,7 @@ $ hledger -f - stats
a $10 =$11.3 a $10 =$11.3
b =$-11.3 b =$-11.3
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 9. Multiple assertions for an account in the same transaction. # ** 9. Multiple assertions for an account in the same transaction.
@ -166,9 +150,7 @@ $ hledger -f - stats
b $-1 = $-3 b $-1 = $-3
b $-1 = $-4 b $-1 = $-4
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 10. Multiple assertions and assignments for an account in the same transaction. # ** 10. Multiple assertions and assignments for an account in the same transaction.
< <
@ -196,9 +178,7 @@ $ hledger -f - stats
c = 50 B c = 50 B
c = 50 A c = 50 A
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 11. Assignments and virtual postings # ** 11. Assignments and virtual postings
< <
@ -214,16 +194,15 @@ $ hledger -f - stats
[a] = $5 [a] = $5
b = $9 b = $9
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 12. Having both assignments and posting dates is not supported. # ** 12. Having both assignments and posting dates is not supported.
< <
2013/1/1 2013/1/1
a $1 =$1 a $1 =$1
b =$-1 ; date:2012/1/1 b =$-1 ; date:2012/1/1
$ hledger -f - stats $ hledger -f - check
>2 /Balance assignments and custom posting dates may not be combined/ >2 /Balance assignments and custom posting dates may not be combined/
>=1 >=1
@ -247,9 +226,7 @@ $ hledger -f - stats
[d] 10 [d] 10
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 14. Mix different commodities # ** 14. Mix different commodities
< <
@ -261,9 +238,7 @@ $ hledger -f - stats
a $-1 = $0 a $-1 = $0
b b
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 15. Mix different commodities and assignments # ** 15. Mix different commodities and assignments
< <
@ -282,9 +257,7 @@ $ hledger -f - stats
a a
b = 0 zorkmids b = 0 zorkmids
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 16. Total assertions (==) parse correctly # ** 16. Total assertions (==) parse correctly
< <
@ -295,9 +268,7 @@ $ hledger -f - stats
2016/1/2 2016/1/2
a == $1 a == $1
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 17. Total assertions consider entire multicommodity amount # ** 17. Total assertions consider entire multicommodity amount
< <
@ -312,7 +283,7 @@ $ hledger -f - stats
2016/1/3 2016/1/3
a 0 == $1 a 0 == $1
$ hledger -f - stats $ hledger -f - check
>2 /Error: -:10:15:/ >2 /Error: -:10:15:/
>=1 >=1
@ -331,9 +302,7 @@ $ hledger -f - stats
b 0 = $-1 b 0 = $-1
b 0 = 0 zorkmids b 0 = 0 zorkmids
$ hledger -f - stats $ hledger -f - check
> /Transactions/
>=0
# ** 19. Cost is ignored when checking balance assertions. # ** 19. Cost is ignored when checking balance assertions.
< <

View File

@ -74,12 +74,12 @@ $ printf '2018/01/01\n (A) 1\n' >included.journal; HOME="$PWD" hledger -f - pr
# They use different file names so a single concurrent shelltest invocation will be fine. # They use different file names so a single concurrent shelltest invocation will be fine.
# ** 7. test that order of include files is maintained # ** 7. test that order of include files is maintained
$ printf 'include _b\n' >_a; touch _b; hledger -f _a stats | grep _ | sed -e 's%.*/%%'; rm -rf _a _b $ printf 'include _b\n' >_a; touch _b; hledger -f _a stats -v | grep _ | sed -e 's%.*/%%'; rm -rf _a _b
_a _a
_b _b
# ** 8. and with --auto code path # ** 8. and with --auto code path
$ printf 'include _d\n=\n' >_c; touch _d; hledger -f _c stats --auto | grep _ | sed -e 's%.*/%%'; rm -rf _c _d $ printf 'include _d\n=\n' >_c; touch _d; hledger -f _c stats -v --auto | grep _ | sed -e 's%.*/%%'; rm -rf _c _d
_c _c
_d _d

View File

@ -146,3 +146,15 @@ $ hledger -f - print expr:"not (tag:transactiontag=B)"
expenses:food expenses:food
>= >=
# ** 11. Posting-based reports handle OR'd open-ended date periods properly. (#2177)
<
2023-12-26 2023
(2023) 2023
2024-01-26 2024
(2024) 2024
$ hledger -f- reg -w80 expr:'date:2023 or date:2024'
2023-12-26 2023 (2023) 2023 2023
2024-01-26 2024 (2024) 2024 4047

View File

@ -7,6 +7,6 @@ $ hledger -f- stats
< <
include a.j include a.j
include b.j include b.j
$ touch a.j b.j; hledger -f- stats; rm -f a.j b.j $ touch a.j b.j; hledger -f- stats -v; rm -f a.j b.j
> /Included files.*\/a\.j > /Included files.*\/a\.j
.*\/b\.j/ .*\/b\.j/

View File

@ -10,32 +10,32 @@
th { white-space: nowrap; } th { white-space: nowrap; }
tr { border-top:thin solid #eee; vertical-align:top; } tr { border-top:thin solid #eee; vertical-align:top; }
td { padding:0 1em; } td { padding:0 1em; }
.tag { color:white; text-shadow: 2px 2px 2px black; font-size:small; padding:2px 8px 4px 6px; border-radius:1em; } /* .tag { color:white; text-shadow: 2px 2px 2px black; font-size:small; padding:2px 8px 4px 6px; border-radius:1em; }
.paletag { color:black; font-weight:bold; font-size:small; padding:2px 8px 4px 6px; border-radius:1em; } */
.tag { color:white; font-weight:bold; font-size:small; padding:2px 8px 4px 6px; border-radius:1em; }
.paletag { color:black; font-weight:bold; font-size:small; padding:2px 8px 4px 6px; border-radius:1em; } .paletag { color:black; font-weight:bold; font-size:small; padding:2px 8px 4px 6px; border-radius:1em; }
</style> </style>
</head> </head>
<body> <body>
<h3 class="text-center">hledger open bugs</h3> <h3 class="text-center">hledger open bugs by user pain (user joy when fixed)</h3>
<p> <p align="center">
Currently our <a href="https://hledger.org/ISSUES.html#prioritising">user pain</a> score is Our <a href="https://hledger.org/ISSUES.html#prioritising">user pain</a> score is
<i>Impact</i> (number of people affected, 1-5) <i>* Severity</i> (for those affected, 1-5) <i>/ 25</i>. impact (number of people affected, 1-5) * severity (for those affected, 1-5) / 25 * 10. <br>
<br>
The possible scores are: The possible scores are:
0.04 0.4
0.08 0.8
0.12 1.2
0.16 1.6
0.20 2.0
0.24 2.4
0.32 3.2
0.36 3.6
0.40 4.0
0.48 4.8
0.60 6.0
0.64 6.4
0.80 8.0
1.00 10.0
.
</p> </p>
<table id="issues"> <table id="issues">
</table> </table>

View File

@ -1,5 +1,5 @@
#!/usr/bin/env stack #!/usr/bin/env stack
{- stack script --resolver lts-18.18 {- stack script --resolver lts-22.12
--package data-default --package data-default
--package extra --package extra
--package process --package process