[Tex/LaTex] Multiple listings in one box with sub captions and using listings counter

captionslistingssubfloats

I am using separate counters for (graphics) figures and listings. I am using the caption and subcaption packages. I construct sub-figures using subfigure:

\begin{figure}
\begin{subfigure}{0.34\textwidth}
...
\caption{sub-1}\label{fig:sub1}
\end{subfigure}
\begin{subfigure}{0.34\textwidth}
...
\caption{sub-2}\label{fig:sub2}
\end{subfigure}
\end{figure}

Now I need the same construction for listings. Like

\newsavebox{\verbsavebox}

\begin{figure}
\begin{lrbox}{\verbsavebox}
\begin{minipage}{.34\textwidth}
\begin{Verbatim}
...
\end{Verbatim}
\end{minipage}
\end{lrbox}%
\begin{subfigure}{0.34\textwidth}
\usebox{\verbsavebox}
\caption{sub-1}\label{lst:sub1}
\end{subfigure}
\begin{lrbox}{\verbsavebox}
\begin{minipage}{.34\textwidth}
\begin{Verbatim}
...
\end{Verbatim}
\end{minipage}
\end{lrbox}%
\begin{subfigure}{0.34\textwidth}
\usebox{\verbsavebox}
\caption{sub-2}\label{lst:sub2}
\end{subfigure}
\end{figure}

The problem is that this uses the figure counter, and the main caption is named "Fig…". What I want is use the listings counter and have the main caption named "Listing…".


EDIT Here is another try using lstlisting:

\documentclass{article}
\usepackage{verbatimbox}
\usepackage[T1]{fontenc}
\usepackage{fancyvrb}
\usepackage{listings}
\usepackage[scaled=.73]{beramono}
\fvset{baselinestretch=0.94}
\parindent=0pt
\parskip = 6pt

% "define" Scala
\lstdefinelanguage{scala}{
  morekeywords={abstract,case,catch,class,def,%
    do,else,extends,false,final,finally,%
    for,if,implicit,import,match,mixin,%
    new,null,object,override,package,%
    private,protected,requires,return,sealed,%
    super,this,throw,trait,true,try,%
    type,val,var,while,with,yield,then}, % we use `then` in the pseudocode
  otherkeywords={=>,<-,<\%,<:,>:,\#,@},
  sensitive=true,
  morecomment=[l]{//},
  morecomment=[n]{/*}{*/},
  morestring=[b]",
  morestring=[b]',
  morestring=[b]"""
}

% activate the language and predefine settings
\lstset{
    basicstyle=\linespread{0.94}\ttfamily,%
    language=scala,%
    commentstyle=\itshape,%
    keywordstyle=\bfseries,%
    fancyvrb=true,%
    mathescape=true,%  for pseudocode
    captionpos=b, % captions at the bottom
}

\begin{document}

In Fig.~\ref{fig:label} versus Listings~\ref{lst:label1} and \ref{lst:label2}.

\begin{figure}
Empty
\caption{fig}\label{fig:label}
\end{figure}

\begin{figure} % [htp]
\begin{lstlisting}{caption={list1},label={lst:label1}}
trait Sys[S <: Sys[S]] {
  type ID <: Ident[S#Tx]
  type Tx
}

trait Muta[S <: Sys[S]] {
  def id: S#ID
  // well defined:
  def dispose(tx: S#Tx) =
    id.dispose(tx)
}

trait Ident[Tx] {
  def dispose(tx: Tx): Unit
}
\end{lstlisting}
\begin{lstlisting}{caption={list2},label={lst:label2}}
trait Sys {
  type ID <: Ident[Tx]
  type Tx
}

trait Muta[S <: Sys] {
  def id: S#ID   
  // incompatible type:
  def dispose(tx: S#Tx) =
    id.dispose(tx)
}
\end{lstlisting}
\begin{lstlisting}{caption={list3},label={lst:label3}}
trait Sys {
  type ID <: Ident[Tx]
  type Tx
}

trait Muta[S <: Sys] {
  // evidence required:
  val s: S
  def id: s.ID
  // well defined:
  def dispose(tx: s.Tx) =
    id.dispose(tx)
}
\end{lstlisting}
\caption{Total caption}\label{lst:total}
\end{figure}

\end{document}

The problem is, the listings box gets numbered "Figure 2" instead of "Listing 1", and there are no sub captions (a) (b) (c). The reference in the text is broken, too. And the three listings should appear in three columns next to each other. So this is how the preceding code looks:

enter image description here

And this is a mock up of how it should look:

enter image description here


EDIT 2

Ok, so I compiled paracol.sty and tried:

\documentclass{article}
\usepackage{verbatimbox}
\usepackage[T1]{fontenc}
\usepackage{fancyvrb}
\usepackage{listings}
\usepackage[scaled=.73]{beramono}
\fvset{baselinestretch=0.94}
\parindent=0pt
\parskip = 6pt
\usepackage{caption}

% "define" Scala
\lstdefinelanguage{scala}{
  morekeywords={abstract,case,catch,class,def,%
    do,else,extends,false,final,finally,%
    for,if,implicit,import,match,mixin,%
    new,null,object,override,package,%
    private,protected,requires,return,sealed,%
    super,this,throw,trait,true,try,%
    type,val,var,while,with,yield,then}, % we use `then` in the pseudocode
  otherkeywords={=>,<-,<\%,<:,>:,\#,@},
  sensitive=true,
  morecomment=[l]{//},
  morecomment=[n]{/*}{*/},
  morestring=[b]",
  morestring=[b]',
  morestring=[b]"""
}

% activate the language and predefine settings
\lstset{
    basicstyle=\linespread{0.94}\ttfamily,%
    language=scala,%
    commentstyle=\itshape,%
    keywordstyle=\bfseries,%
    fancyvrb=true,%
    mathescape=true,%  for pseudocode
    captionpos=b, % captions at the bottom
}

\usepackage{capt-of}
\usepackage{paracol}

\begin{document}

In Fig.~\ref{fig:label} versus Listings~\ref{lst:label1} and \ref{lst:label2}.

\begin{paracol}{3}
\begin{lstlisting}
trait Sys[S <: Sys[S]] {
  type ID <: Ident[S#Tx]
  type Tx
}

trait Muta[S <: Sys[S]] {
  def id: S#ID
  // well defined:
  def dispose(tx: S#Tx) =
    id.dispose(tx)
}

trait Ident[Tx] {
  def dispose(tx: Tx): Unit
}
\end{lstlisting}
\switchcolumn
\begin{lstlisting}
trait Sys {
  type ID <: Ident[Tx]
  type Tx
}

trait Muta[S <: Sys] {
  def id: S#ID   
  // incompatible type:
  def dispose(tx: S#Tx) =
    id.dispose(tx)
}
\end{lstlisting}
\switchcolumn
\begin{lstlisting}
trait Sys {
  type ID <: Ident[Tx]
  type Tx
}

trait Muta[S <: Sys] {
  // evidence required:
  val s: S
  def id: s.ID
  // well defined:
  def dispose(tx: s.Tx) =
    id.dispose(tx)
}
\end{lstlisting}
\end{paracol}

\begin{figure}
Empty
\caption{fig}\label{fig:label}
\end{figure}

\end{document}

This produces three identical caption numbers and not 1a, 1b, 1c:

enter image description here

Best Answer

The following should be right up your allow. It's achieved with the aid of subcaption and some manual float management:

enter image description here

\documentclass{article}
\usepackage{verbatimbox}
\usepackage[T1]{fontenc}
\usepackage{fancyvrb,listings,caption}
\usepackage[labelformat=simple]{subcaption}
\usepackage[scaled=.73]{beramono}
\fvset{baselinestretch=0.94}
\parindent=0pt
\parskip = 6pt

\makeatletter
\AtBeginDocument{\DeclareCaptionSubType{lstlisting}
\renewcommand{\p@sublstlisting}{\thelstlisting}
\renewcommand{\thesublstlisting}{(\alph{sublstlisting})}
}
\makeatother
% "define" Scala
\lstdefinelanguage{scala}{
  morekeywords={abstract,case,catch,class,def,%
    do,else,extends,false,final,finally,%
    for,if,implicit,import,match,mixin,%
    new,null,object,override,package,%
    private,protected,requires,return,sealed,%
    super,this,throw,trait,true,try,%
    type,val,var,while,with,yield,then}, % we use `then` in the pseudocode
  otherkeywords={=>,<-,<\%,<:,>:,\#,@},
  sensitive=true,
  morecomment=[l]{//},
  morecomment=[n]{/*}{*/},
  morestring=[b]",
  morestring=[b]',
  morestring=[b]"""
}

% activate the language and predefine settings
\lstset{
    basicstyle=\linespread{0.94}\ttfamily,%
    language=scala,%
    commentstyle=\itshape,%
    keywordstyle=\bfseries,%
    fancyvrb=true,%
    mathescape=true,%  for pseudocode
    captionpos=b, % captions at the bottom
}
\newsavebox{\verbsavebox}
\begin{document}

In Fig.~\ref{fig:label} versus Listings~\ref{lst:label1} and \ref{lst:label2}.

\begin{figure}
Empty
\caption{fig}\label{fig:label}
\end{figure}

\begin{figure} % [htp]
% Let's make this an lstlisting, not a figure...
\makeatletter\def\@captype{lstlisting}\makeatother
\begin{lrbox}{\verbsavebox}
\begin{lstlisting}[xrightmargin=.6667\linewidth]
trait Sys[S <: Sys[S]] {
  type ID <: Ident[S#Tx]
  type Tx
}

trait Muta[S <: Sys[S]] {
  def id: S#ID
  // well defined:
  def dispose(tx: S#Tx) =
    id.dispose(tx)
}

trait Ident[Tx] {
  def dispose(tx: Tx): Unit
}
\end{lstlisting}
\end{lrbox}
\subcaptionbox{list1\label{lst:label1}}{\usebox{\verbsavebox}}\hfill%
\begin{lrbox}{\verbsavebox}
\begin{lstlisting}[xrightmargin=.6667\linewidth]
trait Sys {
  type ID <: Ident[Tx]
  type Tx
}

trait Muta[S <: Sys] {
  def id: S#ID   
  // incompatible type:
  def dispose(tx: S#Tx) =
    id.dispose(tx)
}
\end{lstlisting}
\end{lrbox}
\subcaptionbox{list2\label{lst:label2}}{\usebox{\verbsavebox}}\hfill%
\begin{lrbox}{\verbsavebox}
\begin{lstlisting}[xrightmargin=.6667\linewidth]
trait Sys {
  type ID <: Ident[Tx]
  type Tx
}

trait Muta[S <: Sys] {
  // evidence required:
  val s: S
  def id: s.ID
  // well defined:
  def dispose(tx: s.Tx) =
    id.dispose(tx)
}
\end{lstlisting}
\end{lrbox}
\subcaptionbox{list3\label{lst:label3}}{\usebox{\verbsavebox}}
\caption{Total caption\label{lst:total}}
\end{figure}

\end{document}

Each of the listings are set in a box \verbsavebox of width .3333\linewidth (by setting xrightmargin=.6667\linewidth). These boxes, once set, are added using \subcaptionbox{<caption>}{\usebox{\verbsavebox}}, where <caption> includes both the caption and the \label.

Immediately inside the figure environment, we strategically update the \@captype to be lstlisting. This fools TeX to think that it's dealing with a float called lstlisting when you call \caption. This is necessary since the \subcaptions are set before the main \caption, which requires \p@lstlisting (the parent counter associated with the subcounter sublstlisting) to be set correctly. This is all related to the functionality of the subcaption package.

The subcaptions are defined \AtBeginDocument, which is to coincide with the float definitions of listings, which is done at the same time. subcaption requires a float to exist before it allows one to define subcaptions for it.

Related Question