使“llap”尊重底部边距

使“llap”尊重底部边距

\llap在自定义环境中使用 在文档左边距中写入一些文本,与代码列表对齐(使用 完成代码列表lstlisting)。每当代码列表位于页面底部时,标签llap都会停留在上一页,而代码列表会移动到下一页。下面显示了一个示例(深色矩形代表文档的边距):

在此处输入图片描述

此示例中的问题在于Out [9]:标签位于页面底部边距以下,而相关的代码列表位于下一页。

我需要在多个页面上分隔长代码列表,所以我不想将标签和列表都包装在里面minipage(这样可以,但不允许在代码列表内分页)。

有什么方法可以llap尊重底部边距吗?下面是 MWE。


\documentclass{article}

\usepackage{listings}
\usepackage[breakable]{tcolorbox}
\usepackage{ifthen}
\usepackage{xcolor}
\usepackage{lipsum}
\usepackage{showframe}

% custom colors
\definecolor{incolor}{HTML}{868686}
\definecolor{outcolor}{HTML}{868686}
\definecolor{cellbackground}{HTML}{F7F7F7}

% prompt
\makeatletter
\newcommand{\boxspacing}{\kern\kvtcb@left@rule\kern\kvtcb@boxsep}
\makeatother

\newcounter{cellcounter}

\lstdefinestyle{style}{
    language=Python, 
    aboveskip=-1.4\medskipamount,
    belowskip=0.5em,
    backgroundcolor=\color{cellbackground}, 
    numbers=none,
}

\makeatletter
\lst@Key{showprompt}{true}{\def\showprompt{#1}}
\lst@Key{promptnumber}{\thecellcounter}{\def\promptnumber{#1}}
\makeatother

\lstnewenvironment{code}[1][]
{   
    \lstset{
        style=style,
        #1
    }
    \addtocounter{cellcounter}{1}
    \ifthenelse{\boolean{\showprompt}}
        {\footnotesize\ttfamily\llap{{\color{outcolor}Out\,[\thecellcounter]:\hspace{3pt}\boxspacing}}}
        {\phantom{\footnotesize\ttfamily\llap{{\color{outcolor}Out\,[\thecellcounter]:\hspace{3pt}\boxspacing}}}}
}{
}

%----------------------------------------------------------------------------------------
%   DOCUMENT
%----------------------------------------------------------------------------------------

\setlength\parindent{0pt}
\setlength\parskip{83pt}
\begin{document}

\lipsum[70]
\lipsum[70]

\lipsum[70]
\lipsum[66]

\begin{code}
df.head()
\end{code}
\begin{code}
0         False       False  ...
1         False       False  ...
3         False       False  ...
4         False       False  ...
...         ...         ...  ...
9064      False       False  ...
9065      False       False  ...
9066      False       False  ...
9067      False       False  ...
\end{code}

\end{document}

在此处输入图片描述

答案1

我认为使用在 的第二个强制参数中明确插入标签的方法来实现这一点会很棘手\lstnewenviroment。这与 无关\llap,而是因为此参数用于设置环境而不是插入文本。在列表真正开始之前明确允许分页符,即在插入标签之后。

但是,您可以通过将标签放在字段中来实现相同的效果title。由于标题后不允许分页符,因此您的标签将始终与第一行内容显示在同一页上。我设置belowcaptionskip=-\baselineskip字段以使标题与内容位于同一行,并将标签放在\makebox宽度为的范围内\linewidth,因为否则它将居中。


这是您的 MWE 的修改版本。更改标记为ADDEDREMOVED

\documentclass{article}

\usepackage{listings}
\usepackage[breakable]{tcolorbox}
\usepackage{ifthen}
\usepackage{xcolor}
\usepackage{lipsum}
\usepackage{showframe}

% custom colors
\definecolor{incolor}{HTML}{868686}
\definecolor{outcolor}{HTML}{868686}
\definecolor{cellbackground}{HTML}{F7F7F7}

% prompt
\makeatletter
\newcommand{\boxspacing}{\kern\kvtcb@left@rule\kern\kvtcb@boxsep}
\makeatother

\newcounter{cellcounter}

%% Following commands are ADDED:
\newcommand*\hbotcodefont{\footnotesize\ttfamily}
\newcommand*\hbotoutlabeltext[1]{Out\,[#1]:\hspace{3pt}}
\newcommand*{\hbotOutTitle}{%
    \hbotcodefont
    \ifthenelse{\boolean{\showprompt}}{%
        \makebox[\linewidth][l]{\llap{%
            \color{outcolor}%
            \hbotoutlabeltext{\thecellcounter}\boxspacing
        }}%
    }{}%
}

\lstdefinestyle{style}{
    language=Python,
    title=\hbotOutTitle, %% <- ADDED
    belowcaptionskip=-\baselineskip, %% <- ADDED
    %% <- REMOVED aboveskip=...
    backgroundcolor=\color{cellbackground},
    numbers=none,
}

\makeatletter
\lst@Key{showprompt}{true}{\def\showprompt{#1}}
\lst@Key{promptnumber}{\thecellcounter}{\def\promptnumber{#1}}
\makeatother

\lstnewenvironment{code}[1][]
{
    \lstset{style=style,#1}
    \hbotcodefont
    \addtocounter{cellcounter}{1}
    %% <- REMOVED label insertion code
}{
}

%----------------------------------------------------------------------------------------
%   DOCUMENT
%----------------------------------------------------------------------------------------

\setlength\parindent{0pt}
\setlength\parskip{83pt}
\begin{document}

\lipsum[70]
\lipsum[70]

\lipsum[70]
\lipsum[66]

\begin{code}
df.head()
\end{code}
\begin{code}
0         False       False  ...
1         False       False  ...
3         False       False  ...
4         False       False  ...
...         ...         ...  ...
9064      False       False  ...
9065      False       False  ...
9066      False       False  ...
9067      False       False  ...
\end{code}

\end{document}

输出

答案2

按照@David Carlisle 的回答这个帖子正如我在评论中所说,您可以在环境定义中\llap替换。\makebox[0pt][r]

以下是您提出的代码,其中有两处进行了更改:

  • \llap替换(两次)为\makebox[0pt][r]
  • 删除了\lipsum[xx]几个blabla\par以便在分页符测试中获得更高的精度。

您可以取消部分注释blabla\par以获得注释中描述的效果:

我希望这能帮助你解决问题。

这个“答案”只是为了向您展示代码,以便您可以告诉我它是否按预期工作。

\documentclass{article}


\usepackage{listings}
\usepackage[breakable]{tcolorbox}
\usepackage{ifthen}
\usepackage{xcolor}
\usepackage{lipsum}
\usepackage{showframe}

% custom colors
\definecolor{incolor}{HTML}{868686}
\definecolor{outcolor}{HTML}{868686}
\definecolor{cellbackground}{HTML}{F7F7F7}

% prompt
\makeatletter
\newcommand{\boxspacing}{\kern\kvtcb@left@rule\kern\kvtcb@boxsep}
\makeatother

\newcounter{cellcounter}

\lstdefinestyle{style}{
    language=Python, 
    aboveskip=-1.4\medskipamount,
    belowskip=0.5em,
    backgroundcolor=\color{cellbackground}, 
    numbers=none,
}

\makeatletter
\lst@Key{showprompt}{true}{\def\showprompt{#1}}
\lst@Key{promptnumber}{\thecellcounter}{\def\promptnumber{#1}}
\makeatother

\lstnewenvironment{code}[1][]
{   
    \lstset{
        style=style,
        #1
    }
    \addtocounter{cellcounter}{1}
    \ifthenelse{\boolean{\showprompt}}
    {\footnotesize\ttfamily\makebox[0pt][r]{{\color{outcolor}Out\,[\thecellcounter]:\hspace{3pt}\boxspacing}}}
    {\phantom{\footnotesize\ttfamily\makebox[0pt][r]{{\color{outcolor}Out\,[\thecellcounter]:\hspace{3pt}\boxspacing}}}}
}{
}

%----------------------------------------------------------------------------------------
%   DOCUMENT
%----------------------------------------------------------------------------------------

\setlength\parindent{0pt}

\begin{document}

    \lipsum[1-4]
    blabla\par
    blabla\par  
    blabla\par
    blabla\par
    blabla\par  
    blabla\par
    blabla\par
    blabla\par  
    blabla\par      % "Out [1]" and the first two lines of "Out [2]" on page 1, the rest on page 2
%   blabla\par      % "Out [1]" on the penultimate line of page 1 (last line blank)
%   blabla\par      % Only "Out [1]" on last line of page 1
%   blabla\par      % Everything on page 2
    \begin{code}
        df.head()
    \end{code}
    \begin{code}
        0         False       False  ...
        1         False       False  ...
        3         False       False  ...
        4         False       False  ...
        ...         ...         ...  ...
        9064      False       False  ...
        9065      False       False  ...
        9066      False       False  ...
        9067      False       False  ...
    \end{code}
    \begin{code}
        blabla
    \end{code}

\end{document}

相关内容