aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/dune7
-rw-r--r--data/ef/examples/diocesan-example.sexp102
-rw-r--r--man/colitur.115
-rw-r--r--test/cli.t5
-rw-r--r--test/dune1
-rw-r--r--test/test_rite_ef.ml31
6 files changed, 157 insertions, 4 deletions
diff --git a/data/dune b/data/dune
index 07e5307..aec4b3c 100644
--- a/data/dune
+++ b/data/dune
@@ -20,4 +20,9 @@
(ef/sanctoral.sexp as ef/sanctoral.sexp)
(ef/adjustments.sexp as ef/adjustments.sexp)
(ef/lectionary.sexp as ef/lectionary.sexp)
- (ef/commons.sexp as ef/commons.sexp)))
+ (ef/commons.sexp as ef/commons.sexp)
+ ; Shipped as runnable documentation, NOT as calendar data: every
+ ; celebration in it is invented, with example- slugs. It is what
+ ; `colitur --overlay` points at in the man page, so it must actually be
+ ; installed rather than only living in the source tree.
+ (ef/examples/diocesan-example.sexp as examples/diocesan-example.sexp)))
diff --git a/data/ef/examples/diocesan-example.sexp b/data/ef/examples/diocesan-example.sexp
new file mode 100644
index 0000000..65acf3a
--- /dev/null
+++ b/data/ef/examples/diocesan-example.sexp
@@ -0,0 +1,102 @@
+; ============================================================================
+; An EXAMPLE overlay calendar for `colitur --overlay`.
+;
+; This file is shipped as documentation you can run, not as calendar data.
+; Every celebration in it is INVENTED, with slugs prefixed `example-` so they
+; cannot collide with anything real. Copy it, gut it, and put your own diocese
+; or parish in its place.
+;
+; colitur day 2026 --overlay <prefix>/share/colitur/examples/diocesan-example.sexp
+;
+; WHAT AN OVERLAY IS
+;
+; A list of directives applied ON TOP of the shipped 1962 universal calendar,
+; never instead of it. colitur applies its own data/ef/adjustments.sexp first,
+; then each --overlay in the order given. Later writers win, so a local
+; calendar can deliberately override a universal entry by naming its slug.
+;
+; AN OVERLAY IS APPLIED, NOT VALIDATED. colitur's five test layers assert
+; things about the SHIPPED calendar; none of them can vouch for this file or
+; yours. A directive naming a slug that does not exist prints a warning on
+; stderr and the run continues, so a typo is visible rather than silent; a
+; file that fails to parse is fatal.
+;
+; THE FOUR DIRECTIVES
+;
+; (Add <entry>) a celebration the universal calendar lacks
+; (Suppress <slug>) remove one it has
+; (Replace <slug> <entry>) swap one out wholesale
+; (Edit <slug> (<edits>)) change named fields only
+;
+; DATES
+;
+; (Fixed (month 7) (day 11)) a civil date, every year
+; (Easter_offset -9) signed days from Easter
+; (Nth_weekday (month 10) (nth 1) (weekday Sun)) nth weekday of a month;
+; negative nth counts back,
+; so (nth -1) is the last
+;
+; RANKS are Class1..Class4; STATUS is Feast or Commemoration_only; COLOUR is
+; White Red Green Violet Rose Black; SUBJECT is Lord Bvm Saint Temporal.
+; NAMES are keyed by language code and any set of languages is allowed.
+; CITATIONS are reading references, never scripture text; omit them and the
+; day falls through to whatever the resolution chain finds.
+; ============================================================================
+((id diocesan-example)
+ (directives
+ (
+
+ ; ---- 1. A fixed-date local patron, with its own proper readings -------
+ ; The commonest thing a local calendar adds. III class is the usual rank
+ ; for a diocesan patron who is not the cathedral's titular.
+ (Add
+ ((date (Fixed (month 7) (day 11)))
+ (cel
+ ((slug example-local-patron)
+ (names ((la "Sancti Exempli Patroni") (en "St Example, Patron")
+ (pl "\197\154w. Przyk\197\130adu, Patrona")))
+ (rank Class3) (status Feast) (colour White) (subject Saint)
+ (citations (((part First) (reference "Ecclus 45:1-6"))
+ ((part Gospel) (reference "Matt 25:14-23"))))
+ (layer diocesan-example)))))
+
+ ; ---- 2. A MOVABLE feast: the first Sunday of October ------------------
+ ; The anniversary of a church's own dedication is I class IN THAT CHURCH,
+ ; which is why this one outranks and displaces the Sunday it lands on --
+ ; at III class it would lose to a II-class Sunday every year.
+ (Add
+ ((date (Nth_weekday (month 10) (nth 1) (weekday Sun)))
+ (cel
+ ((slug example-dedication)
+ (names ((la "Dedicatio Ecclesiae Exempli")
+ (en "Dedication of the Example Church")))
+ (rank Class1) (status Feast) (colour White) (subject Saint)
+ (citations (((part First) (reference "Apoc 21:2-5"))
+ ((part Gospel) (reference "Luke 19:1-10"))))
+ (layer diocesan-example)))))
+
+ ; ---- 3. An EASTER-RELATIVE local commemoration ------------------------
+ ; Easter+61 is the Friday after Corpus Christi. A commemoration never
+ ; wins the day; it is added to whatever office the day already has,
+ ; subject to the admission limits of RG 111.
+ (Add
+ ((date (Easter_offset 61))
+ (cel
+ ((slug example-local-commemoration)
+ (names ((la "Commemoratio Exempli") (en "A Local Commemoration")))
+ (rank Class4) (status Commemoration_only) (colour White)
+ (subject Saint) (citations ()) (layer diocesan-example)))))
+
+ ; ---- 4. RAISING a universal feast for local use -----------------------
+ ; A saint the whole Church keeps at III class may be the patron of your
+ ; diocese and kept higher. Edit changes only the fields named; everything
+ ; else, including the date and the readings, stays as shipped.
+ (Edit stanislaus ((Set_rank Class1) (Set_colour Red)))
+
+ ; ---- 5. SUPPRESSING one -----------------------------------------------
+ ; Shown for completeness and commented out, because suppressing a
+ ; universal feast is a real liturgical act and should be a deliberate
+ ; one. Uncomment only if your own calendar genuinely omits it.
+ ;
+ ; (Suppress example-not-kept-here)
+ )))
diff --git a/man/colitur.1 b/man/colitur.1
index a18b299..8a52858 100644
--- a/man/colitur.1
+++ b/man/colitur.1
@@ -160,8 +160,15 @@ in days, or an
.I Nth_weekday
of a month \(em so a patronal feast on "the first Sunday of October" or a
dedication anniversary reckoned from Easter are both expressible. See
-.I test/fixtures/overlay\-example\-diocesan.sexp
-in the source distribution for a worked example of both shapes.
+.I <prefix>/share/colitur/examples/diocesan\-example.sexp
+for a worked, runnable example of all four directives and all three date
+shapes:
+.RS
+.nf
+
+.B colitur day 2026 \-\-overlay <prefix>/share/colitur/examples/diocesan\-example.sexp
+.fi
+.RE
.PP
Accepted on
.B day
@@ -199,6 +206,10 @@ mode this program refuses.
The installed calendar data: the sanctoral calendar, its one hand\-authored
overlay, the temporal lectionary and the Commons. Four S\-expression files.
.TP
+.I <prefix>/share/colitur/examples/diocesan\-example.sexp
+A worked example overlay, shipped as runnable documentation. Every
+celebration in it is invented; copy it and put your own calendar in its place.
+.TP
.I <exedir>/../data/ef/
The build\-tree location, used when running from a source checkout.
.PP
diff --git a/test/cli.t b/test/cli.t
index 39354c6..0c79db4 100644
--- a/test/cli.t
+++ b/test/cli.t
@@ -336,3 +336,8 @@ An unknown option is rejected rather than treated as a positional word:
colitur: unknown option --diocese
colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> (try: colitur --help)
[2]
+
+The shipped example overlay is runnable documentation, and it must actually
+load -- an example that silently rotted would be worse than none. The cram
+sandbox cannot reach data/, so the assertion that it loads and applies lives
+in test_lectionary_ef.ml, which reads it from the source tree directly.
diff --git a/test/dune b/test/dune
index fb5127f..1e58c26 100644
--- a/test/dune
+++ b/test/dune
@@ -8,6 +8,7 @@
../data/ef/expected-divergences-missalemeum.sexp
../data/ef/lectionary.sexp
../data/ef/commons.sexp
+ ../data/ef/examples/diocesan-example.sexp
fixtures/lectio-ef-2005-2050.txt
fixtures/missalemeum-ef-2026-2027.txt
fixtures/missalemeum-ef-2038.txt
diff --git a/test/test_rite_ef.ml b/test/test_rite_ef.ml
index 4da6d73..f4991f3 100644
--- a/test/test_rite_ef.ml
+++ b/test/test_rite_ef.ml
@@ -526,9 +526,38 @@ let test_maurice_thomas_band_fidelity_end_to_end () =
[ "maurice-and-companions-martyrs" ]
(List.map (fun (c, _) -> slug_of c) day.LD.omitted)
+
+(* The SHIPPED example overlay (data/ef/examples/diocesan-example.sexp) is
+ documentation a user is invited to run and copy, and the man page names its
+ installed path. An example that silently stopped loading -- a directive
+ renamed, a Date_spec variant changed -- would be worse than shipping none,
+ because it would fail only for whoever tried it.
+
+ This asserts it PARSES against the REAL EF rank vocabulary and that it
+ still demonstrates the range it claims to. It deliberately does NOT assert
+ which days it produces: those celebrations are invented, and pinning their
+ dates would make an illustrative file behave like calendar data. *)
+let test_shipped_example_overlay_loads () =
+ let path = "../data/ef/examples/diocesan-example.sexp" in
+ match Overlay.load Rite_ef.Vocab_ef.rank_of_sexp path with
+ | Error e -> Alcotest.failf "the shipped example overlay must load: %s" e
+ | Ok o ->
+ Alcotest.(check string) "its id" "diocesan-example" o.Overlay.id;
+ Alcotest.(check bool) "it demonstrates at least four directives" true
+ (List.length o.Overlay.directives >= 4);
+ (* Applying it must be clean: a directive naming a slug the universal
+ calendar lacks would warn, and an EXAMPLE that warns teaches the
+ wrong lesson. *)
+ let layer = real_layer () in
+ let _, diagnostics = Overlay.apply layer o in
+ Alcotest.(check (list string)) "it applies with no diagnostics" []
+ (List.map Overlay.diagnostic_to_string diagnostics)
+
let suite =
( "Rite_ef (real data: overlay-in-effect, domain-ceiling)",
- [ Alcotest.test_case "the overlay suppression is observably in effect" `Quick
+ [ Alcotest.test_case "the shipped example overlay loads and applies cleanly" `Quick
+ test_shipped_example_overlay_loads;
+ Alcotest.test_case "the overlay suppression is observably in effect" `Quick
test_vigil_of_christmas_suppressed;
Alcotest.test_case "RG16(a) task: the two subject retags are in effect, the other four untouched"
`Quick test_rg16a_subject_retag_in_effect;