package bible import ( "regexp" "strconv" "strings" ) var refRe = regexp.MustCompile(`^(.*?)\s+(\d+):(.+)$`) // SplitRef splits a ref whose verse list mixes single verses and ranges into // one ref per group (the kjv tools reject a mixed list in a single query). func SplitRef(ref string) []string { m := refRe.FindStringSubmatch(ref) if m == nil { return []string{ref} } book, chap, verses := m[1], m[2], m[3] if !strings.Contains(verses, ",") { return []string{ref} } var out []string for _, g := range strings.Split(verses, ",") { g = strings.TrimSpace(g) if g == "" { continue } if strings.Contains(g, ":") { out = append(out, book+" "+g) } else { out = append(out, book+" "+chap+":"+g) } } return out } // Lookup resolves an English-style reference against a version, returning the // matched verses (in order) and the sub-refs the corpus had no entry for. func Lookup(version, ref string) ([]Verse, []string) { var verses []Verse var missing []string for _, part := range SplitRef(ref) { m := refRe.FindStringSubmatch(part) if m == nil { missing = append(missing, part) continue } book, ok := ResolveBook(m[1]) if !ok { missing = append(missing, part) continue } chap, _ := strconv.Atoi(m[2]) from, to := verseRange(m[3]) found := false for _, v := range Verses(version, book, chap) { if v.Verse >= from && v.Verse <= to { verses = append(verses, v) found = true } } if !found { missing = append(missing, part) } } return verses, missing } func verseRange(s string) (int, int) { s = strings.TrimSpace(s) if i := strings.IndexAny(s, "-–—"); i >= 0 { from, _ := strconv.Atoi(strings.TrimSpace(s[:i])) to, _ := strconv.Atoi(strings.TrimSpace(s[i+1:])) return from, to } n, _ := strconv.Atoi(s) return n, n }