For almost a year now I have been keeping my personal finances using a plain text accounting tool called hledger. One of the issues I have with it is that I can’t use it from Clojure (or Java) and it’s hard to build apps around it. I would like to enter transactions using a Gnome extension or another GUI application and have some nice features like
auto-complete
syntax checking
validation
syntax highlighting
As you can see, having a grammar opens up many possibilities.
I was also looking for an excuse to work with Anltr.
So the universe aligned and I decided to work on building a grammar so I can work on my apps. I decided to make it open source so other people can use it and improve it.
The project is available at hledger-grammars . Submit feedback, issues and patches there.
Right now it has a working grammar for timeclock. Check the source for updates or even ask about the status.
If you like to show interest in the project, please star the git repository and send me feedback. |
If you would like to be kept up to date please follow me on https://twitter.com/ieugen222 . |
My plan is to implement Antlr grammars for hledger journal formats and some examples on how to use them.
Since the accounting journal can be quite complex I plan to support only a subset that I use. If people are interested they can contribute patches for their use-cases or they can make their own version.
I haven’t decided yet if and what bindings to publish.
I started with a grammar for timeclock journal since the format is quite simple. I am new to Antlr and wanted something easy to get results and give me time to learn.
Timeclock is a simple journal format used for time logging. The format is simple but very powerful.
i 2015/03/30 09:00:00 some:account name optional description after two spaces
o 2015/03/30 09:20:00
i 2015/03/31 22:21:45 another account
o 2015/04/01 02:00:34
It is this power and flexibility that lead me to use plain text accounting tools.
A timeclock transaction
is composed of a clock-in
and clock-out
pair with accounts and optional description.
From this entry (event) log you are able to derive a lot of information and reports.
The grammar for it was simple to implement and is available in the git repository. I’ve used a clojure library called clj-antlr to develop the grammar.
This was immensely helpful since I could use REPL driven development and iterate ery fast on the design.
To give you an idea, all the code I wrote to develop the library is bellow:
(ns ieugen.hledger.timeclock
(:require [clj-antlr.core :as antlr]
[clojure.pprint :as pp]))
(defn load-grammar [path]
(antlr/parser path))
(def tclock (load-grammar "grammars/timeclock.g4"))
(comment
(let [tclock (antlr/parser "grammars/timeclock.g4")
source (slurp "test/samples/sample.timeclock")
parsed (tclock source)]
parsed)
0)
During development all I had to do was work on my grammar and execute the clojure comment block for instant feedback.
I was able to iterate very fast. I managed to build the project in less than a day from no repo to a working Antlr grammar.
For learning Antlr I found a very nice tutorial online that I recommend Antlr mega tutorial .
Now that I have the grammar I started working on adding syntax highlighting for monaco-editor . Monaco is the web version of Visual Studio Code from Microsoft. I use VSCode daily and Calva to develop Clojure and I think it makes for a good integration example.
To make this work I will have to improve the grammar and also split it into a lexer and a parser grammar.
I am developing the example using ClojureScript so I will have to generate JavaScript bindings for my grammar as well.
Once this is done I will have to do the monaco-editor integration.
Hopefully, next week I’ll be able to finish this up and have it working online.
After this is done I’ll probably start working on the grammar for hledger journal files. Maybe a VSCode extension for hledger timeclock is also in order.
So stay tuned.