如何正确对齐源代码列表的行号和边距?

如何正确对齐源代码列表的行号和边距?

我想使用 listings 包在文档中包含代码片段。在我的文档中,有以下内容:

\begin{figure}[!htbp]
\setlength{\fboxsep}{0pt}%
\setlength{\fboxrule}{0pt}%
\begin{center}
  \lstset{language=Java, numbers=left, showspaces=false,
    showstringspaces=false, tabsize=2, breaklines=true}

\begin{lstlisting}
public class AutoRegistry {
  public void registerCar(int ssn, int vin) {
    // ...
    PersonCarDirect personCar = new PersonCarDirect();
    personCar.setId(ssn);
    personCar.setVin(vin);
    // ...
  }
}
\end{lstlisting}
\end{center}
\vspace{-12pt}
\caption{AutoRegistry client class}
\label{fig:autoRegistryClientC}
\end{figure} 

当我使用 pdflatex 生成 PDF 文档时,行号太靠左 - 我不希望它们位于页边距中。(见下图。)我该如何纠正这个问题?

在此处输入图片描述

答案1

您可以使用\begin{lstlisting}[xleftmargin=5.0ex]调整左边距,或将此选项添加到\lstset。这会将您的列表向右移动,包括行号和任何框架。

lipsum包用于在列表前提供一些虚拟文本。我还提供了查看边距的geometry选项。[showframe]

在此处输入图片描述

\documentclass{article}
\usepackage[showframe]{geometry}
\usepackage{lipsum}
\usepackage{listings}
\begin{document}
\lipsum[1]

\begin{figure}[!htbp]
\setlength{\fboxsep}{0pt}%
\setlength{\fboxrule}{0pt}%
%\begin{center}
\centering
  \lstset{language=Java, numbers=left, showspaces=false,
    showstringspaces=false, tabsize=2, breaklines=true,
    xleftmargin=5.0ex,
    %numberstyle=\scriptsize,numbersep=0pt
}

\begin{lstlisting}
public class AutoRegistry {
  public void registerCar(int ssn, int vin) {
    // ...
    PersonCarDirect personCar = new PersonCarDirect();
    personCar.setId(ssn);
    personCar.setVin(vin);
    // ...
  }
}
\end{lstlisting}
%\end{center}
%\vspace{-12pt}
\caption{AutoRegistry client class}
\label{fig:autoRegistryClientC}
\end{figure} 
\end{document}

正如@Mico 指出的那样,你应该使用\centering而不是\begin{center}...\end{center}。这也可以让你消除\vspace{-12pt}。参见我应该对图形和表格使用 center 还是 centering ?了解更多详情。以防有人复制上述代码而不阅读其他解决方案,我已经在代码中做了那些更改,并将您的原始代码保留为注释。


将数字与列右侧对齐

如果空间有限并且想要将数字对齐到列的右侧,则使用:

\newlength{\MaxSizeOfLineNumbers}%
\settowidth{\MaxSizeOfLineNumbers}{99}% Adjust to maximum number of lines
\addtolength{\MaxSizeOfLineNumbers}{2.5ex}%

并设置:

xleftmargin=\MaxSizeOfLineNumbers

这项2.5ex调整是将数字放在边距左侧,然后我们根据数字的宽度进行移动99

当然,这假设您的列表中的行数少于 100,因此请进行相应调整。此外,如果您碰巧使用 之类的东西更改了数字样式numberstyle=\tiny{99}则应将参数相应调整为{\tiny 99}

答案2

listings包裹通过宏 排版行号\lst@PlaceNumber。此宏根据为键 指定的值具有不同的含义numbers。但是,边距对齐键xleftmargin与 中包含的元素没有任何联系\lst@PlaceNumber,因此很难准确地使数字与左边距齐平。即使@JanHlavacek 的回答很好地将长度元素添加到一起,使得列表行号与左边距齐平,我认为重新定义为\lst@PlaceNumber用户提供了对行号和分隔符间距的更多控制,并且使调整更容易xleftmargin。例如,

\makeatletter
\def\lst@PlaceNumber{%
  \makebox[3em][l]{\normalfont\lst@numberstyle{\thelstnumber}}%
}
\makeatother

将数字放在宽度为 的左对齐框中3em(从而固定宽度,而不必担心行号分隔符或左边距的移动)。因此, 的含义xleftmargin已被修改,并且更容易理解为整个列表的缩进,包括行号。

以下是一个例子:

\documentclass{article}
\usepackage[showframe]{geometry}% http://ctan.org/pkg/geometry
\usepackage{listings}% http://ctan.org/pkg/listings
\usepackage{lipsum}% http://ctan.org/pkg/lipsum

\begin{document}

\newlength{\linenumwidth} \setlength{\linenumwidth}{3em}% Redefine as required
\makeatletter
\def\lst@PlaceNumber{%
  \makebox[\linenumwidth][l]{\normalfont\lst@numberstyle{\thelstnumber}}%
}
\makeatother

\lipsum[1]
\begin{figure}[!htb]
  \centering
  \lstset{language=Java, showspaces=false,%
    showstringspaces=false, tabsize=2, breaklines=true}
\begin{lstlisting}[firstnumber=8]
public class AutoRegistry {
   public void registerCar(int ssn, int vin) {
      // ...
      PersonCarDirect personCar = new PersonCarDirect();
      personCar.setId(ssn);
      personCar.setVin(vin);
      // ...
   }
}
\end{lstlisting}
  \caption{AutoRegistry client class}
  \label{fig:autoRegistryClientC}
\end{figure} 
\lipsum[2]

\end{document}

在此处输入图片描述

下面是一个将整个列表缩进的示例20pt

\lstset{language=Java, showspaces=false, xleftmargin=20pt,%
  showstringspaces=false, tabsize=2, breaklines=true}

在此处输入图片描述

以下是稍微复杂一点的行号对齐:

\usepackage{calc}% http://ctan.org/pkg/calc
...
\makeatletter
\newlength{\linenumwidth} \setlength{\linenumwidth}{3em}% Redefine as required
\newlength{\numwidth}%
\setlength{\numwidth}{\widthof{\normalfont{\lst@numberstyle{99}}}}% Up to 2-digit (99) line numbers
\def\lst@PlaceNumber{%
  \makebox[\numwidth+1em][l]{%
    \makebox[\numwidth][r]{\normalfont\lst@numberstyle{\thelstnumber}}%
  }%
}
\makeatother

在此处输入图片描述

答案3

你可以发出指令

\lstset{numberstyle=\scriptsize,numbersep=3pt}

减小字体大小和行号的水平间距。

顺便说一句,如果您用单个指令替换命令对\begin{center}... ,那么您也可以摆脱命令前的命令。:-)\end{center}\centering\vspace{-12pt}\caption

答案4

这里结合了 Peter Grill 的自动宽度检测(将数字对齐到列的右侧)、Werner 的\lst@PlaceNumber以及我自己的程序,后者使用totcount包和一些丑陋的代码来记住最大值lstnumber,并循环遍历所有数字以查找最大值。我这样做是因为例如 9999 比 11111 宽,而您的最大行号将是 11111。LaTeX 的默认字体不是这种情况,但可能是另一种字体的情况,或者您在排版行号时可能有一些条件性的东西。

行号空间适应最大行号

请注意,您需要通过 LaTeX 处理两次(因为它存储了文件中的最大行号aux,并使用前一次运行的值来计算保留宽度)。

\documentclass{article}
\usepackage{lipsum}

\usepackage{listings}
\usepackage{totcount}
\newcounter{maxlstnumber}
\regtotcounter{maxlstnumber}
\def\updatemaxlstnumber{%
  \ifnum\value{lstnumber}>\value{maxlstnumber}%
  \setcounter{maxlstnumber}{\the\value{lstnumber}}%
  \fi%
}
\lstset{numbers=left, gobble=2, numbersep=5pt, firstnumber=11109, escapeinside={//*}{*//}}
\newlength{\MaxSizeOfLineNumbers}%

\makeatletter
% The following command allows you to customize line number style, without affecting \ref{}.
% Here, the style is "\thelstnumber." (with a dot at the end)
\def\renderlstnumber{\normalfont\lst@numberstyle{\thelstnumber.}\kern\lst@numbersep}
\def\lst@PlaceNumber{\updatemaxlstnumber\makebox[\MaxSizeOfLineNumbers][r]{\renderlstnumber}}
% This must be called after \begin{document}
\def\autosizelstnumber{
  \newlength{\LoopSizeOfLineNumber}
  \setcounter{lstnumber}{\the\totvalue{maxlstnumber}}
  \loop\ifnum\value{lstnumber}>\z@
  \settowidth{\LoopSizeOfLineNumber}{\renderlstnumber}
  \ifdim\LoopSizeOfLineNumber>\MaxSizeOfLineNumbers
  \setlength{\MaxSizeOfLineNumbers}{\LoopSizeOfLineNumber}
  %\message{Found larger line number \the\value{lstnumber}}
  \fi
  \addtocounter{lstnumber}{-1}
  \repeat
%  \setcounter{maxlstnumber}{0}
}
\makeatother

\begin{document}
\autosizelstnumber

\parindent 0pt

\lipsum[1]

\begin{lstlisting}
  aline
  bline//*\label{bline}*//
  yet another line//*\label{largestline}*//
\end{lstlisting}

Line \ref{bline} contains the character \verb!b!. Notice that even
though the line numbering says ``\ref{bline}.'', the
\verb!\ref{bline}! used here says ``\ref{bline}''. The dot is taken
into account when calculating the width to reserve for line numbers.

\begin{lstlisting}[firstnumber=123]
  class Foo {
    public static void main() {}
  }//*\label{lastline}*//
\end{lstlisting}

Notice that even if we end with line \ref{lastline}, the with reserved
for line numbers is large enough to include \ref{largestline}, the
largest line.

\lipsum[2]

\end{document}

相关内容