aboutsummaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-20 16:01:39 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-20 16:01:39 +0200
commit9dfa264f2941f1ca38eff08b6157a94d332cffbd (patch)
tree3c88ace24b4f45f0098f9ef7cf8911582d271bd6 /bin
parentc02e77b73aad34fb5a672a5234a66d64f23b45ce (diff)
downloadcolitur-9dfa264f2941f1ca38eff08b6157a94d332cffbd.tar.gz
colitur-9dfa264f2941f1ca38eff08b6157a94d332cffbd.zip
feat(lang): traditions.ini, and its install rule
Which book a reference denotes does not vary by language, so it lives in its own file rather than in la.ini beside [weekday]. Six mappings, not four: Osee/Jonas are the same question as 3 Kings in transliteration form. The install rule is added in the same commit deliberately -- lang/ once shipped without one, so the feature worked from the source tree and was broken once installed. bin/dune gains colitur_citation as a linked library, needed for the new loader; lang_list's directory scan now excludes traditions.ini, which is not a language file and does not parse as one.
Diffstat (limited to 'bin')
-rw-r--r--bin/dune7
-rw-r--r--bin/main.ml74
2 files changed, 78 insertions, 3 deletions
diff --git a/bin/dune b/bin/dune
index 28c04d7..0702a84 100644
--- a/bin/dune
+++ b/bin/dune
@@ -6,4 +6,9 @@
; colitur.opam's frozen depends, only a new library this executable links
; against. Used by Task 12's [mkdir_p] (colitur publish, recursive
; directory creation) and nowhere else.
- (libraries colitur_kernel rite_ef colitur_render colitur_naming unix))
+ ;
+ ; [colitur_citation] backs [load_tradition]'s own reading of
+ ; lang/traditions.ini (which book a reference DENOTES, {!Colitur_citation.Book}) --
+ ; a sibling library to [colitur_naming] (what a book is CALLED), not a
+ ; replacement for it.
+ (libraries colitur_kernel rite_ef colitur_render colitur_naming colitur_citation unix))
diff --git a/bin/main.ml b/bin/main.ml
index cf6cb33..5c9f342 100644
--- a/bin/main.ml
+++ b/bin/main.ml
@@ -641,6 +641,67 @@ let load_lang ~raw ~flag ~config =
| Error _ -> t
| Ok base -> Colitur_naming.Lang.with_fallback t base))))
+(* lang/traditions.ini answers a different question from la.ini/en.ini's own
+ [\[bible\]] section: which book a reference DENOTES, not what it is
+ CALLED. Naming varies by language (a [\[bible\]] section per language
+ file); denoting does not -- "modern numbering" is the same decision in
+ Latin, Polish and English -- so it gets its own file, read once here
+ rather than duplicated per language.
+
+ Reuses {!lang_dir} rather than adding a second probe: a tradition file
+ must resolve the same way a language file does, or an installed binary
+ could find one and not the other. Note carefully what that reuse implies
+ -- [lang_dir]'s own installed-vs-source-tree choice is gated on [la.ini]
+ existing, so it can legitimately return a directory that HAS [la.ini] but
+ NOT [traditions.ini] (an older install upgraded in place, from before
+ this file shipped). That case, like an unknown [name] naming no section
+ in the file, degrades to {!Colitur_citation.Book.vulgate} with a WARNING
+ on stderr -- never fatal. This deliberately does NOT mirror [load_lang]'s
+ own PRIMARY-file behaviour (a missing/unparsing la.ini is fatal, [exit 2])
+ -- it mirrors [load_lang]'s own FALLBACK-chain behaviour just above,
+ which already degrades silently rather than taking a good language table
+ down over a defect in a file it merely NAMES. Asking for a renumbering is
+ optional the way asking for a language is not: a run should not be lost
+ over a typo in [--sigla-tradition] (wired in Task 8) the way it is lost
+ over a typo in [--lang].
+
+ [name = "vulgate"] takes no shortcut around the file: [\[vulgate\]] is
+ shipped as a deliberately empty section (see traditions.ini's own
+ comment), and an empty field list is exactly {!Colitur_citation.Book.vulgate}
+ ([[]]) via the same {!Colitur_citation.Book.tradition_of_fields} path
+ every other tradition uses -- one code path, not a special case for the
+ default.
+
+ Not called from anywhere in this file yet: citations reach output at
+ exactly two places, [View.citation_ref] and [part_ref] below, and
+ threading [Sigla.t] (which this feeds) through both is a dedicated task
+ on its own, deliberately not done here alongside the loader. [-32] is
+ silenced for exactly that reason -- this is a complete, correct,
+ ready-to-call function with no caller yet, not dead code. *)
+let[@warning "-32"] load_tradition name =
+ let path = Filename.concat (lang_dir ()) "traditions.ini" in
+ let vulgate () = Colitur_citation.Book.vulgate in
+ match read_file path with
+ | Error _ ->
+ Printf.eprintf "colitur: no %s; tradition %S falls back to the Vulgate\n" path name;
+ vulgate ()
+ | Ok text -> (
+ match Colitur_kernel.Overlay_ini.parse_sections text with
+ | Error e ->
+ Printf.eprintf "colitur: %s: %s; tradition %S falls back to the Vulgate\n" path e name;
+ vulgate ()
+ | Ok sections -> (
+ match List.find_opt (fun (s : Colitur_kernel.Overlay_ini.section) -> s.name = name) sections with
+ | None ->
+ Printf.eprintf "colitur: %s: no tradition %S; falling back to the Vulgate\n" path name;
+ vulgate ()
+ | Some sec ->
+ List.iter
+ (fun k ->
+ Printf.eprintf "colitur: %s: [%s]: unknown book %S (ignored)\n" path name k)
+ (Colitur_citation.Book.unknown_fields sec.fields);
+ Colitur_citation.Book.tradition_of_fields sec.fields))
+
let extension path =
match String.rindex_opt path '.' with
| Some i -> String.sub path i (String.length path - i)
@@ -1514,7 +1575,16 @@ let convert_report path =
[lang_dir ()], the same probe [load_lang] itself uses. Each is opened and
parsed (not merely listed by filename) so a malformed file is flagged
here rather than only failing later when someone actually tries to use
- it. *)
+ it.
+
+ [traditions.ini] lives in the same directory but is not a language file
+ -- it answers which book a reference DENOTES, not what it is CALLED (see
+ [load_tradition] above) -- and does not even parse as one ([Lang.of_string]
+ requires its own [\[meta\]] section, which traditions.ini has no reason to
+ carry). Without this exclusion it would list here as "(unreadable: ...)",
+ which is not a defect in the file, only a mismatch between what this scan
+ assumes every [.ini] in the directory is and what is actually shipped
+ there now. *)
let lang_list () =
let dir = lang_dir () in
match Sys.readdir dir with
@@ -1525,7 +1595,7 @@ let lang_list () =
Array.sort compare files;
Array.iter
(fun f ->
- if Filename.check_suffix f ".ini" then begin
+ if Filename.check_suffix f ".ini" && f <> "traditions.ini" then begin
let code = Filename.remove_extension f in
match read_file (Filename.concat dir f) with
| Ok t -> (