moonledger

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/moonledger
Log | Files | Refs

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:
Amoonledger-accounts | 24++++++++++++++++++++++++
Amoonledger.lua | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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}}