summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-22 11:21:14 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-22 11:21:14 +0200
commitfd8a4f115d3c62450368cf9b3fed5705ce78e805 (patch)
treef935ec0e2e4c39cb3ddbba364ebc1f873c1b0574 /bin
parent27b07b447be9cf960d1a44e480d8356245481d17 (diff)
downloadcolitur-fd8a4f115d3c62450368cf9b3fed5705ce78e805.tar.gz
colitur-fd8a4f115d3c62450368cf9b3fed5705ce78e805.zip
feat(cli): colitur rubrics prints the day's Mass formulary
Separate from day for the reason readings is: a formulary name contains spaces and day's row is space-separated with a variable-length tail. Modelled on readings' own structure (year parsing, --overlay plumbing, error handling): --overlay is accepted, since an overlay can change which celebration is observed and hence which Mass is said. --lang, --raw and --sigla-* are refused rather than silently ignored -- this row resolves no display name and no citation for any of them to affect. Output is TAB-separated (date, formulary slug, source), not space or " | " like the two existing reports: a resolved formulary NAME is a column a later task may add, and it can carry both spaces and punctuation a citation never does, ruling out either separator already in use. day and readings verified byte-identical (sha256) against a v0.10.1 build across 1583/1900/2026/2038/9999. Man page documents rubrics beside readings and renders through groff with no errors.
Diffstat (limited to 'bin')
-rw-r--r--bin/main.ml82
1 files changed, 75 insertions, 7 deletions
diff --git a/bin/main.ml b/bin/main.ml
index 18fd2f5..e00e020 100644
--- a/bin/main.ml
+++ b/bin/main.ml
@@ -362,6 +362,44 @@ let readings_line ~lang ~sigla (d : (Rite_ef.Vocab_ef.season, Rite_ef.Vocab_ef.r
(part_ref Colitur_kernel.Citation.Gospel)
name_suffix
+(* Task 4 (celebrant-rubrics-phase1): the day's own Mass formulary -- which
+ slug's Mass is actually said, and how that was decided
+ ({!Colitur_kernel.Mass_formulary.source}: proper/own/preceding-sunday/
+ common/votive).
+
+ A SEPARATE command from `day` and `readings`, for the identical mechanical
+ reason CLAUDE.md already records for `readings`: a formulary NAME (not
+ built yet, but the reason this row is shaped the way it is) contains
+ spaces ("Mass of the 9th Sunday after Pentecost"), and `day`'s own row is
+ fixed-width space-separated with a variable-length "+slug" tail, so
+ appending anything with its own internal whitespace there would leave the
+ row unsplittable by field number.
+
+ TAB-separated rather than reusing [readings_line]'s " | " -- deliberately
+ a THIRD delimiter, not a second use of the existing one -- because a
+ later column on this row (the resolved formulary name, once one exists)
+ can itself contain a literal "|" inside punctuation a citation never
+ does, and because TAB is what stays unambiguous once a field may carry
+ both spaces and arbitrary punctuation. This is also why `rubrics` does
+ not (yet) take --lang/--raw/--sigla-*: there is no display name or
+ citation on this row for any of them to resolve.
+
+ [d.formulary] is documented as [Some] on every day of every year for EF,
+ asserted by {!Colitur_kernel.Validate}'s own ["formulary"] check -- but
+ the type itself permits [None] (a rite with no lectionary), so this
+ prints "-" rather than pattern-matching partially and crashing on a
+ guarantee that belongs to DATA, not to the type. *)
+let rubrics_line (d : (Rite_ef.Vocab_ef.season, Rite_ef.Vocab_ef.rank) Colitur_kernel.Liturgical_day.t)
+ =
+ let said, via =
+ match d.Colitur_kernel.Liturgical_day.formulary with
+ | Some f ->
+ ( Colitur_kernel.Slug.to_string f.Colitur_kernel.Mass_formulary.said,
+ Colitur_kernel.Mass_formulary.source_to_string f.Colitur_kernel.Mass_formulary.via )
+ | None -> ("-", "-")
+ in
+ Printf.printf "%s\t%s\t%s\n" (D.to_iso8601 d.Colitur_kernel.Liturgical_day.date) said via
+
(* One civil year, Jan 1 - Dec 31, matching [temporal_report]'s own scan --
NOT one liturgical year: [Colitur_kernel.Calendar.year] resolves a single
Advent-anchored liturgical year, which straddles two civil years, so a
@@ -456,6 +494,7 @@ let resolved_year_report ~line ~overlays y =
let day_report ~lang ~overlays y = resolved_year_report ~line:(day_line ~lang) ~overlays y
let readings_report ~lang ~sigla ~overlays y =
resolved_year_report ~line:(readings_line ~lang ~sigla) ~overlays y
+let rubrics_report ~overlays y = resolved_year_report ~line:rubrics_line ~overlays y
(* Task 8: `colitur emit` -- the five template-family emitters built in
Tasks 5-7, wired to a year RANGE rather than a single year, because a
@@ -1182,7 +1221,9 @@ usage:
colitur temporal <year> the temporal cycle, one line per day
colitur day <year> the resolved day identity, one line per day
colitur readings <year> the Mass reading citations, one line per day
+ colitur rubrics <year> the Mass formulary said, one line per day
colitur day|readings <year> [--overlay FILE ...] [--lang CODE|FILE] [--raw]
+ colitur rubrics <year> [--overlay FILE ...]
colitur emit --format csv|json|sexp|xml|ics --from Y --to Y
[--overlay FILE ...] [--dtstamp S] [--lang CODE|FILE] [--raw]
render a resolved year range through one of five emitters
@@ -1216,6 +1257,8 @@ output formats:
2026-04-05 sunday paschaltide 1 ef-easter-sunday class-1 white
readings date slug | Epistle | Gospel [| name]
2026-12-25 ef-nativity | Heb 1:1-12 | John 1:1-14
+ rubrics date, formulary slug, source -- TAB-separated
+ 2026-01-01[TAB]ef-circumcision[TAB]own
A citation contains spaces, so readings uses " | " between its fields while
day stays space-separated; that is why they are separate commands rather
@@ -1228,6 +1271,17 @@ output formats:
for that particular day, the trailing field is simply absent, which is
what makes --raw byte-identical to this program's pre-naming output.
+ rubrics prints which Mass is actually said and how that was decided
+ (source: proper/own/preceding-sunday/common/votive) -- not always the
+ day's own: a weekday with no proper resumes the preceding Sunday's, a
+ saint with no proper says his assigned Common. TAB-separated rather than
+ space or " | ": a resolved formulary NAME is a column a later version may
+ add, and it can carry both spaces and punctuation a citation never does,
+ which rules out either alternative already in use above. --overlay is
+ accepted (the observed celebration it changes decides the formulary);
+ --lang/--raw/--sigla-* are refused -- this row resolves no display name
+ and no citation for any of them to affect.
+
emit one schema (season, week, slug, rank, colour, subject, names,
citations, commemorations), rendered five ways: csv (RFC 4180,
one header for the whole run), json, sexp, xml (schema/colitur-
@@ -1240,9 +1294,10 @@ overlays:
the shipped universal one, never instead of it, so local feasts
add to it rather than replacing it. Later files win over earlier
ones, and over the universal calendar, when they name the same
- slug. Accepted on `day`, `readings`, `emit`, `table`, `render` and
- `publish` -- `easter` and `temporal` read no sanctoral data, so
- the flag is refused there rather than silently ignored.
+ slug. Accepted on `day`, `readings`, `rubrics`, `emit`, `table`,
+ `render` and `publish` -- `easter` and `temporal` read no
+ sanctoral data, so the flag is refused there rather than
+ silently ignored.
An overlay is applied, NOT validated: colitur's test layers assert
things about the shipped calendar and cannot vouch for a file you
@@ -1435,10 +1490,10 @@ let print_help () =
let usage () =
prerr_endline
"colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur \
- readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template \
- FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | \
- colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | \
- colitur new-overlay (try: colitur --help)";
+ readings <year> | colitur rubrics <year> | colitur emit --format FMT --from Y --to Y | colitur \
+ table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish \
+ --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show \
+ | colitur check FILE | colitur new-overlay (try: colitur --help)";
exit 2
let with_year ys f =
@@ -2269,6 +2324,19 @@ let () =
~sigla_tradition_flag:sigla_tradition ~config
in
with_year ys (readings_report ~lang:lang_t ~sigla ~overlays:effective_overlays)
+ | [ "rubrics"; ys ] ->
+ (* --overlay accepted, same reasoning as `readings`: an overlay can
+ change which celebration is observed, hence which Mass formulary
+ is said. --lang/--raw/--sigla-* are refused, unlike `readings`
+ -- this row resolves no display name and no citation for any of
+ them to affect. *)
+ reject_emit "rubrics";
+ reject_table "rubrics";
+ reject_publish "rubrics";
+ reject_lang "rubrics";
+ reject_lang_sub "rubrics";
+ reject_sigla "rubrics";
+ with_year ys (rubrics_report ~overlays:effective_overlays)
| [ "emit" ] -> (
reject_table "emit";
reject_publish "emit";