1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
package bible
import (
"regexp"
"strconv"
"strings"
"github.com/lukaszkasprzak/lectio/internal/psalter"
)
var (
// ofCiteRe splits an English-canonical citation into book, chapter and the
// verse tail: "2 Samuel 6:12b-15,17-19" -> ("2 Samuel", "6", "12b-15,17-19").
// The book is non-greedy so a leading ordinal ("2 Samuel") stays with it.
ofCiteRe = regexp.MustCompile(`^(.*?)\s+(\d+):(.+)$`)
// ofVerseLetterRe drops sub-verse part letters so lookups resolve at whole
// verses: "12b" -> "12", "3ab" -> "3", "3cd" -> "3".
ofVerseLetterRe = regexp.MustCompile(`(\d)[a-z]+`)
)
// normalizeOFVerses rewrites a citation's verse tail into the shape
// bible.Lookup parses: cross-chapter semicolons become commas, ranges use a
// plain hyphen, sub-verse letters are dropped, and spaces are removed.
func normalizeOFVerses(tail string) string {
tail = strings.ReplaceAll(tail, ";", ",")
tail = dashRe.ReplaceAllString(tail, "-")
tail = ofVerseLetterRe.ReplaceAllString(tail, "$1")
tail = strings.ReplaceAll(tail, " ", "")
return tail
}
// OFRef turns an English-canonical Ordinary Form citation (lectio's authored
// form) into a bible.Lookup-ready reference for the target corpus's Psalter.
//
// Every citation's verse tail is normalized (see normalizeOFVerses). Only the
// Psalms differ between Psalters, so their chapter/verse is additionally
// renumbered:
//
// - "vulgate" (vul/grb/wuj): shift the Hebrew chapter to its Vulgate
// equivalent (Ps 27 -> 26, Ps 147 -> 146). Verse numbers are kept, so the
// rare intra-psalm verse-boundary shifts are not corrected here.
// - "drb": the Douay-Rheims corpus keeps modern (Hebrew) chapter numbers, so
// the chapter is kept; only the DRB title-fold verse shift applies (see
// psalter.DrbVerse).
// - "hebrew" / anything else: already in the corpus's numbering.
//
// A citation OFRef cannot parse (no "chapter:verse") is returned unchanged for
// bible.Lookup to accept or reject.
func OFRef(citation, system string) string {
m := ofCiteRe.FindStringSubmatch(citation)
if m == nil {
return citation
}
book, chap, verses := m[1], m[2], normalizeOFVerses(m[3])
if book == "Psalms" {
heb, err := strconv.Atoi(chap)
if err == nil {
switch system {
case "vulgate":
chap = strconv.Itoa(psalter.HebrewToVulgateChapter(heb))
case "drb":
verses = digitsRe.ReplaceAllStringFunc(verses, func(s string) string {
n, _ := strconv.Atoi(s)
return strconv.Itoa(psalter.DrbVerse(heb, n))
})
}
}
}
return book + " " + chap + ":" + verses
}
|