2023-03-26 02:56:06 +03:00
|
|
|
#!/usr/bin/env bash
|
2023-05-24 06:14:31 +03:00
|
|
|
# hledger-bar - see below
|
2023-03-26 02:56:06 +03:00
|
|
|
|
|
|
|
usage() {
|
|
|
|
cat <<'EOS'
|
2023-05-24 06:14:31 +03:00
|
|
|
hledger-bar - show quick bar charts in the terminal
|
2023-03-26 02:56:06 +03:00
|
|
|
Usage:
|
|
|
|
hledger-bar [-h|--help]
|
|
|
|
hledger-bar [-v|-vv] [SCALE] BALARGS
|
|
|
|
hledger bar -- [-v|-vv] [SCALE] BALARGS # might need extra quoting
|
|
|
|
|
|
|
|
Requires bash (or osh) and hledger >= ~1.25.
|
|
|
|
|
|
|
|
With no arguments, shows this help.
|
|
|
|
Otherwise, runs hledger's 'balance' command, reporting monthly
|
|
|
|
balance changes by default, and shows the period totals as a bar chart
|
|
|
|
in the terminal, with positive amounts shown as '+' and negatives as '-'
|
2023-04-21 03:44:04 +03:00
|
|
|
(in green and red respectively, unless NO_COLOR is set).
|
2023-03-26 02:56:06 +03:00
|
|
|
|
|
|
|
Bars are not auto-sized; they will be (amount divided by SCALE) long, where
|
|
|
|
SCALE is 100 by default. This is overrideable by a numeric first argument.
|
|
|
|
Eg if bars are too long, try 200; if they are too short, try 50.
|
|
|
|
|
|
|
|
Most other options/arguments understood by the balance command can be
|
|
|
|
used, such as one or more account names, or different report intervals
|
|
|
|
like -W (weekly) or -Q (quarterly). There are two restrictions:
|
|
|
|
|
|
|
|
- You must ensure the report is for a single commodity. So use eg
|
|
|
|
'cur:€' or 'cur:\\$' or 'cur:\\\\$' or '-B' or '-X$ --infer-market-prices'
|
|
|
|
as needed.
|
|
|
|
|
|
|
|
- You can't use spaces in arguments (even quoted). If needed,
|
|
|
|
you could write '.' instead of space.
|
|
|
|
|
|
|
|
If you don't see the results you expect:
|
|
|
|
|
|
|
|
- Note that revenues appear negative and expenses positive,
|
|
|
|
as with the balance command; to flip signs, use --invert.
|
|
|
|
|
|
|
|
- Run as 'hledger-bar' to minimise command line quoting issues.
|
|
|
|
|
|
|
|
- Use -v as first argument to also show the (unscaled, rounded) amounts.
|
|
|
|
|
|
|
|
- Use -vv as first argument to show the amounts and the balance command
|
2023-04-21 03:44:04 +03:00
|
|
|
(approximately; you might need to add one level of quoting).
|
2023-03-26 02:56:06 +03:00
|
|
|
Tip: remove some of this command's first options to see a more
|
|
|
|
human-readable balance report.
|
|
|
|
|
2023-04-21 03:44:04 +03:00
|
|
|
- When you are reporting changes in asset/liability/equity accounts,
|
|
|
|
you will probably want to exclude opening/closing balance transactions,
|
|
|
|
eg with not:desc:'(opening|closing)' or not:tag:clopen if you use those.
|
2023-03-26 02:56:06 +03:00
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
|
|
|
$ hledger-bar food # monthly food expenses
|
2023-04-21 03:44:04 +03:00
|
|
|
$ hledger-bar 1 --count food # monthly food posting counts
|
2023-03-26 02:56:06 +03:00
|
|
|
$ hledger-bar -v 1 -f $TIMELOG -D # daily hours, with numbers
|
|
|
|
$ hledger-bar type:c not:tag:clopen cur:\\$ -W # weekly cashflow, $ only
|
|
|
|
$ hledger-bar type:al not:tag:clopen cur:\\$ # monthly net worth change ($)
|
2023-04-21 03:44:04 +03:00
|
|
|
$ hledger-bar type:rx --invert cur:\\$ # monthly profit/loss ($)
|
2023-03-26 02:56:06 +03:00
|
|
|
$ hledger-bar type:rx --invert cur:\\$ --infer-market-prices --value=then,$
|
|
|
|
# monthly profit/loss ($, plus anything that can be converted to $,
|
|
|
|
# using conversion rates on transaction dates)
|
2023-04-21 03:44:04 +03:00
|
|
|
$ hledger-bar . cur:\\$ # all accounts' change ($)
|
2023-03-26 02:56:06 +03:00
|
|
|
$ hledger bar -- . cur:\\\\$ # as hledger subcommand
|
|
|
|
|
|
|
|
EOS
|
|
|
|
}
|
|
|
|
###############################################################################
|
|
|
|
|
|
|
|
set -e
|
|
|
|
|
|
|
|
defscale=100
|
|
|
|
negchar="-"
|
|
|
|
poschar="+"
|
|
|
|
|
|
|
|
# utils
|
|
|
|
|
2023-05-10 00:30:46 +03:00
|
|
|
# https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit and 24-bit colors.
|
|
|
|
# Disable if stdout is not a terminal or NO_COLOR is defined.
|
2024-01-22 08:55:32 +03:00
|
|
|
if [[ ! -t 1 || -n ${NO_COLOR} ]]; then
|
2023-03-26 02:56:06 +03:00
|
|
|
red=''
|
|
|
|
green=''
|
|
|
|
nocol=''
|
|
|
|
else
|
|
|
|
red='\e[38;5;1m'
|
|
|
|
green="\e[38;5;2m"
|
|
|
|
nocol="\e[0m"
|
|
|
|
fi
|
|
|
|
|
|
|
|
unquote() { s="${1%\"}"; echo "${s#\"}"; }
|
|
|
|
|
|
|
|
# process command line
|
|
|
|
shownum=0
|
|
|
|
verbose=0
|
2024-01-22 08:55:32 +03:00
|
|
|
scale=${defscale}
|
2023-03-26 02:56:06 +03:00
|
|
|
if [[ $# -eq 0 || $1 == --help || $1 == -h ]]; then usage; exit; fi
|
|
|
|
if [[ $1 == -v ]]; then shownum=1; shift; elif [[ $1 == -vv ]]; then shownum=1; verbose=1; shift; fi
|
|
|
|
if [[ $1 =~ ^[0-9]+$ ]]; then scale=$1; shift; fi
|
|
|
|
|
|
|
|
# helpers
|
|
|
|
|
2023-11-21 22:27:26 +03:00
|
|
|
# The hledger reporting command. It should produce a two-column CSV
|
|
|
|
# report with one line per period and one currency. It must have a
|
|
|
|
# report interval for --transpose to work. shellcheck disable=SC2124
|
2024-01-22 23:29:47 +03:00
|
|
|
cmd="hledger balance -Ocsv --transpose -N -0 --layout=bare -M $*"
|
2023-03-26 02:56:06 +03:00
|
|
|
|
|
|
|
printcmd() {
|
|
|
|
echo "From command (might need added quotes):" # don't know how to print all the slashes
|
2024-01-22 08:55:32 +03:00
|
|
|
echo "${cmd}"
|
2023-03-26 02:56:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
printamterr() {
|
|
|
|
cat <<EOS
|
|
|
|
Error: could not parse as a single-commodity amount: $1
|
|
|
|
The report must be restricted or converted to a single commodity.
|
|
|
|
Eg to report $, try: cur:\\\\$ or cur:\\\\\\\\$ or -B or -X$ --infer-market-prices
|
|
|
|
EOS
|
|
|
|
printcmd
|
|
|
|
}
|
|
|
|
|
|
|
|
# main
|
2024-01-22 08:55:32 +03:00
|
|
|
# shellcheck disable=SC2312
|
|
|
|
${cmd} | while IFS=, read -r period amount; do
|
|
|
|
if [[ ! ${amount} =~ [0-9] ]]; then continue; fi # ignore lines where amount has no digits
|
|
|
|
if [[ ${amount} =~ , ]]; then printamterr "${amount}"; exit 1; fi # check there is a single amount column
|
2024-02-18 06:29:15 +03:00
|
|
|
shopt -s inherit_errexit
|
2024-01-22 08:55:32 +03:00
|
|
|
int=$(printf '%.f' "$(unquote "${amount}")")
|
|
|
|
if [[ ${shownum} -gt 0 ]]; then num=$(printf "%10d " "${int}"); else num=""; fi
|
|
|
|
if [[ ${int} -lt 0 ]]; then c="${negchar}"; col=${red}; else c="${poschar}"; col=${green}; fi
|
2023-03-26 02:56:06 +03:00
|
|
|
n=$((int / scale))
|
|
|
|
absn=${n#-}
|
2024-01-22 08:55:32 +03:00
|
|
|
bar=$(while [[ ${absn} -gt 0 ]]; do printf "%s" "${c}"; absn=$((absn - 1)); done)
|
|
|
|
printf '%s\t%b%s%s%b\n' "$(unquote "${period}")" "${col}" "${num}" "${bar}" "${nocol}"
|
2023-03-26 02:56:06 +03:00
|
|
|
done
|
|
|
|
|
2024-01-22 08:55:32 +03:00
|
|
|
if [[ ${verbose} -gt 0 ]]; then printcmd; fi
|