diff options
Diffstat (limited to 'internal/bible/registry.go')
| -rw-r--r-- | internal/bible/registry.go | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/internal/bible/registry.go b/internal/bible/registry.go new file mode 100644 index 0000000..2ab721b --- /dev/null +++ b/internal/bible/registry.go @@ -0,0 +1,110 @@ +package bible + +import ( + "os" + "path/filepath" + "sort" + "strings" + "sync" +) + +var ( + regMu sync.Mutex + userDir string + regBuilt bool + regMeta map[string]CorpusMeta // code -> meta (user overrides embed) + regUserTSV map[string]string // code -> user .tsv path (override source) +) + +// SetUserCorporaDir sets the drop-in dir and invalidates the registry cache. +// Empty string disables user corpora (used by tests). +func SetUserCorporaDir(dir string) { + regMu.Lock() + userDir = dir + regBuilt = false + regMu.Unlock() + + corporaMu.Lock() + corpora = map[string]*corpus{} // drop cached loads so overrides take effect + corporaMu.Unlock() +} + +func buildRegistry() { + if regBuilt { + return + } + regMeta = map[string]CorpusMeta{} + regUserTSV = map[string]string{} + // embedded first + ents, _ := corporaFS.ReadDir("corpora") + for _, e := range ents { + if code, ok := strings.CutSuffix(e.Name(), ".ini"); ok { + if m, ok := embeddedCorpusMeta(code); ok { + regMeta[code] = m + } + } + } + // user dir overrides + if userDir != "" { + ents, _ := os.ReadDir(userDir) + for _, e := range ents { + name := e.Name() + if code, ok := strings.CutSuffix(name, ".tsv"); ok { + regUserTSV[code] = filepath.Join(userDir, name) + if _, have := regMeta[code]; !have { + regMeta[code] = CorpusMeta{Code: code, PsalmSystem: "vulgate"} + } + } + } + for _, e := range ents { + if code, ok := strings.CutSuffix(e.Name(), ".ini"); ok { + data, err := os.ReadFile(filepath.Join(userDir, e.Name())) + if err == nil { + regMeta[code] = parseCorpusMeta(code, data) + } + } + } + } + regBuilt = true +} + +// Corpora returns all known corpora, sorted by code. +func Corpora() []CorpusMeta { + regMu.Lock() + defer regMu.Unlock() + buildRegistry() + out := make([]CorpusMeta, 0, len(regMeta)) + for _, m := range regMeta { + out = append(out, m) + } + sort.Slice(out, func(i, j int) bool { return out[i].Code < out[j].Code }) + return out +} + +// Meta returns a corpus's metadata. +func Meta(code string) (CorpusMeta, bool) { + regMu.Lock() + defer regMu.Unlock() + buildRegistry() + m, ok := regMeta[code] + return m, ok +} + +// CorporaForLang returns corpora whose lang == lang, sorted by code. +func CorporaForLang(lang string) []CorpusMeta { + var out []CorpusMeta + for _, m := range Corpora() { + if m.Lang == lang { + out = append(out, m) + } + } + return out +} + +// userTSVPath returns the override .tsv path for code, or "". +func userTSVPath(code string) string { + regMu.Lock() + defer regMu.Unlock() + buildRegistry() + return regUserTSV[code] +} |
