1

In the following MWE

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[utf8]{inputenc}

\usepackage[pdftex,unicode,final]{hyperref}
\input{glyphtounicode}
\pdfgentounicode=1

\makeatletter
\newcommand*{\boilerplate}{\@ifstar\@@boilerplate\@boilerplate}
\newcommand*{\@boilerplate}{Boilerplate for running text}
\newcommand*{\@@boilerplate}{Boilerplate for headings in capalized form}
\makeatother

\begin{document}

\section{\boilerplate*}

\end{document}

the star is used to obtain an alternative variant of the boilerplate. The MWE fails with

Token not allowed in a PDF string (Unicode):
(hyperref)                removing `\@ifnextchar' on input line 19.

Obviously, the problem is the order of macro expansions. I have already tried to play around with \expandafter but did not find a solution.

Remark: If possibly, I would like to keep the starred-version to select the variant of the boilerplate. This design has been agreed upon some time ago and is used at myriads of places. In other words changing the macro definition to something like \boilerplateNormal and \boilerplateVariant is not an option, because that would break compatibility with other authors using the sty-file.

4
  • Try \section{$\setminus$boilerplate*}
    – M S
    Commented May 28, 2019 at 10:35
  • 1
    The problem is that \@ifnextchar (used in \@ifstar) is not expandable, and text in pdf strings (such as section titles) must expand completely. It is possible to make the command expandable but your \boilerplate command would require at least a final mandatory argument: \section{\boilerplate*{}} or \section{\boilerplate{}}. Commented May 28, 2019 at 10:37
  • 1
    You can probably use \texorpdfstring, see tex.stackexchange.com/questions/53513/….
    – Marijn
    Commented May 28, 2019 at 10:49
  • 1
    Don't add the pdftex option.
    – egreg
    Commented May 28, 2019 at 10:49

1 Answer 1

2

The command \boilerplate is fragile, with the current definition.

Either use \protect\boilerplate when in a moving argument, or do

\DeclareRobustCommand{\boilerplate}{\@ifstar\@@boilerplate\@boilerplate}

instead of \newcommand.

Alternatively, add \usepackage{xparse} and change the definition into

\NewDocumentCommand{\boilerplate}{s}{%
  \IfBooleanTF{#1}{%
    Boilerplate for headings in capitalized form% \boilerplate*
  }{%
    Boilerplate for running text% \boilerplate (with no *)
  }%
}

Don't expect the expansion of \boilerplate (with or without *) finds its way in the bookmarks, though. It can be done if the macro \boilerplate takes a regular argument.

Assuming that in moving arguments you use the *-variant, you can use \pdfstringdefDisableCommand:

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage{xparse}

\usepackage[unicode,final]{hyperref}
\input{glyphtounicode}
\pdfgentounicode=1

\NewDocumentCommand{\boilerplate}{s}{%
  \IfBooleanTF{#1}{%
    Boilerplate for headings in capitalized form% \boilerplate*
  }{%
    Boilerplate for running text% \boilerplate (with no *)
  }%
}
\pdfstringdefDisableCommands{\def\boilerplate*{Boilerplate for bookmark}}

\begin{document}

\section{\boilerplate*}

\boilerplate

\end{document}

enter image description here

6
  • "Don't expect the expansion of \boilerplate (with or without *) finds its way in the bookmarks" --> Unfortunately, this is not an option. I tried your solution, but then the bookmarks only contain an asterisk.
    – nagmat84
    Commented May 28, 2019 at 11:17
  • @nagmat84 This can be adjusted, but something more about the real use case is needed.
    – egreg
    Commented May 28, 2019 at 11:51
  • @nagmat84 As Phelype wrote in his comment, if will probably only work if there is e.g. a {} after the input, (so \boilerplate{}). Commented May 28, 2019 at 11:53
  • @egreg What information do you miss about the real use case?
    – nagmat84
    Commented May 28, 2019 at 15:32
  • @nagmat84 Is the addition something you like?
    – egreg
    Commented May 28, 2019 at 15:53

You must log in to answer this question.

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