Skip to content

[macros] Avoid page break between example and codeblock introducers #4237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions source/macros.tex
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@
\newcommand{\leftshift}[1]{\ensuremath{\mathbin{\mathsf{lshift}_{#1}}}}

%% Notes and examples
\newcommand{\noteintro}[1]{[\textit{#1}:}
\newcommand{\noteintro}[1]{[\textit{#1}: }
\newcommand{\noteoutro}[1]{\textit{\,---\,#1}\kern.5pt]}

% \newnoteenvironment{ENVIRON}{BEGIN TEXT}{END TEXT}
Expand All @@ -292,7 +292,7 @@
\newcommand{\newnoteenvironment}[3]{
\newsubclausecounter{#1}
\newenvironment{tail#1}
{\par\small\stepcounter{#1}\noteintro{#2}}
{\par\small\stepcounter{#1}\noteintro{#2}\hbox to 0pt{}\ignorespaces}
{\noteoutro{#3}}
\newenvironment{#1}
{\begin{tail#1}}
Expand Down Expand Up @@ -497,7 +497,12 @@
% Our usual abbreviation for 'listings'. Comments are in
% italics. Arbitrary TeX commands can be used if they're
% surrounded by @ signs.
\newcommand{\CodeBlockSetup}{%
\def\codeblockbeginpenalty{-1} % default: no penalty change before codeblock
\newcommand{\CodeBlockSetup}{
\ifnum\codeblockbeginpenalty=-1
\else
\presetkeys{lst}{beginpenalty=\codeblockbeginpenalty}{}%
\fi
\lstset{escapechar=@, aboveskip=\parskip, belowskip=0pt,
midpenalty=500, endpenalty=-50,
emptylinepenalty=-250, semicolonpenalty=0}%
Expand All @@ -508,8 +513,27 @@

\lstnewenvironment{codeblock}{\CodeBlockSetup}{}

% Left-align listings titles
\makeatletter

\newsavebox\@signalbox

% Redefine \begin{codeblock} to look for an immediately-preceding
% \begin{example}.
Comment on lines +520 to +521
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of redefining it, can we rename the listing environment and define our codeblock environment in terms of the listings environment? Or is that not possible due to the way that listings monkeys with the input stream?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what you mean. We already have \lstnewenvironment{codeblock}{\CodeBlockSetup}{}, above.
The problem is that I can't put the "detect marker" code into \CodeBlockSetup, because that's too late and I can't get at the preceding box anymore. In order to get control earlier, I'm redefining the codeblock environment to get an earlier grab.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm asking is whether we can instead use (say) \lstnewenvironment{codeblockimpl}.... and then define a new codeblock environment in terms of codeblockimpl. Modifying an existing environment like this, rather than composing this environment out of the existing one, is a hack that we should avoid if we can. (Maybe we can't; so be it.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried this:

\newenvironment{codeblock}
{%
  \ifhmode%                             no last box in vertical mode
    \setbox\@signalbox=\lastbox%        grab and consume last box
    \copy\@signalbox%                   typeset the last box again
    \ifhbox\@signalbox%
      \ifdim\wd\@signalbox=0pt%         zero-width box is our marker
        \def\codeblockbeginpenalty{100}%
      \fi%
    \fi%
  \fi%
\begin{codeblockimpl}}
{\end{codeblockimpl}}

Result:

! Extra }, or forgotten \endgroup.
\egroup

l.228 ...( ) < > % : ; . ? * + - / ^ & | ~ ! = , @
\textbackslash@ " '

So, the environment nesting appears to negatively impact @ recognition. No idea why.

\global\@namedef{codeblock}{%
\def\lstenv@name {codeblock}\begingroup%
\ifhmode% no last box in vertical mode
\setbox\@signalbox=\lastbox% grab and consume last box
\copy\@signalbox% typeset the last box again
\ifhbox\@signalbox%
\ifdim\wd\@signalbox=0pt% zero-width box is our marker
\def\codeblockbeginpenalty{100}%
\fi%
\fi%
\fi%
\lst@setcatcodes \catcode \active=\active \csname codeblock@\endcsname%
}

% Left-align listings titles
\def\lst@maketitle{\@makeleftcaption\lst@title@dropdelim}
\long\def\@makeleftcaption#1#2{%
\vskip\abovecaptionskip
Expand Down