如何取消保护命令以扩展它?

如何取消保护命令以扩展它?

这是另一个关于保护和扩展的问题,我仍然不太明白……(我想这是我的问题)。我特别阅读了我如何“取消保护”一个论点?,还有其他许多人。

我正在尝试为标题创建自动和上下文标签(如果需要,请参阅下文了解详细信息)。如果我写例如 \myref{My_title_here},标签的链接为例如“A.II.3.d 我的标题在这里”,指向第1部分第2章第3节第4小节。是“标题编号”,是(这里是)A.II.3.d的结果,我想把它放进去,但是:\getrefnumber {#1}#1My_title_here\templabel

    %\edef \templabel {\getrefnumber {#1}} doesn't work

\getrefnumber {#1}我想要的是得到(的结果(扩展)例如 A.II.3.d) \templabel。同样,如果需要的话,代码位于最后。


解决方法

\edef没有用,所以我最后尝试过\protected@edef(是否\protected\edef相同\protected@edef?):

    \protected@edef \templabel {\getrefnumber {#1}}
    %\show \templabel->A.\protect \textlatin  {I}.1.

最后找到这个来删除\protect

    \expandafter \expandafter \expandafter \def \expandafter \expandafter \expandafter \templabel \expandafter \expandafter \expandafter {\getrefnumber {#1}}
    %\show \templabel ->A.\textlatin {I}.1.

我查看了 的定义\textlatin,发现它看起来确实像\textbf。这是一个格式化命令。要删除该\textlatin命令,我使用以下命令:

    \def \textlatin #1{#1}

问题

最后终于可以工作了,但是:

  1. 你能简单解释一下这里有什么问题吗?有保护和扩展吗?为什么我不能\getrefnumber {#1}直接使用?

  2. 我想知道是否有更好的解决方案,或者更通用的解决方案,或者至少,解决方案是否涵盖了这里的所有情况:如何直接获取A.I.1而不是A.\protect \textlatin {I}.1

  3. 此解决方案\expandafter在每种情况下都有效吗?我在这里可能会遇到哪些命令,在\getrefnumber {#1}\textlatin\textgreek(因为我使用\greek?)还有什么?

  4. 我处理 \textlatin 命令的方式更好吗?这个解决方案有什么缺点吗?(我不明白 的定义\textlatin,它就像\textbf

  5. 如果我使用-而不是.(A-II-3-4)?是否-会被视为算术运算,例如在扩张期间?

请随时提供有关代码的建议,我正在学习。


上下文,以防万一

我使用以下编号:

\def \thepart          {\Alph   {part}}
\def \thechapter       {\Roman  {chapter}}
\def \thesection       {\arabic {section}}
\def \thesubsection    {\alph   {subsection}}
\def \thesubsubsection {\greek  {\value{subsubsection}}}
\setcounter {secnumdepth} {3} % Paragraphs and subparagraphs unnumbered

我为标题创建了“信息性”编号(来源:(重新)定义包含部分编号的章节的 \ref):

\def \p@chapter       {\thepart.}
\def \p@section       {\thepart.\thechapter.}
\def \p@subsection    {\thepart.\thechapter.\thesection.}
\def \p@subsubsection {\thepart.\thechapter.\thesection.\thesubsection.}

然后我创建标签命令,并将其修补到分区命令中(来源:
自动创建标签的分段命令
根据相应 \label 的位置更改 \ref 的输出
如何根据 \ref 相对于 \label 的调用位置来更改其外观
自动创建标签)。

\newcommand {\myref }[1]{%
    \@ifundefined {r@#1} {??} {\begingroup
    %\edef \templabel {\getrefnumber {#1}} doesn't work

要进入A.I.2.b\templabel这是问题

然后我将使用 xstrings 分割字符串:

    \StrCut \templabel         {.} \part@number         \part@tail
    \StrCut \part@tail         {.} \chapter@number      \chapter@tail
    % …
    \StrCut \paragraph@tail    {.} \subparagraph@number \subparagraph@tail

并创建上下文链接(该链接的编号是例如“A-III-2-b 此处的标题” 但如果链接在 A-III 中,它将仅是“2-b 此处的标题”;它是上下文的):

    \edef \templink {\getrefbykeydefault {#1} {anchor} {}}
    \IfStrEq \thepart \part@number
        {\IfStrEq \thechapter \chapter@number
            %…
            {\textcolor{red}{X} \hyperlink \templink \part@tail}}%
        {\textcolor{red}{X} \hyperlink \templink \templabel}%
    \endgroup}}

数学家协会

\documentclass[greek]{book} % THE GREEK OPTION IS THE CAUSE

\usepackage {hyperref}
\usepackage {babel}

\makeatletter
\def \p@chapter       {\thepart.}
\def \p@section       {\thepart.\thechapter.}
\def \p@subsection    {\thepart.\thechapter.\thesection.}
\def \p@subsubsection {\thepart.\thechapter.\thesection.\thesubsection.}

\newcommand {\myref}[1]{%
    \@ifundefined {r@#1} {??} {\begingroup
        \edef \temp {\getrefnumber {#1}}
        % \show \temp->A.\textlatin {I}.1.
        \endgroup }}
\makeatother

\begin{document}
\mainmatter

\part{Hi :\\introduction}\label{Hi}
\chapter{Chapter}\label{Chapter}
See \myref{Test} below.
\section{Test}\label{Test}

\enddocument

答案1

部分答案,没有时间回答更多。

\getrefnumber来自包refcount并且完全可扩展。这意味着,它可以在 内部使用\edef。但如果引用包含可破坏的内容,\getrefnumber则将安全地提取此引用,但引用本身将中断。在您的例子中,\textlatin被引入(可能是babel),它因 的硬扩展而中断\edef

由于是一个遵循 LaTeX 保护协议的宏,因此正如您所观察到的,\textlatin通过扩展是安全的。\protected@edef

在 LaTeX 中,宏可以通过 进行保护\DeclareRobustCommand。然后出现了 e-TeX,它提供了\protected定义命令来使宏变得健壮,并防止在可扩展上下文(如 内部)中扩展\edef,写入文件。

\protected\edef\macro{definition text}制作一个受保护的\macro文本并以困难的方式扩展定义文本。\protected@edef制作一个正常的(不受保护的)\macro文本并在 LaTeX 的保护机制生效的情况下扩展定义文本。

refcount顺便说一句,如果您使用类似包的可扩展提取命令\getrefnumber,那么\refused应该在扩展上下文之外使用相同的标签,以获得未定义引用的适当警告。

相关内容