编号LaTeX中带有listings包的最后一行

编号LaTeX中带有listings包的最后一行,latex,listings,Latex,Listings,我将LaTeX与清单软件包一起使用,每五行代码的编号如下: \lstset{ numbers=left, stepnumber=5, firstnumber=1, numberfirstline=true } 现在,由于这些设置中的numberfirstline=true,除了5的倍数外,每个列表的第一行也被编号,但我希望代码的最后一行也被编号。因此,如果我有一个包含17行代码的列表,我希望看到编号的行是1 5 10 1517 有没有什么方法可以让列表像这样运行?我尝试了numberlastl

我将LaTeX与
清单
软件包一起使用,每五行代码的编号如下:

\lstset{
numbers=left,
stepnumber=5,
firstnumber=1,
numberfirstline=true
}
现在,由于这些设置中的
numberfirstline=true
,除了5的倍数外,每个列表的第一行也被编号,但我希望代码的最后一行也被编号。因此,如果我有一个包含17行代码的列表,我希望看到编号的行是1 5 10 1517

有没有什么方法可以让列表像这样运行?我尝试了
numberlastline=true
,但这似乎不存在


编辑:我更愿意将其用于
\lsInputListing
,而不必修改以这种方式导入的代码。

事实上,由于您使用的是
numberfirstline=true
,这比您想象的要简单。<>代码>清单包提供了一种机制,可以通过代码< > HaveEng/<代码>在列表中间退出逐字模式,以便能够插入附加宏。这里的技巧是,在从转义代码返回后,它会再次将下一行视为“第一”行,即使没有重置计数。因此,您所要做的就是在清单的倒数第二行退出(什么也不做!)。如果你在最后一刻做,那就太晚了!下面的示例演示如何使用它来获得所需的内容

\documentclass{article}
\usepackage{listings}

\lstset{
numbers=left,
stepnumber=5,
firstnumber=1,
numberfirstline=true
escapeinside={|(}{)|}
}

\begin{document}

\begin{lstlisting}
lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
duis aute irure dolor in reprehenderit
in voluptate velit esse cillum dolore
eu fugiat nulla pariatur.
excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt|()|
mollit anim id est laborum.
\end{lstlisting}

\end{document}

你也应该退房

更新

这需要修改列表源,因此在使用
\lsInputListing
时可能不够。另一种方法是,当通过
lastline
linerange
键明确指定最后一行时,修改listings包本身的逻辑以对其进行编号,如下所示

\documentclass{article}
\usepackage{listings}

\lstset{
numbers=left,
stepnumber=5,
firstnumber=1,
numberfirstline=true,
}

\makeatletter

\gdef\lst@SkipOrPrintLabel{%
    \ifnum\lst@skipnumbers=\z@
        \global\advance\lst@skipnumbers-\lst@stepnumber\relax
        \lst@PlaceNumber
        \lst@numberfirstlinefalse
    \else
        \ifnum\lst@lineno=\lst@lastline
            \lst@PlaceNumber
            \lst@numberfirstlinefalse
        \fi
        \lst@ifnumberfirstline
            \lst@PlaceNumber
            \lst@numberfirstlinefalse
        \fi
    \fi
    \global\advance\lst@skipnumbers\@ne}

\makeatother

\begin{document}

\lstinputlisting[lastline=13]{input.tex}

\end{document}
这确实需要您手动指定每个列表的最后行号,但考虑到操作临时文件的难度,这似乎是一个合理的牺牲,临时文件可能是动态发现只需要纯TeX的行号的唯一真正解决方案。如果可以接受不可移植的解决方案,您可以通过
\write18
运行shell命令,如
wc-l
,以获取行数。当然,这将要求所选命令出现在使用源代码的所有系统上,如果这些系统跨越不同的操作系统,则可能会造成困难。有关
\write18
的说明以及如何捕获其输出,请参阅


值得注意的是,当使用
linerange
时,它将对每个范围的最后一行进行编号,但在使用
numberfirstline=true
时,它不会对每个范围的第一行进行编号。虽然这同样可以改变,
linerange
已经导致了足够多的此类怪癖,如果这是一个问题,那么它很可能与当前的问题分离。

这是一个非常好的方法,感谢您的回答。只是我没有将列表作为显式文本(我可以在其中插入
|()|
),而是通过
\lsInputListing
!我不能把这个转义码放在我的源文件里。那么该怎么办呢?顺便说一句,我对stackoverflow还是相当陌生的:我是否应该编辑我的问题,包括我想使用
\lsInputListing
?是的,对代码使用的澄清可以帮助您获得更好的回答。另请参见,虽然它看起来并不理想,但没有任何东西可以阻止您使用与
\begin{lstlisting}…\end{lstlisting}
相同的方法使用
\lstinputlisting}。只需将
escapeinside
文本移动到
\lstset
定义中(我可能应该将其放在第一位)。然而,这确实需要您修改所述来源,这可能不像您所述的那样是可取的。一个与我提到的问题类似的更奇特的解决方案可能会通过改变列表包本身的行为来实现你想要的,但我明天必须尝试研究一下。我还没有时间弄清楚这一点,但如果你能在我之前弄清楚,这是我目前的逻辑。您想要的问题是,行号是确定的,并在每一行上输出,在完成当前行之前,您不知道是否会有下一行。因此,在到达最后一行之前,您确实需要知道最后一行是什么,这只能通过手动或在处理输入之前额外扫描一段时间来完成。我的运行思路是两个步骤:通过执行与我在答案中链接的问题类似的操作,有效地添加
lastlinenumber=n
能力,然后将输入扫描到一个临时文件中,并对行进行计数,以便能够动态获取最后一行的编号。也可以在不创建临时文件的情况下处理输入,同时仍然能够计算行数,但我不确定是否以及如何处理。不幸的是,这是我即将进行的一些商务旅行的时间,因此我没有时间提前解决您的问题。我不知道你是否仍然面临这个问题,但我已经更新了我的答案,以反映你的需求。它仍然需要为每个列表手动指定最后一行,但是使用已经存在的键,并且有足够的意义。我放弃了临时文件的想法,即动态地、可移植地计算行数,因为像这样操作低级I/O比我想象的要困难。如果你想要这个,我在回答中建议了一个可能的不可移植的解决方案。