[Tex/LaTex] lstlisting – line number gaps

line-numberinglistings

Is it possible to add non-number characters on the left of a code block?

Specifically, I want to add ... to correspond with some source code (see image).

enter image description here

I am currently using commands to stop / start the line numbers.
Here is the code:

\documentclass[12pt]{article}

\usepackage[a4paper, margin = 20mm, top = 30mm, bottom = 25mm]{geometry}
\usepackage{xcolor, soul}
\usepackage{listings}

\definecolor{codebackground}{rgb}{0.95, 0.95, 0.92}

\lstset
{
    frame            = tb, % hrule above and below
    keepspaces       = true,
    columns          = flexible,
    basicstyle       = {\normalsize\ttfamily},
    escapeinside     = {(*@}{@*)}, % for escaping
    backgroundcolor  = \color{codebackground},
    showstringspaces = false,
    language         = C,
    keywordstyle     = \color{blue},
    stringstyle      = \color{red},
    commentstyle     = \color{teal},
    numbers          = left, % {none, left, right}
    firstnumber      = 1,
    numberstyle      = \scriptsize\color{black},
    numbersep        = 5pt
}

\let\origthelstnumber\thelstnumber
\makeatletter
% for stopping line numbers
\newcommand*\stopnumber
{
    \lst@AddToHook{OnNewLine}
    {
        \let\thelstnumber\relax
        \advance\c@lstnumber-\@ne\relax
    }
}
% for starting line numbers
\newcommand*\startnumber[1]
{
    \setcounter{lstnumber}{\numexpr#1-1\relax}
    \lst@AddToHook{OnNewLine}
    {
        \let\thelstnumber\origthelstnumber
        \refstepcounter{lstnumber}
    }
}
\makeatother

\begin{document}
\begin{lstlisting}[firstnumber = 456]
int third_function(const int c)
{
    /* error checking */
    if(c < 0)
    {
        return;
    } (*@ \stopnumber @*)

    ...
    (*@ \startnumber{512} @*)
    /* other stuff */
    int d = 4;
    char* word = "third function"; (*@ \stopnumber @*)

    ...
    (*@ \startnumber{678} @*)
    return (c * d);
}
\end{lstlisting}
\end{document}

Best Answer

Here's a simple solution that makes use of the mathescape option to modify the counter and printing of line numbers. You could also use escapeinside if you want to use different escape characters than the standard $...$.

\documentclass{article}
\usepackage{listings}

\lstset{basicstyle=\ttfamily, language=c, numbers=left}

\makeatletter
\let\orig@lstnumber=\thelstnumber

\newcommand\lstsetnumber[1]{\gdef\thelstnumber{#1}}
\newcommand\lstresetnumber{\global\let\thelstnumber=\orig@lstnumber}
\makeatother

\begin{document}
\begin{lstlisting}[firstnumber=100, mathescape=true]
int foo(int x) {
    // some code$\lstsetnumber{\ldots}$
    ...$\lstresetnumber\setcounter{lstnumber}{199}$

    // more code with extra spacing$\lstsetnumber{}$
    $\lstsetnumber{\ldots}$
    ...$\lstsetnumber{}$
    $\lstresetnumber\setcounter{lstnumber}{299}$

    return x;
}
\end{lstlisting}
\end{document}

enter image description here

The \lstsetnumber macro redefines the output macro for line numbers, in the above example to the fixed value \ldots. \lstresetnumber resets the output to the standard definition.

Note that you have to subtract 1 from the next line number if you modify the line counter via \setcounter{lstnumber} as listings automatically increases the counter on the next line.

The code for adding extra empty lines is a bit clumsy, not sure how to add vertical space in a more flexible way here.

Related Question