One way of doing this would be to patch the command that typesets the chapter heading \@@makechapterhead
and insert the desired space. This way it is automated and won't form part of the ToC entries. Patching is possible using the etoolbox
package.
In the MWE below, you need to specify the lengths \chapnumwidth
and \chaplabelsep
using \setlength
commands, and the patch will take care of the rest. Using/setting lengths this way makes for a more generalized solution that can be modified in the future with very little hassle.
\documentclass{scrbook}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\makeatletter
\newsavebox{\@chapnumbox}% Box to store chapter number
\patchcmd{\@@makechapterhead}% <cmd>
{\size@chapter{#1}}% <search>
{\sbox{\@chapnumbox}{\size@chapter{\thechapter}}% Store chapter number
\size@chapter{\hspace*{\dimexpr\chaplabelsep-\chapnumwidth+\wd\@chapnumbox\relax}#1}}% <replace>
{}% <success>
{}% <failure>
\makeatother
\renewcommand*{\chapterformat}{\makebox[\chapnumwidth][l]{\thechapter}}
\newlength{\chapnumwidth} \setlength{\chapnumwidth}{5mm}% Chapter number/label width
\newlength{\chaplabelsep} \setlength{\chaplabelsep}{2em}% Chapter number/label separation
\begin{document}
\chapter{A very long chapter title asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd}
kjdhfaksdjhf
\setcounter{chapter}{21}
\chapter{A very long chapter title asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd}
kjdhfaksdjhf
\end{document}
The format for patching is
\patchcmd{<cmd>}{<search>}{<replace>}{<success>}{<failure>}
which replaces <search>
in <cmd>
with <replace>
and executes <success>
if successful, or <failure>
otherwise. You'll notice that the patching in the MWE saves the chapter number (in the appropriate font size/format) in a box
\sbox{\@chapnumbox}{\size@chapter{\thechapter}}% Store chapter number
and adds
\hspace*{dimexpr\chaplabelsep-\chapnumwidth+\wd\@chapnumbox\relax}
before the chapter heading (#1
). This means that your chapter heading will start exactly \chaplabelsep
from the chapter label, since the removed \chapnumwidth
is the actual \chapterformat
width. Of course, you can modify as needed.
In summary, the width from the left margin for the chapter heading is specified by the \chapterformat
command (as you've already done), while the first line is adjusted using the patched form of \@@makechapterhead
which restores the \chapterformat
width and subsequently advances it by the width of the chapter number/label and \chaplabelsep
.
My previous solution had problems with the numbering of blank lines. I have added a new solution and kept the old one further down.
New Solution
What one really needs to do is reset the counter lstnumber
at the beginning of each range. To achieve this one needs to hook into an internal command \lst@SkipToFirst
. One approach is to define a new key matchrangestart
initialised as false via
\lst@Key{matchrangestart}{f}{\lstKV@SetIf{#1}\lst@ifmatchrangestart}
and then add the following test at the beginning of \lst@SkiptoFirst
:
\lst@ifmatchrangestart\c@lstnumber=\numexpr-1+\lst@firstline\fi
This the general way listings
set-up keys with true/false values and how it handles the counter lstnumber
. This code says if the matchrangestart
key is true then when skipping forward to the beginning of a rang set lstnumber
to one less than the first line number of the range. When the line gets printed this number is then incremented before being printed so we get the desired output.
\documentclass{article}
\usepackage{filecontents,listings}
\lstset{
basicstyle=\ttfamily\footnotesize
}
\begin{filecontents*}{mycode.txt}
Line 1
Line 2
Line 3
Line 6
Line 7
Line 9
Line 10
\end{filecontents*}
\makeatletter
\lst@Key{matchrangestart}{f}{\lstKV@SetIf{#1}\lst@ifmatchrangestart}
\def\lst@SkipToFirst{%
\lst@ifmatchrangestart\c@lstnumber=\numexpr-1+\lst@firstline\fi
\ifnum \lst@lineno<\lst@firstline
\def\lst@next{\lst@BeginDropInput\lst@Pmode
\lst@Let{13}\lst@MSkipToFirst
\lst@Let{10}\lst@MSkipToFirst}%
\expandafter\lst@next
\else
\expandafter\lst@BOLGobble
\fi}
\makeatother
\begin{document}
\begin{minipage}{0.45\linewidth}
Standard
\lstset{numbers=left}
\lstinputlisting[linerange={1-3}]{mycode.txt}
\lstinputlisting[linerange={2-6}]{mycode.txt}
\lstinputlisting[linerange={2-2,4-6,8-9}]{mycode.txt}
\end{minipage}
\begin{minipage}{0.45\linewidth}
Literal
\lstset{numbers=left,matchrangestart=t}
\lstinputlisting[linerange={1-3}]{mycode.txt}
\lstinputlisting[linerange={2-6}]{mycode.txt}
\lstinputlisting[linerange={2-2,4-6,8-9}]{mycode.txt}
\end{minipage}
\end{document}
Old Solution
This places wrong numbers on blank lines
The listings
package has an internal plain counter \lst@lineno
holding the line number you are after. Now the numbers=left
option, runs the code
\def\lst@PlaceNumber{\llap{\normalfont
\lst@numberstyle{\thelstnumber}\kern\lst@numbersep}}
so all we need to do is take this code and replace the printed latex counter \thelstnumber
by \the\list@lineno
:
\documentclass{article}
\usepackage{filecontents,listings}
\lstset{
basicstyle=\ttfamily\footnotesize
}
\begin{filecontents*}{mycode.txt}
Line 1
Line 2
Line 3
Line 4
Line 5
\end{filecontents*}
\makeatletter
\def\lst@PlaceNumber{\llap{\normalfont
\lst@numberstyle{\the\lst@lineno}\kern\lst@numbersep}}
\makeatother
\begin{document}
\lstinputlisting[linerange={1-3}]{mycode.txt}
\lstinputlisting[linerange={2-4}]{mycode.txt}
\lstinputlisting[linerange={2-2,4-5}]{mycode.txt}
\end{document}
The above coding sets this style globally. If you wish to have local switches then you can extend the listings
definition of the numbers
option, adding a leftliteral
type as follows:
\documentclass{article}
\usepackage{filecontents,listings}
\makeatletter
\lst@Key{numbers}{none}{%
\let\lst@PlaceNumber\@empty
\lstKV@SwitchCases{#1}%
{none&\\%
left&\def\lst@PlaceNumber{\llap{\normalfont
\lst@numberstyle{\thelstnumber}\kern\lst@numbersep}}\\%
leftliteral&\def\lst@PlaceNumber{\llap{\normalfont
\lst@numberstyle{\the\lst@lineno}\kern\lst@numbersep}}\\%
right&\def\lst@PlaceNumber{\rlap{\normalfont
\kern\linewidth \kern\lst@numbersep
\lst@numberstyle{\thelstnumber}}}%
}{\PackageError{Listings}{Numbers #1 unknown}\@ehc}}
\makeatother
\lstset{
basicstyle=\ttfamily\footnotesize
}
\begin{filecontents*}{mycode.txt}
Line 1
Line 2
Line 3
Line 4
Line 5
\end{filecontents*}
\begin{document}
\begin{minipage}{0.3\linewidth}
Standard
\lstset{numbers=left}
\lstinputlisting[linerange={1-3}]{mycode.txt}
\lstinputlisting[linerange={2-4}]{mycode.txt}
\lstinputlisting[linerange={2-2,4-5}]{mycode.txt}
\end{minipage}
\begin{minipage}{0.3\linewidth}
Literal
\lstset{numbers=leftliteral}
\lstinputlisting[linerange={1-3}]{mycode.txt}
\lstinputlisting[linerange={2-4}]{mycode.txt}
\lstinputlisting[linerange={2-2,4-5}]{mycode.txt}
\end{minipage}
\begin{minipage}{0.3\linewidth}
Standard
\lstset{numbers=left}
\lstinputlisting[linerange={1-3}]{mycode.txt}
\lstinputlisting[linerange={2-4}]{mycode.txt}
\lstinputlisting[linerange={2-2,4-5}]{mycode.txt}
\end{minipage}
\end{document}
Best Answer
You need to alter the value of
\labelsep
for the list. The default is0.5em
. This changes that to1.5em
: