I use only lualatex, but perhaps this is a general LaTeX question.
Assume that TeXlive 2023 or later is used, since there is no need
for backwards compatibility.
I have looked at atbegshi and some other docs, but they do not do what I need,
or are much more complex than necessary. I also see that, not too long ago,
someone asked a similar question, but without a useful answer:
Use shipout hooks to manipulate global state
Situation: I have two commands, which I will call \foo and \unfoo.
The \foo command includes \clearpage at its top, so I do not need to
worry about where \foo appears when typeset. The \unfoo command
finishes with \clearpage.
If a page has \foo, then the same page must have \unfoo. If the user fails
to write \unfoo before the \foo page ships, it is an error. I know how to
write a suitable error message, halting compile. I do not need to store, edit,
discard, or otherwise manipulate the page contents.
My question: Is there a simple way to use the \shipout hook
(or something similar) to do this? Although atbegshi looks like it should
be capable, there is a lot going on with that package, which makes me nervous.
MWE:
\documentclass{article} % Compile with lualatex.
\usepackage{fontspec}
\newif\ifusedfoo
\def\foo{\clearpage Hello.\par\usedfootrue}
\def\unfoo{Goodbye.\par\usedfoofalse\clearpage}
% \WhenPageShips{ % This is what I need. I know how to create an error, instead of typeout.
% \ifusedfoo
% \typeout{EEEEK. The page with \string\foo\space did not have \string\unfoo.}
% \fi
% }
\begin{document}
Welcome.\par
\foo
No problem here.\par
\unfoo
\foo % With too many lines on that page, causes problem:
x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\
x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\
x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\
x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\par
% Whether or not there is a later \unfoo, does not matter.
Moving right along\par
\clearpage
This is too late.\par
\unfoo
I cannot wait until this far in the document.\par
\end{document}
Also: I do not wish to use an aux file for this. The code does not appear within anything complicated (such as bibliography, table of contents, etc.). Just within running text.
EDIT: Made it clear that the problem should be detected quickly, not later in the document.
EDIT2: The accepted solution works in my specific situation but may not work in the general situation. See comments.
\setmainfont{Latin Modern Roman}is unnecessary. The default font withlualatexandxelatexis LM only. You can remove that line safely without any changes in the output. – Niranjan Feb 08 '24 at 04:18\setmainfont, you don't really need\usepackage{fontspec}too... ;-) – Niranjan Feb 08 '24 at 04:39shipout-mechanisms, but you may want to go throughltshipout-doc.pdf. – Niranjan Feb 08 '24 at 04:44texdoc source2e, readltmarksandltshipout(assume you're proficient enough) // possibly related: https://tex.stackexchange.com/questions/18849/how-do-i-check-whether-the-text-will-fit-in-one-page – user202729 Feb 08 '24 at 06:21lthooks-docbeforeltshipout-docunless you're already familiar with the hooks stuff. See page 7 ofltshipout-doc: if you loadatbegshiwith current LaTeX, you're loading an emulation (atbegshi-ltx.sty), but it's recommended to use the hooks directly in new code. – cfr Feb 08 '24 at 07:26ltshipout-docfor instructional purposes. – rallg Feb 08 '24 at 15:41\foo...\unfoois because the actual command (not foo) is similar to a LaTeX command that does something else. This is a way to trap the situation where users write the wrong command. – rallg Feb 08 '24 at 21:50\unfoois defined do do\parbefore\usedfoofalsewithout that it wouldn't work at all, so as long as your real document commands have that then you may be ok with this. – David Carlisle Feb 08 '24 at 22:21\paris automatically inserted, if it is in horizontal mode there. – rallg Feb 08 '24 at 22:40\fooand\unfooin the same paragraph with a page break between but with the specific definitions here that way is excluded, – David Carlisle Feb 08 '24 at 22:52