Skip to content

Commit 6832be8

Browse files
jensmaurerzygoloid
authored andcommitted
[styles] Make page breaks before/after/inside listings configurable
Add keywords beginpenalty, endpenality, midpenalty, emptylinepenalty, semicolonpenalty. Also avoid redefining \everypar, because it interferes with section headings.
1 parent d1ba29b commit 6832be8

File tree

1 file changed

+193
-0
lines changed

1 file changed

+193
-0
lines changed

source/styles.tex

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,196 @@
149149
%% set section numbering limit, toc limit
150150
\maxsecnumdepth{subparagraph}
151151
\setcounter{tocdepth}{1}
152+
153+
%%--------------------------------------------------
154+
%% override some functions from the listings package to avoid bad page breaks
155+
%% (copied verbatim from listings.sty version 1.6 except where commented)
156+
\makeatletter
157+
\def\lst@Init#1{%
158+
\begingroup
159+
\ifx\lst@float\relax\else
160+
\edef\@tempa{\noexpand\lst@beginfloat{lstlisting}[\lst@float]}%
161+
\expandafter\@tempa
162+
\fi
163+
\ifx\lst@multicols\@empty\else
164+
\edef\lst@next{\noexpand\multicols{\lst@multicols}}
165+
\expandafter\lst@next
166+
\fi
167+
\ifhmode\ifinner \lst@boxtrue \fi\fi
168+
\lst@ifbox
169+
\lsthk@BoxUnsafe
170+
\hbox to\z@\bgroup
171+
$\if t\lst@boxpos \vtop
172+
\else \if b\lst@boxpos \vbox
173+
\else \vcenter \fi\fi
174+
\bgroup \par\noindent
175+
\else
176+
\lst@ifdisplaystyle
177+
\lst@EveryDisplay
178+
% make penalty configurable
179+
\par\lst@beginpenalty
180+
\vspace\lst@aboveskip
181+
\fi
182+
\fi
183+
\normalbaselines
184+
\abovecaptionskip\lst@abovecaption\relax
185+
\belowcaptionskip\lst@belowcaption\relax
186+
\lst@MakeCaption t%
187+
\lsthk@PreInit \lsthk@Init
188+
\lst@ifdisplaystyle
189+
\global\let\lst@ltxlabel\@empty
190+
\if@inlabel
191+
\lst@ifresetmargins
192+
\leavevmode
193+
\else
194+
\xdef\lst@ltxlabel{\the\everypar}%
195+
\lst@AddTo\lst@ltxlabel{%
196+
\global\let\lst@ltxlabel\@empty
197+
\everypar{\lsthk@EveryLine\lsthk@EveryPar}}%
198+
\fi
199+
\fi
200+
% A section heading might have set \everypar to apply a \clubpenalty
201+
% to the following paragraph, changing \everypar in the process.
202+
% Unconditionally overriding \everypar is a bad idea.
203+
% \everypar\expandafter{\lst@ltxlabel
204+
% \lsthk@EveryLine\lsthk@EveryPar}%
205+
\else
206+
\everypar{}\let\lst@NewLine\@empty
207+
\fi
208+
\lsthk@InitVars \lsthk@InitVarsBOL
209+
\lst@Let{13}\lst@MProcessListing
210+
\let\lst@Backslash#1%
211+
\lst@EnterMode{\lst@Pmode}{\lst@SelectCharTable}%
212+
\lst@InitFinalize}
213+
214+
\def\lst@DeInit{%
215+
\lst@XPrintToken \lst@EOLUpdate
216+
\global\advance\lst@newlines\m@ne
217+
\lst@ifshowlines
218+
\lst@DoNewLines
219+
\else
220+
\setbox\@tempboxa\vbox{\lst@DoNewLines}%
221+
\fi
222+
\lst@ifdisplaystyle \par\removelastskip \fi
223+
\lsthk@ExitVars\everypar{}\lsthk@DeInit\normalbaselines\normalcolor
224+
\lst@MakeCaption b%
225+
\lst@ifbox
226+
\egroup $\hss \egroup
227+
\vrule\@width\lst@maxwidth\@height\z@\@depth\z@
228+
\else
229+
\lst@ifdisplaystyle
230+
% make penalty configurable
231+
\par\lst@endpenalty
232+
\vspace\lst@belowskip
233+
\fi
234+
\fi
235+
\ifx\lst@multicols\@empty\else
236+
\def\lst@next{\global\let\@checkend\@gobble
237+
\endmulticols
238+
\global\let\@checkend\lst@@checkend}
239+
\expandafter\lst@next
240+
\fi
241+
\ifx\lst@float\relax\else
242+
\expandafter\lst@endfloat
243+
\fi
244+
\endgroup}
245+
246+
247+
\def\lst@NewLine{%
248+
\ifx\lst@OutputBox\@gobble\else
249+
\par
250+
% add configurable penalties
251+
\lst@ifeolsemicolon
252+
\lst@semicolonpenalty
253+
\lst@eolsemicolonfalse
254+
\else
255+
\lst@domidpenalty
256+
\fi
257+
% Manually apply EveryLine and EveryPar; do not depend on \everypar
258+
\noindent \hbox{}\lsthk@EveryLine%
259+
% \lsthk@EveryPar uses \refstepcounter which balloons the PDF
260+
\fi
261+
\global\advance\lst@newlines\m@ne
262+
\lst@newlinetrue}
263+
264+
% new macro for empty lines, avoiding an \hbox that cannot be discarded
265+
\def\lst@DoEmptyLine{%
266+
\ifvmode\else\par\fi\lst@emptylinepenalty
267+
\vskip\parskip
268+
\vskip\baselineskip
269+
% \lsthk@EveryLine has \lst@parshape, i.e. \parshape, which causes an \hbox
270+
% \lsthk@EveryPar increments line counters; \refstepcounter balloons the PDF
271+
\global\advance\lst@newlines\m@ne
272+
\lst@newlinetrue}
273+
274+
\def\lst@DoNewLines{
275+
\@whilenum\lst@newlines>\lst@maxempty \do
276+
{\lst@ifpreservenumber
277+
\lsthk@OnEmptyLine
278+
\global\advance\c@lstnumber\lst@advancelstnum
279+
\fi
280+
\global\advance\lst@newlines\m@ne}%
281+
\@whilenum \lst@newlines>\@ne \do
282+
% special-case empty printing of lines
283+
{\lsthk@OnEmptyLine\lst@DoEmptyLine}%
284+
\ifnum\lst@newlines>\z@ \lst@NewLine \fi}
285+
286+
% add keys for configuring before/end vertical penalties
287+
\lst@Key{beginpenalty}\relax{\def\lst@beginpenalty{\penalty #1}}
288+
\let\lst@beginpenalty\@empty
289+
\lst@Key{midpenalty}\relax{\def\lst@midpenalty{\penalty #1}}
290+
\let\lst@midpenalty\@empty
291+
\lst@Key{endpenalty}\relax{\def\lst@endpenalty{\penalty #1}}
292+
\let\lst@endpenalty\@empty
293+
\lst@Key{emptylinepenalty}\relax{\def\lst@emptylinepenalty{\penalty #1}}
294+
\let\lst@emptylinepenalty\@empty
295+
\lst@Key{semicolonpenalty}\relax{\def\lst@semicolonpenalty{\penalty #1}}
296+
\let\lst@semicolonpenalty\@empty
297+
298+
\lst@AddToHook{InitVars}{\let\lst@domidpenalty\@empty}
299+
\lst@AddToHook{InitVarsEOL}{\let\lst@domidpenalty\lst@midpenalty}
300+
301+
% handle semicolons and closing braces (could be in \lstdefinelanguage as well)
302+
\def\lst@eolsemicolontrue{\global\let\lst@ifeolsemicolon\iftrue}
303+
\def\lst@eolsemicolonfalse{\global\let\lst@ifeolsemicolon\iffalse}
304+
\lst@AddToHook{InitVars}{
305+
\global\let\lst@eolsemicolonpending\@empty
306+
\lst@eolsemicolonfalse
307+
}
308+
% If we found a semicolon or closing brace while parsing the current line,
309+
% inform the subsequent \lst@NewLine about it for penalties.
310+
\lst@AddToHook{InitVarsEOL}{%
311+
\ifx\lst@eolsemicolonpending\relax
312+
\lst@eolsemicolontrue
313+
\global\let\lst@eolsemicolonpending\@empty
314+
\fi%
315+
}
316+
\lst@AddToHook{SelectCharTable}{%
317+
% In theory, we should only detect trailing semicolons or braces,
318+
% but that would require un-doing the marking for any other character.
319+
% The next best thing is to undo the marking for closing parentheses,
320+
% because loops or if statements are the only places where we will
321+
% reasonably have a semicolon in the middle of a line, and those all
322+
% end with a closing parenthesis.
323+
\lst@DefSaveDef{41}\lstsaved@closeparen{% handle closing parenthesis
324+
\lstsaved@closeparen
325+
\ifnum\lst@mode=\lst@Pmode % regular processing mode (not a comment)
326+
\global\let\lst@eolsemicolonpending\@empty % undo semicolon setting
327+
\fi%
328+
}%
329+
\lst@DefSaveDef{59}\lstsaved@semicolon{% handle semicolon
330+
\lstsaved@semicolon
331+
\ifnum\lst@mode=\lst@Pmode % regular processing mode (not a comment)
332+
\global\let\lst@eolsemicolonpending\relax
333+
\fi%
334+
}%
335+
\lst@DefSaveDef{125}\lstsaved@closebrace{% handle closing brace
336+
\lst@eolsemicolonfalse % do not break before a closing brace
337+
\lstsaved@closebrace % might invoke \lst@NewLine
338+
\ifnum\lst@mode=\lst@Pmode % regular processing mode (not a comment)
339+
\global\let\lst@eolsemicolonpending\relax
340+
\fi%
341+
}%
342+
}
343+
344+
\makeatother

0 commit comments

Comments
 (0)