# Using listing inside a custom command

Good afternoon, I am having the following problem: I have to describe a set of items that have all the same format, let's say property 1, property 2, ecc. For this reason I created a new command, so that i can specify only the relevant information and rely on the fixed structure. The problem comes when I want to give as an argument to the command a piece of code using \lstinline. Here the piece that gives me trouble:

The command:

%1: title
%2: description
%3: HTTP request
%4: Path parameters
%5: Request body
%6: Response body
\newcommand{\API}[6]{
\subsubsection*{#1}
#2 \\ \\
\textbf{HTTP request:} \api{#3} \\
\textbf{Path parameters:} #4 \\
\textbf{Request body:} #5 \\
\textbf{Response body:} #6
}


Usage in document:

\API{getProfile}
{Gets the current user's Gmail profile.}
{GET /gmail/v1/users/{userId}/profile}
{
\begin{itemize}
\item \textbf{userId:} The user's email address. The special value me can be used to indicate the authenticated user.
\end{itemize}
}
{The request body must be empty.}
{If successful, the response body contains data with the following structure:
\lstinline{
{
"messagesTotal": integer,
"historyId": string
}
}}


The problem is that generates various errors and it is not rendered as expected. Can you provide me a way to make things work? Every further advice to obtain a better result is welcome.

EDIT: Here there is an example in Overleaf.

• Welcome to TeX.SX! You can't use verbatim environments (as lstlisting) as arguments in commands... maybe you can use an environment. See texfaq.org/FAQ-verbwithin – Rmano Feb 5 at 18:48
• Welcome to TeX.SX! Please make your code compilable (if possible), or at least complete it with \documentclass{...}, the required \usepackage's, \begin{document}, and \end{document}. That may seem tedious to you, but think of the extra work it represents for TeX.SX users willing to give you a hand. Help them help you: remove that one hurdle between you and a solution to your problem. – Rmano Feb 5 at 18:48
• @Rmano ok, as you suggested I added a link to overleaf. I used listings only because is the only one I know, do you have another solution that will allow me to achieve the wanted result? – Zack Feb 5 at 19:09
• A link to Overleaf does not count as a complete example. It could become invalid, and it's doubtful that you've trimmed this down to the minimal required. Rmano's texfaq link has several options for you to consider; have you looked through them? – Teepeemm Feb 5 at 19:45
• @UlrichDiez it is just an example from Google's API, just to present the format. I am sorry for the link on Overleaf, I forgot that even to see it is necessary to have an account. I read the cited article, but I also need some colour for the listings, for this reason I wanted to use listings package. However I didn't try to use that hints to work with listings. – Zack Feb 9 at 10:22

• You try to use \lstinline for creating a code-listing which consists of several lines. This is not possible. The entire argument of \lstinline must occur within the same line of .tex-input.
• \lstinline's syntax is similar to the syntax of \verb, where in the .tex-input the argument also must not span several lines, and which also cannot be used within macro-definitions and the like as it also relies on having the argument tokenized under different category-code-régime/under verbatim-category-code-régime:
You can do \lstinline|some code snippet|.
As an exceptional case, if the left-delimiter is {, then the right delimiter is to be }. The problem with this exceptional case is that \lstinline will not keep track of brace-matching.
Therefore \lstinline{Some {nice} code} will not work out as expected: \lstinline will take Some {nice for the code-snippet. The trailing  code} contains an unmatched closing-brace which causes an error-message ! Extra }, or forgotten \endgroup.
• As you use inputenc with utf8-encoding (, which, by the way, is the default with recent TeX-installations), I recommend reading section 2.5 Special characters of the manual of the listings package.

How one could approach the matter:

You can probably use the xparse-package's +v-type-argument for having LaTeX read and tokenize everything in verbatim-category-code-régime and then passing things to \scantokens for re-tokenization.

Some remarks about the idea of doing it the verbatim-argument→\scantokens-way:

• If you do this, the command \API can be used in ways only where it gets its arguments either by reading/tokenizing .tex-input or by having them passed from another macro where they got tokenized under verbatim-category-code-régime.
• If you do this, you need to pay attention within your .tex-input to get the indentation right when using environments like lstlistings or verbatim that process verbatim-material.

\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{xparse}
\usepackage{listings}

\begingroup
\newcommand\scantokenswithendlinechar[1]{%
\endgroup
\DeclareRobustCommand\scantokenswithendlinechar[1]{%
\begingroup\newlinechar=\endlinechar\scantokens{\endgroup##1#1}%
}%
}%
\catcode\%=12\relax
\scantokenswithendlinechar{%}%

\newcommand\apibreak{%
\ifhmode\\\null\else\ifvmode\noindent\fi\fi
}%

\newcommand{\api}[1]{\textbf{\texttt{#1}}}

\NewDocumentCommand\API{}{%
\begingroup
\catcode\^^I=12 %
\innerAPI
}%
\NewDocumentCommand{\innerAPI}{+v+v+v+v+v+v}{%
\endgroup
\subsubsection*{\scantokenswithendlinechar{#1}}%
\scantokenswithendlinechar{#2}\apibreak\bigskip
\textbf{HTTP request:} \api{\scantokenswithendlinechar{#3}}\apibreak
\textbf{Path parameters:} \scantokenswithendlinechar{#4}\apibreak
\textbf{Request body:} \scantokenswithendlinechar{#5}\apibreak
\textbf{Response body:} \scantokenswithendlinechar{#6}\par
}

\begin{document}

\API{getProfile}
{Gets the current user's Gmail profile.}
{GET /gmail/v1/users/{userId}/profile}
{%
\begin{itemize}
\item \textbf{userId:} The user's email address. The special value me
can be used to indicate the authenticated user.
\end{itemize}
}%
{The request body must be empty.}
{If successful, the response body contains data with the following structure:
%!!! Be aware of the indenting with verbatim-environments !!!
\begin{lstlisting}
{
"messagesTotal": integer,
"historyId": string
}
\end{lstlisting}
}

\end{document}


You probably are interested in using the description-environment:

\documentclass[12pt]{article}

%% The following three packages are not needed with up-to-date LaTeX
%% but may be needed with not so recent LaTeX distros:
%\usepackage[utf8]{inputenc}
%\usepackage[T1]{fontenc}
%% \NewDocumentCommand  etc:
% \usepackage{xparse}

%% These packages provide bold typewriter font:
%\usepackage[ttdefault=true]{AnonymousPro}
%\usepackage{tgcursor}
\usepackage{lmodern}

%% For code-listings:
\usepackage{listings}
\lstset{basicstyle=\ttfamily}

\begingroup
\newcommand\scantokenswithendlinechar[1]{%
\endgroup
\DeclareRobustCommand\scantokenswithendlinechar[1]{%
\begingroup\newlinechar=\endlinechar\scantokens{\endgroup##1#1}%
}%
}%
\catcode\%=12\relax
\scantokenswithendlinechar{%}%

\NewDocumentCommand\API{}{%
\begingroup
\catcode\^^I=12 %
\innerAPI
}%
\NewDocumentCommand{\innerAPI}{+v+v+v+v+v+v}{%
\endgroup
\subsubsection*{\scantokenswithendlinechar{#1}}%
\scantokenswithendlinechar{#2}%
\bigskip
\begin{description}%
\item[{HTTP request:}]%
\expandafter\scantokenswithendlinechar\expandafter{%
% !!!!! It is assumed that the argument #3 for the HTTP-request  !!!!!
% !!!!! does _not_ contain the character |                       !!!!!
% !!!!! If the case of #3 containing | can occur, for delimiting !!!!!
% !!!!! #3 choose a different character which definitely never   !!!!!
% !!!!! occurs within #3                                         !!!!!
\string\lstinline[basicstyle=\bfseries\ttfamily]|#3|%
}%
\item[{Path parameters:}]\scantokenswithendlinechar{#4}%
\item[{Request body:}]\scantokenswithendlinechar{#5}%
\item[{Response body:}]\scantokenswithendlinechar{#6}%
\end{description}%
}

\makeatletter
% ----------------------------------------------------------------------
% Environment adjustitemize where itemlabels of itemizations are aligned
% with second lines of surrounding description-items:
% ----------------------------------------------------------------------
\settowidth{\labelwidth}{%
\csname labelitem%
\romannumeral
\numexpr\@itemdepth\ifnum\@itemdepth >\thr@@\else+1\fi\relax
\endcsname
}%
\csname leftmargin%
\romannumeral
\numexpr\@listdepth\ifnum \@listdepth >5 \else+1\fi\relax
\endcsname
=\dimexpr\labelwidth+\labelsep\relax
\itemize
}%
%
% ----------------------------------------------------------------------
% Environment adjustdescription where description-labels have
% enumeration-bullets:
% ----------------------------------------------------------------------
\list{}{%
\settowidth\labelwidth{%
\hspace\labelsep
{\csname labelitem\romannumeral\@itemdepth\endcsname}%
}%
\labelwidth=\z@
\itemindent -\leftmargin
}%
}%
\hspace\labelsep
{\csname labelitem\romannumeral\@itemdepth\endcsname}%
\hspace\labelsep
{\normalfont\bfseries#1}%
}%
% ----------------------------------------------------------------------
\makeatother

\begin{document}

\API{getProfile}
{Gets the current user's Gmail profile.}
{GET /gmail/v1/users/{userId}/profile}
{%
% The \empty rule makes the line non-empty so that \\ is possible
\rule{0pt}{0pt}%
\item[userId:]The user's email address. The special value me
can be used to indicate the authenticated user.
\item[userId:]The user's email address. The special value me
can be used to indicate the authenticated user.
\item \textbf{userId:} The user's email address. The special value me
can be used to indicate the authenticated user.
\item \textbf{userId:} The user's email address. The special value me
can be used to indicate the authenticated user.
Let's test the \verb|description|-environment:
\begin{description}
\item[userId:]The user's email address. The special value me
can be used to indicate the authenticated user.
\item[userId:]The user's email address. The special value me
can be used to indicate the authenticated user.
\end{description}
}%
{The request body must be empty. The request body must be empty.
The request body must be empty. The request body must be empty.}
{If successful, the response body contains data with the following structure:
%!!! Be aware of the indenting with verbatim-environments !!!
\begin{lstlisting}
{

• Thanks for your answer! This is a lot more complicated than I thought! I tried as workaround to use \lstinputlisting and putting the content on a file, but this is much better. – Zack Feb 9 at 10:26
• @Zack The "infrastructure" provided by the listings-package cannot handle utf8-characters whose encoding requires more than one byte. In case your code-listings happen to contain such utf8-characters, \lstinputlisting in combination with the package listingsutf8 ,which provides a workaround specifically for the \lstinputlisting-command, might be the right choice. In case you need color with code-listings and more fancy formatting, the package minted might be of interest. – Ulrich Diez Feb 9 at 16:32