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.

I want to \hypertarget some of my sections. I know I could \label them or hypertarget right before them, but this is part of a larger framework and I don't want to treat the case where the target happens to be a section title differently. Here is my minimal example, it works with \section* but it doesn't with \section. Why?

\documentclass[a4paper,12pt]{article}
\usepackage[pdfstartview=FitH]{hyperref}
\usepackage{bookmark}
\begin{document}

\section*{one\hypertarget{sec:one}{}}
\bookmark[dest=sec:one]{sec one}

\section{two\hypertarget{sec:two}{}}
\bookmark[dest=sec:two]{sec two}

\end{document}

ps: fantastic, neither hypertarget nor section are valid tags. somebody please insert something useful in there.

edit: incorparating \texorpdfstring the above minimal example works, but as ususal it was too minimal, my production code doesnt compile. i created a minimal example closer to the real use, it creates a correct file but with a lot of error messages, the terrible anonymous undefined control sequence on the line the macro is used. how can i debug this error message? can someone tell me what is wrong with the code?

\documentclass[a4paper,12pt]{article}
\usepackage{amsmath}
\usepackage[pdfstartview=FitH]{hyperref}
\usepackage[atend]{bookmark}
\newcounter{nops}
\makeatletter
\newcommand{\nopimpl}{\stepcounter{nops}\Hy@raisedlink{\hypertarget{nop\arabic{nops}}{}}\begingroup\edef\x{\endgroup\noexpand\BookmarkAtEnd{\noexpand\bookmark[dest=nop\arabic{nops}]{page \arabic{nops}}}}\x}
\newcommand{\nop}{\texorpdfstring{\iffirstchoice@\nopimpl\fi}{}}
\makeatother
\begin{document}

\section{one\nop}
\section{two\nop}

\end{document}

edit2: thanks again. now those errors are gone, but in the real file there is a toc, and the toc items get their own target. how can i prevent that?

also how come robustness is only a matter of declaration? i thought it should be a property of the code that is to be executed. if i can simply declare stuff robust, why doesnt latex make everything robust?

\documentclass[a4paper,12pt]{article}
\usepackage{amsmath}
\usepackage[pdfstartview=FitH]{hyperref}
\usepackage[atend]{bookmark}
\newcounter{nops}
\makeatletter
\DeclareRobustCommand{\nopimpl}{\stepcounter{nops}\Hy@raisedlink{\hypertarget{nop\arabic{nops}}{}}\begingroup\edef\x{\endgroup\noexpand\BookmarkAtEnd{\noexpand\bookmark[dest=nop\arabic{nops}]{page \arabic{nops}}}}\x}
\DeclareRobustCommand{\nop}{\texorpdfstring{\iffirstchoice@\nopimpl\fi}{}}
\makeatother
\begin{document}
\tableofcontents
\section{one\nop}
\section{two\nop}
\end{document}
share|improve this question
    
Very specific tags are not that useful so we use 'sectioning' for sections, subsections, chapters etc. Also instead of 'hypertarget' you can use 'hyperref' and 'links'. –  Martin Scharrer May 4 '11 at 10:39
    
thanks for adding them for me. –  peter May 4 '11 at 21:10
1  
About the robustness: \DeclareRobustCommand{\foo}{bar} actually defines \foo to be \protect\foo<space> and defines \foo<space> to {bar}. A special trick is used so that the space is allowed in that internal macro, but is taken as normal space if written to the .toc or .aux file. I know, its a little complicated. Some macro should be expandable, so they should not be robust. Moving arguments are the exception not the rule and making all macro robust would be an overhead. –  Martin Scharrer May 5 '11 at 10:26

2 Answers 2

up vote 7 down vote accepted

The content of normal sectioning macros like \section is called a moving argument because it also moves from its normal location to other places, namely the table of contents and to the PDF bookmark sidebar. For this is is written to some auxiliary files (.aux, .out) and is expanded in this process. Only robust macros which don't mind getting expanded work here and other fragile macros must be protected by placing \protect before them. Also some material is not allowed in PDF bookmarks (e.g. some math symbols). The hyperref package provides \texofpdfstring{<tex>}{<pdf>} which can be used to select different text for the document and PDF bookmarks. So you could use \section{two\texorpdfstring{\protect\hypertarget{sec:two}{}}{}} to only have the \hypertarget in the document but not in the PDF bookmark where it doesn't make sense. Another option is to use the optional argument of \section to provide an alternative text for the ToC and PDF bookmarks.

\documentclass[a4paper,12pt]{article}
\usepackage[pdfstartview=FitH]{hyperref}
\usepackage{bookmark}
\begin{document}

\section*{one\hypertarget{sec:one}{}}
\bookmark[dest=sec:one]{sec one}

\section{two\texorpdfstring{\protect\hypertarget{sec:two}{}}{}}
\bookmark[dest=sec:two]{sec two}

\section[three]{three\hypertarget{sec:three}{}}
\bookmark[dest=sec:three]{sec three}

\end{document}

To answer your updated answer:
As mentioned all macros used in moving arguments must be robust to not cause trouble. This can be achieved by using \protect in front of it, i.e. \section{one\protect\nop} or by defining \nop robust from the start by using \DeclareRobustCommand instead of \newcommand. One problem is that the \nop will also be used in the ToC, so you should define \nop first to be empty and redefine it after the \tableofcontents. You could use \g@addto@macro to add the definition code to this macro.

\documentclass[a4paper,12pt]{article}
\usepackage{amsmath}
\usepackage[pdfstartview=FitH]{hyperref}
\usepackage[atend]{bookmark}
\newcounter{nops}
\makeatletter
\DeclareRobustCommand{\nopimpl}{\stepcounter{nops}\Hy@raisedlink{\hypertarget{nop\arabic{nops}}{}}\begingroup\edef\x{\endgroup\noexpand\BookmarkAtEnd{\noexpand\bookmark[dest=nop\arabic{nops}]{page \arabic{nops}}}}\x}
\newcommand{\nop}{}
\g@addto@macro{\tableofcontents}{\DeclareRobustCommand{\nop}{\texorpdfstring{\iffirstchoice@\nopimpl\fi}{}}}

\makeatother
\begin{document}
\tableofcontents

\section{one\nop}
\section{two\nop}

\end{document}

You might also just define some macro \mysection[2]{\section[#1]{#1#2} and use it like \mysection{section text}{\nop}. This would avoid some of the trouble.

share|improve this answer
    
thanks. i dont like the idea of typing the section title twice, so i will try to use \texorpdfstring. please look at my edited question to see if you can help me with it. –  peter May 4 '11 at 22:00
    
sorry, my minimal examples tend to be too minimal. you fixed it again, but still we're not done yet. i find that editing weird though, i prefer how threads work in other forums. do you think i should rather open new questions? –  peter May 4 '11 at 22:39
    
nice, thanks, this '\g@addto@macro' trick works! (sorry for not seeing the edit earlier.) –  peter Jun 15 '11 at 7:36

try this one: \section[two]{two\hypertarget{sec:two}{}}

share|improve this answer

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.