8

I have a scenario where xparse's \NewDocumentCommand has a regression compared to any alternative I know, including ones defining robust commands. So I'm avoiding \NewDocumentCommand in this case, but I would like to understand where the problem lies.

I am trying to understand the difference between robust commands and commands defined by \NewDocumentCommand, from the point of view of hyperref's processing of bookmarks. Consider the following MWE and the comments inside.

\documentclass{article}

\usepackage{xparse}

\usepackage[T1]{fontenc}
\usepackage[utf8x]{inputenc}
\usepackage[unicode=true]{hyperref}

\usepackage{bookmark}
% The problem appears also without bookmark, but you need to compile twice to 
% see the correct result.

% Allow using \lambda in section headers, in two parts.
% Part one (no problem here):
\PrerenderUnicode{λ}

% Part two:
% Problem: The following command can be robust, but cannot be defined via 
% \NewDocumentCommand.

% All these definitions work:

%\def\TitleLambda{\texorpdfstring{$\lambda$}{λ}}
%\newcommand{\TitleLambda}{\texorpdfstring{$\lambda$}{λ}}
%\DeclareRobustCommand{\TitleLambda}{\texorpdfstring{$\lambda$}{λ}}

% This one doesn't:

\NewDocumentCommand{\TitleLambda}{}{\texorpdfstring{$\lambda$}{λ}}

% Done!

\begin{document}
\section{The \TitleLambda{}-calculus}
\end{document}

The above MWE gives the warning:

Package hyperref Warning: Token not allowed in a PDF string (Unicode):
(hyperref)                removing `\TitleLambda' on input line 34.

As a consequence, the bookmark in the resulting file will contain no lambda character, unlike intended.

Replacing \NewDocumentCommand by any alternative avoids the problem. So the problem does not happen simply because \NewDocumentCommand defines robust commands, though what is happening appears similar. I've even tested using \def + \MakeRobustCommand from the makerobust package:

\usepackage{makerobust}
\MakeRobustCommand\TitleLambda

and everything still worked.

Who's at fault? I see three possibilities:

  • me;
  • xparse;
  • hyperref.

Edit: I should have phrased my question better. I'm mainly curious about what happens, given that I have a working solution.

  • 1
    Motivation: I don't like to use \texorpdfstring directly in the section header, it's distracting for me and coauthors. – Blaisorblade Nov 07 '13 at 23:54
  • 1
    It's simple: \NewDocumentCommand creates a robust command similarly to \DeclareRobustCommand, but hyperref doesn't know how to deal with it. You just need \newcommand. – egreg Nov 07 '13 at 23:54
  • So hyperref would need to add explicit support for \NewDocumentCommand? How inelegant. – Blaisorblade Nov 07 '13 at 23:55
  • @egreg: yours should really be an answer, however short. – Blaisorblade Nov 07 '13 at 23:56
  • I think the recommended approach here would be to use \DeclareExpandableDocumentCommand. – Bruno Le Floch Nov 08 '13 at 02:04
  • The question for xparse is how to handle 'might need to be expandable' in a general manner. At present, we've not got a good plan for that (it's OK in your case but what about commands with optional arguments, etc.). – Joseph Wright Nov 08 '13 at 07:03
  • To make sure I understand your last comments: is it correct that fragile commands just work, while hyperref needs to pay extra attention only to handle robust commands? Also, is it true that the command is never fragile, even when declared as expanding (http://tex.stackexchange.com/q/4736/1340)? – Blaisorblade Nov 08 '13 at 07:59

1 Answers1

8

While hyperref is able to cope with \DeclareRobustCommand, it isn't with \NewDocumentCommand (this might be a feature request).

But \newcommand is all you need.

There is another way, though. It's incompatible with utf8x, but you can judge about its elegance.

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{newunicodechar}
\usepackage[unicode=true]{hyperref}
\usepackage{bookmark}
\newunicodechar{λ}{\texorpdfstring{\ensuremath{\lambda}}{λ}}

\begin{document}
\section{The λ-calculus}
\end{document}

enter image description here

egreg
  • 1,121,712
  • This should not be a feature request for hyperref, but for the L3 team: Integrate hyperref into L3. – Martin Schröder Nov 08 '13 at 22:50
  • @MartinSchröder That's of course in the (long term) plans. – egreg Nov 08 '13 at 22:53
  • I agree the second solution is rather elegant for people like me. – Blaisorblade Nov 22 '13 at 17:16
  • I also wonder whether that could be integrated in something like unicode-math, but probably people don't want this to interfere with Unicode in normal input (outside of $). – Blaisorblade Nov 22 '13 at 17:29
  • @Blaisorblade What makes you think it doesn't work with unicode-math? It does, by the way. ;-) Of course not if the document is in Greek. – egreg Nov 22 '13 at 17:40
  • With unicode-math you need no trick, actually. – egreg Nov 22 '13 at 17:58
  • I'm wondering how clean (Greek-respectful) this is. I want a math lambda there, but most users will want math lambdas only when they write $λ$, and text lambdas otherwise. I guess I'm thinking of something like:

    \newunicodechar{λ}{\texorpdfstring{\ifmmode\lambda\else\textgreek{l}\fi}{λ}} (together with dependencies of \textgreek or some equivalent). But I'm rather ignorant of plain TeX, so please expect the above to be rather buggy.

    – Blaisorblade Nov 23 '13 at 00:32