\string と \newcommand はどのように機能しますか?

\string と \newcommand はどのように機能しますか?

各表記が最初の出現にリンクできるコマンドを記述しようとします。表記 A とベクトル B を考えます。x=/=' に対して fun{'}=B' および fun{x}=B^{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含まれている場合は\hyperlink、単に false ブランチを実行するのではなく、エラーが発生します。

答え: パッケージに説明されているようにifthen#1拡大比較する文字列を取得します。

生のコンテンツを比較する場合は、 を使用します\detokenize

\string限られた場合にのみ機能します。

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

代替アプローチ: expl3 と\str_if_eq:nnTFor を使用します\tl_if_eq:nnTF

答え2

\stringコマンド名では、名前を文字列(catcode 12の文字のシーケンス)として返すので、\usepackage単一のトークンですが、\string\usepackage11個のトークンです。\ u s e p a c k a g e

\ifthenelse equal2 つの引数を展開し、それらが等しいかどうかをテストします。

\equal{\string\hyperaword}{456}

11個のトークン\ハイパーワードが3個のトークン4 5 6と等しいかどうかをテストします。これは決して真ではありません。

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

いつも456

2 番目のテストでは、は既に catcode 12 の文字であるため\string(に展開されます。ただし、 は脆弱なコマンドであるため、展開コンテキストでは使用できません。いずれにせよ、pdftex プリミティブを使用してリンクが構築されるため (pdftex を使用している場合)、特に で囲まれている場合は、 が に等しくなることはありません。を使用することでこのエラーを回避できますが、この場合のテストは、3 つのトークンが 3 つのトークンに等しいかどうかであり、これもまた真になることはありません。((\hyperlink()456\protect\hyperlink( \hyperlink )4 5 6

答え3

PDFビューアがPDFファイルを表示しているとき、「ハイパーターゲット」とは、基本的に、識別できる名前を持つ PDF ファイルのページ上の領域1です。

PDF ビューアが PDF ファイルを表示している場合、「ハイパーリンク」は基本的にPDF ファイルのページ上の領域1であり、そこをクリックするとPDF ファイルが表示されているウィンドウまで PDF ファイルの別の領域2がスクロールする効果があります。

したがって、マクロは\hypertarget、PDF ファイルの表示時、つまり LaTeX コンパイラがもう実行されていないときに PDF 表示プログラムが PDF ファイル内の領域に名前を付けるために使用するディレクティブを PDF ファイルに書き込むための LaTeX コンパイラへの指示です。このような名前付き領域は「ターゲット」と呼ばれます。このような領域の名前は「宛先」と呼ばれます。このような名前付き領域が非常に小さく、PDF ファイル内の単一のポイントと見なせる場合は、「アンカー」とも呼ばれます。3

そして、このマクロは\hyperlink、LaTeX コンパイラが PDF ファイル ディレクティブに書き込むための命令であり、PDF ファイルを表示するとき、つまり、LaTeX コンパイラがもう実行されていないときに、PDF 表示プログラムは、クリックすると PDF ファイルが表示されるウィンドウに PDF ファイルの別の (ターゲット) 領域をスクロールする命令と接続するために使用します。

TeX 実行中、pdfTeX ベースのエンジンは、名前付き領域 (ターゲット/アンカー) の名前 (宛先) を追跡し、pdf ファイル内のターゲット領域/アンカーに対応する名前を提供して対応する宛先を導入せずにハイパーリンクを配置した場合には、TeX 実行の終了時にエラー メッセージを表示します。

しかしTeX エンジンは、PDF ファイルの名前付きスクロール可能領域に出現するテキスト フレーズなどを追跡するために\hypertarget/メカニズムを使用しません。\hyperlink

要約:

このマクロは、\hyperlinkLaTeX の実行中に有用な情報を返しません。PDF ファイルの表示時に PDF 表示プログラムによって処理される PDF ファイルへの書き込み指示をトリガーするだけです。つまり、これらの命令は、LaTeX コンパイラではなく、別のプログラム、つまり PDF 表示プログラムによって処理されます。つまり、これらの命令は、LaTeX コンパイラが実行中でなくなり、LaTeX コンパイラの実行中にのみ存在するすべてのデータが存在しなくなったときに処理されます。

コード内の や のような式は
\ifthenelse{\equal{\string\hyperaword}{456}}{123}{456}
、latex コンパイラの実行中に
\ifthenelse{\equal{\string (\hyperlink{1}{456})}
適用した「結果」を何らかの方法で評価しようとする試みを示します。\hyperlink

したがって、あなたが正確に何を達成しようとしているのかはわかりませんが、マクロが、\hyperlinkTeX 実行中にさらに処理/検査することで役立つトークン/情報を提供するとは考えられません。

私の理解が正しければ、現在の質問には 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-run が必要になります。

したがって、LaTeX を再実行する必要があることに関するターミナルおよび .log ファイルの情報と警告に従ってください (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}

関連情報