mirror of
https://git.pumpin.online/funkpower/typikon.git
synced 2026-10-22 18:57:13 +00:00
Every desktop shell that reads typikon today runs the binary and parses its JSON. That costs about 1.5ms and is the right answer for a calendar that changes once a day, but it is the wrong shape for anything with an FFI and no business spawning a process on every redraw. Dates cross as Julian Day Numbers, so no struct layout is part of the contract. A day is opaque and owns its strings, built once when it is reckoned: an accessor returns the same borrowed pointer every time, so a statusline polling one in a loop allocates nothing. The accessors carry every field of the JSON, so nothing on the other side needs a parser. The Python bindings and this were resolving a jurisdiction by two copies of the same logic, and the copy here leaked one per call. Both now share jurisdictions::resolve_full, which interns the combinations instead. The header is a promise made in a second file, and a second file drifts: a test reads both and fails if either has a symbol the other does not, and does the same for the LuaJIT cdef, where a stale declaration is a segfault rather than a compile error.
41 lines
1.3 KiB
Lua
41 lines
1.3 KiB
Lua
-- What a statusline would do with it: one line, no subprocess, no JSON.
|
|
--
|
|
-- cargo build --release --features capi
|
|
-- TYPIKON_LIB=target/release/libtypikon.so \
|
|
-- luajit examples/lua/statusline.lua rocor
|
|
|
|
package.path = (arg[0]:match("(.*/)") or "./") .. "?.lua;" .. package.path
|
|
|
|
local typikon = require("typikon")
|
|
|
|
local day, e = typikon.today({ jurisdiction = arg[1] })
|
|
if not day then
|
|
io.stderr:write(e, "\n")
|
|
os.exit(1)
|
|
end
|
|
|
|
-- The one line.
|
|
print(("%s %s %s%s"):format(
|
|
day.emoji,
|
|
day.church_date,
|
|
day.sign and (day.sign .. " ") or "",
|
|
day.title))
|
|
|
|
-- And the detail a tooltip would carry.
|
|
print()
|
|
print((" %-14s %s (%s, %s)"):format("reckoning", day.jurisdiction, day.calendar, day.tradition))
|
|
print((" %-14s %s%s"):format("fast", day.fast_label,
|
|
day.is_obligatory and " [obligatory]" or ""))
|
|
if day.binds then
|
|
print((" %-14s %s"):format("law requires", day.binds))
|
|
end
|
|
print((" %-14s %s"):format("because", day.reason))
|
|
if day.season then print((" %-14s %s"):format("season", day.season)) end
|
|
if day.cycle then print((" %-14s %s"):format("cycle", day.cycle)) end
|
|
for i = 2, #day.commemorations do
|
|
print((" %-14s %s"):format(i == 2 and "also" or "", day.commemorations[i]))
|
|
end
|
|
|
|
print((" %-14s %d days (%s)"):format("to Pascha", day.days_to_pascha,
|
|
("%04d-%02d-%02d"):format(typikon.ymd(day.pascha_jdn))))
|