0

I try to write a command that each notation can link to the first appearance. Consider a notations A and a vector B. Define a command that fun{'}=B' and fun{x}=B^{x} for x=/='. If I want to write B^(A), then I need to use the code "fun{(A)}". Notice that this "A" uses the code "hyperlink". But \equal is not work when \equal{(\hyperlink{x}{y})}{z}.

Here's a minimal example of my issue:

\documentclass{article}
\usepackage{hyperref}
\usepackage{ifthen}

\newcommand{\hyperaword}{(\hyperlink{1}{456})}

\begin{document}

\hypertarget{1}{3} % work \hyperlink{1}{2} % work \ifthenelse{\equal{\string\hyperaword}{456}}{123}{456} % work \ifthenelse{\equal{\string (\hyperlink{1}{456})}{456}}{123}{456} % ERROR: Use of \hyper@link@ doesn't match its definition. \end{document}

This problem only happens when I use "(\hyperlink{xx}{xx})". If I use "\hyperlink{xx}{xx}" not use "( )", then it is fine.

3 Answers3

2

\string on a command name returns the name as a string (a sequence of characters of catcode 12) so \usepackage is a single token but \string\usepackage is the 11 tokens \ u s e p a c k a g e

\ifthenelse equal expands the two arguments then tests if they are equal.

\equal{\string\hyperaword}{456}

tests if the 11 tokens \ h y p e r a w o r d are equal to the three tokens 4 5 6 this is never true, so

\ifthenelse{\equal{\string\hyperaword}{456}}{123}{456}

is always 456

In the second test \string( expands to ( as ( is already a character of catcode 12. but \hyperlink is a fragile command you can not use in an expansion context. It anyway consructs a link using pdftex primitives (if you are using pdftex) so that, especially when surrounded by (), is never going to be equal to 456 you could avoid the error by using \protect\hyperlink but then the test is if the three tokens ( \hyperlink ) are equal to the three tokens 4 5 6 and again this is never true.

David Carlisle
  • 757,742
2

Let me rewrite your question:

I have a command

\newcommand \f [1] { \ifthenelse { \equal {#1} {...} } ... }

This works most of the time, but when #1 contains \hyperlink, it errors out instead of just running the false branch.

Answer: As explained in the ifthen package, #1 is expanded to get the string to be compared.

If you want to compare the raw content, use \detokenize.

\string only work in limited cases.

\newcommand \f [1] { \ifthenelse { \equal {\detokenize{#1}} {\detokenize{...}} } ... }

Alternative approach: use expl3 and \str_if_eq:nnTF or \tl_if_eq:nnTF.

user202729
  • 7,143
  • More info: Why hyperlink does not work when expanded: https://tex.stackexchange.com/questions/4736/what-is-the-difference-between-fragile-and-robust-commands-when-and-why-do-we-n/ ■ what expanded is: https://tex.stackexchange.com/questions/158827/what-is-expansion ■ what \string is: read the TeX book or TeX by topic ■ what detokenize is: see texdoc etex_man ■ if all of those doesn't make sense: read package writing - Where do I start LaTeX programming? - TeX - LaTeX Stack Exchange – user202729 Apr 16 '22 at 03:03
  • Basically don't arbitrarily copy paste things that you don't completely understand (e.g. \string probably doesn't work the way you expect in this case). TeX is extremely counter-intuitive. – user202729 Apr 16 '22 at 03:10
1

When the pdf-viewer is showing the pdf-file, a "hypertarget" basically is just an area1 on a page of a pdf-file which has a name by which it can be identified.

When the pdf-viewer is showing the pdf-file, a "hyperlink" basically is just an area1 on a page of the pdf-file where clicking has the effect of scrolling2 another area of the pdf-file to the window wherein the pdf-file is displayed.

So the macro \hypertarget is an instruction for the LaTeX-compiler for writing to the pdf-file directives which at the time of viewing the pdf-file, i.e., at a time when the LaTeX-compiler doesn't run any more, the pdf-viewing-program uses for giving an area in the pdf-file a name. Such a named area is called a "target". The name of such an area is called "destination". If such a named area is so small that it can be considered a single point in the pdf-file, then it is also called an "anchor".3

And the macro \hyperlink is an instruction for the LaTeX-compiler to write to the pdf-file directives which at the time of viewing the pdf-file, i.e., at a time when the LaTeX-compiler doesn't run any more, the pdf-viewing-program uses for connecting an area of the pdf-file with the instruction of scrolling another (target-)area of the pdf-file to the window where the pdf-file is displayed when clicking.

During the TeX-run pdfTeX-based engines keep track of names=destinations of named areas=targets/anchors and raise error-messages at the end of the TeX-run in case of having placed a hyperlink without having introduced a corresponding destination by providing a corresponding name for a target-area/anchor within the pdf-file.

But no TeX-engine uses the \hypertarget/\hyperlink-mechanism for keeping track of textual phrases etc occurring in those named scrollable areas of the pdf-file.

Summa summarum:

The macro \hyperlink does not return any useful information during the LaTeX run. It merely triggers writing instructions to the pdf file which are processed by the pdf-viewing program at the time of viewing the pdf file. I.e., these instructions are not processed by the latex-compiler but by a different program, namely the pdf-viewing program. I. e., these instructions are processed at a time when the latex-compiler isn't running any more and when all pieces of data that only exist during the run of the latex-compiler have ceased to exist.

Expressions in your code like
\ifthenelse{\equal{\string\hyperaword}{456}}{123}{456}
and
\ifthenelse{\equal{\string (\hyperlink{1}{456})}
indicate attempts of somehow evaluating a "result" of applying \hyperlink during the run of the latex-compiler.

So although I don't know what exactly you try to achieve, I doubt that the macro \hyperlink delivers tokens/information whose further processing/examination during the TeX-run would be of any use to you.

If I understand it correctly, the question right now involves a misunderstanding of what the TeX-macro \hyperlink actually is about, which already makes it difficult to understand the question.

Please specify exactly what you wish to achieve. Probably I then can modify my answer for adding a code-example exhibiting an approach to the matter.


1In case of page-breaks/column-breaks and the like, both hypertargets and hyperlinks may consist of several areas, not just a single area.

2The meaning of "scrolling another area of the pdf-file to the window wherein the pdf-file is displayed" depends on the program in use for viewing the pdf-file, because the "actions" in the course of obeying these instructions are implemented into that program. The behavior of different pdf-viewing-programs varies in edge cases.

3The hyperref package works with anchors in many situations, assuming that an anchor point is scrolled to the upper left corner of the window in which the pdf file is displayed when a corresponding link is clicked. Internally, the hyperref package specifies the position of an anchor point in relation to the reference point of that box which contains the text/material that is to be seen in the display window when the link is clicked. In horizontal mode, where TeX itself divides things into boxes, as far as I know it is the reference point of the first horizontal box that contains parts of the text/material that should be seen in the display window when the link is clicked.



The following example provides a macro \LinkOrTarget{<destination name>}{<phrase>} whereof the first instance with a specified ⟨destination name⟩ forms the hypertarget and subsequent instances form hyperlinks.

If a command \IntroduceHypertargetHere{<destination name>}{<phrase>} occurs, then that forms the hypertarget while all instances of \LinkOrTarget{<destination name>}{<phrase>} form hyperlinks.
If a command \IntroduceHypertargetHere{<destination name>}{<phrase>} occurs, you need more than one latex-run until everything matchs out.

Thus: Obey the infos and warnings on the terminal and in the .log-file about the need of re-running LaTeX (without deleting aux-files between LaTeX-runs).

Don't place \IntroduceHypertargetHere{<destination name>}{<phrase>} for the same ⟨destination name⟩ more than once. If you do you will get warnings about multiply-defined labels and the hypertarget will be created at the first of these instances.

\documentclass{article}
\usepackage{hyperref}
\usepackage{zref}

\makeatletter \zref@newprop{DestinationExplicitlyPlaced}{}% \newcommand\WrapHypertargetInHy@raisedlink[2]{% \Hy@raisedlink{\hypertarget{#1}{}}#2% }% \newcommand\IntroduceHypertargetHere[1]{% \zref@setcurrent{DestinationExplicitlyPlaced}{true}% \zref@labelbyprops{ExplicitDestination-#1}{DestinationExplicitlyPlaced}% \IntroduceHypertargetHereInternal{#1}% }% \newcommand\IntroduceHypertargetHereInternal[2]{% @ifundefined{NameOfDestination_#1}{% \expandafter\gdef\csname NameOfDestination_#1\endcsname{}% \WrapHypertargetInHy@raisedlink }{\hyperlink}{#1}{#2}% }% \newcommand\LinkOrTarget[2]{% \zref@ifrefundefined{ExplicitDestination-#1}{\IntroduceHypertargetHereInternal}{% \zref@ifrefcontainsprop{ExplicitDestination-#1}{DestinationExplicitlyPlaced}% {\hyperlink}{\IntroduceHypertargetHereInternal}% }% {#1}{#2}% }% \makeatother

\begin{document}

Dummy page \newpage Smme text \LinkOrTarget{destination name}{Phrase which either is in link area or is in target area}. \newpage Some text \LinkOrTarget{destination name}{Phrase which either is in link area or is in target area}. \newpage Some text \LinkOrTarget{destination name}{Phrase which either is in link area or is in target area}. %Some text \IntroduceHypertargetHere{destination name}{Phrase which is in target area}. \newpage Some text \LinkOrTarget{destination name}{Phrase which either is in link area or is in target area}. \newpage Some text \LinkOrTarget{destination name}{Phrase which either is in link area or is in target area}.

\end{document}

Ulrich Diez
  • 28,770