[Tex/LaTex] How to make “sub-level” numbering for listings, similar to subcaption

listingsnumberingsubcaptiontable of contents

I think what I'm trying to do may be complicated, so if not all of it is possible then that's OK. I'm using the listings package and I've done something similar to Custom numbering of listings elsewhere on tex.sx, where listings are numbered 2.a 2.b 2.c, but I'd like it to be better. I've drawn a picture of the output I'd like to achieve (the coloured boxes are just for illustrating the idea):

Link to my drawing because new users can't post pictures...

Each "sub-listing" has a letter and then there's a number at the bottom for all three of them together. I'd like to be able to refer to the sub-listings so that 8.a or 8.(a) or whatever is shown in the document.

I tried (and failed miserably) to do this by adapting examples from the subcaption package which used figures and images, but compilation failed with "Missing number, treated as zero", probably because I have no idea what I'm doing with subcaption. What I tried with sub-caption was something like:

\usepackage{caption,subcaption}

...

\begin{figure}

  \begin{subfigure}
    \lstinputlisting[language=sql]{path/to/file1}
    \caption{Caption for first listing}
    \label{lst:file1}
  \end{subfigure}

  \begin{subfigure}
    \lstinputlisting[language=xml]{path/to/file2}
    \caption{Caption for second listing}
    \label{lst:file2}
  \end{subfigure}

  \caption{General caption for all 3}

\end{figure}

A lot of subcaption seems to deal with putting things next to each other, but as these are listings I'd like them above each other like normal, and only used subcaption to try to get the numbering to change. I also have a List of Listings and it would be great if in there, these a, b and c listings were indented after #8, as happens when you make sections and sub-sections in the Table of Contents.

Any help with this will be greatly appreciated.

Best Answer

\documentclass{article}

\usepackage{listings}
\AtBeginDocument{\DeclareCaptionSubType{lstlisting}}
\usepackage{caption,subcaption}

\begin{document}

\lstlistoflistings

\begin{figure}[!ht]
\captionsetup{type=lstlisting}
\begin{sublstlisting}{\linewidth}
\begin{lstlisting}
test listing one
\end{lstlisting}
\caption{Caption for first listing}
\label{lst:file1}
\end{sublstlisting}
\begin{sublstlisting}{\linewidth}
\begin{lstlisting}
test listing two
\end{lstlisting}
\caption{Caption for second listing}
\label{lst:file2}
\end{sublstlisting}
\caption{General caption for all 3}
\label{lst:general}
\end{figure}

As we can see in Listings~\ref{lst:file1} and~\ref{lst:file2}...

\end{document}

This solution was taken from Gonzalo Medina, and the tricks 1 to 4 have been replaced by a different one:

The listings package defines some stuff needed for captions \AtBeginDocument, so \DeclareCaptionSubType won't work straight-forward on lstlisting. Unfortunately the (sub)caption package needs to do important stuff \AtBeginDocument, too, and \DeclareCaptionSubType must be executed before that stuff. So in total I use \AtBeginDocument{\DeclareCaptionSubType{lstlisting}} after loading the listings package but before loading the (sub)caption package to make it work.

This way we don't need an extra counter, no counter saving, no manual counter incrementation, no suppressing of the list entry, and no doing the list entry by hand.

(If the listings should not float just replace the figure environment by a minipage environment.)

P.S.: For details on \DeclareCaptionSubType just take a look at my subcaption package documentation.