From 45bcbde502e07ad73b96039fcbb62471a3c94781 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Wed, 19 Aug 2026 13:34:53 +0200 Subject: feat(naming): the language table Maps strings to strings and nothing else -- no calendars, no dates, no filesystem. That is what lets every command use it without the kernel learning about presentation. Every lookup is total, and a miss returns THE KEY rather than the empty string. A partial translation is therefore usable from its first line, and the fully-degraded case is exactly today's output (bare slugs) rather than a blank page. --raw is a real identity table, not a special case threaded through every call site: one value the whole program passes around. Reuses Overlay_ini's INI reader rather than growing a second one that would drift in its comment, quoting and trimming rules; parse_sections is exposed in the .mli for that, with no behaviour change. Fixes one defect found while running the brief's own tests rather than transcribing them blind: weekday's internal lookup key is an English day-name word (month's is already the numeral string), so on a miss it echoed that word instead of the documented numeral, breaking both the 0=Sunday convention and Lang.raw's own identity contract for weekday. weekday/month now fall back to string_of_int n directly on a miss instead of through get's generic echo-the-search-key path; month is byte-identical since its key already equals string_of_int n. --- test/test_colitur.ml | 1 + 1 file changed, 1 insertion(+) (limited to 'test/test_colitur.ml') diff --git a/test/test_colitur.ml b/test/test_colitur.ml index 04bbdee..dd1274a 100644 --- a/test/test_colitur.ml +++ b/test/test_colitur.ml @@ -2,6 +2,7 @@ let () = Alcotest.run "colitur" [ Test_date.suite; Test_computus.suite; Test_colour.suite; Test_slug.suite; Test_names.suite; + Test_lang.suite; Test_overlay.suite; Test_overlay_ini.suite; Test_temporal_ef.suite; Test_validate.suite; Test_precedence.suite; Test_calendar.suite; Test_precedence_ef.suite; Test_sanctoral_ef.suite; Test_rite_ef.suite; Test_differential.suite; Test_oracle.suite; Test_oracle.suite_2038; Test_oracle.suite_2035; Test_golden.suite; -- cgit v1.3 From b26089630a61a54060c86ec26be6dc4fe5418b12 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Wed, 19 Aug 2026 13:38:54 +0200 Subject: feat(naming): the config file Owns precedence and provenance and nothing else, and never reads the filesystem, so it is as testable as the language table. resolve returns the value AND its source, because a setting that silently comes from a file the user forgot about is worse than no setting at all -- config --show can then say where each effective value came from. overlay accumulates rather than last-wins: a user has more than one. An unknown key is reported, never fatal. A config written for a newer colitur must still work on an older one, but silently dropping a line the user wrote is how a typo becomes invisible. --- lib/naming/config.ml | 43 +++++++++++++++++++++++++++++++++++ lib/naming/config.mli | 28 +++++++++++++++++++++++ test/test_colitur.ml | 1 + test/test_config.ml | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 lib/naming/config.ml create mode 100644 lib/naming/config.mli create mode 100644 test/test_config.ml (limited to 'test/test_colitur.ml') diff --git a/lib/naming/config.ml b/lib/naming/config.ml new file mode 100644 index 0000000..ce1b433 --- /dev/null +++ b/lib/naming/config.ml @@ -0,0 +1,43 @@ +module OI = Colitur_kernel.Overlay_ini + +type t = { + lang : string option; + overlays : string list; + template : string option; + format : string option; + unknown_keys : string list; +} + +let empty = { lang = None; overlays = []; template = None; format = None; unknown_keys = [] } + +let lang t = t.lang +let overlays t = t.overlays +let template t = t.template +let format t = t.format +let unknown_keys t = t.unknown_keys + +let of_string text = + match OI.parse_sections text with + | Error e -> Error e + | Ok sections -> ( + match List.find_opt (fun (s : OI.section) -> s.OI.name = "defaults") sections with + | None -> Ok empty + | Some s -> + let acc = + List.fold_left + (fun acc (k, v) -> + match k with + | "lang" -> { acc with lang = Some v } + | "template" -> { acc with template = Some v } + | "format" -> { acc with format = Some v } + (* accumulates: a user has more than one overlay *) + | "overlay" -> { acc with overlays = acc.overlays @ [ v ] } + | other -> { acc with unknown_keys = acc.unknown_keys @ [ other ] }) + empty s.OI.fields + in + Ok acc) + +let resolve ~flag ~config ~default = + match flag with + | Some v -> (v, "flag") + | None -> ( match config with Some v -> (v, "config") | None -> (default, "default")) diff --git a/lib/naming/config.mli b/lib/naming/config.mli new file mode 100644 index 0000000..41ff429 --- /dev/null +++ b/lib/naming/config.mli @@ -0,0 +1,28 @@ +(** The config file: what the user wants by default, and where each value came + from. + + Owns precedence and provenance and nothing else. Never reads the filesystem + -- callers hand it text -- so it is as testable as the language table. + + A config file is OPTIONAL. With none, colitur behaves exactly as it does + without this feature, except that names resolve through the default + language. *) + +type t + +val empty : t +val of_string : string -> (t, string) result + +val lang : t -> string option +val overlays : t -> string list +val template : t -> string option +val format : t -> string option + +(** Keys present in the file that this build does not understand. Reported, never + fatal: a config written for a newer colitur must still work on an older one, + but silently ignoring a line the user wrote is how a typo becomes invisible. *) +val unknown_keys : t -> string list + +(** [resolve ~flag ~config ~default] returns [(value, source)] with source one of + ["flag"], ["config"], ["default"]. Precedence is flag > config > default. *) +val resolve : flag:string option -> config:string option -> default:string -> string * string diff --git a/test/test_colitur.ml b/test/test_colitur.ml index dd1274a..1c445a6 100644 --- a/test/test_colitur.ml +++ b/test/test_colitur.ml @@ -3,6 +3,7 @@ let () = Alcotest.run "colitur" [ Test_date.suite; Test_computus.suite; Test_colour.suite; Test_slug.suite; Test_names.suite; Test_lang.suite; + Test_config.suite; Test_overlay.suite; Test_overlay_ini.suite; Test_temporal_ef.suite; Test_validate.suite; Test_precedence.suite; Test_calendar.suite; Test_precedence_ef.suite; Test_sanctoral_ef.suite; Test_rite_ef.suite; Test_differential.suite; Test_oracle.suite; Test_oracle.suite_2038; Test_oracle.suite_2035; Test_golden.suite; diff --git a/test/test_config.ml b/test/test_config.ml new file mode 100644 index 0000000..9100380 --- /dev/null +++ b/test/test_config.ml @@ -0,0 +1,62 @@ +module C = Colitur_naming.Config + +let ok = function Ok x -> x | Error e -> Alcotest.failf "parse: %s" e + +let sample = + "[defaults]\n\ + lang = pl\n\ + overlay = ~/a.ini\n\ + overlay = ~/b.ini\n\ + template = ~/my-ordo.tex\n\ + format = json\n" + +let test_reads_defaults () = + let c = ok (C.of_string sample) in + Alcotest.(check (option string)) "lang" (Some "pl") (C.lang c); + Alcotest.(check (option string)) "template" (Some "~/my-ordo.tex") (C.template c); + Alcotest.(check (option string)) "format" (Some "json") (C.format c) + +(* Repeated keys accumulate for overlay -- a user has more than one. The INI + reader keeps every line, so this asserts we do not silently take the last. *) +let test_overlays_accumulate () = + let c = ok (C.of_string sample) in + Alcotest.(check (list string)) "both overlays" [ "~/a.ini"; "~/b.ini" ] (C.overlays c) + +let test_empty_config_is_all_none () = + Alcotest.(check (option string)) "lang" None (C.lang C.empty); + Alcotest.(check (list string)) "overlays" [] (C.overlays C.empty) + +(* THE precedence rule: flag > config > default, and the SOURCE is reported, + because a setting that silently comes from a file the user forgot about is + worse than no setting at all. *) +let test_precedence_and_provenance () = + let check ~flag ~config ~default (ev, es) = + let v, s = C.resolve ~flag ~config ~default in + Alcotest.(check string) "value" ev v; + Alcotest.(check string) "source" es s + in + check ~flag:(Some "en") ~config:(Some "pl") ~default:"la" ("en", "flag"); + check ~flag:None ~config:(Some "pl") ~default:"la" ("pl", "config"); + check ~flag:None ~config:None ~default:"la" ("la", "default") + +let test_malformed_is_error_not_crash () = + match C.of_string "[defaults\nbroken" with + | Error _ -> () + | Ok _ -> Alcotest.fail "a malformed config must be an Error, never accepted" + +(* An unknown key is a WARNING case, not a hard error: a config written for a + newer colitur must still work on an older one. But it must be reportable, so + it is not silently dropped either. *) +let test_unknown_key_is_reported_not_fatal () = + match C.of_string "[defaults]\nlang = la\nnonsense = 1\n" with + | Error _ -> Alcotest.fail "an unknown key must not be fatal" + | Ok c -> Alcotest.(check (option string)) "known key still read" (Some "la") (C.lang c) + +let suite = + ( "Config", + [ Alcotest.test_case "reads defaults" `Quick test_reads_defaults; + Alcotest.test_case "overlays accumulate" `Quick test_overlays_accumulate; + Alcotest.test_case "empty is all none" `Quick test_empty_config_is_all_none; + Alcotest.test_case "precedence and provenance" `Quick test_precedence_and_provenance; + Alcotest.test_case "malformed is error" `Quick test_malformed_is_error_not_crash; + Alcotest.test_case "unknown key not fatal" `Quick test_unknown_key_is_reported_not_fatal ] ) -- cgit v1.3 From f00f7a66d073815249e94cec1b6ef10539d773e7 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Wed, 19 Aug 2026 14:12:52 +0200 Subject: feat(lang): Latin temporal names from the Missal Every entry is transcribed from the 1962 Missal's own propers headings in docs/research/LT.txt and cites where it came from; names constructed by following a neighbouring pattern are marked as such, so a reader can tell transcription from inference. The coverage test is the point of this commit. It walks every day of 2020-2045 and fails naming any slug with no Latin name -- the test that would have caught the original defect, where a printed booklet said ef-septuagesima-sunday-2 because nothing asserted that names exist. The three Triduum names reuse the exact strings temporal_ef.ml already carries, so the engine and the language file cannot disagree. --- lang/la.ini | 717 +++++++++++++++++++++++++++++++++++++++++++++ test/dune | 1 + test/test_colitur.ml | 1 + test/test_lang_coverage.ml | 73 +++++ 4 files changed, 792 insertions(+) create mode 100644 lang/la.ini create mode 100644 test/test_lang_coverage.ml (limited to 'test/test_colitur.ml') diff --git a/lang/la.ini b/lang/la.ini new file mode 100644 index 0000000..9b1ccf7 --- /dev/null +++ b/lang/la.ini @@ -0,0 +1,717 @@ +; colitur -- Latin names, transcribed from the 1962 Missale Romanum. +; Every celebration entry cites where its name came from: a line number in +; docs/research/LT.txt (the electronic transcription, gitignored, present +; locally only), a citation to code that already carries a scan-verified +; string, or -- where the Missal genuinely gives no heading for a day the +; engine emits -- an explicit "PATTERN" marker naming the neighbour rule the +; constructed name follows. An uncited name is worse than a slug: a slug is +; honestly a key, a wrong name is a false claim. +; +; TASK 3 SCOPE: this file currently carries the TEMPORAL half of +; [celebration] only (every ef-* slug the engine can emit, 2020-2045 +; measured). The sanctoral half (a fixed saint's day, not a season/week +; slug) arrives in Task 4, together with the removal of the "^ef-" filter in +; test/test_lang_coverage.ml's own coverage test. +; +; Typographic normalisation applied uniformly, disclosed once here rather +; than per entry: +; - ae/oe replace the ae/oe ligatures LT.txt itself prints +; -- matching the convention already established by every hand-written +; Latin string in lib/rites/rite_ef/temporal_ef.ml (e.g. "Sanctae +; Familiae Iesu, Mariae, Ioseph", "Officium sanctae Mariae in sabbato"), +; none of which use the ligature either. +; - the consonantal i (Iesu, Ianuarius) replaces j/J (Jesu, Januarius) +; throughout, the same existing code convention (temporal_ef.ml's own +; [holy_name_names] is "Sanctissimi Nominis Iesu", never "...Jesu"). +; - abbreviations the source prints (Ss.mi, Ss.mae, D.ni) are spelled out +; in full (Sanctissimi, Sanctissimae, Domini Nostri) -- again matching +; temporal_ef.ml's own precedent of spelling these out in full rather +; than reusing the Missal's own abbreviated form. +; None of these three changes the WORDS a heading uses, only their spelling +; convention; every substantive word choice below is either transcribed +; verbatim (case aside) or explicitly marked PATTERN. + +[meta] +lang = la +name = Latine + +[weekday] +; The Missal's own ferial vocabulary: Sunday is Dominica, and the weekdays +; are numbered feriae from II (Monday) to VII (Saturday) -- except Saturday, +; which the Missal always calls Sabbatum, never "Feria VII" (confirmed +; throughout docs/research/LT.txt's own Proprium de Tempore table of +; contents, e.g. "Sabbato post Dominicam II in Quadragesima", never "Feria +; VII ..."). Standard Latin vocabulary, not itself a Missal heading to cite +; line by line. +sunday = Dominica +monday = Feria II +tuesday = Feria III +wednesday = Feria IV +thursday = Feria V +friday = Feria VI +saturday = Sabbatum + +[month] +; Standard Latin month names -- general vocabulary, not a Missal heading. +1 = Ianuarius +2 = Februarius +3 = Martius +4 = Aprilis +5 = Maius +6 = Iunius +7 = Iulius +8 = Augustus +9 = September +10 = October +11 = November +12 = December + +[season] +; RG 71-77's own season names. Five of eight are direct Proprium de Tempore +; section headings in docs/research/LT.txt (line numbers below); the other +; three are noted individually -- colitur's own eight-season split does not +; align 1:1 with the Missal's own table-of-contents section boundaries, so +; not every colitur season has one clean matching heading. +advent = Tempus Adventus +; LT.txt:8631. +christmastide = Tempus Nativitatis +; NOT a direct match. LT.txt has "Tempus Epiphaniae" (LT.txt:8661, covering +; 6-13 January) for what colitur calls the tail of Christmastide, and a +; SEPARATE "Tempus per annum ante Septuagesimam" (LT.txt:8668, covering the +; numbered Sundays II-VI post Epiphaniam) for what colitur calls +; time-after-epiphany -- colitur's own season boundary (RG 72-73/77: 14 +; January) falls inside neither TOC section. Using the section that covers +; the bulk of colitur's own time-after-epiphany (the numbered weeks), with +; this caveat rather than a silent pick. +time-after-epiphany = Tempus per annum ante Septuagesimam +septuagesima = Tempus Septuagesimae +; LT.txt:8675. +lent = Tempus Quadragesimae +; LT.txt:8685. +passiontide = Tempus Passionis +; LT.txt:8719. +paschaltide = Tempus Paschatis +; LT.txt:8751. CORRECTED from an earlier draft's "Tempus Paschale": LT.txt's +; own TOC consistently uses "Tempus " (Adventus, +; Nativitatis, Epiphaniae, Septuagesimae, Quadragesimae, Passionis, +; Paschatis, Ascensionis) -- "Paschale" is an adjective and does not match +; that pattern or the source text. +time-after-pentecost = Tempus per annum post Pentecosten +; LT.txt:8785. + +[rank] +; RG 8's four classes. "I classis" is directly attested, not only in the +; Rubricae Generales but in a Mass propers heading itself -- +; LT.txt:12459, "D.NI NOSTRI JESU CHRISTI REGIS / I classis" (Christ the +; King). The other three ordinals follow the identical, standard pattern. +class-1 = I classis +class-2 = II classis +class-3 = III classis +class-4 = IV classis + +[colour] +; RG 117 enumerates the five colours; RG 127/128 assign green/violet to the +; seasons, RG 131 rose (an indult, two Sundays only), RG 117-120 the rest. +; White, red and violet are directly attested as rubric words in +; docs/research/LT.txt ("color albus"/"color ruber"/"color violaceus", +; e.g. LT.txt:1873,1912,1980); green appears once (LT.txt, "viridis"). +; Rose and black do not occur anywhere in LT.txt's own captured text (LT.txt +; is a partial 2006 web capture of Mass propers, and rose is used on two +; Sundays a year, black mostly in Requiem/Good-Friday rubrics the capture +; does not include) -- both are standard rubrical Latin, cited to RG 117/131 +; rather than to a line number, not invented. +white = albus +red = ruber +green = viridis +violet = violaceus +rose = rosaceus +black = niger + +[term] +; Standard liturgical Latin, all directly attested in docs/research/LT.txt +; (Epistola, Lectio, Evangelium, Commemoratio, Hebdomada/Hebdomadae each +; appear repeatedly as rubric labels throughout the propers text; "Ordo" is +; the running page header "ORDO MISSAE"; "Index" appears once). +ordo = Ordo +contents = Index +epistle = Epistola +lesson = Lectio +gospel = Evangelium +commemoration = Commemoratio +week = Hebdomada + +[celebration] +; --------------------------------------------------------------------- +; TEMPORAL slugs only (^ef-). Sanctoral names arrive in Task 4, together +; with the coverage test's own "^ef-" filter being removed +; (test/test_lang_coverage.ml) -- until then this table intentionally does +; NOT name a sanctoral slug, and that is expected, not a gap. +; --------------------------------------------------------------------- + +; Christmas cycle -- LT.txt:8627,8632,8657,8662 (Proprium de Tempore TOC). +; 1 January: the TOC's own heading is "In Octava Nativitatis Domini", NOT +; "In Circumcisione Domini" -- RG 68 confirms the 1960 rubrics renamed the +; day ("Octava Nativitatis Domini modo peculiari ordinatur"); the older +; title never appears anywhere in LT.txt. colitur's own slug ("circumcision") +; is a lectio-inherited key, not a claim about the Missal's own title. +ef-nativity-vigil = In Vigilia Nativitatis Domini +ef-nativity = In Nativitate Domini +ef-circumcision = In Octava Nativitatis Domini +ef-epiphany = In Epiphania Domini + +; The Octave of the Nativity, days 5-7 -- LT.txt:8649-8655. +ef-nativity-octave-day-5 = De V Die infra Octavam Nativitatis Domini +ef-nativity-octave-day-6 = De VI Die infra Octavam Nativitatis Domini +ef-nativity-octave-day-7 = De VII Die infra Octavam Nativitatis Domini + +; Advent Sundays -- LT.txt:8614,8616,8617,8626. +ef-advent-sunday-1 = Dominica I Adventus +ef-advent-sunday-2 = Dominica II Adventus +ef-advent-sunday-3 = Dominica III Adventus +ef-advent-sunday-4 = Dominica IV Adventus + +; The Gesimae, named not numbered -- LT.txt:8676,8682,8683. +ef-septuagesima-sunday-1 = Dominica in Septuagesima +ef-septuagesima-sunday-2 = Dominica in Sexagesima +ef-septuagesima-sunday-3 = Dominica in Quinquagesima + +; Time after Epiphany Sundays -- LT.txt:8669-8673 (the ordinary occurrence). +; ef-time-after-epiphany-sunday-1 is Holy Family, not an ordinary numbered +; Sunday -- LT.txt:8663-8664 itself glosses it "Dominica I post Epiphaniam, +; Sanctae Familiae Iesu, Mariae, Ioseph", and temporal_ef.ml's own +; [holy_family_sunday] branch already carries the identical Latin title +; ("Sanctae Familiae Iesu, Mariae, Ioseph", scan-verified there); reused +; verbatim here so the engine's own Celebration.names and this table cannot +; disagree, the same discipline the Triduum names below follow. +; CAUTION -- a genuine one-slug/two-names limitation: colitur's own slug +; numbering also reuses ef-time-after-epiphany-sunday-3..6 for the RESUMED +; tail after a short Time-after-Pentecost (Precedence's own "surplus +; Sundays" branch) -- LT.txt:8822-8825 heads THOSE occurrences +; "Dominica III/IV/V/VI quae superfuit post Epiphaniam", a different string +; from the ordinary-occurrence heading used below. This table can carry only +; one Latin name per slug; the ordinary (far more common) occurrence wins, +; and the resumed-tail wording is not modelled -- flagged here rather than +; silently picking one with no record of the other. +ef-time-after-epiphany-sunday-1 = Sanctae Familiae Iesu, Mariae, Ioseph +ef-time-after-epiphany-sunday-2 = Dominica II post Epiphaniam +ef-time-after-epiphany-sunday-3 = Dominica III post Epiphaniam +ef-time-after-epiphany-sunday-4 = Dominica IV post Epiphaniam +ef-time-after-epiphany-sunday-5 = Dominica V post Epiphaniam +ef-time-after-epiphany-sunday-6 = Dominica VI post Epiphaniam + +; Ash Wednesday and the three days after it -- LT.txt:8686-8689. +ef-ash-wednesday = Feria IV Cinerum +ef-lent-after-ashes-thursday = Feria V post Cineres +ef-lent-after-ashes-friday = Feria VI post Cineres +ef-lent-after-ashes-saturday = Sabbato post Cineres + +; Lent Sundays -- LT.txt:8690,8697,8704,8711. +ef-lent-sunday-1 = Dominica I in Quadragesima +ef-lent-sunday-2 = Dominica II in Quadragesima +ef-lent-sunday-3 = Dominica III in Quadragesima +ef-lent-sunday-4 = Dominica IV in Quadragesima + +; Lent ferias, week by week -- LT.txt:8691-8717. Every weekday of every Lent +; week is individually headed in the source (unlike every other ferial block +; below) -- week 1's Wed/Fri/Sat are the Lenten Ember days, named separately. +ef-lent-1-monday = Feria II post Dominicam I in Quadragesima +ef-lent-1-tuesday = Feria III post Dominicam I in Quadragesima +ef-lent-1-thursday = Feria V post Dominicam I in Quadragesima +ef-lent-2-monday = Feria II post Dominicam II in Quadragesima +ef-lent-2-tuesday = Feria III post Dominicam II in Quadragesima +ef-lent-2-wednesday = Feria IV post Dominicam II in Quadragesima +ef-lent-2-thursday = Feria V post Dominicam II in Quadragesima +ef-lent-2-friday = Feria VI post Dominicam II in Quadragesima +ef-lent-2-saturday = Sabbato post Dominicam II in Quadragesima +ef-lent-3-monday = Feria II post Dominicam III in Quadragesima +ef-lent-3-tuesday = Feria III post Dominicam III in Quadragesima +ef-lent-3-wednesday = Feria IV post Dominicam III in Quadragesima +ef-lent-3-thursday = Feria V post Dominicam III in Quadragesima +ef-lent-3-friday = Feria VI post Dominicam III in Quadragesima +ef-lent-3-saturday = Sabbato post Dominicam III in Quadragesima +ef-lent-4-monday = Feria II post Dominicam IV in Quadragesima +ef-lent-4-tuesday = Feria III post Dominicam IV in Quadragesima +ef-lent-4-wednesday = Feria IV post Dominicam IV in Quadragesima +ef-lent-4-thursday = Feria V post Dominicam IV in Quadragesima +ef-lent-4-friday = Feria VI post Dominicam IV in Quadragesima +ef-lent-4-saturday = Sabbato post Dominicam IV in Quadragesima + +; Passion Sunday and its own week's ferias -- LT.txt:8725-8731, all six +; weekdays individually headed. +ef-passion-sunday = Dominica I Passionis +ef-passiontide-1-monday = Feria II post Dominicam I Passionis +ef-passiontide-1-tuesday = Feria III post Dominicam I Passionis +ef-passiontide-1-wednesday = Feria IV post Dominicam I Passionis +ef-passiontide-1-thursday = Feria V post Dominicam I Passionis +ef-passiontide-1-friday = Feria VI post Dominicam I Passionis +ef-passiontide-1-saturday = Sabbato post Dominicam I Passionis + +; Holy Week -- LT.txt:8734,8737-8739. Thursday/Friday/Saturday are NOT taken +; from LT.txt here: temporal_ef.ml's own [triduum_names] already carries +; these three exact strings (scan-verified there, register-cited RG 91 entry +; 2), reused verbatim -- the brief's own worked example wrote "Sabbato +; Sancto" (capital S); the code's actual literal is "Sabbato sancto" +; (lowercase), which is what ships here, precisely so the engine and this +; table cannot disagree. +ef-palm-sunday = Dominica II Passionis seu in Palmis +ef-passiontide-2-monday = Feria II Hebdomadae Sanctae +ef-passiontide-2-tuesday = Feria III Hebdomadae Sanctae +ef-passiontide-2-wednesday = Feria IV Hebdomadae Sanctae +ef-passiontide-2-thursday = Feria V in Cena Domini +ef-passiontide-2-friday = Feria VI in Passione et Morte Domini +ef-passiontide-2-saturday = Sabbato sancto + +; Easter Octave -- LT.txt:8753-8760. Saturday of the octave is its own name, +; "Sabbato in Albis", not "...infra Octavam Paschae" like Mon-Fri. +ef-easter-sunday = Dominica Resurrectionis +ef-easter-1-monday = Feria II infra Octavam Paschae +ef-easter-1-tuesday = Feria III infra Octavam Paschae +ef-easter-1-wednesday = Feria IV infra Octavam Paschae +ef-easter-1-thursday = Feria V infra Octavam Paschae +ef-easter-1-friday = Feria VI infra Octavam Paschae +ef-easter-1-saturday = Sabbato in Albis +ef-low-sunday = Dominica in Albis + +; Sundays after Easter through the Sunday after Ascension -- LT.txt:8761, +; 8767-8769,8775. colitur's own week count runs one ahead of the Missal's +; own ordinal (Easter Day itself is colitur's week 1, so what the Missal +; calls "Dominica II post Pascha" is colitur's "sunday-3"; documented once +; here rather than on each line. +ef-easter-sunday-3 = Dominica II post Pascha +ef-easter-sunday-4 = Dominica III post Pascha +ef-easter-sunday-5 = Dominica IV post Pascha +ef-easter-sunday-6 = Dominica V post Pascha +ef-easter-sunday-7 = Dominica post Ascensionem + +; Ascension and Pentecost, vigils and octave -- LT.txt:8771,8774,8776-8783. +ef-ascension-vigil = In Vigilia Ascensionis +ef-ascension = In Ascensione Domini +ef-pentecost-vigil = Sabbato in Vigilia Pentecostes +ef-pentecost = Dominica Pentecostes +ef-easter-8-monday = Feria II infra Octavam Pentecostes +ef-easter-8-tuesday = Feria III infra Octavam Pentecostes +ef-easter-8-thursday = Feria V infra Octavam Pentecostes + +; Sundays after Pentecost -- LT.txt:8790,8793-8802,8808-8821 (II-XXIII), +; LT.txt:8826 (XXIV, "et ultima" -- always this Mass on the last Sunday +; before Advent regardless of the actual count that year, temporal_ef.ml's +; own [sunday_slug] comment). There is no "Dominica I post Pentecosten": in +; the 1962 Missal Trinity Sunday permanently occupies that position (LT.txt +; has no such heading anywhere), matching colitur's own ef-trinity being a +; separate, earlier-intercepted slug. +ef-time-after-pentecost-sunday-2 = Dominica II post Pentecosten +ef-time-after-pentecost-sunday-3 = Dominica III post Pentecosten +ef-time-after-pentecost-sunday-4 = Dominica IV post Pentecosten +ef-time-after-pentecost-sunday-5 = Dominica V post Pentecosten +ef-time-after-pentecost-sunday-6 = Dominica VI post Pentecosten +ef-time-after-pentecost-sunday-7 = Dominica VII post Pentecosten +ef-time-after-pentecost-sunday-8 = Dominica VIII post Pentecosten +ef-time-after-pentecost-sunday-9 = Dominica IX post Pentecosten +ef-time-after-pentecost-sunday-10 = Dominica X post Pentecosten +ef-time-after-pentecost-sunday-11 = Dominica XI post Pentecosten +ef-time-after-pentecost-sunday-12 = Dominica XII post Pentecosten +ef-time-after-pentecost-sunday-13 = Dominica XIII post Pentecosten +ef-time-after-pentecost-sunday-14 = Dominica XIV post Pentecosten +ef-time-after-pentecost-sunday-15 = Dominica XV post Pentecosten +ef-time-after-pentecost-sunday-16 = Dominica XVI post Pentecosten +ef-time-after-pentecost-sunday-17 = Dominica XVII post Pentecosten +ef-time-after-pentecost-sunday-18 = Dominica XVIII post Pentecosten +ef-time-after-pentecost-sunday-19 = Dominica XIX post Pentecosten +ef-time-after-pentecost-sunday-20 = Dominica XX post Pentecosten +ef-time-after-pentecost-sunday-21 = Dominica XXI post Pentecosten +ef-time-after-pentecost-sunday-22 = Dominica XXII post Pentecosten +ef-time-after-pentecost-sunday-23 = Dominica XXIII post Pentecosten +ef-time-after-pentecost-sunday-24 = Dominica XXIV et ultima post Pentecosten + +; The Christmas Sunday within the Octave (26 Dec onward) -- colitur-only key +; (temporal_ef.ml's own comment: lectio has no narrower key here either); no +; direct LT.txt heading -- PATTERN, following the Nativity Octave's own +; "infra Octavam Nativitatis Domini" wording (LT.txt:8644's own general +; heading for that stretch, "Dominica infra Octavam Nativitatis Domini"). +ef-christmas-sunday-0 = Dominica infra Octavam Nativitatis Domini + +; Trinity, Corpus Christi, Sacred Heart -- LT.txt:8786,8788-8789,8791-8792 +; (the Proprium de Tempore TOC's own combined lines, not a standalone body +; heading -- LT.txt is a partial 2006 web capture and does not carry these +; three Masses' own propers pages). Spelled out in full +; ("Sanctissimae"/"Sacratissimi"), not the source's "Ss.mae"/"Ss.mi" +; abbreviation, matching the precedent already set by temporal_ef.ml's own +; [holy_name_names] ("Sanctissimi Nominis Iesu", spelled out, not "Ss.mi"). +ef-trinity = In Festo Sanctissimae Trinitatis +ef-corpus-christi = In Festo Sanctissimi Corporis Christi +ef-sacred-heart = In Festo Sacratissimi Cordis Iesu + +; Christ the King -- LT.txt:12453,12457-12458, the Mass's own in-body +; heading (filed, unusually, in this transcription's Proprium Sanctorum +; section by calendar date rather than the Proprium de Tempore, even though +; RG 17(d) places it in the temporal cycle by rule): "Dominica ultima +; Octobris" / "D.NI NOSTRI JESU CHRISTI REGIS". "Jesu" normalised to +; "Iesu" and "D.ni" expanded to "D. N.", matching this file's own +; consonantal-i convention (see header). +ef-christ-the-king = Dominica ultima Octobris, D. N. Iesu Christi Regis + +; Holy Name of Jesus, both shapes (RG 17(a)) -- temporal_ef.ml's own +; [holy_name_names] already carries this exact Latin string, itself +; scan-verified there against the Mass propers' own heading; LT.txt's own +; TOC corroborates it independently at LT.txt:8659 ("Ss.mi Nominis Jesu", +; the abbreviated TOC form of the same title). Reused verbatim, the same +; no-disagreement discipline as the Triduum above -- ONE feast, two shapes +; (the Sunday and the 2 January fallback), one name either way. +ef-holy-name-sunday = Sanctissimi Nominis Iesu +ef-holy-name = Sanctissimi Nominis Iesu + +; Ember days, all four sets -- LT.txt:8618,8620,8622 (Advent), +; 8693,8695-8696 (Lent), 8780,8782-8783 (Pentecost/Whitsun), +; 8813-8815 (September). +ef-advent-ember-wed = Feria IV Quatuor Temporum Adventus +ef-advent-ember-fri = Feria VI Quatuor Temporum Adventus +ef-advent-ember-sat = Sabbato Quatuor Temporum Adventus +ef-lent-ember-wed = Feria IV Quatuor Temporum Quadragesimae +ef-lent-ember-fri = Feria VI Quatuor Temporum Quadragesimae +ef-lent-ember-sat = Sabbato Quatuor Temporum Quadragesimae +ef-pentecost-ember-wed = Feria IV Quatuor Temporum Pentecostes +ef-pentecost-ember-fri = Feria VI Quatuor Temporum Pentecostes +ef-pentecost-ember-sat = Sabbato Quatuor Temporum Pentecostes +ef-september-ember-wed = Feria IV Quatuor Temporum Septembris +ef-september-ember-fri = Feria VI Quatuor Temporum Septembris +ef-september-ember-sat = Sabbato Quatuor Temporum Septembris + +; The Minor Litanies (Rogation Monday/Tuesday, RG 87-89) -- PATTERN. No +; heading for either day survives in LT.txt (only the general section marker +; "In Litaniis majoribus et minoribus", LT.txt:8770, which names the +; observance but not these two specific days); temporal_ef.ml's own comment +; records both as "colitur-only keys", so there is nothing narrower to +; extract. Constructed from RG 87's own vocabulary ("Litaniae minores"), +; already cited in temporal_ef.ml against LT.txt:691 (a different scan file +; index, not this TOC). +ef-rogation-monday = Feria II in Litaniis Minoribus +ef-rogation-tuesday = Feria III in Litaniis Minoribus + +; The votive Office of the BVM on Saturday (RG 78-79, RG 91 entry 27) -- +; temporal_ef.ml's own [bvm_saturday_names] already carries this exact Latin +; string, scan-verified there against RG 91's own table title and RG 79's +; own heading; not in LT.txt (LT.txt is Proprium de Tempore/Sanctorum only, +; this is General Rubrics text). Reused verbatim. +; +; This is NOT a pattern name -- it is what temporal_ef.ml's own code +; UNCONDITIONALLY substitutes, at resolution time, for every one of the +; slugs below whenever it is the observed day: every Saturday in Time after +; Epiphany/Septuagesima/Time after Pentecost/ordinary Paschaltide has +; ferial_rank Class4 (Vocab_ef.ml's own catch-all), and is_bvm_saturday +; fires on rank=Class4 && weekday=Saturday unconditionally -- there is no +; code path left by which one of these slugs is observed as a plain, +; unnamed feria. Advent's own Saturdays (weeks 1-2, Class2/3, never Class4) +; and Lent/Passiontide's own Saturdays (Class3, individually named above +; already) are the only in-range Saturdays this rule does NOT reach, and +; week 1 of Easter is excluded too (the privileged Easter octave overrides +; to Class1) -- both correctly excluded from this block. +ef-time-after-epiphany-1-saturday = Officium sanctae Mariae in sabbato +ef-time-after-epiphany-5-saturday = Officium sanctae Mariae in sabbato +ef-time-after-epiphany-6-saturday = Officium sanctae Mariae in sabbato +ef-septuagesima-1-saturday = Officium sanctae Mariae in sabbato +ef-septuagesima-2-saturday = Officium sanctae Mariae in sabbato +ef-christmas-1-saturday = Officium sanctae Mariae in sabbato +ef-christmas-2-saturday = Officium sanctae Mariae in sabbato +ef-easter-2-saturday = Officium sanctae Mariae in sabbato +ef-easter-3-saturday = Officium sanctae Mariae in sabbato +ef-easter-4-saturday = Officium sanctae Mariae in sabbato +ef-easter-5-saturday = Officium sanctae Mariae in sabbato +ef-easter-6-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-1-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-2-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-3-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-4-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-5-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-6-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-7-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-8-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-9-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-10-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-11-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-12-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-13-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-14-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-15-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-16-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-17-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-19-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-20-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-21-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-22-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-23-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-24-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-25-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-26-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-27-saturday = Officium sanctae Mariae in sabbato +ef-time-after-pentecost-28-saturday = Officium sanctae Mariae in sabbato + +; Advent ferias -- PATTERN. LT.txt carries no per-week Advent feria headings +; at all (only the Ember days, already transcribed above) -- constructed +; from the Advent Sundays' own numbering (LT.txt:8614-8626) using the exact +; grammar the Lent/Passiontide blocks above attest ("Feria post +; Dominicam ..."). +ef-advent-1-monday = Feria II post Dominicam I Adventus +ef-advent-1-tuesday = Feria III post Dominicam I Adventus +ef-advent-1-wednesday = Feria IV post Dominicam I Adventus +ef-advent-1-thursday = Feria V post Dominicam I Adventus +ef-advent-1-friday = Feria VI post Dominicam I Adventus +ef-advent-1-saturday = Sabbato post Dominicam I Adventus +ef-advent-2-monday = Feria II post Dominicam II Adventus +ef-advent-2-tuesday = Feria III post Dominicam II Adventus +ef-advent-2-wednesday = Feria IV post Dominicam II Adventus +ef-advent-2-thursday = Feria V post Dominicam II Adventus +ef-advent-2-friday = Feria VI post Dominicam II Adventus +ef-advent-2-saturday = Sabbato post Dominicam II Adventus +ef-advent-3-monday = Feria II post Dominicam III Adventus +ef-advent-3-tuesday = Feria III post Dominicam III Adventus +ef-advent-3-thursday = Feria V post Dominicam III Adventus +ef-advent-4-monday = Feria II post Dominicam IV Adventus +ef-advent-4-tuesday = Feria III post Dominicam IV Adventus +ef-advent-4-wednesday = Feria IV post Dominicam IV Adventus +ef-advent-4-thursday = Feria V post Dominicam IV Adventus +ef-advent-4-friday = Feria VI post Dominicam IV Adventus + +; Time after Epiphany ferias -- PATTERN, same reasoning: LT.txt gives only +; the Sundays (already transcribed above), no ferial headings. Week 1's own +; Sunday is Holy Family, but the TOC's own combined heading +; (LT.txt:8663-8664) still numbers it "Dominica I post Epiphaniam", so week +; 1's ferias use the same numbered pattern as every other week here. +ef-time-after-epiphany-1-monday = Feria II post Dominicam I post Epiphaniam +ef-time-after-epiphany-1-tuesday = Feria III post Dominicam I post Epiphaniam +ef-time-after-epiphany-1-wednesday = Feria IV post Dominicam I post Epiphaniam +ef-time-after-epiphany-1-thursday = Feria V post Dominicam I post Epiphaniam +ef-time-after-epiphany-1-friday = Feria VI post Dominicam I post Epiphaniam +ef-time-after-epiphany-2-monday = Feria II post Dominicam II post Epiphaniam +ef-time-after-epiphany-2-tuesday = Feria III post Dominicam II post Epiphaniam +ef-time-after-epiphany-2-wednesday = Feria IV post Dominicam II post Epiphaniam +ef-time-after-epiphany-2-thursday = Feria V post Dominicam II post Epiphaniam +ef-time-after-epiphany-2-friday = Feria VI post Dominicam II post Epiphaniam +ef-time-after-epiphany-4-monday = Feria II post Dominicam IV post Epiphaniam +ef-time-after-epiphany-4-wednesday = Feria IV post Dominicam IV post Epiphaniam +ef-time-after-epiphany-4-thursday = Feria V post Dominicam IV post Epiphaniam +ef-time-after-epiphany-4-friday = Feria VI post Dominicam IV post Epiphaniam +ef-time-after-epiphany-5-wednesday = Feria IV post Dominicam V post Epiphaniam +ef-time-after-epiphany-5-thursday = Feria V post Dominicam V post Epiphaniam +ef-time-after-epiphany-5-friday = Feria VI post Dominicam V post Epiphaniam +ef-time-after-epiphany-6-monday = Feria II post Dominicam VI post Epiphaniam +ef-time-after-epiphany-6-tuesday = Feria III post Dominicam VI post Epiphaniam +ef-time-after-epiphany-6-wednesday = Feria IV post Dominicam VI post Epiphaniam +ef-time-after-epiphany-6-thursday = Feria V post Dominicam VI post Epiphaniam +ef-time-after-epiphany-6-friday = Feria VI post Dominicam VI post Epiphaniam + +; Septuagesima-tide ferias -- PATTERN. The three Sundays are named, not +; numbered (LT.txt:8676,8682-8683), so their ferias follow suit here +; ("post Dominicam in ") rather than being given a false ordinal. +ef-septuagesima-1-monday = Feria II post Dominicam in Septuagesima +ef-septuagesima-1-tuesday = Feria III post Dominicam in Septuagesima +ef-septuagesima-1-wednesday = Feria IV post Dominicam in Septuagesima +ef-septuagesima-1-thursday = Feria V post Dominicam in Septuagesima +ef-septuagesima-1-friday = Feria VI post Dominicam in Septuagesima +ef-septuagesima-2-monday = Feria II post Dominicam in Sexagesima +ef-septuagesima-2-tuesday = Feria III post Dominicam in Sexagesima +ef-septuagesima-2-wednesday = Feria IV post Dominicam in Sexagesima +ef-septuagesima-2-thursday = Feria V post Dominicam in Sexagesima +ef-septuagesima-2-friday = Feria VI post Dominicam in Sexagesima +ef-septuagesima-3-monday = Feria II post Dominicam in Quinquagesima +ef-septuagesima-3-tuesday = Feria III post Dominicam in Quinquagesima + +; Time after Pentecost ferias -- PATTERN, the largest block by far (most of +; the liturgical year has no proper ferial Mass here, RG 91 entry 28's +; unqualified IV-class catch-all). Unlike the other PATTERN blocks above, +; this exact grammar is directly attested in LT.txt, just for a different +; day: LT.txt:8791, "Feria VI post Dominicam II post Pentecosten, in festo +; Sacratissimi Cordis Iesu" (the Sacred Heart's own alternate dating, +; already used above) shows the Missal DOES write "post Dominicam N post +; Pentecosten" for an ordinary Friday of this season -- applied here to +; every other weekday of every other week on the same attested grammar, +; still marked PATTERN because no day in this block has its OWN heading. +ef-time-after-pentecost-1-monday = Feria II post Dominicam I post Pentecosten +ef-time-after-pentecost-1-tuesday = Feria III post Dominicam I post Pentecosten +ef-time-after-pentecost-1-wednesday = Feria IV post Dominicam I post Pentecosten +ef-time-after-pentecost-1-friday = Feria VI post Dominicam I post Pentecosten +ef-time-after-pentecost-2-monday = Feria II post Dominicam II post Pentecosten +ef-time-after-pentecost-2-tuesday = Feria III post Dominicam II post Pentecosten +ef-time-after-pentecost-2-wednesday = Feria IV post Dominicam II post Pentecosten +ef-time-after-pentecost-2-thursday = Feria V post Dominicam II post Pentecosten +ef-time-after-pentecost-3-monday = Feria II post Dominicam III post Pentecosten +ef-time-after-pentecost-3-tuesday = Feria III post Dominicam III post Pentecosten +ef-time-after-pentecost-3-wednesday = Feria IV post Dominicam III post Pentecosten +ef-time-after-pentecost-3-thursday = Feria V post Dominicam III post Pentecosten +ef-time-after-pentecost-3-friday = Feria VI post Dominicam III post Pentecosten +ef-time-after-pentecost-4-monday = Feria II post Dominicam IV post Pentecosten +ef-time-after-pentecost-4-tuesday = Feria III post Dominicam IV post Pentecosten +ef-time-after-pentecost-4-wednesday = Feria IV post Dominicam IV post Pentecosten +ef-time-after-pentecost-4-thursday = Feria V post Dominicam IV post Pentecosten +ef-time-after-pentecost-4-friday = Feria VI post Dominicam IV post Pentecosten +ef-time-after-pentecost-5-monday = Feria II post Dominicam V post Pentecosten +ef-time-after-pentecost-5-tuesday = Feria III post Dominicam V post Pentecosten +ef-time-after-pentecost-5-wednesday = Feria IV post Dominicam V post Pentecosten +ef-time-after-pentecost-5-thursday = Feria V post Dominicam V post Pentecosten +ef-time-after-pentecost-5-friday = Feria VI post Dominicam V post Pentecosten +ef-time-after-pentecost-6-monday = Feria II post Dominicam VI post Pentecosten +ef-time-after-pentecost-6-tuesday = Feria III post Dominicam VI post Pentecosten +ef-time-after-pentecost-6-wednesday = Feria IV post Dominicam VI post Pentecosten +ef-time-after-pentecost-6-thursday = Feria V post Dominicam VI post Pentecosten +ef-time-after-pentecost-6-friday = Feria VI post Dominicam VI post Pentecosten +ef-time-after-pentecost-7-monday = Feria II post Dominicam VII post Pentecosten +ef-time-after-pentecost-7-tuesday = Feria III post Dominicam VII post Pentecosten +ef-time-after-pentecost-7-wednesday = Feria IV post Dominicam VII post Pentecosten +ef-time-after-pentecost-7-thursday = Feria V post Dominicam VII post Pentecosten +ef-time-after-pentecost-7-friday = Feria VI post Dominicam VII post Pentecosten +ef-time-after-pentecost-8-monday = Feria II post Dominicam VIII post Pentecosten +ef-time-after-pentecost-8-tuesday = Feria III post Dominicam VIII post Pentecosten +ef-time-after-pentecost-8-wednesday = Feria IV post Dominicam VIII post Pentecosten +ef-time-after-pentecost-8-thursday = Feria V post Dominicam VIII post Pentecosten +ef-time-after-pentecost-8-friday = Feria VI post Dominicam VIII post Pentecosten +ef-time-after-pentecost-9-monday = Feria II post Dominicam IX post Pentecosten +ef-time-after-pentecost-9-tuesday = Feria III post Dominicam IX post Pentecosten +ef-time-after-pentecost-9-wednesday = Feria IV post Dominicam IX post Pentecosten +ef-time-after-pentecost-9-thursday = Feria V post Dominicam IX post Pentecosten +ef-time-after-pentecost-9-friday = Feria VI post Dominicam IX post Pentecosten +ef-time-after-pentecost-10-monday = Feria II post Dominicam X post Pentecosten +ef-time-after-pentecost-10-tuesday = Feria III post Dominicam X post Pentecosten +ef-time-after-pentecost-10-wednesday = Feria IV post Dominicam X post Pentecosten +ef-time-after-pentecost-10-thursday = Feria V post Dominicam X post Pentecosten +ef-time-after-pentecost-10-friday = Feria VI post Dominicam X post Pentecosten +ef-time-after-pentecost-11-monday = Feria II post Dominicam XI post Pentecosten +ef-time-after-pentecost-11-tuesday = Feria III post Dominicam XI post Pentecosten +ef-time-after-pentecost-11-wednesday = Feria IV post Dominicam XI post Pentecosten +ef-time-after-pentecost-11-thursday = Feria V post Dominicam XI post Pentecosten +ef-time-after-pentecost-11-friday = Feria VI post Dominicam XI post Pentecosten +ef-time-after-pentecost-12-monday = Feria II post Dominicam XII post Pentecosten +ef-time-after-pentecost-12-tuesday = Feria III post Dominicam XII post Pentecosten +ef-time-after-pentecost-12-wednesday = Feria IV post Dominicam XII post Pentecosten +ef-time-after-pentecost-12-thursday = Feria V post Dominicam XII post Pentecosten +ef-time-after-pentecost-12-friday = Feria VI post Dominicam XII post Pentecosten +ef-time-after-pentecost-13-monday = Feria II post Dominicam XIII post Pentecosten +ef-time-after-pentecost-13-tuesday = Feria III post Dominicam XIII post Pentecosten +ef-time-after-pentecost-13-wednesday = Feria IV post Dominicam XIII post Pentecosten +ef-time-after-pentecost-13-thursday = Feria V post Dominicam XIII post Pentecosten +ef-time-after-pentecost-13-friday = Feria VI post Dominicam XIII post Pentecosten +ef-time-after-pentecost-14-monday = Feria II post Dominicam XIV post Pentecosten +ef-time-after-pentecost-14-tuesday = Feria III post Dominicam XIV post Pentecosten +ef-time-after-pentecost-14-wednesday = Feria IV post Dominicam XIV post Pentecosten +ef-time-after-pentecost-14-thursday = Feria V post Dominicam XIV post Pentecosten +ef-time-after-pentecost-14-friday = Feria VI post Dominicam XIV post Pentecosten +ef-time-after-pentecost-15-monday = Feria II post Dominicam XV post Pentecosten +ef-time-after-pentecost-15-tuesday = Feria III post Dominicam XV post Pentecosten +ef-time-after-pentecost-15-wednesday = Feria IV post Dominicam XV post Pentecosten +ef-time-after-pentecost-15-thursday = Feria V post Dominicam XV post Pentecosten +ef-time-after-pentecost-15-friday = Feria VI post Dominicam XV post Pentecosten +ef-time-after-pentecost-16-monday = Feria II post Dominicam XVI post Pentecosten +ef-time-after-pentecost-16-tuesday = Feria III post Dominicam XVI post Pentecosten +ef-time-after-pentecost-16-wednesday = Feria IV post Dominicam XVI post Pentecosten +ef-time-after-pentecost-16-thursday = Feria V post Dominicam XVI post Pentecosten +ef-time-after-pentecost-16-friday = Feria VI post Dominicam XVI post Pentecosten +ef-time-after-pentecost-17-monday = Feria II post Dominicam XVII post Pentecosten +ef-time-after-pentecost-17-tuesday = Feria III post Dominicam XVII post Pentecosten +ef-time-after-pentecost-17-wednesday = Feria IV post Dominicam XVII post Pentecosten +ef-time-after-pentecost-17-thursday = Feria V post Dominicam XVII post Pentecosten +ef-time-after-pentecost-17-friday = Feria VI post Dominicam XVII post Pentecosten +ef-time-after-pentecost-18-monday = Feria II post Dominicam XVIII post Pentecosten +ef-time-after-pentecost-18-tuesday = Feria III post Dominicam XVIII post Pentecosten +ef-time-after-pentecost-18-wednesday = Feria IV post Dominicam XVIII post Pentecosten +ef-time-after-pentecost-18-thursday = Feria V post Dominicam XVIII post Pentecosten +ef-time-after-pentecost-18-friday = Feria VI post Dominicam XVIII post Pentecosten +ef-time-after-pentecost-19-monday = Feria II post Dominicam XIX post Pentecosten +ef-time-after-pentecost-19-tuesday = Feria III post Dominicam XIX post Pentecosten +ef-time-after-pentecost-19-wednesday = Feria IV post Dominicam XIX post Pentecosten +ef-time-after-pentecost-19-thursday = Feria V post Dominicam XIX post Pentecosten +ef-time-after-pentecost-19-friday = Feria VI post Dominicam XIX post Pentecosten +ef-time-after-pentecost-20-monday = Feria II post Dominicam XX post Pentecosten +ef-time-after-pentecost-20-tuesday = Feria III post Dominicam XX post Pentecosten +ef-time-after-pentecost-20-wednesday = Feria IV post Dominicam XX post Pentecosten +ef-time-after-pentecost-20-thursday = Feria V post Dominicam XX post Pentecosten +ef-time-after-pentecost-20-friday = Feria VI post Dominicam XX post Pentecosten +ef-time-after-pentecost-21-monday = Feria II post Dominicam XXI post Pentecosten +ef-time-after-pentecost-21-tuesday = Feria III post Dominicam XXI post Pentecosten +ef-time-after-pentecost-21-wednesday = Feria IV post Dominicam XXI post Pentecosten +ef-time-after-pentecost-21-thursday = Feria V post Dominicam XXI post Pentecosten +ef-time-after-pentecost-21-friday = Feria VI post Dominicam XXI post Pentecosten +ef-time-after-pentecost-22-monday = Feria II post Dominicam XXII post Pentecosten +ef-time-after-pentecost-22-tuesday = Feria III post Dominicam XXII post Pentecosten +ef-time-after-pentecost-22-wednesday = Feria IV post Dominicam XXII post Pentecosten +ef-time-after-pentecost-22-thursday = Feria V post Dominicam XXII post Pentecosten +ef-time-after-pentecost-22-friday = Feria VI post Dominicam XXII post Pentecosten +ef-time-after-pentecost-23-monday = Feria II post Dominicam XXIII post Pentecosten +ef-time-after-pentecost-23-tuesday = Feria III post Dominicam XXIII post Pentecosten +ef-time-after-pentecost-23-wednesday = Feria IV post Dominicam XXIII post Pentecosten +ef-time-after-pentecost-23-thursday = Feria V post Dominicam XXIII post Pentecosten +ef-time-after-pentecost-23-friday = Feria VI post Dominicam XXIII post Pentecosten +ef-time-after-pentecost-24-monday = Feria II post Dominicam XXIV post Pentecosten +ef-time-after-pentecost-24-tuesday = Feria III post Dominicam XXIV post Pentecosten +ef-time-after-pentecost-24-wednesday = Feria IV post Dominicam XXIV post Pentecosten +ef-time-after-pentecost-24-thursday = Feria V post Dominicam XXIV post Pentecosten +ef-time-after-pentecost-24-friday = Feria VI post Dominicam XXIV post Pentecosten +ef-time-after-pentecost-25-monday = Feria II post Dominicam XXV post Pentecosten +ef-time-after-pentecost-25-tuesday = Feria III post Dominicam XXV post Pentecosten +ef-time-after-pentecost-25-wednesday = Feria IV post Dominicam XXV post Pentecosten +ef-time-after-pentecost-25-thursday = Feria V post Dominicam XXV post Pentecosten +ef-time-after-pentecost-25-friday = Feria VI post Dominicam XXV post Pentecosten +ef-time-after-pentecost-26-monday = Feria II post Dominicam XXVI post Pentecosten +ef-time-after-pentecost-26-tuesday = Feria III post Dominicam XXVI post Pentecosten +ef-time-after-pentecost-26-wednesday = Feria IV post Dominicam XXVI post Pentecosten +ef-time-after-pentecost-26-thursday = Feria V post Dominicam XXVI post Pentecosten +ef-time-after-pentecost-26-friday = Feria VI post Dominicam XXVI post Pentecosten +ef-time-after-pentecost-27-tuesday = Feria III post Dominicam XXVII post Pentecosten +ef-time-after-pentecost-27-wednesday = Feria IV post Dominicam XXVII post Pentecosten +ef-time-after-pentecost-27-thursday = Feria V post Dominicam XXVII post Pentecosten +ef-time-after-pentecost-27-friday = Feria VI post Dominicam XXVII post Pentecosten +ef-time-after-pentecost-28-tuesday = Feria III post Dominicam XXVIII post Pentecosten +ef-time-after-pentecost-28-wednesday = Feria IV post Dominicam XXVIII post Pentecosten +ef-time-after-pentecost-28-thursday = Feria V post Dominicam XXVIII post Pentecosten + +; Paschaltide ferias, weeks 2-7 (Monday-Friday; each week's own Saturday +; through week 6 is the votive BVM Office, above -- week 7's Saturday is +; the Pentecost Vigil, already named above) -- PATTERN, same "post +; Dominicam ... post Pascha" grammar the Time-after-Pentecost block +; attests, substituting "Pascha" for "Pentecosten"; week 2 follows Low +; Sunday itself so reads "post Dominicam in Albis" rather than an ordinal, +; and week 7 follows "Dominica post Ascensionem" (no ordinal either) so +; reads "post Dominicam post Ascensionem". +ef-easter-2-monday = Feria II post Dominicam in Albis +ef-easter-2-tuesday = Feria III post Dominicam in Albis +ef-easter-2-wednesday = Feria IV post Dominicam in Albis +ef-easter-2-thursday = Feria V post Dominicam in Albis +ef-easter-2-friday = Feria VI post Dominicam in Albis +ef-easter-3-monday = Feria II post Dominicam II post Pascha +ef-easter-3-tuesday = Feria III post Dominicam II post Pascha +ef-easter-3-wednesday = Feria IV post Dominicam II post Pascha +ef-easter-3-thursday = Feria V post Dominicam II post Pascha +ef-easter-3-friday = Feria VI post Dominicam II post Pascha +ef-easter-4-monday = Feria II post Dominicam III post Pascha +ef-easter-4-tuesday = Feria III post Dominicam III post Pascha +ef-easter-4-wednesday = Feria IV post Dominicam III post Pascha +ef-easter-4-thursday = Feria V post Dominicam III post Pascha +ef-easter-4-friday = Feria VI post Dominicam III post Pascha +ef-easter-5-monday = Feria II post Dominicam IV post Pascha +ef-easter-5-tuesday = Feria III post Dominicam IV post Pascha +ef-easter-5-wednesday = Feria IV post Dominicam IV post Pascha +ef-easter-5-thursday = Feria V post Dominicam IV post Pascha +ef-easter-5-friday = Feria VI post Dominicam IV post Pascha +ef-easter-6-friday = Feria VI post Dominicam V post Pascha +ef-easter-7-monday = Feria II post Dominicam post Ascensionem +ef-easter-7-tuesday = Feria III post Dominicam post Ascensionem +ef-easter-7-wednesday = Feria IV post Dominicam post Ascensionem +ef-easter-7-thursday = Feria V post Dominicam post Ascensionem +ef-easter-7-friday = Feria VI post Dominicam post Ascensionem + +; 2-5 January (between the Nativity Octave Day and Epiphany) -- PATTERN. +; temporal_ef.ml's own comment on [christmastide_feria_slug] is explicit +; that this whole window is a colitur-only key with no lectio or Missal +; counterpart ("a further lectionary gap"); constructed here, not +; transcribed from anywhere. +ef-christmas-1-monday = Feria II ante Epiphaniam +ef-christmas-1-tuesday = Feria III ante Epiphaniam +ef-christmas-1-wednesday = Feria IV ante Epiphaniam +ef-christmas-1-thursday = Feria V ante Epiphaniam +ef-christmas-1-friday = Feria VI ante Epiphaniam + +; 7-13 January before the actual first-Sunday-after-Epiphany origin -- +; PATTERN, same reasoning as the block immediately above (temporal_ef.ml's +; own comment: "a further lectionary gap"). +ef-christmas-2-monday = Feria II post Epiphaniam +ef-christmas-2-tuesday = Feria III post Epiphaniam +ef-christmas-2-wednesday = Feria IV post Epiphaniam +ef-christmas-2-thursday = Feria V post Epiphaniam +ef-christmas-2-friday = Feria VI post Epiphaniam diff --git a/test/dune b/test/dune index b9cc2a7..6e2ac87 100644 --- a/test/dune +++ b/test/dune @@ -4,6 +4,7 @@ (deps ../data/ef/sanctoral.sexp ../data/ef/adjustments.sexp + ../lang/la.ini ../data/ef/expected-divergences.sexp ../data/ef/expected-divergences-missalemeum.sexp ../data/ef/lectionary.sexp diff --git a/test/test_colitur.ml b/test/test_colitur.ml index 1c445a6..1bdd220 100644 --- a/test/test_colitur.ml +++ b/test/test_colitur.ml @@ -3,6 +3,7 @@ let () = Alcotest.run "colitur" [ Test_date.suite; Test_computus.suite; Test_colour.suite; Test_slug.suite; Test_names.suite; Test_lang.suite; + Test_lang_coverage.suite; Test_config.suite; Test_overlay.suite; Test_overlay_ini.suite; Test_temporal_ef.suite; Test_validate.suite; Test_precedence.suite; Test_calendar.suite; Test_precedence_ef.suite; Test_sanctoral_ef.suite; Test_rite_ef.suite; diff --git a/test/test_lang_coverage.ml b/test/test_lang_coverage.ml new file mode 100644 index 0000000..d72484f --- /dev/null +++ b/test/test_lang_coverage.ml @@ -0,0 +1,73 @@ +module L = Colitur_naming.Lang + +let read path = + let ic = open_in_bin path in + let s = really_input_string ic (in_channel_length ic) in + close_in ic; + s + +let la () = + match L.of_string (read "../lang/la.ini") with + | Ok t -> t + | Error e -> Alcotest.failf "lang/la.ini: %s" e + +(* Every TEMPORAL slug the engine can emit must have a Latin name. THIS IS THE + TEST THAT WOULD HAVE CAUGHT THE ORIGINAL DEFECT -- a booklet printed + "ef-septuagesima-sunday-2" because nothing asserted coverage. It must fail + loudly the moment a new slug appears without a name. + + RESTRICTED TO "^ef-" SLUGS FOR NOW (Task 3's own scope: la.ini's + [celebration] table currently carries the temporal half only). Task 4 adds + the sanctoral names and REMOVES this filter -- see this file's own + [is_temporal_slug] below, kept as one clearly-named, easy-to-find place to + change, rather than an inline condition. *) +let is_temporal_slug slug = String.length slug >= 3 && String.sub slug 0 3 = "ef-" + +let test_every_temporal_slug_has_a_latin_name () = + let t = la () in + let layer = match Test_support.load_ef_layer () with Ok l -> l | Error e -> Alcotest.failf "%s" e in + let ctx = Test_support.ef_context () in + let missing = ref [] in + for y = 2020 to 2045 do + Array.iter + (fun (d : (Rite_ef.Vocab_ef.season, Rite_ef.Vocab_ef.rank) Colitur_kernel.Liturgical_day.t) -> + let slug = + Colitur_kernel.Slug.to_string + d.Colitur_kernel.Liturgical_day.observed.Colitur_kernel.Celebration.slug + in + (* A miss returns the key itself, so name = slug means "no entry". *) + if + is_temporal_slug slug + && L.celebration t slug = slug + && not (List.mem slug !missing) + then missing := slug :: !missing) + (Colitur_kernel.Calendar.year ctx layer y) + done; + if !missing <> [] then + Alcotest.failf "%d slugs have no Latin name, e.g. %s" (List.length !missing) + (String.concat ", " (List.filteri (fun i _ -> i < 5) !missing)) + +let test_vocabularies_are_complete () = + let t = la () in + List.iter + (fun s -> if L.season t s = s then Alcotest.failf "no Latin season name for %S" s) + [ "advent"; "christmastide"; "time-after-epiphany"; "septuagesima"; "lent"; + "passiontide"; "paschaltide"; "time-after-pentecost" ]; + List.iter + (fun r -> if L.rank t r = r then Alcotest.failf "no Latin rank name for %S" r) + [ "class-1"; "class-2"; "class-3"; "class-4" ]; + List.iter + (fun c -> if L.colour t c = c then Alcotest.failf "no Latin colour name for %S" c) + [ "white"; "red"; "green"; "violet"; "rose"; "black" ]; + for n = 0 to 6 do + if L.weekday t n = string_of_int n then Alcotest.failf "no Latin weekday for %d" n + done; + for n = 1 to 12 do + if L.month t n = string_of_int n then Alcotest.failf "no Latin month for %d" n + done + +let suite = + ( "Lang/coverage", + [ Alcotest.test_case "every temporal slug has a Latin name" `Slow + test_every_temporal_slug_has_a_latin_name; + Alcotest.test_case "vocabularies complete" `Quick test_vocabularies_are_complete ] ) -- cgit v1.3