diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-22 11:21:14 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-22 11:21:14 +0200 |
| commit | fd8a4f115d3c62450368cf9b3fed5705ce78e805 (patch) | |
| tree | f935ec0e2e4c39cb3ddbba364ebc1f873c1b0574 /bin | |
| parent | 27b07b447be9cf960d1a44e480d8356245481d17 (diff) | |
| download | colitur-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.ml | 82 |
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"; |
