#!/bin/sh
umask 077
dir="$(mktemp -d "${TMPDIR:-/tmp}/hledger-vega.XXXXXXXXXX")"
trap "rm -r $dir" EXIT
datasetsdir=./datasets
chartsdir=./charts
outdir=./charts
log(){
echo >&2 $* # stderr to fit with make_chart_data
}
# initialize a semaphore with a given number of tokens
open_sem(){
mkfifo $dir/pipe-$$
exec 3<>$dir/pipe-$$
rm $dir/pipe-$$
local i=$1
for((;i>0;i--)); do
printf %s 000 >&3
done
}
# run the given command asynchronously and pop/push tokens
run_with_lock(){
local x
# this read waits until there is something to read
read -u 3 -n 3 x && ((0==x)) || exit $x
(
( "$@"; )
# push the return code of the command to the semaphore
printf '%.3d' $? >&3
)#& # comment the & to run single threaded, for clearer logging
}
# Create the data directory if it doesn't exist
mkdir -p "$outdir"
# Use 4 jobs
N=4
open_sem $N
hledger_with_name() {
local namewithext="$(basename "$1")"
local name="${namewithext%.*}"
log "hledger balance --output-format=csv --layout=tidy --daily @"$1"" # > "$dir/$name.csv""
hledger balance --output-format=csv --layout=tidy --daily @"$1" > "$dir/$name.csv"
if [[ $(wc -l < "$dir/$name.csv") -le 1 ]]; then
log "Warning: hledger produced no output from \"$1\""
fi
}
make_chart_data() {
local namewithext="$(basename "$1")"
local name="${namewithext%.*}"
local IFS=";"
local first=1
log "$outdir/$name.csv:"
while read -a line; do
local csv="$dir/${line[0]}.csv"
local label="${line[1]}"
log " $(basename "$csv")"
{
if [[ $first -eq 1 ]]; then
cat "$csv"
else
tail -n "+2" "$csv"
fi
} | sed -e "s/^\"...\"/\"$label\"/"
first=0
done < "$1" \
> "$outdir/$name.csv"
}
log "Generating hledger data sets (in $dir):"
for args in "$datasetsdir"/*.args; do
run_with_lock hledger_with_name "$args"
done
wait
log "Combining data sets into chart data (in $chartsdir):"
for chart in "$chartsdir"/*.datasets; do
run_with_lock make_chart_data "$chart"
done
wait