From 0bcddd4ed0aff66452397dc0973337c535c0d2ed Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Mon, 27 Jul 2026 20:29:31 +0200 Subject: feat(cli): lectio --corpus-check validator --- internal/cli/corpus.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 internal/cli/corpus.go (limited to 'internal/cli/corpus.go') diff --git a/internal/cli/corpus.go b/internal/cli/corpus.go new file mode 100644 index 0000000..15a140c --- /dev/null +++ b/internal/cli/corpus.go @@ -0,0 +1,69 @@ +package cli + +import ( + "encoding/json" + "fmt" + "io" + "path/filepath" + "strings" + + "github.com/lukaszkasprzak/lectio/internal/bible" + "github.com/lukaszkasprzak/lectio/internal/config" +) + +// runCorpusCheck handles --corpus-check : validates a bible +// corpus's sidecar + text (bible.CheckCorpus) and prints the report, plain or +// (with asJSON) as JSON. It exits 1 if the report has any errors, 0 +// otherwise -- coverage warnings never fail the check. +// +// arg is either a bare corpus code, resolved against the user corpora dir +// (config.CorporaDir(), which overrides the embedded built-ins the same way +// normal rendering does), or a path to a .tsv file -- its directory +// becomes the user corpora dir for this run and its basename (minus ".tsv") +// the code. The path form lets a corpus be validated before it is copied +// into internal/bible/corpora/ (see scripts/corpus-validate.sh, make +// add-corpus). +func runCorpusCheck(arg string, asJSON bool, stdout, stderr io.Writer) int { + code := arg + if strings.Contains(arg, "/") || strings.HasSuffix(arg, ".tsv") { + dir := filepath.Dir(arg) + code = strings.TrimSuffix(filepath.Base(arg), ".tsv") + bible.SetUserCorporaDir(dir) + } else if dir, err := config.CorporaDir(); err == nil { + bible.SetUserCorporaDir(dir) + } + + report := bible.CheckCorpus(code) + + if asJSON { + enc := json.NewEncoder(stdout) + enc.SetIndent("", " ") + if err := enc.Encode(report); err != nil { + fmt.Fprintln(stderr, "lectio:", err) + return 1 + } + } else { + printCorpusReport(stdout, report) + } + + if !report.OK() { + return 1 + } + return 0 +} + +// printCorpusReport renders a CorpusReport as plain text: one line per +// error/warning, then a summary line. +func printCorpusReport(w io.Writer, r bible.CorpusReport) { + for _, e := range r.Errors { + fmt.Fprintf(w, "ERROR: %s\n", e) + } + for _, wm := range r.Warnings { + fmt.Fprintf(w, "WARNING: %s\n", wm) + } + if r.OK() { + fmt.Fprintf(w, "ok: %s (%d warning(s))\n", r.Code, len(r.Warnings)) + } else { + fmt.Fprintf(w, "FAIL: %s (%d error(s), %d warning(s))\n", r.Code, len(r.Errors), len(r.Warnings)) + } +} -- cgit v1.3