Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I use the listings package for source-code and have read all documentation. However, it appears that leading zeros for line numbers are not implemented as standard option yet. How can I redefine the line numbering so that it uses additional zeros?

Given: 1 ... 10 ... 100 ... 1000 ....
Want: 01 ... 10 ... 99 (if largest printed number <100)
Want: 001 ... 010 ... 100 ... 999 (if largest printed number <1000) etc.

Alternatively: How can I redefine the alignment after the number with the most digits?

Given:    Want:
1            1
...        ...
10          10
...        ...
100        100

Added Latex sample:

\documentclass{article}
\usepackage{listings} 
\lstset{language=Ruby,
        basicstyle=\ttfamily, 
        numbers=right,
        numberstyle=\ttfamily, 
      % solution for right alignment:
      % numberstyle=\ttfamily\makebox[3em][r],
        showstringspaces=false}

\begin{document}
\begin{lstlisting}
#!/usr/bin/env ruby
# test of latex listings package
# uses line numbering with 1-12. 
# should be using leading zeros, like 01-12.
puts "line number 05."
puts "line number 06."
puts "line number 07."    
puts "line number 08."
puts "line number 09."
puts "line number 10."
puts "line number 11."
puts "line number 12."
\end{lstlisting}
\begin{lstlisting}[firstnumber=98]
puts "line number 098."
puts "line number 099."
puts "line number 100."
puts "line number 101."
puts "line number 102."
\end{lstlisting}
\begin{lstlisting}[firstnumber=998]
puts "line number 0998."
puts "line number 0999."
puts "line number 1000."
puts "line number 1001."
puts "line number 1002."
\end{lstlisting}
\begin{lstlisting}[firstnumber=9998]
puts "line number 09998."
puts "line number 09999."
puts "line number 10000."
puts "line number 10001."
puts "line number 10002."
\end{lstlisting}
\begin{lstlisting}[firstnumber=8]
puts "line number 08."
puts "line number 09."
puts "line number 10."
puts "line number 11."
puts "line number 12."
\end{lstlisting}
\end{document}
share|improve this question
    
Welcome to TeX.SE. It would be helpful if you composed a fully compilable MWE including \documentclass and the appropriate packages that sets up the problem. While solving problems is fun, setting them up is not. Then those trying to help can simply cut and paste your MWE and get started on solving problem. –  Peter Grill Jan 22 '13 at 18:54
5  
I think using \renewcommand*\thelstnumber{\makebox[3em][r]{\the\value{lstnumber}}} should do the job. –  Peter Grill Jan 22 '13 at 18:57
1  
@PeterGrill: I suggest using numberstyle=\ttfamily\makebox[3em][r] instead of redefining \thelstnumber as doing the latter will cause problems with referencing (eg to determine the last line number in the listing). –  cyberSingularity Jan 22 '13 at 20:40
    
@cyberSingularity that is correct and works better. I tried to use Peter's solution in my longer scrbook document with lots of references (like toc, figures, listings, acronyms, bibliography, index, urls, nameref etc.) and it produced a COMPILE ERROR I couldn't solve. Just as info: {ERROR MESSAGE: TeX capacity exceeded, sorry [text input levels=50]. @file@und ->HelloWorld.java END MESSAGE. The log-file states that the source-code-file was permanently tried to be loaded.} –  Benjamin Jan 22 '13 at 22:12
    
solved as shown in marked answer –  Benjamin Jan 22 '13 at 23:31
add comment

2 Answers

up vote 3 down vote accepted

Here's an approach that attempts to automatically determine the number of lines in the listing:

  • Assigns a unique (incremental) number to each listing
  • Saves the value of the lstnumber counter at the end of every listing (but is one too large), using the \label mechanism
  • Retrieves the saved value of the lstnumber counter using the \ref mechanism (thus needs two runs to be correct)
  • Decrements the restored value, and attempts to count the number of digits in it
  • Sets \padzeroes accordingly
  • Sets the numberstyle to invoke \decimalnum from the fmtcount package, which uses the number set in the previous step

Probably not the most elegant way to do this...

Code:

\documentclass{article}
\usepackage{listings}
\lstset{language=Ruby,
        basicstyle=\ttfamily,
        numbers=right,
        numberstyle=\ttfamily\boxeddecimalnum,
        showstringspaces=false}
\errorcontextlines=\maxdimen

\newcommand*{\boxeddecimalnum}[1]{\makebox[3em][r]{\decimalnum{#1}}}
\usepackage{refcount}
\usepackage{fmtcount}
\usepackage{intcalc}

\def\getnumdigitsaux #1{%
    \ifx#1\quark
    \expandafter\relax
    \else
    +1\expandafter\getnumdigitsaux
    \fi
}

\def\quark{\quark}
\newcommand\getnumdigits[1]{%
    \the\numexpr\getnumdigitsaux #1\quark
}

\newcounter{lstuniquenumber}
\makeatletter
\lst@AddToHook{Init}{\stepcounter{lstuniquenumber}\edef\lastlineincurrentlisting{\intcalcDec{\getrefnumber{lastlineinlisting\thelstuniquenumber}}}\padzeroes[\expandafter\getnumdigits\expandafter{\lastlineincurrentlisting}]}% at the start of each listing, count the listing, and try to restore the line number saved in the previous run
\lst@AddToHook{DeInit}{\label{lastlineinlisting\thelstuniquenumber}}% at the end of each listing, save one past the last line number
\makeatother

\begin{document}

\begin{lstlisting}
#!/usr/bin/env ruby
# test of latex listings package
# uses line numbering with 1-12. 
# should be using leading zeros, like 01-12.
puts "line number 05."
puts "line number 06."
puts "line number 07."
puts "line number 08."
puts "line number 09."
puts "line number 10."
puts "line number 11."
puts "line number 12."
\end{lstlisting}
\begin{lstlisting}[firstnumber=98]
puts "line number 098."
puts "line number 099."
puts "line number 100."
puts "line number 101."
puts "line number 102."
\end{lstlisting}
\begin{lstlisting}[firstnumber=998]
puts "line number 0998."
puts "line number 0999."
puts "line number 1000."
puts "line number 1001."
puts "line number 1002."
\end{lstlisting}
\begin{lstlisting}[firstnumber=9998]
puts "line number 09998."
puts "line number 09999."
puts "line number 10000."
puts "line number 10001."
puts "line number 10002."
\end{lstlisting}

\end{document}

Output:

Illustration of output

share|improve this answer
    
PERFECT. FINALLY it works! This is a feature I would propose to have in the listings package by default. –  Benjamin Jan 22 '13 at 23:44
add comment

To add one leading zero for numbers below 10 simply add \ifnum\value{lstnumber}<10 0\fi in front of the number. It is much trickier to get the maximum line number of a lstlisting. It would be easier to redefine \thelstnumber appropriate for these who are longer than 99 lines. There also add \ifnum\value{lstnumber}<100 0\fi to the front.

\documentclass{article}
\usepackage{listings} 
\lstset{language=Ruby,
        basicstyle=\ttfamily,
        numbers=right,
        numberstyle=\ttfamily,
        showstringspaces=false}

% solution for right alignment provided by Peter works!
\renewcommand*\thelstnumber{\makebox[3em][r]{\ifnum\value{lstnumber}<10 0\fi\the\value{lstnumber}}}

% solution for leading zeros is still pending!

\begin{document}
\begin{lstlisting}
#!/usr/bin/env ruby
# test of latex listings package
# uses line numbering with 1-12. 
# should be using leading zeros, like 01-12.
puts "line number 05."
puts "line number 06."
puts "line number 07."
puts "line number 08."
puts "line number 09."
puts "line number 10."
puts "line number 11."
puts "line number 12."
\end{lstlisting}
\end{document}
share|improve this answer
    
Also see How to output a counter with leading zeros? –  Werner Jan 22 '13 at 21:04
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.