summaryrefslogtreecommitdiff
path: root/internal/cli/cli.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-07-24 15:25:50 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-07-24 15:25:50 +0200
commited7717fef53db3b3aa5593fbb2649313e75a0f31 (patch)
tree023601285808a4704f5646bf6e4777beea6dd93a /internal/cli/cli.go
parent1e4939874a14d8abb13e82b2273bfc5f9d653295 (diff)
downloadlectio-ed7717fef53db3b3aa5593fbb2649313e75a0f31.tar.gz
lectio-ed7717fef53db3b3aa5593fbb2649313e75a0f31.zip
cli: --rand/--rand-v (random verse) + --rand-ch (random chapter) from the corpus, using the config default version; v0.16.0
Diffstat (limited to 'internal/cli/cli.go')
-rw-r--r--internal/cli/cli.go100
1 files changed, 97 insertions, 3 deletions
diff --git a/internal/cli/cli.go b/internal/cli/cli.go
index ef00010..ff1299a 100644
--- a/internal/cli/cli.go
+++ b/internal/cli/cli.go
@@ -7,6 +7,7 @@ import (
"flag"
"fmt"
"io"
+ "math/rand"
"os"
"regexp"
"strconv"
@@ -45,6 +46,8 @@ Flags:
--list list all books + abbreviations (dialect from sigla_style)
--citation print the day's gospel reference (scripts/cron) and exit
--week list the coming week's gospel references and exit
+ --rand, --rand-v print a random verse (corpus version) and exit
+ --rand-ch print a random chapter and exit
-v, --version print the version and exit
-h, --help this help
@@ -63,6 +66,7 @@ Examples:
lectio --list list every book + abbreviations
lectio --citation today's gospel reference
lectio --week 2026-07-22 a week of gospel references from a date
+ lectio --rand-v a random verse (for cron/prompt)
Flags override config. Exit codes: 0 ok, 1 runtime error (fetch/parse),
2 usage error (bad flag, bad date, bad version, bad --lectionary/--lang).
@@ -101,6 +105,7 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
}
var all, raw, refresh, offline, update, clean, pagerFlag, noPager, citation, week bool
+ var randV, randCh bool
var bibleVer, compareList, lectionary, lang string
var width int
var list bool
@@ -140,6 +145,9 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
fs.BoolVar(&list, "list", false, "list all books + abbreviations (in your sigla_style)")
fs.BoolVar(&citation, "citation", false, "print the day's gospel reference and exit")
fs.BoolVar(&week, "week", false, "list the coming week's gospel references and exit")
+ fs.BoolVar(&randV, "rand", false, "print a random verse from the corpus and exit")
+ fs.BoolVar(&randV, "rand-v", false, "print a random verse from the corpus and exit")
+ fs.BoolVar(&randCh, "rand-ch", false, "print a random chapter from the corpus and exit")
if err := fs.Parse(rest); err != nil {
return 2
@@ -181,12 +189,21 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
cfg.TraditionalLang = lang
}
- if citation || week {
+ if citation || week || randV || randCh {
tbl, _ := bible.LoadBookTable(userBooksTOML())
- if citation {
+ switch {
+ case randV || randCh:
+ ver, verr := randVersion(cfg, bibleVer)
+ if verr != nil {
+ fmt.Fprintln(stderr, "lectio:", verr)
+ return 2
+ }
+ return runRand(cfg, tbl, ver, randCh, raw, width, stdout, stderr)
+ case citation:
return runCitation(cfg, tbl, date, refresh, stdout, stderr)
+ default:
+ return runWeek(cfg, tbl, date, refresh, stdout, stderr)
}
- return runWeek(cfg, tbl, date, refresh, stdout, stderr)
}
effAll := all || cfg.All
@@ -693,6 +710,83 @@ func renderCompare(cfg config.Config, list, date string, all, raw bool, width in
return 0
}
+// randVersion picks the corpus version for --rand: an explicit -b VER (rejected
+// if it has no corpus), else the configured default_version if it has a corpus,
+// else the first corpus version in cfg.Versions, else "wuj". So a config whose
+// default is "bt" (no corpus) still yields a random passage.
+func randVersion(cfg config.Config, bibleVer string) (string, error) {
+ if bibleVer != "" {
+ if !isCorpusVersion(bibleVer) {
+ return "", fmt.Errorf("--rand needs a corpus version; %q has no full text (use wuj, vul, grb, drb)", bibleVer)
+ }
+ return bibleVer, nil
+ }
+ if isCorpusVersion(cfg.DefaultVersion) {
+ return cfg.DefaultVersion, nil
+ }
+ for _, v := range cfg.Versions {
+ if isCorpusVersion(v) {
+ return v, nil
+ }
+ }
+ return "wuj", nil
+}
+
+// runRand prints a random verse (chapter=false) or whole chapter (chapter=true)
+// from version's embedded corpus, for a "verse of the day" cron/pipe. It picks a
+// random book -> chapter -> verse (not perfectly uniform across all verses, but
+// fine for the purpose). Non-raw prints the reference (in cfg's sigla dialect)
+// then the text; raw prints just the text (verse-numbered for a chapter).
+func runRand(cfg config.Config, tbl *bible.BookTable, version string, chapter, raw bool, width int, stdout, stderr io.Writer) int {
+ books := bible.CorpusBooks(version)
+ if len(books) == 0 {
+ fmt.Fprintf(stderr, "lectio: no corpus for version %q\n", version)
+ return 1
+ }
+ rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+
+ var book string
+ var chap int
+ var verses []bible.Verse
+ for tries := 0; tries < 20 && len(verses) == 0; tries++ {
+ book = books[rng.Intn(len(books))]
+ chaps := bible.Chapters(version, book)
+ if len(chaps) == 0 {
+ continue
+ }
+ chap = chaps[rng.Intn(len(chaps))]
+ verses = bible.Verses(version, book, chap)
+ }
+ if len(verses) == 0 {
+ fmt.Fprintln(stderr, "lectio: could not pick a random passage")
+ return 1
+ }
+
+ w := resolveWidth(width, false, stdout)
+ dialect := cfg.SiglaLang()
+
+ if chapter {
+ if !raw {
+ fmt.Fprintln(stdout, fmt.Sprintf("%s %d", tbl.Abbrev(dialect, book), chap))
+ fmt.Fprintln(stdout)
+ }
+ lines := make([]string, 0, len(verses))
+ for _, v := range verses {
+ lines = append(lines, wrapText(fmt.Sprintf("%d %s", v.Verse, v.Text), w))
+ }
+ fmt.Fprintln(stdout, strings.Join(lines, "\n"))
+ return 0
+ }
+
+ v := verses[rng.Intn(len(verses))]
+ if !raw {
+ fmt.Fprintln(stdout, tbl.FormatRef(dialect, fmt.Sprintf("%s %d:%d", book, chap, v.Verse)))
+ fmt.Fprintln(stdout)
+ }
+ fmt.Fprintln(stdout, wrapText(v.Text, w))
+ return 0
+}
+
// isCorpusVersion reports whether v is a scripture-text version with an
// embedded corpus (wuj/vul/grb/drb) -- i.e. a valid version that is not "bt"
// (the niedziela.pl scrape, which has no full text to look a passage up in).