
Я пытаюсь написать команду, которую каждая нотация может связать с первым появлением. Рассмотрим нотацию A и вектор B. Определим команду, которая fun{'}=B' и fun{x}=B^{x} для x=/='. Если я хочу написать B^(A), то мне нужно использовать код "fun{(A)}". Обратите внимание, что это "A" использует код "hyperlink". Но \equal
это не работает, когда \equal{(\hyperlink{x}{y})}{z}
.
Вот минимальный пример моей проблемы:
\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}
Эта проблема возникает только тогда, когда я использую "(\hyperlink{xx}{xx})". Если я использую "\hyperlink{xx}{xx}", а не "( )", то все в порядке.
решение1
Позвольте мне переформулировать ваш вопрос:
У меня есть команда
\newcommand \f [1] { \ifthenelse { \equal {#1} {...} } ... }
В большинстве случаев это работает, но когда
#1
contains\hyperlink
, возникает ошибка вместо того, чтобы просто запустить ложную ветвь.
Отвечать: Как поясняется на ifthen
упаковке, #1
эторасширенныйчтобы получить строку для сравнения.
Если вы хотите сравнить необработанный контент, используйте \detokenize
.
\string
работают только в ограниченных случаях.
\newcommand \f [1] { \ifthenelse { \equal {\detokenize{#1}} {\detokenize{...}} } ... }
Альтернативный подход: используйте expl3 и \str_if_eq:nnTF
или \tl_if_eq:nnTF
.
решение2
\string
на имя команды возвращает имя в виде строки (последовательность символов кода 12), поэтому \usepackage
это один токен, но \string\usepackage
это 11 токенов\
u
s
e
p
a
c
k
a
g
e
\ifthenelse
equal
раскрывает два аргумента, а затем проверяет, равны ли они.
\equal{\string\hyperaword}{456}
проверяет, равны ли 11 токенов \ гиперслово трем токенам 4 5 6, это никогда не бывает правдой, поэтому
\ifthenelse{\equal{\string\hyperaword}{456}}{123}{456}
всегда456
Во втором тесте \string(
расширяется до (
as (
уже является символом catcode 12. но \hyperlink
это хрупкая команда, которую вы не можете использовать в контексте расширения. Она в любом случае создает ссылку с использованием примитивов pdftex (если вы используете pdftex), так что, особенно когда окружена ()
, никогда не будет равна 456
вы можете избежать ошибки, используя \protect\hyperlink
но тогда тест заключается в том, (
\hyperlink
)
равны ли три токена трем токенам 4
5
6
, и снова это никогда не бывает правдой.
решение3
Когда программа просмотра PDF-файлов показывает PDF-файл,«гиперцель» по сути представляет собой просто область 1 на странице PDF-файла, имеющую имя, по которому ее можно идентифицировать.
Когда программа просмотра PDF-файлов отображает PDF-файл, «гиперссылка» по сути представляет собой просто область 1 на странице PDF-файла, щелчок по которой приводит к прокрутке 2 другой области PDF-файла в окно, в котором отображается PDF-файл.
Итак, макрос \hypertarget
— это инструкция для LaTeX-компилятора для записи в pdf-файл директив, которые во время просмотра pdf-файла, т. е. в то время, когда LaTeX-компилятор больше не работает, программа просмотра pdf-файла использует для присвоения области в pdf-файле имени. Такая именованная область называется «целью». Имя такой области называется «местом назначения». Если такая именованная область настолько мала, что ее можно считать одной точкой в pdf-файле, то ее также называют «якорем». 3
А макрос \hyperlink
представляет собой инструкцию для LaTeX-компилятора записать в pdf-файл директивы, которые во время просмотра pdf-файла, т.е. в то время, когда LaTeX-компилятор уже не запущен, программа просмотра pdf-файла использует для соединения области pdf-файла с инструкцией прокрутки другой (целевой) области pdf-файла в окно, в котором отображается pdf-файл при щелчке.
Во время запуска TeX движки на основе pdfTeX отслеживают имена=назначения именованных областей=целей/якорей и выдают сообщения об ошибках в конце запуска TeX в случае размещения гиперссылки без указания соответствующего назначения путем указания соответствующего имени для целевой области/якоря в pdf-файле.
НоНи один движок TeX не использует механизм \hypertarget
/ \hyperlink
для отслеживания текстовых фраз и т.п., встречающихся в именованных прокручиваемых областях PDF-файла.
Подводя итог:
Макрос \hyperlink
не возвращает никакой полезной информации во время работы LaTeX. Он просто запускает инструкции записи в файл pdf, которые обрабатываются программой просмотра pdf во время просмотра файла pdf.То есть, эти инструкции обрабатываются не latex-компилятором, а другой программой, а именно программой просмотра pdf-файлов. То есть, эти инструкции обрабатываются в то время, когда latex-компилятор уже не работает и когда все фрагменты данных, которые существуют только во время работы latex-компилятора, перестали существовать.
Выражения в вашем коде, такие как
\ifthenelse{\equal{\string\hyperaword}{456}}{123}{456}
и
\ifthenelse{\equal{\string (\hyperlink{1}{456})}
указывают на попытки каким-либо образом оценить «результат» применения \hyperlink
во время работы latex-компилятора.
Поэтому, хотя я и не знаю, чего именно вы пытаетесь добиться, я сомневаюсь, что макрос \hyperlink
предоставляет токены/информацию, дальнейшая обработка/исследование которой во время запуска TeX будет вам полезна.
Если я правильно понимаю, то в данном случае вопрос связан с непониманием сути макроса TeX \hyperlink
, что уже само по себе затрудняет понимание вопроса.
Пожалуйста, укажите точно, чего вы хотите добиться. Вероятно, я тогда смогу изменить свой ответ, добавив пример кода, демонстрирующий подход к вопросу.
1 В случае разрывов страниц/колонок и т. п. как гиперцели, так и гиперссылки могут состоять из нескольких областей, а не только из одной области.
2 Значение "прокрутки другой области pdf-файла к окну, в котором отображается pdf-файл" зависит от программы, используемой для просмотра pdf-файла, поскольку "действия" в ходе выполнения этих инструкций реализованы в этой программе. Поведение различных программ просмотра pdf-файлов различается в крайних случаях.
3 Пакет hyperref работает с якорями во многих ситуациях, предполагая, что точка якоря прокручивается в верхний левый угол окна, в котором отображается файл pdf, при щелчке по соответствующей ссылке. Внутри пакет hyperref определяет положение точки якоря относительно опорной точки того блока, который содержит текст/материал, который должен быть виден в окне отображения при щелчке по ссылке. В горизонтальном режиме, где сам TeX делит вещи на блоки, насколько мне известно, это опорная точка первого горизонтального блока, который содержит части текста/материала, которые должны быть видны в окне отображения при щелчке по ссылке.
В следующем примере представлен макрос \LinkOrTarget{<destination name>}{<phrase>}
, первый экземпляр которого с указанным⟨название пункта назначения⟩формирует гиперцель, а последующие экземпляры формируют гиперссылки.
Если команда \IntroduceHypertargetHere{<destination name>}{<phrase>}
происходит, то это формирует гиперцель, в то время как все экземпляры \LinkOrTarget{<destination name>}{<phrase>}
формируют гиперссылки.
Если команда \IntroduceHypertargetHere{<destination name>}{<phrase>}
происходит, вам нужно больше одного запуска latex, пока все не совпадет.
Таким образом: Следуйте информации и предупреждениям на терминале и в .log-файле о необходимости повторного запуска LaTeX (не удаляя aux-файлы между запусками LaTeX).
Не ставьте \IntroduceHypertargetHere{<destination name>}{<phrase>}
на то же самое⟨название пункта назначения⟩более одного раза. Если вы это сделаете, вы получите предупреждения о множественно определенных метках, и гиперцель будет создана в первом из этих случаев.
\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}