aboutsummaryrefslogtreecommitdiff
path: root/bin/main.ml
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-20 16:19:25 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-20 16:19:25 +0200
commit87b155b913cea7f5c55b5a2391aff7819ba541a6 (patch)
tree616df0de0f9fa8a08f6fd4156fa5fdac8fb9a1c3 /bin/main.ml
parent263d0d889073d214229aef9655d3db29540c0d12 (diff)
downloadcolitur-87b155b913cea7f5c55b5a2391aff7819ba541a6.tar.gz
colitur-87b155b913cea7f5c55b5a2391aff7819ba541a6.zip
feat(config): sigla_style, sigla_book and sigla_tradition
Same flag > config > default precedence as --lang, and each reported by config --show with its source, so an override is visible rather than mysterious. A language file's [sigla] section IS a style; a config key SELECTS one and may override settings within it -- the two are not a duplicate setting.
Diffstat (limited to 'bin/main.ml')
-rw-r--r--bin/main.ml147
1 files changed, 128 insertions, 19 deletions
diff --git a/bin/main.ml b/bin/main.ml
index 5c9f342..8434586 100644
--- a/bin/main.ml
+++ b/bin/main.ml
@@ -672,13 +672,15 @@ let load_lang ~raw ~flag ~config =
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 =
+ Called from [config_show] below (Task 8's own [--sigla-tradition]
+ plumbing), which discards the returned [tradition] and keeps only the
+ validation side effect -- `config --show` reports the RESOLVED STRING,
+ exactly like every other row, not a loaded object. Citations themselves
+ still reach output at exactly two places, [View.citation_ref] and
+ [part_ref] below, and threading the loaded [tradition] through both to
+ actually renumber a reference is Task 9's own dedicated job, not this
+ one's. *)
+let load_tradition name =
let path = Filename.concat (lang_dir ()) "traditions.ini" in
let vulgate () = Colitur_citation.Book.vulgate in
match read_file path with
@@ -1157,6 +1159,24 @@ naming:
it is `colitur lang`'s own identity table, under which every
lookup echoes its key back unchanged.
+ --sigla-style CODE|FILE, --sigla-book full|abbr, --sigla-tradition NAME
+ settings for how a Mass reading CITATION is written -- WHICH
+ punctuation/abbreviation style, WHICH book form, and WHICH
+ numbering tradition. Each has a config-key counterpart
+ (`sigla_style`/`sigla_book`/`sigla_tradition`) resolved with
+ the identical flag > config > default precedence as --lang, and
+ each is reported by `colitur config --show` with its source.
+ Defaults: `sigla_style` the resolved language code (so a
+ booklet's citations follow its own --lang unless told
+ otherwise), `sigla_book` `abbr`, `sigla_tradition` `vulgate`.
+ An unrecognised `--sigla-book` is a hard ERROR (want `full` or
+ `abbr`), the same discipline as an unknown `--lang`; an
+ unrecognised `--sigla-tradition` is not -- it degrades to the
+ Vulgate with a stderr warning, because asking for a renumbering
+ is optional the way asking for a language is not. Settings
+ only, for now: this build resolves and reports them but does
+ not yet render a citation through them.
+
colitur lang --list which language files this build can find, and
each one's own declared fallback, if any.
colitur lang --dump CODE the named language's full key set, in INI
@@ -1170,7 +1190,8 @@ naming:
anything is unknown, so it fits a Makefile or
a pre-commit hook.
colitur config --show every effective setting -- lang, overlay,
- template, format -- its resolved value, and
+ template, format, sigla_style, sigla_book,
+ sigla_tradition -- its resolved value, and
where it came from: `flag`, `config` or
`default`. See colitur-config(5) for the
config file's location and full precedence.
@@ -1322,6 +1343,10 @@ let with_year ys f =
the same shape as [prune]. [dump]/[check]/[list]/[show] (Task 7,
`colitur lang`/`colitur config`) follow the identical two shapes --
[dump]/[check] each take one value, [list]/[show] are bare. *)
+(* [sigla_style]/[sigla_book]/[sigla_tradition] (Task 8) are three more
+ single-valued optional settings, the same shape as [lang] -- each has a
+ config-key counterpart in [Colitur_naming.Config] and is resolved through
+ the identical [Config.resolve] precedence (flag > config > default). *)
type parsed_args = {
overlays : string list;
format : string option;
@@ -1339,6 +1364,9 @@ type parsed_args = {
check : string option;
list : bool;
show : bool;
+ sigla_style : string option;
+ sigla_book : string option;
+ sigla_tradition : string option;
positional : string list;
}
@@ -1373,6 +1401,12 @@ let parse_args argv =
| [ "--check" ] -> Error "--check needs a file path"
| "--list" :: rest -> go { acc with list = true } rest
| "--show" :: rest -> go { acc with show = true } rest
+ | "--sigla-style" :: v :: rest -> go { acc with sigla_style = Some v } rest
+ | [ "--sigla-style" ] -> Error "--sigla-style needs a language code or file path"
+ | "--sigla-book" :: v :: rest -> go { acc with sigla_book = Some v } rest
+ | [ "--sigla-book" ] -> Error "--sigla-book needs a value (full or abbr)"
+ | "--sigla-tradition" :: v :: rest -> go { acc with sigla_tradition = Some v } rest
+ | [ "--sigla-tradition" ] -> Error "--sigla-tradition needs a section name from lang/traditions.ini"
(* The recognised bare flags pass through as positional words for the
dispatch below to match; anything else beginning with '-' is rejected
rather than silently treated as a command or a year. *)
@@ -1386,7 +1420,8 @@ let parse_args argv =
go
{ overlays = []; format = None; from_y = None; to_y = None; dtstamp = None; year = None;
template = None; flavour = None; out = None; prune = false; lang = None; raw = false;
- dump = None; check = None; list = false; show = false; positional = [] }
+ dump = None; check = None; list = false; show = false; sigla_style = None; sigla_book = None;
+ sigla_tradition = None; positional = [] }
argv
(* Sibling to [reject_overlays_for]: `emit`'s own four flags have no meaning
@@ -1467,6 +1502,21 @@ let reject_lang_subcommand_flags_for cmd ~dump ~check ~list ~show =
exit 2
end
+(* Sibling again: `--sigla-style`/`--sigla-book`/`--sigla-tradition` (Task 8)
+ are settings plumbing only -- resolved and reported by `colitur config
+ --show` alone. Actually rendering a citation through them is Task 9's
+ job, so every OTHER command refuses the three flags rather than silently
+ accepting and ignoring them, the same discipline every rejector above
+ keeps; `config` is the one place that wires them in. *)
+let reject_sigla_for cmd ~sigla_style ~sigla_book ~sigla_tradition =
+ if sigla_style <> None || sigla_book <> None || sigla_tradition <> None then begin
+ Printf.eprintf
+ "colitur: --sigla-style/--sigla-book/--sigla-tradition have no effect on `%s`; refusing rather \
+ than ignoring them\n"
+ cmd;
+ exit 2
+ end
+
(* `colitur check FILE...` -- load a user overlay, apply it to the real
shipped calendar, and say what it did, without printing a year of output.
@@ -1739,24 +1789,68 @@ let lang_check path =
given these SAME command-line flags (so `config --show --lang fr` shows
exactly what a real `--lang fr` run would use); [overlay] is a list, so
it has no single "value" to resolve -- shown as one line per effective
- entry instead, with its own source. *)
-let config_show ~lang_flag ~template_flag ~format_flag ~overlays_flag config =
+ entry instead, with its own source.
+
+ [sigla_style]/[sigla_book]/[sigla_tradition] (Task 8) join the same
+ scalar rows, resolved through the identical [Config.resolve]. Two are
+ NOT arbitrary strings, though, so "report" also means "validate", the
+ same way an unknown [--lang] is an error rather than a silent Latin
+ fallback:
+ - [sigla_book] is a closed two-value setting ([full]/[abbr]) --
+ [Colitur_citation.Render.with_book] takes a variant, not a string, so
+ an unrecognised value could never mean anything downstream. Checked
+ HERE, not deferred to Task 9's actual renderer, because this is
+ currently the only place that consumes the value at all.
+ - [sigla_tradition] names a section of [lang/traditions.ini]; resolving
+ it for real (via [load_tradition], the same reader Task 9's renderer
+ will use) rather than only printing the string means a typo is caught
+ right here too -- though, unlike [sigla_book], [load_tradition] is
+ BY DESIGN never fatal (see its own comment: asking for a renumbering
+ is optional, unlike asking for a language), so an unknown tradition
+ degrades to a stderr warning and the Vulgate, exactly as it will under
+ Task 9, not a [config --show] failure.
+ [sigla_style] gets no such check: like [lang] itself, it is an open
+ language code or path, not a closed set, and [config --show] does not
+ validate [lang] either (that only happens when a command actually loads
+ it via [load_lang]). *)
+let config_show ~lang_flag ~template_flag ~format_flag ~overlays_flag ~sigla_style_flag ~sigla_book_flag
+ ~sigla_tradition_flag config =
let cpath = config_path () in
Printf.printf "config file: %s (%s)\n" cpath
(if cpath <> "" && Sys.file_exists cpath then "exists" else "not found");
let scalar name flag cfgval default =
let v, src = Colitur_naming.Config.resolve ~flag ~config:cfgval ~default in
- Printf.printf "%-10s %-24s (%s)\n" name v src
+ Printf.printf "%-16s %-24s (%s)\n" name v src;
+ v
+ in
+ let lang_value = scalar "lang" lang_flag (Colitur_naming.Config.lang config) "la" in
+ let _ = scalar "template" template_flag (Colitur_naming.Config.template config) "(none)" in
+ let _ = scalar "format" format_flag (Colitur_naming.Config.format config) "(none)" in
+ (* Default is the resolved LANGUAGE, not a literal "la": a booklet that
+ asked for --lang fr and named no --sigla-style of its own gets French
+ citations too, not a silent switch back to Latin punctuation. *)
+ let _ = scalar "sigla_style" sigla_style_flag (Colitur_naming.Config.sigla_style config) lang_value in
+ let sigla_book_value, sigla_book_src =
+ Colitur_naming.Config.resolve ~flag:sigla_book_flag ~config:(Colitur_naming.Config.sigla_book config)
+ ~default:"abbr"
+ in
+ if sigla_book_value <> "full" && sigla_book_value <> "abbr" then begin
+ Printf.eprintf "colitur: unknown --sigla-book %S (want \"full\" or \"abbr\")\n" sigla_book_value;
+ exit 2
+ end;
+ Printf.printf "%-16s %-24s (%s)\n" "sigla_book" sigla_book_value sigla_book_src;
+ let sigla_tradition_value, sigla_tradition_src =
+ Colitur_naming.Config.resolve ~flag:sigla_tradition_flag
+ ~config:(Colitur_naming.Config.sigla_tradition config) ~default:"vulgate"
in
- scalar "lang" lang_flag (Colitur_naming.Config.lang config) "la";
- scalar "template" template_flag (Colitur_naming.Config.template config) "(none)";
- scalar "format" format_flag (Colitur_naming.Config.format config) "(none)";
+ let _ = load_tradition sigla_tradition_value in
+ Printf.printf "%-16s %-24s (%s)\n" "sigla_tradition" sigla_tradition_value sigla_tradition_src;
(match overlays_flag with
- | _ :: _ as l -> List.iter (fun o -> Printf.printf "%-10s %-24s (%s)\n" "overlay" o "flag") l
+ | _ :: _ as l -> List.iter (fun o -> Printf.printf "%-16s %-24s (%s)\n" "overlay" o "flag") l
| [] -> (
match Colitur_naming.Config.overlays config with
- | [] -> Printf.printf "%-10s %-24s (%s)\n" "overlay" "(none)" "default"
- | l -> List.iter (fun o -> Printf.printf "%-10s %-24s (%s)\n" "overlay" o "config") l))
+ | [] -> Printf.printf "%-16s %-24s (%s)\n" "overlay" "(none)" "default"
+ | l -> List.iter (fun o -> Printf.printf "%-16s %-24s (%s)\n" "overlay" o "config") l))
(* `colitur new-overlay` -- a starter file on stdout, for redirection.
Deliberately printed rather than written: the user picks the path, and a
@@ -1819,12 +1913,13 @@ let () =
Printf.eprintf "colitur: %s\n" msg;
usage ()
| Ok { overlays; format; from_y; to_y; dtstamp; year; template; flavour; out; prune; lang;
- raw; dump; check; list; show; positional } -> (
+ raw; dump; check; list; show; sigla_style; sigla_book; sigla_tradition; positional } -> (
let reject_emit = reject_emit_flags_for ~format ~from_y ~to_y ~dtstamp in
let reject_table = reject_table_flags_for ~year ~template ~flavour in
let reject_publish = reject_publish_flags_for ~out ~prune in
let reject_lang = reject_lang_for ~lang ~raw in
let reject_lang_sub = reject_lang_subcommand_flags_for ~dump ~check ~list ~show in
+ let reject_sigla = reject_sigla_for ~sigla_style ~sigla_book ~sigla_tradition in
(* Loaded once, unconditionally: a config file the user wrote and
colitur cannot honour (missing HOME aside, [load_config] treats
that as "no config" rather than an error) is worth surfacing on
@@ -1855,6 +1950,7 @@ let () =
reject_publish "--help";
reject_lang "--help";
reject_lang_sub "--help";
+ reject_sigla "--help";
print_help ()
| [ ("-V" | "--version" | "version") ] ->
reject_overlays_for "--version" overlays;
@@ -1863,6 +1959,7 @@ let () =
reject_publish "--version";
reject_lang "--version";
reject_lang_sub "--version";
+ reject_sigla "--version";
print_endline version;
exit 0
| [ "easter"; ys ] ->
@@ -1872,6 +1969,7 @@ let () =
reject_publish "easter";
reject_lang "easter";
reject_lang_sub "easter";
+ reject_sigla "easter";
with_year ys easter_report
| [ "temporal"; ys ] ->
reject_overlays_for "temporal" overlays;
@@ -1880,6 +1978,7 @@ let () =
reject_publish "temporal";
reject_lang "temporal";
reject_lang_sub "temporal";
+ reject_sigla "temporal";
with_year ys temporal_report
| "check" :: (_ :: _ as files) ->
reject_overlays_for "check" overlays;
@@ -1888,6 +1987,7 @@ let () =
reject_publish "check";
reject_lang "check";
reject_lang_sub "check";
+ reject_sigla "check";
check_report files
| [ "convert"; path ] ->
reject_overlays_for "convert" overlays;
@@ -1896,6 +1996,7 @@ let () =
reject_publish "convert";
reject_lang "convert";
reject_lang_sub "convert";
+ reject_sigla "convert";
convert_report path
| [ "new-overlay" ] ->
reject_overlays_for "new-overlay" overlays;
@@ -1904,6 +2005,7 @@ let () =
reject_publish "new-overlay";
reject_lang "new-overlay";
reject_lang_sub "new-overlay";
+ reject_sigla "new-overlay";
print_string new_overlay_template;
exit 0
| [ "lang" ] -> (
@@ -1912,6 +2014,7 @@ let () =
reject_table "lang";
reject_publish "lang";
reject_lang "lang";
+ reject_sigla "lang";
if show then begin
Printf.eprintf "colitur: --show has no effect on `lang`; refusing rather than ignoring it\n";
exit 2
@@ -1956,23 +2059,27 @@ let () =
exit 2
end;
config_show ~lang_flag:lang ~template_flag:template ~format_flag:format ~overlays_flag:overlays
+ ~sigla_style_flag:sigla_style ~sigla_book_flag:sigla_book ~sigla_tradition_flag:sigla_tradition
config
| [ "day"; ys ] ->
reject_emit "day";
reject_table "day";
reject_publish "day";
reject_lang_sub "day";
+ reject_sigla "day";
with_year ys (day_report ~lang:(resolved_lang ()) ~overlays:effective_overlays)
| [ "readings"; ys ] ->
reject_emit "readings";
reject_table "readings";
reject_publish "readings";
reject_lang_sub "readings";
+ reject_sigla "readings";
with_year ys (readings_report ~lang:(resolved_lang ()) ~overlays:effective_overlays)
| [ "emit" ] -> (
reject_table "emit";
reject_publish "emit";
reject_lang_sub "emit";
+ reject_sigla "emit";
match (match format with Some f -> Some f | None -> Colitur_naming.Config.format config) with
| None ->
Printf.eprintf "colitur: emit requires --format csv|json|sexp|xml|ics\n";
@@ -1992,6 +2099,7 @@ let () =
reject_emit cmd;
reject_publish cmd;
reject_lang_sub cmd;
+ reject_sigla cmd;
match (match template with Some t -> Some t | None -> Colitur_naming.Config.template config) with
| None ->
Printf.eprintf "colitur: %s requires --year YEAR and --template FILE\n" cmd;
@@ -2010,6 +2118,7 @@ let () =
reject_table "publish";
reject_format_for "publish" format;
reject_lang_sub "publish";
+ reject_sigla "publish";
match out with
| None ->
Printf.eprintf "colitur: publish requires --out DIR\n";