[Tex/LaTex] Label a lstlisting listing in the lower right corner

listingspositioning

I want to put a label in the lower right corner of my listings, in this case to indicate the kind of code listed there. I have a bad hack that works somewhat and illustrates what I want:

\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\definecolor{light-gray}{gray}{0.95}
\newcommand{\mylabel}[1]{\raisebox{1em}[0pt][0pt]{\makebox[0pt][l]{\makebox[\linewidth][r]{\color{gray}{\sffamily #1}\hspace{3.5em}}}}\ignorespaces}
\lstnewenvironment{code}{\lstset{
    ,frame=single
    ,xleftmargin=2em
    ,xrightmargin=2em
    ,backgroundcolor=\color{light-gray}
    ,belowskip=0pt
}}{\mylabel{Code}}
\begin{document}
\begin{code}
This is
some code
set with lstlisting
\end{code}

This is again regular text.
\end{document}

Which looks like this:

enter image description here

The problem is that it

  • does not work well with page breaks directly after the listing, i.e. the label may appear on the next page
  • If the listing is followed by a blank line, the spacing is increased twice (due to the zero-sized but still existing content between the listing and the paragraph).
  • It is not elegant.

Are there nicer ways of obtaining this result?

Best Answer

One easy option would be to use the escapechar option to escape to LaTeX and simply put the label generation into the last line of the listing:

\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\definecolor{light-gray}{gray}{0.95}

\newcommand{\mylabel}[1]{\hfill{\color{gray}{\sffamily #1\strut}\hspace{1em}}}

\lstnewenvironment{code}{\lstset{
    ,frame=single
    ,xleftmargin=2em
    ,xrightmargin=2em
    ,backgroundcolor=\color{light-gray}
    ,belowskip=0pt,
    ,escapechar={§},
}}{}
\begin{document}
\begin{code}
This is
some code
set with lstlisting §\mylabel{Code}§
\end{code}

This is again regular text.
\end{document}

enter image description here


The above has – depending on the viewpoint – the (dis-)advantage that you (have to/can) specify the label in the actual listing source code.

If you want the label as a parameter to the code environment, a bit more work is necessary:

\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{adjustbox,tikz}
\definecolor{light-gray}{gray}{0.95}

\makeatletter
\newcommand{\mylabel}[1]{\color{gray}{\sffamily #1}\hspace{1em}}    

\lstnewenvironment{code}[1]{
    \lstset{
        ,frame=single
        ,xleftmargin=2em
        ,xrightmargin=2em
        ,backgroundcolor=\color{light-gray}
        ,belowskip=0pt,
    }%
    \def\code@arg{#1}%
    \setbox0\hbox\bgroup%
}
{%
    \egroup\usebox0% printout the listing
    \raisebox{\dimexpr-\dp0+\ht\strutbox\relax}{% move near bottom of listing
        \makebox[\dimexpr-\wd0+\lst@linewidth\relax][r]{% makebox to right border
            \mylabel{\code@arg}%
        }%
    }%
}
\makeatother

\begin{document}
\begin{code}{Label}
This is
some code
set with lstlisting
\end{code}

This is again regular text bla bla.
\end{document}

enter image description here