0

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{
    {
      "emailAddress": string,
      "messagesTotal": integer,
      "threadsTotal": 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.

5
  • 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
  • 1
    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
  • 1
    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
1

Some remarks about your code:

  • 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}
{
  "emailAddress": string,
  "messagesTotal": integer,
  "threadsTotal": integer,
  "historyId": string
}
\end{lstlisting}
    }

\end{document}

enter image description here

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:
% ----------------------------------------------------------------------
\newcommand\adjustitemize{%
  \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
}%
\@ifundefined{endadjustitemize}%
             {\let\endadjustitemize=\enditemize}%
             {\@ifdefinable\endadjustitemize{}}%
%
% ----------------------------------------------------------------------
% Environment adjustdescription where description-labels have 
% enumeration-bullets:
% ----------------------------------------------------------------------
\newcommand\adjustdescription{%
  \ifnum \@itemdepth >\thr@@\@toodeep\else\advance\@itemdepth\@ne\fi
  \list{}{%
     \settowidth\labelwidth{%
       \hspace\labelsep
       {\csname labelitem\romannumeral\@itemdepth\endcsname}%
     }%
     \advance\leftmargin\labelwidth
     \labelwidth=\z@
     \itemindent -\leftmargin 
     \let\makelabel\adjustdescriptionlabel 
  }%
}%
\newcommand*\adjustdescriptionlabel[1]{%
  \hspace\labelsep
  {\csname labelitem\romannumeral\@itemdepth\endcsname}%
  \hspace\labelsep
  {\normalfont\bfseries#1}%
}%
\@ifundefined{endadjustdescription}%
             {\let\endadjustdescription=\enddescription}%
             {\@ifdefinable\endadjustdescription{}}%
% ----------------------------------------------------------------------
\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}%
      \\Let's test the \verb|adjustdescription|-environment:
      \begin{adjustdescription}
      \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{adjustdescription}
      Let's test the \verb|adjustitemize|-environment:
      \begin{adjustitemize}
      \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.
      \end{adjustitemize}
      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}
{
  "emailAddress": string,
  "messagesTotal": integer,
  "threadsTotal": integer,
  "historyId": string
}
\end{lstlisting}
    }

\end{document}

enter image description here

2
  • 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.