Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Background (simplified)

I'm using the todonotes package to add todonotes to sections in my documents. I have created a macro to add the todonotes to sections such that they appear alongside the section's entry in the table of contents. I am also using the nameref macro from the hyperref package to refer to various sections of my document by name. Partly because of this, my macro also allows a label to be specified for the section. Here's a somewhat simplified version of the output my macro produces:

\section[{\todo{A todonote about the foo section}}{foo}]{foo}%
\label{sec:foo}

The problem

The trouble with this is that when using the \nameref to refer to a section with a todonote contained in the title, as above, the todonote also gets attached to the reference.

MWE:

\documentclass{article}

\usepackage{todonotes}
\usepackage[colorlinks,linkcolor=blue]{hyperref}

\begin{document}

\tableofcontents

\section{foo}
\begin{itemize}
    \item A reference to the \nameref{sec:bar} section
\end{itemize}

\section[{\todo{A todonote about the bar section}}{bar}]{bar}
\label{sec:bar}
A section called bar

\section{baz}
A section called baz

\end{document}

Which produces (after three or four compiles/builds for good measure):

A screenshot of the output from the MWE demonstrating the problem

What's happening:

So the call to \nameref{sec:bar} is presumably producing a reference which includes {\todo{A todonote about the bar section}}{bar} and todonotes is (correctly but undesirably) producing a duplicate todonote because of this. To clarify, I would like the reference to the bar section to be produced as just bar without the duplicate todonote.

Approach to finding a solution

Although this is my use case, I would prefer to know how to make nameref ignore any commands within the section title as I feel this would probably be more generally useful (and not just for me).

As a side note, an alternative solution to ignoring the commands could possibly be to define some nameref-specific reference text for the section somehow. However, this is less desirable as it would require a little maintenance to keep it relevant to the section name.

share|improve this question
    
@lockstep: Just curious, what's the notes tag intended to be used for/mean? (Is it in reference to the todonotes package?) –  Staves Mar 25 '12 at 0:08
    
In a sense, yes, but I chose the more general tag. Feel free to replace notes with todonotes. –  lockstep Mar 25 '12 at 0:10
    
@lockstep: Ah ok, thanks. I think I shall change it as, although todonotes shows the problem I'm having with nameref, it's not actually the cause. There may be a todonotes related solution, but it's not really a notes(-caused) problem, if that makes sense. –  Staves Mar 25 '12 at 0:17
    
@Staves Please, keep Stefan's as the accepted answer. –  egreg Mar 25 '12 at 16:40
    
@egreg: Although I'm not sure if this might be slightly against the consensus on accepting solutions (somewhat relevant - meta.tex.stackexchange.com/q/535/11869) I strongly agree that Stephan deserves a lot of credit. If you're saying that this is cool then I shall leave it as it (now) is, otherwise I shall accept your answer so that it will be the first a new user/visitor sees. –  Staves Mar 25 '12 at 17:57
show 1 more comment

2 Answers

up vote 5 down vote accepted

A simplified version of Stefan Lehmke's solution:

\documentclass{article}

\usepackage{etoolbox}
\usepackage{todonotes}
\usepackage[colorlinks,linkcolor=blue]{hyperref}

\makeatletter
\newcommand\@namedisablecommands{}
\newcommand{\addnamedisablecommand}[1]{%
  \g@addto@macro\@namedisablecommands{\renewcommand#1{}}%
  \pdfstringdefDisableCommands{\renewcommand#1{}}%
}
\AtBeginDocument{ 
  \patchcmd{\T@nameref}
  {\let\label\@gobble}
  {\let\label\@gobble\@namedisablecommands}
  {}{}
}
\makeatother

\addnamedisablecommand{\todo[2][]}

Notice the changed syntax; to keep Stefan's write

\newcommand{\addnamedisablecommand}[2]{%
  \g@addto@macro\@namedisablecommands{\renewcommand#1#2{}}%
  \pdfstringdefDisableCommands{\renewcommand#1#2{}}%
}

instead.

After doing this, \@namedisablecommands will expand to

\renewcommand\todo[2][]{}

which will neutralize its expansion. The warning

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

is avoided by adding \todo (or other similar commands) in the disabled command list for hyperref.

share|improve this answer
    
That's really much simpler ;-) –  Stephan Lehmke Mar 25 '12 at 16:34
    
@StephanLehmke Yours was a very good inspiration. –  egreg Mar 25 '12 at 16:40
    
Just saw egreg's comment on the question, so leaving Stephan's answer as the accepted one. (@StephanLehmke) –  Staves Mar 25 '12 at 17:33
    
Really neat solution! I'm very interested in finding out if the method you and @StephanLehmke propose can be extended to limiting the scope of commands other than \T@nameref. I currently have a bounty on an open question that concerns, in part, limiting the scope of a TeX macro that invokes some lua code; see tex.stackexchange.com/q/48516/5001. Any and all help would be very much appreciated. –  Mico Mar 26 '12 at 13:21
    
I already saw your comment, but I doubt there is a connection. What we did here is a rather standard method for deactivating commands which have "moved" to a place they don't belong, because like in this case they are part of some section heading or such which gets saved by nameref. This is well-known for instance in the context of \pdfstringdefDisableCommands. Unfortunately, I don't see a connection with your case (protect macro names and arguments from search/replace). –  Stephan Lehmke Mar 26 '12 at 13:34
show 4 more comments

Interestingly, \nameref seems to know there are some things which should be disabled (for instance, \label), but it doesn't offer an interface for adjusting it.

Hence, patching seems to be a solution. I repeat the full example:

\documentclass{article}

\usepackage{etoolbox}
\usepackage{todonotes}
\usepackage[colorlinks,linkcolor=blue]{hyperref}

\makeatletter
\newcommand\@namedisablecommands{}%
\newcount\@namedisablegenericmacro
\newcommand\addnamedisablecommand[2]
{%
  \global\advance\@namedisablegenericmacro\@ne
  \expandafter\newcommand
  \csname @namedisablegobble\number\@namedisablegenericmacro\endcsname
  #2{}%
  \global\expandafter\let
  \csname @namedisablegobble\number\@namedisablegenericmacro\expandafter\endcsname
  \csname @namedisablegobble\number\@namedisablegenericmacro\endcsname
  \edef\@namedisablecommands{%
    \unexpanded\expandafter{\@namedisablecommands}%
    \let\noexpand#1\expandafter\noexpand
    \csname @namedisablegobble\number\@namedisablegenericmacro\endcsname
  }%
}
\AtBeginDocument
{%
  \patchcmd{\T@nameref}
  {\let\label\@gobble}
  {\let\label\@gobble\@namedisablecommands}
  {}{}%
}
\addnamedisablecommand{\todo}{[2][]}
\expandafter\pdfstringdefDisableCommands\expandafter
{%
  \@namedisablecommands
}%
\makeatother
\begin{document}

\tableofcontents

\section{foo}
\begin{itemize}
\item A reference to the \nameref{sec:bar} section
\end{itemize}

\section[{\todo{A todonote about the bar section}}{bar}]{bar}
\label{sec:bar}
A section called bar

\section{baz}
A section called baz

\end{document}

enter image description here

share|improve this answer
    
+1 for mentioning that \nameref has built-in functionality to keep it from operating on certain commands, such as \label. –  Mico Mar 25 '12 at 10:20
    
Thanks for this, I have accepted it as it does indeed solve the problem I am experiencing. Presumably this could also be expanded to ignore/gobble any number of commands? –  Staves Mar 25 '12 at 12:17
    
@Staves: Exactly, you can iterate the patch as often as you wish. –  Stephan Lehmke Mar 25 '12 at 12:21
    
Nice one :) Could the \let and \@gobble surrounding \todo be moved into the \addnamedisablecommand macro (around the #1)? - This works for me with \todo it but I'm not sure if there might be ramifications with other commands and so on... –  Staves Mar 25 '12 at 13:04
    
I thought about that, but the next step of abstraction is a lot more effort. The main complication is to handle commands with differing numbers of arguments. –  Stephan Lehmke Mar 25 '12 at 13:13
show 10 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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