From 723f223690ce6a01124ea5fbd12e1a90ee0ab3f4 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Tue, 28 Jul 2026 22:08:06 +0200 Subject: cmd/clectio-gen: generator for the tiny C build; bible.LookupKeyed clectio (~/git/projects/clectio) is a tiny suckless-C daily-readings build that compiles the calendar, citations and scripture text in. clectio-gen is its data compiler: it reuses this engine to compute, for a year range, each day's name/colour/readings and emits corpus-independent C tables plus the verse KEYS, so the C side is a dumb lookup and the hard liturgical logic stays here (oracle-validated). - bible.LookupKeyed(version, ref) returns each resolved verse's (book, chapter, verse) key, mirroring Lookup's splitting/versification. clectio-gen uses it to record the exact pericopes a lectionary cites. - Verified: clectio's output is byte-identical to lectio's readings, day names 157/157 over a 3-year sample. --- internal/bible/ref.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'internal/bible/ref.go') diff --git a/internal/bible/ref.go b/internal/bible/ref.go index d0a615d..9e44060 100644 --- a/internal/bible/ref.go +++ b/internal/bible/ref.go @@ -112,6 +112,60 @@ func Lookup(version, ref string) ([]Verse, []string) { return verses, missing } +// KeyedVerse is a resolved verse tagged with its canonical book, for tools that +// need the (book, chapter, verse) key rather than the text -- e.g. extracting +// the exact set of pericopes a lectionary cites (cmd/clectio-gen). +type KeyedVerse struct { + Book string + Chapter, Verse int +} + +// LookupKeyed resolves a reference like Lookup but returns each matched verse's +// (book, chapter, verse) key instead of its text, in the same order and with the +// same splitting/cross-chapter/versification handling -- so the keys correspond +// exactly to the verses Lookup would return for the same version and ref. +func LookupKeyed(version, ref string) []KeyedVerse { + var out []KeyedVerse + for _, part := range SplitRef(ref) { + m := refRe.FindStringSubmatch(part) + if m == nil { + continue + } + book, ok := ResolveBook(m[1]) + if !ok { + continue + } + chap, _ := strconv.Atoi(m[2]) + if cm := crossChapRangeRe.FindStringSubmatch(m[3]); cm != nil { + from, _ := strconv.Atoi(cm[1]) + toChap, _ := strconv.Atoi(cm[2]) + toVerse, _ := strconv.Atoi(cm[3]) + for c := chap; c <= toChap; c++ { + lo, hi := 1, noUpperBound + if c == chap { + lo = from + } + if c == toChap { + hi = toVerse + } + for _, v := range Verses(version, book, c) { + if v.Verse >= lo && v.Verse <= hi { + out = append(out, KeyedVerse{book, v.Chapter, v.Verse}) + } + } + } + } else { + from, to := verseRange(m[3]) + for _, v := range Verses(version, book, chap) { + if v.Verse >= from && v.Verse <= to { + out = append(out, KeyedVerse{book, v.Chapter, v.Verse}) + } + } + } + } + return out +} + func verseRange(s string) (int, int) { s = strings.TrimSpace(s) if i := strings.IndexAny(s, "-–—"); i >= 0 { -- cgit v1.3