diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-21 12:09:35 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-21 12:09:35 +0200 |
| commit | aaf3dc5ba55d46b6b318bb761305013f4c533b26 (patch) | |
| tree | 7b60e382a93a496330c8c925494a261ec42591d1 /bin | |
| parent | 83cc11e31c08d14fd3449f95872f346a4daaf2b8 (diff) | |
| download | colitur-aaf3dc5ba55d46b6b318bb761305013f4c533b26.tar.gz colitur-aaf3dc5ba55d46b6b318bb761305013f4c533b26.zip | |
fix(cli): diagnose an INI overlay passed to --overlay
The INI overlay form is a SOURCE format that 'colitur convert' turns into
the S-expression one. Handing the INI to --overlay instead failed deep in
the sexp reader with 'more than one S-expression in file', which names
neither the cause nor the cure -- and the shipped examples under
data/ef/examples/ are exactly the files someone would try that with.
The detector reads past the comment header to the first real line and
looks for a [section]. Its first version capped that scan at 40 lines and
poland.ini's own header is 43, so it silently never fired on the very
file it was written for; the cap now bounds only how much of a binary
gets read, and is not a guess at header length.
Diffstat (limited to 'bin')
| -rw-r--r-- | bin/main.ml | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/bin/main.ml b/bin/main.ml index 51c4989..c915255 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -169,8 +169,42 @@ let load_ef_layer ?(user_overlays = []) () = let dir = data_dir () in let sanctoral_path = Filename.concat dir "sanctoral.sexp" in let adjustments_path = Filename.concat dir "adjustments.sexp" in + (* An overlay handed to --overlay must be the S-expression form. The INI + form is real but is a SOURCE format: `colitur convert` turns it into one. + Feeding the INI here otherwise fails deep inside the sexp reader with + "more than one S-expression in file", which names neither the cause nor + the cure. Detect it and say both. *) + let looks_like_ini path = + match open_in path with + | exception _ -> false + | ic -> + (* Skip the comment header and stop at the first real line. The cap + only bounds how much of a binary file gets read; it is NOT a guess + at how long a header may be. The first version capped at 40 and + poland.ini's own header is 43 lines, so the detection silently + never fired on the very file it was written for. *) + let rec scan n = + if n > 2000 then false + else + match input_line ic with + | exception End_of_file -> false + | line -> + let l = String.trim line in + if l = "" || l.[0] = ';' || l.[0] = '#' then scan (n + 1) + else String.length l > 1 && l.[0] = '[' && l.[String.length l - 1] = ']' + in + let r = scan 0 in + close_in_noerr ic; + r + in let load_overlay path = match Colitur_kernel.Overlay.load Rite_ef.Vocab_ef.rank_of_sexp path with + | Error _ when looks_like_ini path -> + Error + (Printf.sprintf + "%s looks like an INI overlay, not an S-expression one.\n\ + colitur: convert it first: colitur convert %s > overlay.sexp" + path path) | Error e -> Error (Printf.sprintf "failed to load %s: %s" path e) | Ok o -> Ok o in |
