From cd46163fa347bbc49bf8008d70d408f62feabda5 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 20 Aug 2026 10:11:48 +0200 Subject: fix(cli): close the flavour-list call sites Typst's addition exposed The task this branch of work set out to test was whether the template engine is genuinely flavour-agnostic outside lib/render/escape.ml. It is not, quite: bin/main.ml's own --flavour error/help text and both man pages hand-typed the flavour list and its count ("the six flavours") as literal prose, so adding Typst as a seventh left three places silently wrong (an incomplete flavour list in two error messages, and "six" where the true count is now seven) until this commit. bin/main.ml's two error messages (unknown --flavour value, and cannot infer a flavour from an extension) now build their flavour list by walking Escape.all/to_string instead of a literal string, so the next flavour added will not reintroduce the same drift; the static --help body text and colitur(1)/colitur-templates(5) still name flavours and their count by hand; there was no equivalent gain available for prose formatted this specifically, so those were updated by hand instead, along with colitur-templates(5)'s FLAVOURS section, which gained typst's own subsection alongside latex/groff/html/xml/ics/none. test/cli.t's two pinned error-text assertions are updated to match, and gained a new case: .typ inferred from extension, and a real shipped citation's hyphen surviving --flavour typst's own escaping live, the same shape the 2035 Ss. Petri et Pauli case already proves for latex's ampersand just above it. --- bin/main.ml | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'bin') diff --git a/bin/main.ml b/bin/main.ml index 0a09a63..cf6cb33 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -650,7 +650,27 @@ let extension path = fallback to [Escape.None_]: guessing the flavour wrong produces malformed output (unescaped LaTeX/HTML metacharacters) that looks fine until it does not -- the same "never silently substitute" discipline [data_dir]'s own - [COLITUR_DATA_DIR] handling documents above. *) + [COLITUR_DATA_DIR] handling documents above. + + Both error messages below list the flavours by walking [Escape.all] + rather than a hand-typed literal, on purpose: a hand-typed list is + exactly the kind of call site the design claims does not exist outside + escape.ml (spec section 5) -- adding Typst as a seventh flavour found + this one had drifted from that claim (it silently still said "the six + flavours" until then), so this is now future-proof against the same + drift the next flavour would otherwise reintroduce. *) +let flavour_names_comma () = + match List.map Colitur_render.Escape.to_string Colitur_render.Escape.all with + | [] -> "" + | [ x ] -> x + | xs -> ( + match List.rev xs with + | last :: rest -> String.concat ", " (List.rev rest) ^ " or " ^ last + | [] -> "") + +let flavour_names_bar () = + String.concat "|" (List.map Colitur_render.Escape.to_string Colitur_render.Escape.all) + let table_report ~lang ~template ~flavour_opt ~overlays y = let flavour = match flavour_opt with @@ -658,16 +678,14 @@ let table_report ~lang ~template ~flavour_opt ~overlays y = match Colitur_render.Escape.of_string name with | Some f -> f | None -> - Printf.eprintf "colitur: unknown flavour %S (want latex, groff, html, xml, ics or none)\n" - name; + Printf.eprintf "colitur: unknown flavour %S (want %s)\n" name (flavour_names_comma ()); exit 2) | None -> ( match Colitur_render.Escape.of_extension (extension template) with | Some f -> f | None -> - Printf.eprintf - "colitur: cannot infer a flavour from %S; pass --flavour latex|groff|html|xml|ics|none\n" - (extension template); + Printf.eprintf "colitur: cannot infer a flavour from %S; pass --flavour %s\n" + (extension template) (flavour_names_bar ()); exit 2) in match read_file template with @@ -1116,11 +1134,12 @@ rendering: --flavour X selects how interpolated VALUES are escaped (never the template's own literal markup, which is the author's). One of: - latex groff html xml ics none + latex typst groff html xml ics none Inferred from --template's extension when --flavour is omitted: .tex -> latex + .typ -> typst .ms .mom .me -> groff .html .htm -> html .xml -> xml @@ -1132,7 +1151,7 @@ rendering: them alone) An extension colitur does not recognise is a hard ERROR naming - the six flavours above, never a silent fallback to `none`: + the seven flavours above, never a silent fallback to `none`: guessing wrong produces output that looks fine until the metacharacters it silently failed to escape show up. @@ -1190,7 +1209,7 @@ Reading references only (e.g. "Jn 3:16"); never scripture text. See colitur(1) for the full description and the sources it computes against, colitur-overlay(5) for the overlay file format in full, colitur-templates(5) for the template format in full -- the syntax, the -remaining scope hazard, the six flavours' escaping, and the full view-model +remaining scope hazard, the seven flavours' escaping, and the full view-model field reference -- and colitur-config(5) for the config file's location and precedence in full.|} -- cgit v1.3