Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

share|improve this question
    
Use as \begin{subfigure}{0.5\linewidth} as the mechanism is looking for the space to be allocated in the figure space (roughly speaking). If you leave an empty line between subfigures, as in your code, it will stack them up. –  percusse Jul 19 '12 at 10:49
    
Thanks, by removing the empty lines and setting the width it now compiles as I want and the references work, now the only problem is the List of Listings. It has added the figure to List of Figures but I'd like it in listings (because it contains listings not figures), and the List of Listings now contains un-numbered items with the filenames of my source code. –  sinisterstuf Jul 19 '12 at 11:13
    
for that you either define a new float within listing options or you use the float package to define a custom float environment. Searc this site for more application examples. –  percusse Jul 19 '12 at 11:28
    
@AxelSommerfelt has provided a much better answer, so you should consider accepting his answer instead of mine. –  Gonzalo Medina Jul 19 '12 at 19:19
add comment

2 Answers

up vote 4 down vote accepted
\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.

share|improve this answer
add comment

If this special structure is to be used once or twice, a "manual" solution can be applied; the code below shows such a solution.

  1. \captionsetup (from the caption package) was used to prevent the general caption for the figure to go to the list of figures and to change the name "Figure" to "Listing" for the caption label.
  2. \addcontentsline was used to add the caption to the list of listings.
  3. The lstlistings counter was stepped.
  4. A temporal counter tmp was used to store the value for the figure counter at the begining of the "faked" figure environment; then the figure counter was assigned the correct value for the lstlisting counter. At the end of the environment, the figure counter is restored to its previously stored value.

    \documentclass{article}
    \usepackage{listings}
    \usepackage{caption,subcaption}
    
    \newcounter{tmp}
    
    \begin{document}
    
    \lstlistoflistings
    \listoffigures
    
    \begin{figure}[!ht]
    \setcounter{tmp}{\thefigure}
    \setcounter{figure}{\thelstlisting}
    \captionsetup{list=no,name=Listing}
    \begin{subfigure}{\linewidth}
    \begin{lstlisting}
    test listing one
    \end{lstlisting}
    \caption{Caption for first listing}
    \label{lst:file1}
    \end{subfigure}
    \begin{subfigure}{\linewidth}
    \begin{lstlisting}
    test listing two
    \end{lstlisting}
    \caption{Caption for second listing}
    \label{lst:file2}
    \end{subfigure}
    \caption{General caption for all 3}
    \label{lst:general}
    \addcontentsline{lol}{lstlisting}{\protect\numberline{\thefigure}General caption for all 3}
    \stepcounter{lstlisting}
    \setcounter{figure}{\thetmp}
    \end{figure}
    
    As we can see in Listings~\ref{lst:file1} and~\ref{lst:file2}...
    
    \end{document}
    

enter image description here

share|improve this answer
    
That worked perfectly, all I needed to do additionally was to add nolol=true to remove the listing filenames which had appeared in the LoL, thanks a lot for your answer! –  sinisterstuf Jul 19 '12 at 14:09
    
One can replace the tricks 1 to 4 with a different one, see my solution below... –  Axel Sommerfeldt Jul 19 '12 at 19:02
    
@AxelSommerfeldt nice! I initially tried a similar approach but it didn't work (I didn't use the \AtBeginDocument trick). –  Gonzalo Medina Jul 19 '12 at 19:17
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.