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
    Commented Feb 5, 2021 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
    Commented Feb 5, 2021 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
    Commented Feb 5, 2021 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
    Commented Feb 5, 2021 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
    Commented Feb 9, 2021 at 10:22

1 Answer 1

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
    Commented Feb 9, 2021 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. Commented Feb 9, 2021 at 16:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .