commit 245895edcdfcc5ef231ee2a3ee1051fb721a127d
parent 3587d7009072d056cefe384f680d3d75470453f2
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Sat, 20 Aug 2022 14:41:51 -0500
add initial moonledger-accounts program and a library
Diffstat:
2 files changed, 115 insertions(+), 0 deletions(-)
diff --git a/moonledger-accounts b/moonledger-accounts
@@ -0,0 +1,24 @@
+#!/usr/bin/lua
+
+ml = require "moonledger"
+
+assert(arg[1], "expected ledger as argument")
+
+ml.check(arg[1])
+accounts = {}
+
+function tx(input)
+ for i, v in ipairs(input.postings) do
+ if accounts[v.account] then
+ accounts[v.account] = accounts[v.account] + Dec.new(v.quantity)
+ else
+ accounts[v.account] = Dec.new(v.quantity)
+ end
+ end
+end
+
+dofile(arg[1])
+
+for k, v in pairs(accounts) do
+ io.stdout:write(k, "\t", Dec.tostring(v), '\n')
+end
diff --git a/moonledger.lua b/moonledger.lua
@@ -0,0 +1,91 @@
+-- moonledger shared functions
+
+Dec = require "decmath"
+
+function checkpostings(transaction)
+ local sum = Dec("0")
+
+ assert(transaction)
+ assert(transaction.postings)
+
+ for i, v in ipairs(transaction.postings) do
+ sum = sum + Dec.new(v.quantity)
+ end
+
+ assert(sum == Dec("0"), string.format('posting \"%s\" sums to %s', transaction.desc, Dec.tostring(sum)))
+end
+
+function check(fname)
+ oldtx = tx
+ tx = checkpostings
+ dofile(fname)
+ tx = oldtx
+end
+
+function dumptransaction(t)
+ io.write(string.format(
+[[tx{
+ date = {year = %d, month = %d, day = %d},
+ desc = "%s",
+ postings = {
+]], t.date.year, t.date.month, t.date.day, t.desc))
+ for _, posting in ipairs(t.postings) do
+ io.write(string.format([[ {account="%s", quantity="%s", unit="%s"},
+]], posting.account, posting.quantity, posting.unit))
+ end
+
+ io.write([[ }
+}
+]]);
+end
+
+-- pulled from https://lua-users.org/wiki/LuaCsv
+function parseCSVLine(line, sep)
+ local res = {}
+ local pos = 1
+ sep = sep or ','
+ while true do
+ local c = string.sub(line,pos,pos)
+ if (c == "") then break end
+ if (c == '"') then
+ -- quoted value (ignore separator within)
+ local txt = ""
+ repeat
+ local startp,endp = string.find(line,'^%b""',pos)
+ txt = txt..string.sub(line,startp+1,endp-1)
+ pos = endp + 1
+ c = string.sub(line,pos,pos)
+ if (c == '"') then txt = txt..'"' end
+ -- check first char AFTER quoted string, if it is another
+ -- quoted string without separator, then append it
+ -- this is the way to "escape" the quote char in a quote. example:
+ -- value1,"blub""blip""boing",value3 will result in blub"blip"boing for the middle
+ until (c ~= '"')
+ table.insert(res,txt)
+ assert(c == sep or c == "")
+ pos = pos + 1
+ else
+ -- no quotes used, just look for the first separator
+ local startp,endp = string.find(line,sep,pos)
+ if (startp) then
+ table.insert(res,string.sub(line,pos,startp-1))
+ pos = endp + 1
+ else
+ -- no separator found -> use rest of string and terminate
+ table.insert(res,string.sub(line,pos))
+ break
+ end
+ end
+ end
+ return res
+end
+
+function csv()
+ local iter = io.lines()
+ return function()
+ local val = iter()
+ if val then return parseCSVLine(val) end
+ end
+end
+
+return {check = check, dumptransaction = dumptransaction, util = {csv = csv}}