summaryrefslogtreecommitdiff
path: root/man
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-19 10:48:06 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-19 10:48:06 +0200
commit18c60c3d0ad273374410dcc0118d82493f90da98 (patch)
tree97e6d9d234702527a7d711e219ea8828833974e9 /man
parentbca7dabd2b436b8fe8de21736c59437b5ea990af (diff)
downloadcolitur-18c60c3d0ad273374410dcc0118d82493f90da98.tar.gz
colitur-18c60c3d0ad273374410dcc0118d82493f90da98.zip
docs(templates): fix a false claim in the worked example (F1)
The worked minimal template iterated the top-level, flat days list and claimed the naive {{name.la}} form would print the enclosing month's name there. It would not: with no {{#months}} wrapping it, the flat days list has no month anywhere on the scope stack, so the naive form on an unnamed day resolves to nothing, not to the month. Reproduced against the live engine before touching the page: the flat shape renders empty; the identical naive form nested inside {{#months}} genuinely does print the month's name on both unnamed days. The example now nests days inside months -- the shape every shipped template actually uses, and the shape the hazard needs to fire -- with a second, verified rendering showing the collision for real, and a closing note stating plainly that the flat shape does not reproduce it. SCOPE AND LOOKUP's own name-collision paragraph gained the same nesting precondition it was missing. Both rendered blocks were checked mechanically: extracted verbatim from the page source and diffed against a fresh colitur table run over the exact templates shown, byte for byte. One cosmetic fix along the way: a transition sentence embedded the full safe-idiom string inline via .B, which groff's justifier stretched into visibly wide gaps when rendered. Reworded to reference the idiom shown above instead of repeating it.
Diffstat (limited to 'man')
-rw-r--r--man/colitur-templates.5109
1 files changed, 96 insertions, 13 deletions
diff --git a/man/colitur-templates.5 b/man/colitur-templates.5
index ec883cb..a7e4992 100644
--- a/man/colitur-templates.5
+++ b/man/colitur-templates.5
@@ -149,8 +149,10 @@ carry a
.I name
field (each an object keyed by language, e.g.
.BR la " and " en ).
-Written naively, inside
-.BR {{#days}} ,
+Written naively, when
+.B {{#days}}
+is nested inside
+.BR {{#months}} ,
a bare
.B {{name.la}}
does
@@ -166,8 +168,36 @@ falls back to the outer scope, which does have one. This is not a corner
case: on an ordinary month, most days carry no Latin name at all (only named
sanctoral days do), so the naive form renders the
.I month's
-name on nearly every day \(em in a flat booklet, dozens of wrong lines; in a
-month grid, EVERY cell reads the month's own name.
+name on nearly every day \(em in a per\-month booklet, dozens of wrong
+lines; in a month grid (whose
+.B {{#weeks}}
+is itself only ever reachable through
+.BR {{#months}} ,
+since
+.I weeks
+is a field of
+.IR month ,
+never a top\-level list) EVERY cell reads the month's own name.
+.PP
+.B The collision needs a month actually on the scope stack to fire.
+Iterating the TOP\-LEVEL, flat
+.B days
+list directly (
+.B {{#days}}...{{/days}}
+at the outermost level, never passing through
+.B {{#months}}
+first) puts no month object anywhere on the stack, so the naive form does
+.I not
+silently substitute the wrong answer there \(em it silently resolves to
+nothing, exactly as any other absent key would, because there is no
+outer scope left to climb to. This is precisely what makes the hazard easy
+to miss: an author who tries the naive form against the flat list first
+sees the unnamed days come out empty, reasonably concludes the form is
+safe, and then hits the real collision the moment the identical fields are
+read from inside
+.BR {{#months}} ,
+which is what every shipped template that produces a grid or a per\-month
+booklet actually does.
.TP
.B num
Both a
@@ -630,15 +660,17 @@ an eighth, empty column and
.B pdflatex
would reject the file outright.
.SH A WORKED MINIMAL TEMPLATE
-A plain\-text booklet, one line per day, using the safe name idiom from
-.BR "SCOPE AND LOOKUP" :
+A plain\-text booklet, days nested inside months \(em the shape every
+shipped template actually uses, and the shape the
+.B SCOPE AND LOOKUP
+hazard needs to fire \(em using the safe name idiom from that section:
.RS
.nf
{{rite}} {{year}}
-{{#days}}
+{{#months}}{{#days}}
{{iso}} {{#name}}{{la}}{{^la}}{{slug}}{{/la}}{{/name}} {{colour}}{{#comms}} +{{slug}}{{/comms}}
-{{/days}}
+{{/days}}{{/months}}
.fi
.RE
.PP
@@ -672,14 +704,65 @@ supplies
instead. The third shows the non\-fallback case: 3 January
.I does
carry a Latin name (the votive Office of the Blessed Virgin Mary on
-Saturday), and the idiom prints it correctly. A template using the unsafe,
-bare
+Saturday), and the idiom prints it correctly.
+.PP
+Now swap only the interpolation \(em the safe idiom above becomes the
+naive, unsafe
+.B {{name.la}} ,
+nesting left exactly as it was:
+.RS
+.nf
+
+{{rite}} {{year}}
+{{#months}}{{#days}}
+{{iso}} {{name.la}} {{colour}}
+{{/days}}{{/months}}
+.fi
+.RE
+.PP
+Rendered against the identical year, same extension and flavour:
+.RS
+.nf
+
+.B colitur table \-\-year 2026 \-\-template minimal\-unsafe.txt | head \-7
+ef 2026
+
+2026\-01\-01 Ianuarius white
+
+2026\-01\-02 Ianuarius white
+
+2026\-01\-03 Officium sanctae Mariae in sabbato white
+.fi
+.RE
+.PP
+The collision fires for real on the first two lines: with a month on the
+scope stack, the day's own missing
+.B la
+key falls back all the way out to the ENCLOSING MONTH's own
+.RB \(lq Ianuarius \(rq
+rather than failing. The third line is untouched, because 3 January's own
+.I name
+object genuinely has a
+.B la
+key, so the dotted path resolves without ever needing to fall back.
+.PP
+.B This is specific to nesting, and that is the point.
+The identical naive
.B {{name.la}}
-form would instead have printed
+written against the TOP\-LEVEL, flat
+.B days
+list (no
+.B {{#months}}
+wrapping it) does
+.I not
+print
.RB \(lq Ianuarius \(rq
-on BOTH of those lines \(em the enclosing month's own name \(em see
+anywhere \(em there is no month on the stack to fall back to, so it prints
+nothing on an unnamed day instead, silently but not wrongly. See
.B SCOPE AND LOOKUP
-above.
+above for why testing the naive form only against a flat list is exactly
+how this hazard goes unnoticed until a template is later nested under
+.BR {{#months}} .
.SH SEE ALSO
.BR colitur (1)
for