diff options
Diffstat (limited to 'test/cli.t')
| -rw-r--r-- | test/cli.t | 252 |
1 files changed, 226 insertions, 26 deletions
@@ -17,7 +17,7 @@ A year outside the supported domain is rejected (exit 2): No/garbage arguments give a usage error (exit 2): $ colitur - colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur check FILE | colitur new-overlay (try: colitur --help) + colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | colitur new-overlay (try: colitur --help) [2] The EF temporal cycle for a year, one line per day: @@ -53,20 +53,20 @@ Easter is the observed day exactly once, and carries no commemoration (an impeded I class day admits at most one PRIVILEGED commemoration, RG 111, and nothing outranks Easter to be impeded by it in the first place): - $ colitur day 2026 | grep -c '^2026-04-05 ' + $ colitur day 2026 --raw | grep -c '^2026-04-05 ' 1 - $ colitur day 2026 | grep '^2026-04-05 ' + $ colitur day 2026 --raw | grep '^2026-04-05 ' 2026-04-05 sunday paschaltide 1 ef-easter-sunday class-1 white Ash Wednesday: I class (RG 91 entry 7), violet, no numbered week (it falls 4 days before Lent I's own origin -- rite_ef/temporal_ef.ml's [week]): - $ colitur day 2026 | grep '^2026-02-18 ' + $ colitur day 2026 --raw | grep '^2026-02-18 ' 2026-02-18 wednesday lent - ef-ash-wednesday class-1 violet Christmas: I class, white (RG 91 entry 1): - $ colitur day 2026 | grep '^2026-12-25 ' + $ colitur day 2026 --raw | grep '^2026-12-25 ' 2026-12-25 friday christmastide - ef-nativity class-1 white All Souls (2 Nov, RG 91 entry 8) end to end: 2 Nov 2025 is a Sunday (verified @@ -77,11 +77,11 @@ itself is not re-asserted here, already covered by test_temporal_ef.ml); RG 95 then transfers All Souls (I class, not a Sunday, not a vigil) and RG 96 places it on 3 Nov, the next day that is not I or II class: - $ colitur day 2025 | grep -c 'commemoration-of-all-souls' + $ colitur day 2025 --raw | grep -c 'commemoration-of-all-souls' 1 - $ colitur day 2025 | grep '^2025-11-02 ' | sed -E 's/ [0-9]+ ef-time-after-pentecost-sunday-[0-9]+ / <week> ef-time-after-pentecost-sunday-<n> /' + $ colitur day 2025 --raw | grep '^2025-11-02 ' | sed -E 's/ [0-9]+ ef-time-after-pentecost-sunday-[0-9]+ / <week> ef-time-after-pentecost-sunday-<n> /' 2025-11-02 sunday time-after-pentecost <week> ef-time-after-pentecost-sunday-<n> class-2 green - $ colitur day 2025 | grep '^2025-11-03 ' + $ colitur day 2025 --raw | grep '^2025-11-03 ' 2025-11-03 monday time-after-pentecost 21 commemoration-of-all-souls class-1 black (week 21: Pentecost 2025 is 8 June (colitur easter 2025); 8 Jun - 3 Nov is @@ -93,9 +93,9 @@ All Souls observed directly on 2 Nov in a year where it does not fall on a Sunday: 2 Nov 2026 is a Monday (1 Jan 2026 is a Thursday, same day-of-year 306 offset, (4+305) mod 7 = 1 = Monday): - $ colitur day 2026 | grep -c 'commemoration-of-all-souls' + $ colitur day 2026 --raw | grep -c 'commemoration-of-all-souls' 1 - $ colitur day 2026 | grep '^2026-11-02 ' + $ colitur day 2026 --raw | grep '^2026-11-02 ' 2026-11-02 monday time-after-pentecost 23 commemoration-of-all-souls class-1 black (week 23: Pentecost 2026 is 24 May (colitur easter 2026); 24 May - 2 Nov is @@ -109,9 +109,9 @@ RG 96 target -- not the Monday after Low Sunday -- is what governs, since the general walk never crosses Easter. Before this fix the unconditional reading sent it to 30 April (Easter + 8) instead: - $ colitur day 2057 | grep '^2057-03-26 ' + $ colitur day 2057 --raw | grep '^2057-03-26 ' 2057-03-26 monday lent 3 annunciation-of-the-blessed-virgin-mary class-1 white +ef-lent-3-monday - $ colitur day 2057 | grep -c 'annunciation-of-the-blessed-virgin-mary' + $ colitur day 2057 --raw | grep -c 'annunciation-of-the-blessed-virgin-mary' 1 A year outside the supported domain is rejected (exit 2): @@ -138,7 +138,7 @@ sabbato", assigned to Christmas through the Purification (RG 309(a)). It is NOT the Christmastide feria's Mass, which is what colitur said before that rule was implemented. - $ colitur readings 2026 | head -3 + $ colitur readings 2026 --raw | head -3 2026-01-01 ef-circumcision | Titus 2:11-15 | Luke 2:21 2026-01-02 ef-christmas-1-friday | Titus 2:11-15 | Luke 2:21 2026-01-03 ef-christmas-1-saturday | Titus 3:4-7 | Luke 2:15-20 @@ -160,16 +160,16 @@ test_golden.ml pins against the photographic scans (each literal there was read out of the Missal before being compared with colitur -- these assert that the CLI path agrees with the library path, nothing more): - $ colitur readings 2038 | grep '^2038-03-08 ' + $ colitur readings 2038 --raw | grep '^2038-03-08 ' 2038-03-08 john-of-god | Ecclus 31:8-11 | Matt 22:34-46 - $ colitur readings 2026 | grep '^2026-02-23 ' + $ colitur readings 2026 --raw | grep '^2026-02-23 ' 2026-02-23 ef-lent-1-monday | Ezech 34:11-16 | Matt 25:31-46 - $ colitur readings 2025 | grep '^2025-12-01 ' + $ colitur readings 2025 --raw | grep '^2025-12-01 ' 2025-12-01 ef-advent-1-monday | Rom 13:11-14 | Luke 21:25-33 - $ colitur readings 2038 | grep '^2038-03-06 ' + $ colitur readings 2038 --raw | grep '^2038-03-06 ' 2038-03-06 sts-felicitas-perpetua | Ecclus 51:1-8, 12 | Matt 13:44-52 The Advent line above is the ferial resumption (chain step 3) and is the one @@ -190,7 +190,7 @@ rather than the guarantee itself: `colitur day`'s own format is unaffected by any of the above: - $ colitur day 2026 | head -1 + $ colitur day 2026 --raw | head -1 2026-01-01 thursday christmastide - ef-circumcision class-1 white A year outside the supported domain is rejected (exit 2): @@ -280,14 +280,14 @@ four while appearing merely to add a local feast. A fixed-date local patron, observed on its own day: - $ colitur day 2026 --overlay fixtures/overlay-example-diocesan.sexp | grep '^2026-07-11 ' + $ colitur day 2026 --overlay fixtures/overlay-example-diocesan.sexp --raw | grep '^2026-07-11 ' 2026-07-11 saturday time-after-pentecost 6 example-local-patron class-3 white +pius-i A MOVABLE one -- the capability the Date_spec work existed to unlock. "The first Sunday of October" is the shape a patronal or dedication feast usually takes, and it lands on a different civil date every year: - $ for y in 2026 2027 2028; do colitur day $y --overlay fixtures/overlay-example-diocesan.sexp | grep 'example-dedication'; done + $ for y in 2026 2027 2028; do colitur day $y --overlay fixtures/overlay-example-diocesan.sexp --raw | grep 'example-dedication'; done 2026-10-04 sunday time-after-pentecost 19 example-dedication class-1 white +ef-time-after-pentecost-sunday-19 2027-10-03 sunday time-after-pentecost 20 example-dedication class-1 white +ef-time-after-pentecost-sunday-20 2028-10-01 sunday time-after-pentecost 17 example-dedication class-1 white +ef-time-after-pentecost-sunday-17 @@ -295,7 +295,7 @@ takes, and it lands on a different civil date every year: The shipped calendar is untouched without the flag -- the same date, no local feast, the ordinary Sunday restored: - $ colitur day 2026 | grep '^2026-10-04 ' + $ colitur day 2026 --raw | grep '^2026-10-04 ' 2026-10-04 sunday time-after-pentecost 19 ef-time-after-pentecost-sunday-19 class-2 green And the shipped overlay's own entries survive alongside the user's, which is @@ -327,14 +327,14 @@ A flag needing a value, given none: $ colitur day 2026 --overlay colitur: --overlay needs a file path - colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur check FILE | colitur new-overlay (try: colitur --help) + colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | colitur new-overlay (try: colitur --help) [2] An unknown option is rejected rather than treated as a positional word: $ colitur day 2026 --diocese colitur: unknown option --diocese - colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur check FILE | colitur new-overlay (try: colitur --help) + colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | colitur new-overlay (try: colitur --help) [2] The shipped example overlay is runnable documentation, and it must actually @@ -383,7 +383,7 @@ own output before emitting it. The full pipeline, INI to a resolved day: p.sexp: ok -- overlay my-parish, 1 directive(s): 1 add, 0 suppress, 0 replace, 0 edit every directive found its target add our-patron - $ colitur day 2026 --overlay p.sexp | grep '^2026-07-11' + $ colitur day 2026 --overlay p.sexp --raw | grep '^2026-07-11' 2026-07-11 saturday time-after-pentecost 6 our-patron class-3 white +pius-i What the INI form cannot express is refused by name, not dropped silently: @@ -413,7 +413,7 @@ An overlay feast competes under the ordinary rules: the Benedictine Transitus is I class and takes 21 March, with the Lenten feria commemorated rather than displaced silently. - $ colitur day 2026 --overlay ben.sexp | grep '^2026-03-21' + $ colitur day 2026 --overlay ben.sexp --raw | grep '^2026-03-21' 2026-03-21 saturday lent 4 transitus-of-our-holy-father-benedict class-1 white +ef-lent-4-saturday CSV emits a header and one row per day: @@ -501,12 +501,90 @@ silently ignored, the same discipline --overlay already gets: day and readings are untouched: - $ colitur day 2027 | head -1 + $ colitur day 2027 --raw | head -1 2027-01-01 friday christmastide - ef-circumcision class-1 white + $ colitur readings 2027 --raw | head -1 + 2027-01-01 ef-circumcision | Titus 2:11-15 | Luke 2:21 + +Names are Latin by default (Task 6): `day` gains a trailing display name and +`readings` a trailing " | name" field, appended rather than substituted into +the slug's own position -- a name contains spaces, and inserting it there +would break every fixed-position field after it for anyone parsing this row +by column, the same reason `readings` is a separate command in the first +place. 1 January 2027 is the Circumcision, kept within the Nativity octave: + + $ colitur day 2027 | head -2 + 2027-01-01 friday christmastide - ef-circumcision class-1 white In Octava Nativitatis Domini + 2027-01-02 saturday christmastide - ef-christmas-1-saturday class-4 white Officium sanctae Mariae in sabbato + $ colitur readings 2027 | head -1 + 2027-01-01 ef-circumcision | Titus 2:11-15 | Luke 2:21 | In Octava Nativitatis Domini + +--raw restores the old byte-exact output -- no trailing field at all, not +merely an empty one, because [Lang.raw] is the identity table (lang.mli): +the resolved name equals the slug already printed, so day_line/readings_line +omit the field entirely rather than repeat the slug a second time. This is +not a special case keyed on --raw itself; it is a direct consequence of the +identity table, verified against the pre-branch binary in the task report +rather than merely asserted: + + $ colitur day 2027 --raw | head -1 + 2027-01-01 friday christmastide - ef-circumcision class-1 white + + $ colitur readings 2027 --raw | head -1 2027-01-01 ef-circumcision | Titus 2:11-15 | Luke 2:21 +A language file by path (--lang accepts a bare code OR a file path -- a +value containing '/' or ending ".ini" is read literally rather than looked +up in the installed language directory). The synthetic file below declares +`fallback = la`, so every slug it does not name itself still resolves +through the chain to la.ini's real name, and only the one it DOES name +shows the override: + + $ printf '[meta]\nlang = xx\nfallback = la\n[celebration]\nef-circumcision = TEST FEAST\n' > lang-xx.ini + $ colitur day 2027 --lang ./lang-xx.ini | head -1 + 2027-01-01 friday christmastide - ef-circumcision class-1 white TEST FEAST + +An unknown language is a usage error naming what is available, never a +silent fallback to Latin: a booklet quietly printed in the wrong language is +worse than one that refuses to print. The exact "(looked in ...)" path is +not pinned here -- it names the cram sandbox's own build tree, the same +reason the data-directory fallback test above is not reproduced literally +either: + + $ colitur day 2027 --lang nonexistent 2>&1 | grep -c 'no language "nonexistent"' + 1 + $ colitur day 2027 --lang nonexistent >/dev/null 2>&1; echo "exit=$?" + exit=2 + +A malformed language file is an error, not a crash: + + $ printf '[celebration\nbroken' > bad-lang.ini + $ colitur day 2027 --lang ./bad-lang.ini + colitur: ./bad-lang.ini: line 1: "[celebration" looks like a section header but does not end with ']' + [2] + +--lang/--raw have no effect on a command that reads no display names at +all, refused rather than silently ignored, the same discipline --overlay +already gets: + + $ colitur easter 2026 --lang la + colitur: --lang/--raw have no effect on `easter`; refusing rather than ignoring them + [2] + + $ colitur temporal 2026 --raw + colitur: --lang/--raw have no effect on `temporal`; refusing rather than ignoring them + [2] + +The ICS SUMMARY line is localised too (found while reviewing the published +site: it used to read the kernel's own unlocalised "(class-1, white)" where +the JSON beside it already said "II classis"/"albus" -- emit_ics.ml was +reading the wrong pair of view fields): + + $ colitur emit --format ics --from 2027 --to 2027 | grep '^SUMMARY' | head -1 + SUMMARY:In Octava Nativitatis Domini (I classis\, albus) + A minimal inline template renders -- table computes and renders in one process (2 January 2027 is a Saturday, not a Sunday, so Holy Name Sunday falls on the 3rd, not the 2nd, that year): @@ -1098,3 +1176,125 @@ over-broad: it still prunes normally when stale. $ test -d /tmp/pub-sec/ef/2028 || echo pruned-2028 pruned-2028 + +`colitur lang` and `colitur config` (Task 7) -- what makes "anyone can write +a language file" true rather than merely permitted, the same idea the +overlay system already established with `new-overlay` and `check`. + +`--list` shows what language files this build can find: + + $ colitur lang --list + en (falls back to la) + la + +`--dump CODE` scaffolds a complete file on stdout, sections in a fixed order +so two dumps of the same table are byte-identical: + + $ colitur lang --dump la > d.ini + $ head -4 d.ini + [meta] + lang = la + + [celebration] + $ grep -c '^ef-epiphany ' d.ini + 1 + +A dump round-trips -- it just IS la.ini's own content, so it covers every +slug the engine can produce over 2020-2045: + + $ colitur lang --check d.ini + d.ini: 725 of 725 celebrations named, 0 missing, 0 unknown + +`--check` reports what is MISSING (a real slug with no entry): + + $ printf '[meta]\nlang = zz\n[celebration]\nef-epiphany = Test\n' > partial.ini + $ colitur lang --check partial.ini | tail -1 + partial.ini: 1 of 725 celebrations named, 724 missing, 0 unknown + +`--check` REJECTS an unknown slug (exit 1), so a typo is visible rather than +silently dead -- its author would otherwise never learn why the name they +wrote never appears: + + $ printf '[meta]\nlang = zz\n[celebration]\nnot-a-real-slug = X\n' > typo.ini + $ colitur lang --check typo.ini | grep 'unknown slug' + unknown slug: not-a-real-slug + $ colitur lang --check typo.ini >/dev/null 2>&1; echo "exit=$?" + exit=1 + +`lang` requires exactly one of --list/--dump/--check: + + $ colitur lang + colitur: lang requires one of --list, --dump CODE or --check FILE + [2] + + $ colitur lang --list --dump la + colitur: lang takes only one of --list, --dump CODE or --check FILE + [2] + +`--dump`/`--check`/`--list`/`--show` have no effect on any other command, +refused rather than silently ignored, the same discipline --overlay/--lang +already get: + + $ colitur day 2027 --dump la + colitur: --dump/--check/--list/--show have no effect on `day`; refusing rather than ignoring them + [2] + +`config --show` reports each effective setting, its resolved value, and +where it came from -- flag, config or default -- via Config.resolve; there +is deliberately no separate provenance function. Run through an isolated +XDG_CONFIG_HOME so this does not depend on whatever the person running the +suite happens to have in their own home directory (the same reason the +data-directory fallback case earlier in this file is not reproduced +literally either): + + $ XDG_CONFIG_HOME=xdg-test colitur config --show + config file: xdg-test/colitur/config.ini (not found) + lang la (default) + template (none) (default) + format (none) (default) + overlay (none) (default) + +A flag on the SAME command line previews exactly what it would resolve to +on any other command -- `overlay` has no single scalar value, so it is +listed one line per effective entry instead: + + $ XDG_CONFIG_HOME=xdg-test colitur config --show --lang fr --overlay mine.sexp + config file: xdg-test/colitur/config.ini (not found) + lang fr (flag) + template (none) (default) + format (none) (default) + overlay mine.sexp (flag) + +A real config file supplies a default that a command with no explicit flag +then uses. An unrecognised key and an unrecognised section are each warned +about and ignored, never silently dropped and never fatal on their own -- +two separate warnings, so a misspelled section (`[deafults]`) reads +differently from a misspelled key inside a recognised one: + + $ mkdir -p xdg-test/colitur + $ printf '[defaults]\nlang = en\noverlay = /nonexistent/parish.sexp\nbogus = 1\n\n[deafults]\nlang = xx\n' > xdg-test/colitur/config.ini + $ XDG_CONFIG_HOME=xdg-test colitur config --show + config file: xdg-test/colitur/config.ini (exists) + lang en (config) + template (none) (default) + format (none) (default) + overlay /nonexistent/parish.sexp (config) + colitur: xdg-test/colitur/config.ini: unknown setting "bogus" (ignored) + colitur: xdg-test/colitur/config.ini: unknown section [deafults] (ignored) + +`config` requires --show: + + $ colitur config + colitur: config requires --show + [2] + +A config file that EXISTS but fails to parse is fatal -- a config the user +wrote and colitur cannot honour is not something to carry on past silently +-- and this is true for every command, not only `config` itself, because +the file is loaded once, unconditionally, before dispatch: + + $ mkdir -p xdg-bad/colitur + $ printf '[defaults\nbroken' > xdg-bad/colitur/config.ini + $ XDG_CONFIG_HOME=xdg-bad colitur day 2027 --raw + colitur: xdg-bad/colitur/config.ini: line 1: "[defaults" looks like a section header but does not end with ']' + [2] |
