summaryrefslogtreecommitdiff
path: root/internal/cli
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-07-24 10:32:28 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-07-24 10:32:28 +0200
commitc9f3bf46f0de09edb796e35f3dcff349febf75c9 (patch)
treec1a0b98b484e4da557c1ab205dfff0d92ce8ac36 /internal/cli
parenta865374755480a4aef2a6156afccdf08a91422ea (diff)
downloadlectio-c9f3bf46f0de09edb796e35f3dcff349febf75c9.tar.gz
lectio-c9f3bf46f0de09edb796e35f3dcff349febf75c9.zip
dayinfo: show feast/day name + colour (modern niedziela + traditional missalemeum) in cli/tui/web; v0.5.0
Diffstat (limited to 'internal/cli')
-rw-r--r--internal/cli/cli.go33
-rw-r--r--internal/cli/cli_test.go40
2 files changed, 70 insertions, 3 deletions
diff --git a/internal/cli/cli.go b/internal/cli/cli.go
index f4aec28..5954e23 100644
--- a/internal/cli/cli.go
+++ b/internal/cli/cli.go
@@ -329,7 +329,7 @@ func cacheTraditionalRange(from, to, lang string) int {
cached := 0
for d := start; !d.After(end); d = d.AddDate(0, 0, 1) {
- if _, err := tradlit.Load(d.Format("2006-01-02"), lang, false); err == nil {
+ if _, _, err := tradlit.Load(d.Format("2006-01-02"), lang, false); err == nil {
cached++
}
}
@@ -383,7 +383,7 @@ func formatFreed(bytes int64) string {
// -b/--bible): fetch via the readings router, apply the offline version
// swap, then render each section's heading and render.GatherVersion blocks.
func fetchAndPrint(cfg config.Config, version, date string, all, raw bool, width int, refresh bool, stdout, stderr io.Writer) int {
- secs, err := readings.Load(cfg, readings.Options{
+ secs, dayInfo, err := readings.Load(cfg, readings.Options{
Date: date,
Refresh: refresh,
Offline: cfg.Offline,
@@ -405,6 +405,7 @@ func fetchAndPrint(cfg config.Config, version, date string, all, raw bool, width
w := resolveWidth(width, false, stdout)
if !raw {
+ printDayInfo(stdout, dayInfo)
banner := bannerFor(cfg.UILanguage, all, date)
fmt.Fprintln(stdout, banner)
fmt.Fprintln(stdout, strings.Repeat("=", minInt(len(banner), w)))
@@ -419,6 +420,31 @@ func fetchAndPrint(cfg config.Config, version, date string, all, raw bool, width
return 0
}
+// printDayInfo prints the day's celebration name -- and, if the source
+// carries one, its temporal Season on its own line -- above the banner.
+// Name/Season are never translated (source-language, like the readings/
+// citations themselves; see liturgy.DayInfo). A source that yielded no
+// DayInfo (info.Name == "") prints nothing: the header is a nice-to-have,
+// never an error condition. Callers only reach this when !raw; --raw skips
+// it entirely, keeping piped output text-only.
+//
+// The CLI has no ANSI styling of its own (unlike the TUI's Faint/dim
+// styles), so "dim" here is expressed structurally: the Season, if any,
+// gets its own line under Name rather than sharing emphasis with it.
+func printDayInfo(stdout io.Writer, info liturgy.DayInfo) {
+ if info.Name == "" {
+ return
+ }
+ name := info.Name
+ if info.Colour != "" {
+ name += " · " + info.Colour
+ }
+ fmt.Fprintln(stdout, name)
+ if info.Season != "" {
+ fmt.Fprintln(stdout, info.Season)
+ }
+}
+
// bannerFor builds the "<Gospel|Readings> <connective> DATE" banner: the
// "readings" word when every part is shown, "gospel" for the gospel-only
// default, and the connective between word and date, all localised via
@@ -475,7 +501,7 @@ func renderCompare(cfg config.Config, list, date string, all, raw bool, width in
}
versions = render.EffectiveVersions(versions, cfg.Lectionary, cfg.Offline)
- secs, err := readings.Load(cfg, readings.Options{
+ secs, dayInfo, err := readings.Load(cfg, readings.Options{
Date: date,
Refresh: refresh,
Offline: cfg.Offline,
@@ -493,6 +519,7 @@ func renderCompare(cfg config.Config, list, date string, all, raw bool, width in
w := resolveWidth(width, true, stdout)
if !raw {
+ printDayInfo(stdout, dayInfo)
banner := bannerFor(cfg.UILanguage, all, date)
fmt.Fprintln(stdout, banner)
fmt.Fprintln(stdout, strings.Repeat("=", minInt(len(banner), w)))
diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go
index 5004af4..6fc5e0e 100644
--- a/internal/cli/cli_test.go
+++ b/internal/cli/cli_test.go
@@ -2,10 +2,14 @@ package cli
import (
"bytes"
+ "net/http"
+ "net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
+
+ "github.com/lukaszkasprzak/lectio/internal/liturgy"
)
func TestHelp(t *testing.T) {
@@ -189,6 +193,42 @@ func TestCleanPreferredOverUpdate(t *testing.T) {
}
}
+// TestDayInfoHeaderShown exercises fetchAndPrint's day-info header end to
+// end (via Run against a fixture server, matching internal/readings'
+// TestLoadModernRoutes): the day's celebration name appears above the
+// banner for the default (non-raw) render, and is entirely absent from
+// --raw output, which stays text-only for piping.
+func TestDayInfoHeaderShown(t *testing.T) {
+ html, err := os.ReadFile("../liturgy/testdata/2026-07-22.html")
+ if err != nil {
+ t.Fatal(err)
+ }
+ srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Write(html)
+ }))
+ defer srv.Close()
+ liturgy.SetBaseURL(srv.URL + "/liturgia/%s/Ewangelia")
+ t.Setenv("XDG_CACHE_HOME", t.TempDir())
+ t.Setenv("XDG_CONFIG_HOME", t.TempDir())
+
+ var out, errb bytes.Buffer
+ if code := Run([]string{"2026-07-22"}, nil, &out, &errb); code != 0 {
+ t.Fatalf("Run code=%d stderr=%q", code, errb.String())
+ }
+ if !strings.Contains(out.String(), "Święto św. Marii Magdaleny") {
+ t.Errorf("stdout missing day-info header: %q", out.String())
+ }
+
+ out.Reset()
+ errb.Reset()
+ if code := Run([]string{"2026-07-22", "-r"}, nil, &out, &errb); code != 0 {
+ t.Fatalf("Run --raw code=%d stderr=%q", code, errb.String())
+ }
+ if strings.Contains(out.String(), "Święto św. Marii Magdaleny") {
+ t.Errorf("--raw stdout should omit the day-info header: %q", out.String())
+ }
+}
+
// TestDateTokenAnyPosition exercises extractDate directly: the date token
// is found regardless of where it appears among other flags.
func TestDateTokenAnyPosition(t *testing.T) {