11

I have the following mwe:

% arara: pdflatex: { shell: true }
% arara: pdflatex: { shell: true }
\documentclass{article}
\usepackage{minted}
\usepackage{listings}
\usepackage{caption}
\captionsetup[lstlisting]{font=sf,labelfont=bf,skip=\smallskipamount}
\usepackage{xparse}
\NewDocumentEnvironment {example} { mm  }
{\VerbatimEnvironment
 \captionof{lstlisting}{#2}\ifx\relax#1\relax\else\label{#1}\fi%
\begin{minted}[linenos=true]{latex}}
{\end{minted}}
\NewDocumentEnvironment {xexample} { o o  }
{\VerbatimEnvironment
  \IfNoValueF { #1 }%
    {\captionof{lstlisting}{#1}%
      \IfNoValueF {#2} { \label{#2} }%
   }%
  \begin{minted}[linenos=true]{latex}}%
 {\end{minted}}

\begin{document}

\begin{example}{TheLabel}{The caption}
\usepackage{minted}
\usepackage{caption,floatrow}
\end{example}

%\begin{xexample}[Another caption]
%\usepackage{minted}
%\usepackage{caption,floatrow}
%\end{xexample}

See Example~\ref{TheLabel}

\end{document}

The environment example works like expected. However this environment has two mandatory arguments. I am a friend of optional arguments/keys. With the environment xexample I tried this implementation but it fails.

What's going on here?

Bonus: Is it possible to pass options to minted as well? (of course with an optional argument ;-))

Marco Daniel
  • 95,681
  • why can't you use \begin{minted}[caption=...,label=...]?? –  May 02 '13 at 18:31
  • @Herbert: minted doesn't provide the options caption nor label. egreg found a nice way: http://chat.stackexchange.com/transcript/message/9247614#9247614 – Marco Daniel May 02 '13 at 18:38
  • it is pretty easy to make all options from fancyvrb available for minted. –  May 02 '13 at 18:42
  • @Herbert: Do you mean \fvset? I have no idea? – Marco Daniel May 02 '13 at 18:44
  • the keys from fancyvrb are imported by minted with \minted@define@extra{...} Replace ... with label and it is known. But I suppose that fancyvrb did not know the caption option. –  May 02 '13 at 18:52

2 Answers2

10

The problem is that when verbatim-style environments take optional arguments, you need to use \obeylines to prevent the body of the environment from being tokenized in the process of checking for arguments.

You should be able to pass options to minted, though if you're primarily working with formatting, passing options directly to \fvset might be easier.

\documentclass{article}
\usepackage{minted}
\usepackage{listings}
\usepackage{caption}
\captionsetup[lstlisting]{font=sf,labelfont=bf,skip=\smallskipamount}
\usepackage{xparse}
\NewDocumentEnvironment {example} { mm  }
{\VerbatimEnvironment
 \captionof{lstlisting}{#2}\ifx\relax#1\relax\else\label{#1}\fi%
\begin{minted}[linenos=true]{latex}}
{\end{minted}}
\NewDocumentEnvironment {xexample} {}
{\VerbatimEnvironment
 \begingroup\obeylines\getargs}%
 {\end{minted}}

\NewDocumentCommand\getargs{ o o }
{\endgroup
  \IfNoValueF { #1 }%
    {\captionof{lstlisting}{#1}%
      \IfNoValueF {#2} { \label{#2} }%
   }%
  \begin{minted}[linenos=true]{latex}}

\begin{document}

\begin{example}{TheLabel}{The caption}
\usepackage{minted}
\usepackage{caption,floatrow}
\end{example}

\begin{xexample}[Another caption]
\usepackage{minted}
\usepackage{caption,floatrow}
\end{xexample}

See Example~\ref{TheLabel}

\end{document}

enter image description here

G. Poore
  • 12,417
7

I propose a different syntax with a key-value interface that enables you to specify much more than the caption and the label, for instance options to be passed to minted and also the language.

% arara: pdflatex: { shell: true }
% arara: pdflatex: { shell: true }
\documentclass{article}
\usepackage{minted}
\usepackage{listings}
\usepackage{caption}
\captionsetup[lstlisting]{font=sf,labelfont=bf,skip=\smallskipamount}
\usepackage{xparse}

\ExplSyntaxOn
\keys_define:nn {xexample}
 {
  caption  .tl_set:N = \l_mdxex_caption_tl,
  label    .tl_set:N = \l_mdxex_label_tl,
  minted   .tl_set:N = \l_mdxex_minted_tl,
  language .tl_set:N = \l_mdxex_language_tl
 }

\NewDocumentEnvironment {xexample} { O {} }
 {
  \keys_set:nn { xexample }
   {
    language=latex,
    #1
   }
  \tl_set:Nx \l__mdxex_temp_tl
   {
    \exp_not:N \VerbatimEnvironment
    \tl_if_empty:NTF \l_mdxex_caption_tl
     {
      \scan_stop:
     }
     {
      \exp_not:N \captionof { lstlisting }{ \exp_not:V \l_mdxex_caption_tl }
      \tl_if_empty:NF \l_mdxex_label_tl
       { \exp_not:N \label { \l_mdxex_label_tl } }
     }
    \exp_not:n { \begin{minted} } [ \l_mdxex_minted_tl ] { \l_mdxex_language_tl }
   }
  \l__mdxex_temp_tl
 }
 {\end{minted}}
\ExplSyntaxOff

\begin{document}

\begin{xexample}[caption=The caption,label=TheLabel,language=bash]
ls -l /usr/local/texlive/2012/texmf-dist
\end{xexample}

\begin{xexample}[caption=Another caption,label=foo,
  minted={linenos=true}]
\usepackage{minted}
\usepackage{caption,floatrow}
\end{xexample}

See example~\ref{TheLabel} and example~\ref{foo}

\end{document}

enter image description here

egreg
  • 1,121,712
  • Is it possible to put the caption below the listings? – Marco Daniel May 02 '13 at 20:01
  • I like this approach, but it's giving me errors when no optional argument is supplied. – G. Poore May 02 '13 at 20:18
  • @G.Poore This should be fixed now. – egreg May 02 '13 at 20:31
  • @egreg Still throws an error for me if no optional arguments are provided: FancyVerb Error: Extraneous input '\usepackage {minted}' between \begin{xexample}[<key=value>] and line end . \FV@Error ... {FancyVerb Error: \space \space #1 } – steve Aug 26 '20 at 14:20