#!/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