[Tex/LaTex] Using \lstinline inside a \item

descriptionlistingslistspandocverbatim

I know about the fragility of verbatim-like commands, and that they should not be used as an argument of another macro, but a need to write a description environment in which the terms to be defined are programming variables and functions, and thus I need use \lstinline with them.

I know about Verbatim description list item, but my question is somewhat different, for the following reasons:

  • I don't want only verbatim output and tt font, I want the syntax highlighting provided by \lstinline.
  • I don't write those description environments, they are automatically generated with a tool (pandoc).

In essence, I have a markdown source file containing for example:

The arguments of the function are:

`foo`
   : Name of the file
`bar`
   : Permissions

(the syntax is a markdown extension for descriptions, implemented by pandoc). When processed through pandoc with the appropiate options, the following tex code is generated:

The arguments of the function are:

\begin{description}
\item[\lstinline!foo!] 
Name of the file
\item[\lstinline!bar!]
Permissions
\end{description}

And of course when latex compiles this, it chokes (strangely enough, it does not produce compiling errors, but in the resulting pdf the defined terms disappeared, and they appear later, all overlayed at the same place, at first \item in the next itemize).

So my questions are (in order of preference):

  1. There is some way to redefine \item or \lstinline so that the above works without changes in the generated tex code?
  2. If not, is it possible to define some other command instead of \item (say, \lstitem) which would produce the defined term typeset (and syntax-highlighted) by listings. In this second case I would write a script which searches the tex file for the \item[\lstinline!.*!] stuff and replaces it by \lstitem{.*}.

Best Answer

You could redefine \item so that it reads the stuff between [ ] as horizontal box, which can hold verbatim. For this you need to scan for the beginning [, start the box storing process and make ] an active character (i.e. like a macro) which adds the end of the box and call the original \item with the box as argument.

Tell me if you need further help understanding the code.

\documentclass{article}

\usepackage{listings}

\makeatletter
\let\orig@item\item

\def\item{%
    \@ifnextchar{[}%
        {\lstinline@item}%
        {\orig@item}%
}

\begingroup
\catcode`\]=\active
\gdef\lstinline@item[{%
    \setbox0\hbox\bgroup
        \catcode`\]=\active
        \let]\lstinline@item@end
}
\endgroup

\def\lstinline@item@end{%
    \egroup
    \orig@item[\usebox0]%
}

\makeatother

\begin{document}

The arguments of the function are:

\begin{description}
\item[\lstinline!foo!]
    Name of the file \\[1cm] % other [ ] still work as normal!
    something
\item[\lstinline!bar!]
Permissions
\item[\lstinline!%^$]_!]
verbatim
%\item[\lstinline!stuff! {doesn't work[]}]
%No other ] allowed in the argument
\end{description}

\end{document}
Related Question