[Tex/LaTex] listings package: no numbering in case the code has only one line

codelistingsnumbering

I have a custom style in lstlisting with numbers on the left and the number step is set every line. I would want to know how the listings could appear without number in case the listing has only one line.

My configuration is the following:

\lstset{
breaklines=true,
captionpos=b, % sets the caption-position to bottom
basicstyle=\ttfamily\footnotesize,
commentstyle=\color{verdeComentario},   
numbers=left, % número de línea a la izquierda
stepnumber=1, % salto de cada línea
tabsize=3,
numberstyle=\tiny,
xleftmargin=15pt,
xrightmargin=15pt,
framesep=5pt,
frame=tb,
framerule=0.2pt,
backgroundcolor=\color{grisDebil},
lineskip=-1pt,
tabsize=3,
escapeinside={@}{@},
aboveskip=20pt,
belowskip=20pt,
}

% -----------------------------
%     Maude
% -----------------------------

\lstdefinelanguage{maude}
{
    alsoletter={\:},
    morecomment=[l]{---},
    morecomment=[l]{***},
    keywords={in, load, pr, protecting, sort, sorts, subsort, subsorts, including, class, msg, msgs, endfm, fmod, is, mod, endm, omod, endom},
    keywords=[2]{eq,  mb, ceq, if, rl, crl, else, then, fi},
    keywords=[3]{ctor, assoc, comm, gather, id\:},
    keywords=[4]{op, ops, var, vars}
}

\lstdefinestyle{maude}{
    language=maude,
    keywordstyle=\bfseries\color{rojoReservado},
    keywordstyle=[2]\bfseries\color{verdeReservado},
    keywordstyle=[3]\bfseries\color{turquesaReservado},
    keywordstyle=[4]\bfseries\color{moradoReservado},
}

I could set in every listing with only one line the option numbers=none but I have a large document just written and I'll be very gratefull if I know how to do it automatically.

Best Answer

Here's a quick solution I put together using Heiko's answer to a question about referring to the number of lines in a listing, but I had to remove the \protect to make it work. None of your configuration is relevant so I have ignored it.

Heiko's code uses the referencing system to save the number of lines in a listing (so this information is not known on the first run and not correct on the first run after changing or adding listings), and I just added code to the PreSet hook of listings to disable the numbers if there is only one line in the listing, and to set numbering on the left otherwise. This can still be overridden by passing options to the individual listings as shown in the last two examples:

\documentclass[a4paper]{article}
\usepackage{listings}
\usepackage{zref-base}

\makeatletter
\newcounter{mylstlisting}
\newcounter{mylstlines}
\lst@AddToHook{PreSet}{%
  \stepcounter{mylstlisting}%
  \ifnum\mylstlines=1\relax
    \lstset{numbers=none}
  \else
    \lstset{numbers=left}
  \fi
  \setcounter{mylstlines}{0}%
}
\lst@AddToHook{EveryPar}{%
  \stepcounter{mylstlines}%
}
\lst@AddToHook{ExitVars}{%
  \begingroup
    \zref@wrapper@immediate{%
      \zref@setcurrent{default}{\the\value{mylstlines}}%
      \zref@labelbyprops{mylstlines\the\value{mylstlisting}}{default}%
    }%
  \endgroup
}

% \mylstlines print number of lines inside listing caption
\newcommand*{\mylstlines}{%
  \zref@extractdefault{mylstlines\the\value{mylstlisting}}{default}{0}%
}
\makeatother

% cosmetics
\usepackage[T1]{fontenc}
\usepackage[variablett]{lmodern}
\lstset{basicstyle=\ttfamily, columns=fullflexible,
    numbers=left, stepnumber=1}

\begin{document}
  \lstlistoflistings

  \section*{Main}
  \begin{lstlisting}[
    caption={Example with \mylstlines\ lines.},
  ]
  Hello
  world
  \end{lstlisting}

  \hrule

  \begin{lstlisting}[
    caption={Example with \mylstlines\ lines.},
  ]
  Hello
  \end{lstlisting}

  \hrule

  \begin{lstlisting}[
    caption={Example with \mylstlines\ lines. Can still override numbering.},numbers=none
  ]
  Hello
  world
  \end{lstlisting}

  \hrule

  \begin{lstlisting}[
    caption={Example with \mylstlines\ lines. Can still override numbering.},numbers=left
  ]
  Hello
  \end{lstlisting}


\end{document}

Screenshot

(Thanks to Peter Grill for pointing out that the previous version of this answer gave errors on the first runs before the aux files were set up. This has now been fixed.)