# Soul “Argument of \xxx has an extra }” after registering custom command with \soulregister

I came across several similar questions and answers with a similar issue, like https://tex.stackexchange.com/a/20055 and https://tex.stackexchange.com/a/46871, but even after registering my custom command, I still get a similar error. Not using the \soulregister command yields the exact same error.

\newcommand{\code}[1]{\sethlcolor{gray}\hl{\texttt{#1}}}
\soulregister{\code}{1}


This is the error I get:

! Argument of \@textcolor has an extra }.
<inserted text>
\par
l.276 \section{\code{virusscan}}


The latex code in question looks like below. I'm using this inside a memoir document.

\section{\code{virusscan}}


Edit:

Defining the command like this:

\sethlcolor{gray}
\newcommand{\code}[1]{\hl{\texttt{#1}}}
\soulregister{\code}{1}


yields

! Argument of \let has an extra }.
<inserted text>
\par
l.277 \section{\code{virusscan}}


Also \texttt{\hl{#1}} doesn't change anything.

Edit 2:

Here's the minimal non-working example:

\documentclass{memoir}

\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{soul}

\newcommand{\code}[1]{\sethlcolor{gray}\hl{\texttt{#1}}}
\soulregister{\code}{1}

\begin{document}

\section{\code{test}}

\end{document}


You also need to make the command robust, because you're using it in a moving argument.

\documentclass{memoir}

\usepackage{xcolor}
\usepackage{soul}

\DeclareRobustCommand{\code}[1]{{\sethlcolor{gray}\hl{\texttt{#1}}}}
\soulregister{\code}{1}

\begin{document}

\section{\code{test} and \hl{xyz}}

\end{document}


With hyperref the problem is different and it's connected to the bookmarks.

\documentclass{memoir}

\usepackage{xcolor}
\usepackage{soul}
\usepackage{hyperref}

\DeclareRobustCommand{\code}[1]{{\sethlcolor{gray}\hl{\texttt{#1}}}}
\soulregister{\code}{1}

\begin{document}

\section{\texorpdfstring{\code{test}{test}}

\end{document}


Alternatively, use \pdfstringdefDisableCommands:

\documentclass{memoir}

\usepackage{xcolor}
\usepackage{soul}
\usepackage{hyperref}

\DeclareRobustCommand{\code}[1]{{\sethlcolor{gray}\hl{\texttt{#1}}}}
\soulregister{\code}{1}
\makeatletter
\pdfstringdefDisableCommands{\let\code\@firstofone}
\makeatother

\begin{document}

\section{\code{test}}

\end{document}

• For me that results in the same error... Might it have someting to do with me using MiKTeX? – BrainStone Jul 9 '18 at 8:53
• Having the package hyperref active breaks your example for me (I updated my MWE to include the package). Thank you regardless for your effort! – BrainStone Jul 9 '18 at 9:09
• @BrainStone That's a completely different problem, of course. Anyway, I added code for that. – egreg Jul 9 '18 at 9:22
• That worked. Thank you so much for solving two issues at once! – BrainStone Jul 9 '18 at 9:32

With your MWE I get the the error both when using \soulregister and when not using \soulregister.

I only get it when trying to use the \code-command inside the argument of the \section-command.

I also get a warning by the hyperref-package:

Package hyperref Warning: Token not allowed in a PDF string (PDFDocEncoding):
(hyperref)                removing \code' on input line 12.


Reason:

The \section command does not just write a nice paragraph heading into the text. It also both places entries into the .aux-file for writing the .toc-file for the table of contents and places entries into the .out-file so that the hyperref package can create a bookmark for the heading of the section. In case of a pagestyle with page-headings it also changes the page-headings.

In order to make sure that the \code-command does not get expanded when the aux-file-entry for the .toc-file and the .toc-file itself is written, have it defined in terms of \DeclareRobustCommand rather than having it defined in terms of \newcommand. In order to make sure that this command does not slip into hyperref-bookmarks, where only plain text should occur, use \texorpdfstring. Either within the definition of \code or when placing \code into the argument of sectioning-commands or captions.

Or for resolving the hyperref-issue, as egreg pointed out, use \pdfstringdefDisableCommands. (Seems he delivered his answer while I wrote mine ;-) .)

\documentclass{memoir}

\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{soul}

\DeclareRobustCommand{\code}[1]{%
\texorpdfstring{{\sethlcolor{gray}\hl{\texttt{#1}}}}%
{#1}%
}
\soulregister{\code}{1}

\begin{document}

%\tableofcontents

\section{\code{test}}

\end{document}


By the way: \code does supply the grey background color not only within the paragraph heading but also within the entry in the table of contents and within the page headings.

If you don't like this but wish to have color only in the paragraph heading, a crude workaround can be checking the meaning of \protect. The LaTeX 2e protection-mechanism for preventing expansion of specific tokens in some situations does redefine that token depending on the situation, whereby situations might be "producing ordinary text on a page", "producing an entry for the .aux-file that is to go into the .toc-file at the end of the LaTeX-run", ...

\documentclass{memoir}

\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{soul}

\makeatletter
\newcommand\code{%
\ifx\protect\@unexpandable@protect
\expandafter\codeinmovingarg
\else
\expandafter\codeintext
\fi
}%
\makeatother
\DeclareRobustCommand{\codeinmovingarg}[1]{%
\texorpdfstring{\texttt}{}{#1}%
}%
\DeclareRobustCommand{\codeintext}[1]{%
\texorpdfstring{{\sethlcolor{gray}\hl{\texttt{#1}}}}%
{#1}%
}%
\soulregister{\code}{1}

\begin{document}

\tableofcontents\cleardoublepage

\section{\code{test}}

\end{document}


By the way again:

Sectioning commands also affect page headings.

Page headings by default are "uppercased" with memoir. In memoir you can enable/disable uppercasing of page headings via \uppercaseheads/\nouppercaseheads.

In case uppercasing of page headings is enabled, your code appearing in the argument of the \section-macro, and thus also appearing in the page-heading, will in the page heading be uppercased as well.

I would not like having code uppercased. If you too don't like this, you can within the argument of \section make your call to the \code-macro an argument of the \NoCaseChange-macro which in turn needs to be \protected:

\documentclass{memoir}

\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{soul}

\DeclareRobustCommand{\code}[1]{%
\texorpdfstring{{\sethlcolor{gray}\hl{\texttt{#1}}}}%
{#1}%
}%
\soulregister{\code}{1}

\begin{document}

\tableofcontents
\cleardoublepage

\section{\protect\NoCaseChange{\code{test}}}

\end{document}

• Thank you for your answer. And yeah egreg was faster, so he'll get the accepted answer. And yes I want the grey box to be in the TOC, page headings, etc. But thanks for pointing it out. – BrainStone Jul 9 '18 at 10:07
• @BrainStone Nonetheless I prefer putting \texorpdfstring into my macro definitions to using \pdfstringdefDisableCommands or having to think about \texorpdfstring` whenever using the macro in question as part of the argument of a sectioning command/caption-command. ;-) – Ulrich Diez Jul 9 '18 at 10:12