Skip to content

Commit

Permalink
;bin: add a justfile (conversion of ft and tt)
Browse files Browse the repository at this point in the history
  • Loading branch information
simonmichael committed Jul 7, 2023
1 parent c0bd0d2 commit 67e5a45
Show file tree
Hide file tree
Showing 2 changed files with 311 additions and 0 deletions.
53 changes: 53 additions & 0 deletions bin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ $ fin # list the scripts available

[`ft`](https://github.com/simonmichael/hledger/blob/master/bin/ft)
is a way to organise your finance-related reports and scripts using standard bash.
(See also [justfile](#justfile) below.)

```shell
$ alias f=~/src/hledger/bin/ft
Expand Down Expand Up @@ -131,6 +132,58 @@ OTHERCMD [ARGS] run other hledger commands on $TIMELOG
Add hledger options to customise reports.
```
### justfile
<https://github.com/casey/just> is like [make](https://en.wikipedia.org/wiki/Make_(software)), but easier and more suitable for running commands.
It is a nice tool for organising financial reports and scripts!
Here is a [justfile](https://github.com/simonmichael/hledger/blob/master/bin/justfile)
reimplementing the `ft` and `tt` scripts more simply:
```shell
$ brew install just # eg
$ alias j=just
$ cd ~/finance
$ cp ~/src/hledger/bin/justfile . # or start from scratch: just --init
$ j
justfile commands:
watch CMD # rerun the given command with watchexec whenever local files change
get-csv # download auto-downloadable CSVs (paypal)
import-dry # import new downloaded transactions to the main journal, dry run
import # import new downloaded transactions to the journal, logging and not printing errors
get-prices *PRICEHISTFETCHOPTS # show prices for main commodities (default: today's)
bs *HLEDGERARGS # show balance sheet
is *HLEDGERARGS # show income statement
a *HLEDGERARGS # show assets
r *HLEDGERARGS # show revenues
x *HLEDGERARGS # show expenses
ab *HLEDGERARGS # show assets bar chart
rb *HLEDGERARGS # show revenues bar chart
xb *HLEDGERARGS # show expenses bar chart
al *HLEDGERARGS # show assets line chart
rl *HLEDGERARGS # show revenues line chart
xl *HLEDGERARGS # show expenses line chart
forecast *HLEDGERARGS # print transactions predicted by forecast rules from last week on
household *HLEDGERARGS # show a draft month-end household adjustment transaction for last month
consulting *HLEDGERARGS # show consulting revenue
tdash *HLEDGERARGS # show time dashboard, redisplaying when timelog files change
tstatus *HLEDGERARGS # show current time status
twhat *HLEDGERARGS # what happened ? Show largest time balances first, today and depth 1 by default
tdots N # print line of N dots, grouped in 4s (suitable for timedot)
tx *HLEDGERARGS # horizontal time summary this year, monthly by default
ty *HLEDGERARGS # vertical time summary this year, monthly by default
tweeks *HLEDGERARGS # this and last week's time budgets
tweekspast *HLEDGERARGS # recent past weeks' time budgets
thours *HLEDGERARGS # show a bar chart of daily hours
taccunused *HLEDGERARGS # show unused / undeclared time accounts
taccunusedcat *HLEDGERARGS # show unused / undeclared time accounts by category
taccadd *HLEDGERARGS # add declarations for all undeclared time accounts
tbudgets *HLEDGERARGS # show monthly time budget performance this year
tbudgetsy *HLEDGERARGS # show monthly time budget performance this year, vertically
tbudgetsw *HLEDGERARGS # show weekly time budget performance this year
tbudgetswx *HLEDGERARGS # show weekly time budget performance this year, horizontally
```
### watchaccounts
[`watchaccounts`](https://github.com/simonmichael/hledger/blob/master/bin/watchaccounts)
Expand Down
258 changes: 258 additions & 0 deletions bin/justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
#!/usr/bin/env just -f
# * financial reports/scripts, runnable with https://github.com/casey/just
# (like make but simpler and more suitable for running commands.)
# ** PREAMBLE ------------------------------------------------------------

PERIOD := "1/1..tomorrow"
TODAY := `date +%Y-%m-%d`

justthis := "just -f " + justfile()
@_help:
{{justthis}} -lu --list-heading=$'{{ file_name(justfile()) }} commands:\n'

# rerun the given command with watchexec whenever local files change
watch CMD:
watchexec -- {{justthis}} {{CMD}}

# XXX HLEDGERARGS are not quoted properly; each one should be free of spaces

# ** IMPORT ------------------------------------------------------------

# where to import most hledger transactions from
IMPORTFILES := '\
wf-bchecking.csv.rules \
wf-pchecking.csv.rules \
wf-bsavings.csv.rules \
wf-psavings.csv.rules \
paypal.csv \
bofi-ichecking.csv.rules \
'

# download auto-downloadable CSVs (paypal)
@get-csv:
paypaljson | paypaljson2csv > paypal.csv

# import new downloaded transactions to the main journal, dry run
@import-dry:
hledger import --dry-run {{IMPORTFILES}}

# import new downloaded transactions to the journal, logging and not printing errors
@import:
date >>import.log
@hledger import {{IMPORTFILES}} 2>>import.log || echo "Failed, check import.log"
echo "Now use ledger-mode's M-q to align entries."

# show prices for main commodities (default: today's)
@get-prices *PRICEHISTFETCHOPTS :
(pricehist fetch -o ledger -s {{TODAY}} alphavantage EUR/USD {{PRICEHISTFETCHOPTS}} | sed -E 's/EUR/€/') &
(pricehist fetch -o ledger -s {{TODAY}} alphavantage GBP/USD {{PRICEHISTFETCHOPTS}} | sed -E 's/GBP/£/') &
(pricehist fetch -o ledger -s {{TODAY}} alphavantage JPY/USD {{PRICEHISTFETCHOPTS}} | sed -E 's/JPY/¥/')
# Parallelised for speed; do slowest last.
# Output order varies, can be sorted with LC_COLLATE=C.UTF-8 sort or hledger -f- prices.

# ** REPORTS ------------------------------------------------------------

# show balance sheet
bs *HLEDGERARGS :
hledger bs --layout bare --pretty --drop 1 -p {{PERIOD}} -E -5 {{HLEDGERARGS}}

# show income statement
is *HLEDGERARGS :
hledger is --layout bare --pretty --drop 1 -p {{PERIOD}} -S {{HLEDGERARGS}}

# show assets
a *HLEDGERARGS :
hledger bal type:al -H --layout bare --pretty --drop 1 -p {{PERIOD}} -E {{HLEDGERARGS}}

# show revenues
r *HLEDGERARGS :
hledger bal type:r --layout bare --pretty --drop 1 -p {{PERIOD}} -S --invert {{HLEDGERARGS}}

# show expenses
x *HLEDGERARGS :
hledger bal type:x --layout bare --pretty --drop 1 -p {{PERIOD}} -S --invert {{HLEDGERARGS}}

# show assets bar chart
ab *HLEDGERARGS :
echo "Quarterly net worth:"
hledger-bar -v 200 -Q type:al -H {{HLEDGERARGS}}

# show revenues bar chart
rb *HLEDGERARGS :
echo "Quarterly revenues:"
hledger-bar -v 40 -Q type:r --invert {{HLEDGERARGS}}

# show expenses bar chart
xb *HLEDGERARGS :
echo "Quarterly expenses:"
hledger-bar -v 40 -Q type:x --invert {{HLEDGERARGS}}

# XXX with partial workaround for https://github.com/gooofy/drawilleplot/issues/4
# show assets line chart
al *HLEDGERARGS :
hledger plot -- bal --depth=1 type:a --historical --terminal --rcParams '{"figure.figsize":[8,3]}' --no-today -q --title "hledger assets" {{HLEDGERARGS}} | sed 's/⠀/ /g'

# show revenues line chart
rl *HLEDGERARGS :
hledger plot -- bal --depth=1 type:r --monthly --invert --terminal --rcParams '{"figure.figsize":[8,3]}' --drawstyle 'steps-mid' --no-today -q --title "hledger monthly revenues" {{HLEDGERARGS}} | sed 's/⠀/ /g'

# show expenses line chart
xl *HLEDGERARGS :
hledger plot -- bal --depth=1 type:x --monthly --terminal --rcParams '{"figure.figsize":[8,3]}' --drawstyle 'steps-mid' --no-today -q --title "hledger monthly expenses" {{HLEDGERARGS}} | sed 's/⠀/ /g'

# print transactions predicted by forecast rules from last week on
forecast *HLEDGERARGS :
hledger print --auto --forecast=lastweek.. -I tag:_generated {{HLEDGERARGS}}

# show a draft month-end household adjustment transaction for last month
household *HLEDGERARGS :
env household "$($date -v-1m +%b)"

# show consulting revenue
consulting *HLEDGERARGS :
hledger reg --invert 'revenues:(cw|ah)' -p {{PERIOD}} {{HLEDGERARGS}}

# estimated-tax *HLEDGERARGS :
# @echo "Federal estimated tax due for this year"
# $(HLEDGER) register liabilities:personal:tax:federal:$(YEAR) --width=130
# @echo State estimated tax due for this year:
# @$(HLEDGER) register liabilities:personal:tax:state:$(YEAR) --width=130
# @echo

# ** TIME REPORTS ------------------------------------------------------------

set export

# The file where actual time data is logged, for dashboard's stats.
# This might or might not be the top-level $TIMELOG file.
#TIMELOGDATA=$TIMELOG
YEAR := `date +%Y`
TIMELOGDATA := 'time-' + YEAR + '.timedot'

# This redisplays only when a file listed by `hledger -f $TIMELOG files` is modified.
# To force a per minute display as well, have $TIMELOG include a dummy file (.update)
# and configure a cron job to touch that every minute.
# (This is better than touching the timelog file itself, which confuses editors.)
#
# show time dashboard, redisplaying when timelog files change
tdash *HLEDGERARGS:
#!/usr/bin/env bash
dir=$(dirname "$TIMELOG")
cd "$dir"
opts="" #--poll=10 # <- uncomment to fix symlinked files being ignored
# files=`hledger -f "$TIMELOG" files | sed -E "s|$dir/||g"`
# watchexec $opts --no-vcs-ignore --filter-file="$files" -c -r justthis status
watchexec $opts --no-vcs-ignore --filter-file=<(hledger -f "$TIMELOG" files | sed -E "s|$dir/||g") -c -r {{justthis}} tstatus
# show time dashboard, redisplaying every minute with watch
# dash-1m *HLEDGERARGS:
# watch -n60 -c tt status
# }

# show current time status
tstatus *HLEDGERARGS:
#!/usr/bin/env bash
date=$(if [ "$(builtin type -p gdate)" ]; then echo gdate; else echo date; fi)
stat=$(if [ "$(builtin type -p gstat)" ]; then echo gstat; else echo stat; fi)
curtime=$($date +'%H:%M %Z, %a %b %-e %Y')
modtime=$($date +'%H:%M %Z' -r "$TIMELOGDATA")
modsecs=$($stat -c %Y "$TIMELOGDATA")
nowsecs=$($date +%s)
agesecs=$((nowsecs - modsecs))
agemins=$(python3 -c "print($agesecs/60)")
agehrs=$(python3 -c "print($agesecs/3600.0)")
ageqtrhrs=$(python3 -c "print(round($agesecs/900.0))")
agedots=$({{justthis}} dots "$ageqtrhrs")
printf "Current time: %s\n" "$curtime"
# old, for osh: use env here to run the system printf, which supports floating point
env printf "Timelog saved: %s, %.0fm / %.1fh / %s ago\n" "$modtime" "$agemins" "$agehrs" "$agedots"
# Show the current day/week/month budget status.
printf "Time plans:\n"
# calculate each period's budget from daily budget
hledger -f "$TIMELOG" bal -1 -p 'daily today' --budget=Daily | tail +2
hledger -f "$TIMELOG" bal -1 -p 'weekly this week' --budget=Daily | tail +2
hledger -f "$TIMELOG" bal -1 -p 'monthly this month' --budget=Daily | tail +2
# or use each period's specific budget
# hledger -f "$TIMELOG" bal -p 'daily today' --budget=Daily -1 | tail +2
# hledger -f "$TIMELOG" bal -p 'weekly this week' --budget=Weekly -1 | tail +2
# hledger -f "$TIMELOG" bal -p 'monthly this month' --budget=Monthly -1 | tail +2
echo
hledger -f "$TIMELOG" check -s tags ordereddates || true
# this comes last because it's slow and variable length
echo
printf "Display activity:\n"
wakelog today | tail -n 6
# what happened ? Show largest time balances first, today and depth 1 by default
@twhat *HLEDGERARGS:
hledger -f "$TIMELOG" bal -S -1 -p today {{HLEDGERARGS}}

# print line of N dots, grouped in 4s (suitable for timedot)
tdots N:
#!/usr/bin/env bash
n={{N}}
ndiv4=$((n/4))
nmod4=$((n-n/4*4))
sep=''
while [[ $ndiv4 -gt 0 ]]; do ndiv4=$((ndiv4-1)); echo -n "$sep...."; sep=' '; done
while [[ $nmod4 -gt 0 ]]; do nmod4=$((nmod4-1)); echo -n "$sep."; sep=''; done
echo
RFLAGS:='-tM' #TA

# horizontal time summary this year, monthly by default
@tx *HLEDGERARGS:
hledger -f "$TIMELOG" bal -1 "$RFLAGS" {{HLEDGERARGS}}

# vertical time summary this year, monthly by default
@ty *HLEDGERARGS:
hledger -f "$TIMELOG" bal -1 "$RFLAGS" --transpose {{HLEDGERARGS}}

# this and last week's time budgets
@tweeks *HLEDGERARGS:
printf "\nLast week, this week:\n"
timeweekly run

# recent past weeks' time budgets
@tweekspast *HLEDGERARGS:
printf "\nPast weeks:\n"
timeweekly past

# show a bar chart of daily hours
@thours *HLEDGERARGS:
hledger-bar -v 1 -f "$TIMELOG" -D {{HLEDGERARGS}}

# show unused / undeclared time accounts
@taccunused *HLEDGERARGS:
echo "Unused: (but declared)"
hledger -f "$TIMELOG" acc --unused {{HLEDGERARGS}} --directives | gsed -E 's/:(.)/.\1/g'
echo
echo "Undeclared: (but used)"
hledger -f "$TIMELOG" acc --undeclared {{HLEDGERARGS}} --directives | gsed -E 's/:(.)/.\1/g'

# show unused / undeclared time accounts by category
@taccunusedcat *HLEDGERARGS:
for a in $(tt acc -1); do line; echo "$a":; tt unused "^$a"; echo; done; line

# add declarations for all undeclared time accounts
@taccadd *HLEDGERARGS:
hledger -f "$TIMELOG" accounts --undeclared --directives | sed 's/:/./g' >>"$TIMELOG"

# show monthly time budget performance this year
@tbudgets *HLEDGERARGS:
{{justthis}} tx --budget=daily -M -p jan..tomorrow {{HLEDGERARGS}}

# show monthly time budget performance this year, vertically
@tbudgetsy *HLEDGERARGS:
{{justthis}} ty --budget=daily -M -p jan..tomorrow {{HLEDGERARGS}}

# dedicated weekly reports, needed to set proper week start date, to ensure simple headings:

# show weekly time budget performance this year
@tbudgetsw *HLEDGERARGS:
{{justthis}} ty --budget=daily -W -p 3/27..tomorrow {{HLEDGERARGS}}

# show weekly time budget performance this year, horizontally
@tbudgetswx *HLEDGERARGS:
{{justthis}} tx --budget=daily -W -p 3/27..tomorrow {{HLEDGERARGS}}

0 comments on commit 67e5a45

Please sign in to comment.