aboutsummaryrefslogtreecommitdiff
path: root/lib/naming
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-20 19:05:13 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-20 19:05:13 +0200
commit7dbd16cdf5880c0006dffacd09214ee607050b64 (patch)
tree01e1ee37a2be97a0b06fad70de975d8007beb702 /lib/naming
parent1aeca948c2a2a82bffaaec65077140aa05f7b3f4 (diff)
parent1da70dc7ac03fe33fb92b172a0e26932764170d6 (diff)
downloadcolitur-7dbd16cdf5880c0006dffacd09214ee607050b64.tar.gz
colitur-7dbd16cdf5880c0006dffacd09214ee607050b64.zip
Merge branch 'citations-and-sigla'
Citations are parsed into structure and re-rendered, so book names, abbreviations, punctuation style and numbering tradition become files a user edits rather than strings frozen in the data. New lib/citation (Book, Parse, Render, Sigla); [bible] and [sigla] sections in language files; lang/traditions.ini for numbering; three config keys and CLI flags. --raw emits every citation byte-for-byte as stored, bypassing the whole pipeline, so output stays diffable against lectio and the raw view does not depend on the parser being correct.
Diffstat (limited to 'lib/naming')
-rw-r--r--lib/naming/config.ml13
-rw-r--r--lib/naming/config.mli24
-rw-r--r--lib/naming/lang.ml24
-rw-r--r--lib/naming/lang.mli27
4 files changed, 83 insertions, 5 deletions
diff --git a/lib/naming/config.ml b/lib/naming/config.ml
index 7d87d62..068b40a 100644
--- a/lib/naming/config.ml
+++ b/lib/naming/config.ml
@@ -5,18 +5,24 @@ type t = {
overlays : string list;
template : string option;
format : string option;
+ sigla_style : string option;
+ sigla_book : string option;
+ sigla_tradition : string option;
unknown_keys : string list;
unknown_sections : string list;
}
let empty =
- { lang = None; overlays = []; template = None; format = None; unknown_keys = [];
- unknown_sections = [] }
+ { lang = None; overlays = []; template = None; format = None; sigla_style = None;
+ sigla_book = None; sigla_tradition = None; unknown_keys = []; unknown_sections = [] }
let lang t = t.lang
let overlays t = t.overlays
let template t = t.template
let format t = t.format
+let sigla_style t = t.sigla_style
+let sigla_book t = t.sigla_book
+let sigla_tradition t = t.sigla_tradition
let unknown_keys t = t.unknown_keys
let unknown_sections t = t.unknown_sections
@@ -65,6 +71,9 @@ let of_string text =
| "lang" -> { acc with lang = Some v }
| "template" -> { acc with template = Some v }
| "format" -> { acc with format = Some v }
+ | "sigla_style" -> { acc with sigla_style = Some v }
+ | "sigla_book" -> { acc with sigla_book = Some v }
+ | "sigla_tradition" -> { acc with sigla_tradition = Some v }
(* accumulates: a user has more than one overlay *)
| "overlay" -> { acc with overlays = v :: acc.overlays }
| other -> { acc with unknown_keys = other :: acc.unknown_keys })
diff --git a/lib/naming/config.mli b/lib/naming/config.mli
index a84f95b..a5205c4 100644
--- a/lib/naming/config.mli
+++ b/lib/naming/config.mli
@@ -29,6 +29,30 @@ val overlays : t -> string list
val template : t -> string option
val format : t -> string option
+(** Which citation style to render a reference in: a language CODE, looked
+ up the same way {!lang} is, or a path -- but a DIFFERENT axis from
+ {!lang}: a language file's own [\[sigla\]] section IS a style
+ ({!Colitur_citation.Render.style_of_fields}), and this key SELECTS
+ which file's [\[sigla\]] section supplies it, independently of which
+ file's other sections supply names elsewhere (a booklet may want
+ Polish names but Latin-convention citations). Same last-wins duplicate
+ policy as {!lang}. *)
+val sigla_style : t -> string option
+
+(** [full] or [abbr] -- overrides the style's own [book] setting rather than
+ replacing the style outright, so a chosen style's punctuation survives
+ even when the book form is overridden ({!Colitur_citation.Render.with_book}).
+ Same last-wins duplicate policy as {!lang}. *)
+val sigla_book : t -> string option
+
+(** The name of a section in [lang/traditions.ini] -- which BOOK a reference
+ DENOTES (Vulgate numbering by default), a different question again from
+ both {!sigla_style} (how a reference is WRITTEN) and {!lang} (what
+ everything else is CALLED): naming and numbering both vary by
+ convention, but not together. Same last-wins duplicate policy as
+ {!lang}. *)
+val sigla_tradition : t -> string option
+
(** Keys present in the [\[defaults\]] section 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
diff --git a/lib/naming/lang.ml b/lib/naming/lang.ml
index 2301513..f0fd989 100644
--- a/lib/naming/lang.ml
+++ b/lib/naming/lang.ml
@@ -16,6 +16,8 @@ type t = {
colour : table;
term : table;
rite : table;
+ bible : table;
+ sigla : table;
chain : t option; (** consulted when this table misses *)
}
@@ -35,6 +37,14 @@ let rank t k = get t (fun x -> x.rank) k
let colour t k = get t (fun x -> x.colour) k
let term t k = get t (fun x -> x.term) k
let rite t k = get t (fun x -> x.rite) k
+let bible t k = get t (fun x -> x.bible) k
+
+(* Not routed through [get]/[chain]: [sigla] is a set of RENDER SETTINGS
+ (Render.style_of_fields), not a per-key translation lookup, and it has no
+ miss-returns-the-key contract to keep -- a caller with no [sigla] table at
+ all just gets []. Order does not matter to callers (Render.style_of_fields
+ reads them by name), so [SM.bindings] (alphabetical) is fine here. *)
+let sigla_fields t = SM.bindings t.sigla
let weekday_key = [| "sunday"; "monday"; "tuesday"; "wednesday"; "thursday"; "friday"; "saturday" |]
@@ -65,7 +75,8 @@ let fallback_code t = t.fallback_code
let raw =
{ code = "raw"; fallback_code = None; celebration = empty_table; weekday = empty_table;
month = empty_table; month_abbr = empty_table; season = empty_table; rank = empty_table;
- colour = empty_table; term = empty_table; rite = empty_table; chain = None }
+ colour = empty_table; term = empty_table; rite = empty_table; bible = empty_table;
+ sigla = empty_table; chain = None }
let with_fallback t base = { t with chain = Some base }
@@ -107,12 +118,21 @@ let of_string text =
colour = find "colour";
term = find "term";
rite = find "rite";
+ bible = find "bible";
+ sigla = find "sigla";
chain = None })
+(* [bible] joins this reference set: it is translatable book names, so a file
+ lacking them is genuinely incomplete and [lang --check] should say so.
+ [sigla] deliberately does NOT: it is five citation-style settings with
+ working defaults (Render.default_style), not names a translator owes --
+ adding it here would make [--check] demand five settings from every
+ language file that has never needed them. *)
let keys t =
let qualify prefix m = SM.bindings m |> List.map (fun (k, v) -> (prefix ^ "." ^ k, v)) in
List.concat
[ qualify "celebration" t.celebration; qualify "weekday" t.weekday;
qualify "month" t.month; qualify "month_abbr" t.month_abbr; qualify "season" t.season;
- qualify "rank" t.rank; qualify "colour" t.colour; qualify "term" t.term; qualify "rite" t.rite ]
+ qualify "rank" t.rank; qualify "colour" t.colour; qualify "term" t.term; qualify "rite" t.rite;
+ qualify "bible" t.bible ]
|> List.sort compare
diff --git a/lib/naming/lang.mli b/lib/naming/lang.mli
index 34a6d5d..3c62d26 100644
--- a/lib/naming/lang.mli
+++ b/lib/naming/lang.mli
@@ -55,6 +55,13 @@ val term : t -> string -> string
degradation an unnamed slug already gets, not a special case. *)
val rite : t -> string -> string
+(** A Bible book's name, from the [\[bible\]] section. The key is
+ [<book_id>.full] or [<book_id>.abbr] (e.g. ["luke.abbr"]). A miss returns
+ the key itself, the same TOTAL-lookup contract as every other function
+ here -- callers turn that into a real fallback via
+ {!Colitur_citation.Book.default_spelling}, not this module. *)
+val bible : t -> string -> string
+
(** [weekday t n], 0 = Sunday. Out-of-range [n] returns [string_of_int n]. *)
val weekday : t -> int -> string
@@ -69,5 +76,23 @@ val month : t -> int -> string
val month_abbr : t -> int -> string
(** Every (section-qualified key, value) pair, sorted. Used by [lang --dump] and
- [lang --check]. Keys are qualified as e.g. ["celebration.ef-epiphany"]. *)
+ [lang --check]. Keys are qualified as e.g. ["celebration.ef-epiphany"].
+
+ Includes [\[bible\]] (["bible.luke.abbr"]): book names are translatable
+ text, so a file missing them is genuinely incomplete and [lang --check]
+ should say so. Deliberately EXCLUDES [\[sigla\]]: those are five citation-
+ style settings with working defaults ({!Colitur_citation.Render.default_style}),
+ not names a translator owes -- listing them here would make [--check]
+ demand five settings from every language file. *)
val keys : t -> (string * string) list
+
+(** The [\[sigla\]] section's raw fields, for
+ {!Colitur_citation.Render.style_of_fields} to read. Values come back
+ TRIMMED (whitespace at both ends) but still QUOTED if the file quoted
+ them -- unquoting is [Render]'s job, not this module's, the same reason
+ {!Colitur_kernel.Overlay_ini} (which this parses through) never unquotes
+ either. An empty (or absent) [\[sigla\]] section returns [[]]; unlike
+ every lookup above, there is no per-key TOTAL contract to keep here --
+ this is a settings bag, not a translation table, and [Render] already
+ supplies its own defaults for whatever is missing. *)
+val sigla_fields : t -> (string * string) list