[Tex/LaTex] First line number in lstinputlisting environment

line-numberinglistings

I use the following code to display line 23-45 of sort.cpp:

\lstinputlisting[language=C++,linerange=23-45]{sort.cpp}

However, the line numbering starts with 1 while I want it start at 23. I found some reference that suggested to change this to

\lstinputlisting[language=C++,linerange=23-45,firstnumber=23]{sort.cpp}

It works, and I want this to be the default setting. According page 31 of the listings documentation,

auto lets the package choose the first number: a new listing starts with
number one, a named listing continues the most recent same-named listing
(see below), and a stand alone file begins with the number corresponding to
the first input line.
last continues the numbering of the most recent listing and number sets
it to the number.

It should be the default. What's wrong here, or am I misundersting the reference?

My listings setting:

\usepackage{xcolor,listings}%color support for listings
\lstset{
basicstyle=\footnotesize,
numbers=left, 
numberstyle=\footnotesize, 
keywordstyle=\color{blue!70}, 
commentstyle=\color{red!50!green!50!blue!50}, 
%stringstyle=\ttfamily, % typewriter type for strings
%frame=shadowbox, 
rulesepcolor=\color{red!20!green!20!blue!20},
escapeinside=``, 
xleftmargin=2em,xrightmargin=2em, aboveskip=1em,
breaklines=true             % sets automatic line breaking
}

Best Answer

This default behaviour is understandable since the listings package has no concern with the layout and/or structure of the imported listing. For that reason, here is one scenario that motivate a separate firstnumber key-value that does not default to the first line of linerange: Your sort.cpp file has a bunch of unrelated procedures/functions in it. Referencing some of the functions with the line numbers starting with the first element of linerange would have no meaning since the line number does not relate to the content.

Though, on a positive note, it is possible to force the listings package to make firstnumber the same as the first element in linerange (called firstline) regardless. To do this, we patch the linerange-parser (\lst@GLI@, short for Get Line Interval) using the etoolbox package command \patchcmd:

\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
...
\makeatletter
\patchcmd{\lst@GLI@}% <command>
  {\def\lst@firstline{#1\relax}}% <search>
  {\def\lst@firstline{#1\relax}\def\lst@firstnumber{#1\relax}}% <replace>
  {\typeout{listings firstnumber=firstline}}% <success>
  {\typeout{listings firstnumber not set}}% <failure>
\makeatother

The above patch print listings firstnumber=firstline if the command \lst@GLI@ was successfully patched, otherwise it will print listings firstnumber not set to the <jobname>.aux file. The patch consists of searching for the spot in \lst@GLI@ where the firstline is established, and adds to it an equivalent assignment of the firstnumber.

Note, however, that the above patch is a permanent replacement and voids further use of the firstnumber key-value.