separate the law that binds from the discipline that is shown

For an Eastern Catholic church these are sharply different questions and the
library was collapsing them. Ruthenian particular law binds on four kinds of
day in the year; the tradition those parishes actually keep is the Byzantine
fast entire. Reporting only the law made a week of the Great Fast read as
'no meat, fish, eggs or dairy' seven times over, which is the legal floor and
not the fast.

--typikon shows the day at the Typikon's discipline while the obligation
still comes from the jurisdiction's own law, because that is the part only it
can say. The Ruthenian rule now answers 'what binds here' separately from
'how is this day kept', which is what makes the two composable at all.

Three tests hold the seam: exactly the same days bind whichever discipline is
displayed, the binding minimum is never stricter than the level shown, and
the flag is a no-op for a jurisdiction already on the Typikon.
This commit is contained in:
funkpower
2026-09-18 12:21:06 -04:00
parent 4838d68b66
commit be45fa6a27
8 changed files with 200 additions and 51 deletions
+7
View File
@@ -48,11 +48,18 @@ pub struct Vocabulary {
pub emoji: fn(Level) -> &'static str,
}
/// What a particular law binds on a given day: the rule that binds, and the
/// minimum it binds to. `None` when the day obliges no one.
pub type Binding = Option<(&'static str, Level)>;
pub struct Rule {
pub name: &'static str,
pub title: &'static str,
pub vocabulary: Vocabulary,
pub fast_for: fn(&Context) -> Fast,
/// What this tradition's particular law binds, where it has one, asked
/// separately from how the day is kept.
pub obligation_for: Option<fn(&Context) -> Binding>,
/// Whether this tradition legislates the fast as precept at all.
pub has_obligation: bool,
}
+1
View File
@@ -257,6 +257,7 @@ pub static RULE: Rule = Rule {
title: "the Typikon",
vocabulary: Vocabulary { label, emoji },
fast_for,
obligation_for: None,
// The Orthodox Church does not legislate the fast as precept, so nothing
// here is reported as binding. See the module docs.
has_obligation: false,
+20 -13
View File
@@ -69,27 +69,33 @@ fn off_weekend(day: Date) -> Date {
}
}
pub fn fast_for(ctx: &Context) -> Fast {
/// What the law actually binds, asked independently of how the day is kept.
///
/// Four kinds of day, and nothing else in the year. Returning the binding
/// minimum separately is what lets the Typikon's own discipline be shown over
/// the top of it without losing the one fact the law contributes.
pub fn obligation_for(ctx: &Context) -> super::Binding {
let mv = ctx.mv;
// The two days the Church binds strictly.
if ctx.civil == mv.clean_monday {
return Fast::binding(Level::WineOil, "the first day of the Great Fast", Level::WineOil);
return Some(("the first day of the Great Fast", Level::WineOil));
}
if ctx.civil == mv.great_friday {
return Fast::binding(Level::WineOil, "Great and Holy Friday", Level::WineOil);
return Some(("Great and Holy Friday", Level::WineOil));
}
// And the days it binds to abstinence from meat. Kept strictly by
// tradition; binding only as far as meat.
if ctx.season == Some(Season::GreatFast)
&& matches!(ctx.weekday, Weekday::Wednesday | Weekday::Friday)
{
return Fast::binding(
Level::WineOil,
"Wednesday and Friday of the Great Fast",
Level::Dairy,
);
// Kept strictly by tradition; binding only as far as meat.
return Some(("Wednesday and Friday of the Great Fast", Level::Dairy));
}
None
}
pub fn fast_for(ctx: &Context) -> Fast {
let mv = ctx.mv;
if let Some((reason, binds)) = obligation_for(ctx) {
return Fast::binding(Level::WineOil, reason, binds);
}
// Fixed vigils and the Exaltation, moved off a weekend where the rule says.
@@ -157,5 +163,6 @@ pub static RULE: Rule = Rule {
title: "Ruthenian particular law",
vocabulary: Vocabulary { label, emoji },
fast_for,
obligation_for: Some(obligation_for),
has_obligation: true,
};