我如何惩罚代码清单中的孤立括号?

我如何惩罚代码清单中的孤立括号?

我想防止代码列表和tcolorbox分页符,并在下一页上仅放置一个括号。请参阅图片中的示例。

在此处输入图片描述

分页符本身对于大型列表来说没问题,但我认为如果 TeX 优化间距,那么我可以在同一页上获得右括号。更改边距大小会影响所有列表(并可能导致其他孤立括号),所以我真的不想这样做。我不确定是否有设置lstlisting可以tcolorbox让我这样做。

答案1

使用 TeX 通常可以很容易地防止某些事情发生后发生中断,但防止中断有些事情通常是不可能的。在这里,我们可以挂接到listings处理命令中,在结束当前行之前检查下一行,这样\penalty如果下一行包含结束括号,我们就可以插入一个。

警告:这填充使用肮脏的伎俩,所以如果未来的更新或“有趣”的输入以某种方式破坏它,我不会感到惊讶。

\documentclass{article}

\usepackage[paperheight=2.2in, paperwidth=6in, showframe]{geometry}

\usepackage{listings}
\lstset{language=Java}

\ExplSyntaxOn\makeatletter
% Define some constant tokens for later comparisons
\tl_new:N \c__max_end_env_tl
\regex_replace_all:nnN { } {
    \cA(\\ end \{ lstlisting \})
} \c__max_end_env_tl

\tl_new:N \c__max_close_brace_tl
\regex_replace_all:nnN { } {
    \cA(\})
} \c__max_close_brace_tl

% Inside an lstlisting environment, at the end of each line, we grab the next
% line and process it.
\def\lst@InitFinalize{
    \__max_make_newline:n {
        \__max_process:n { ##1 }
        \tl_if_eq:NnT \c__max_end_env_tl { ##1 } {
            \__max_reset_newline:
        }
        \lst@MProcessListing ##1 ##2
    }
}

% Process the line. Here, we insert an infinite penalty if the next line
% contains a closing brace.
\newif\ifpreventbreakbeforebrace
\cs_new:Nn \__max_process:n {
    \ifpreventbreakbeforebrace
        \tl_if_in:nVTF { #1 } \c__max_close_brace_tl {
            \hook_gput_next_code:nn { para / after } {
                \penalty20000
            }
        }
    \fi
}

% Auxiliary macros.
\cs_new:Nn \__max_make_newline:n {
    \exp_args:NNo \exp_args:No
        \__max_make_newline_aux_i:nn
        { \char_generate:nn { 13 } { 13 } }
        { #1 }
}

\cs_new:Nn \__max_make_newline_aux_i:nn {
    \cs_set:Nn \__max_make_newline_aux_ii:nn { #2 } { #1 }
    \cs_set:Npn #1 ##1 #1 {
        \__max_make_newline_aux_ii:nn { ##1 } { #1 }
    }
}

\cs_new:Nn \__max_reset_newline: {
    \char_set_active_eq:nN { 13 } \scan_stop:
}
\makeatother\ExplSyntaxOff

\begin{document}

\preventbreakbeforebracefalse
\begin{lstlisting}
public static void main(String[] args) {
    System.out.println("Hello, world!");
}
public static void main(String[] args) {
    System.out.println("Hello, world!");
}
public static void main(String[] args) {
    System.out.println("Hello, world!");
}
\end{lstlisting}
\clearpage

\preventbreakbeforebracetrue
\begin{lstlisting}
public static void main(String[] args) {
    System.out.println("Hello, world!");
}
public static void main(String[] args) {
    System.out.println("Hello, world!");
}
public static void main(String[] args) {
    System.out.println("Hello, world!");
}
\end{lstlisting}
\clearpage

\end{document}

输出

相关内容