\p@COUNTER 的使用

\p@COUNTER 的使用

例如,当通过 定义新计数器时\newcounter,也会定义\newcounter{mycounter}命令。在 中\p@mycounter设置 时,我可以看到再次弹出此信息。我想知道在这种情况下 的目的是什么,在哪里可以找到此类文档?\@currentlabel\refstepcounter\p@mycounter

答案1

引自LaTeX 2e 来源 (https://ctan.org/pkg/source2e), 文件 m ltcounts.dtx, 第 22.1 节:环境计数器宏

环境foo具有由以下控制序列定义的相关计数器:

\c@foo
包含计数器的数值。它定义为\newcount\foocounter

\thefoo
扩展为 的打印值的宏\foocounter
例如,如果章节内的节被编号,并且节标题看起来像
第 II-3 节。计数器的性质
可能\thesection定义为:
\def\thesection{\@Roman{\c@chapter}-\@arabic{\c@section}}

\p@foo
扩展为计数器的打印“参考前缀”的宏foo
任何\ref由 counter 创建的值都会在执行命令时foo产生扩展。请参阅\p@foo\thefoo\label文件 ltxref.dtx以扩展这一机制。

\cl@foo
步进时要重置的计数器列表foo
格式为\@elt{countera}\@elt{counterb}\@elt{counterc}

注意:
\thefoo\p@foo必须以这样的方式定义,即\edef\bar{\thefoo}\edef\bar{\p@foo}定义\bar,以便它将评估 时的计数器值\edef,即使在\foocounter和 任何其他计数器已更改之后也是如此。如果您使用标准命令\@arabic\@Roman等,就会发生这种情况。

引自LaTeX 2e 来源 (https://ctan.org/pkg/source2e), 文件 x ltxref.dtx, 第 52.1 节:交叉引用

实现方式如下。CNT命令 增加一个可引用计数器\refstepcounter{CNT},设置\@currentlabel == {CNT}{eval(\p@cnt\theCNT)}。然后,该命令\label{FOO}在文件 上写入以下内容\@auxout
\newlabel{FOO}{{eval(\@currentlabel)}{eval(\thepage)}}
[...]
\label\refstepcounter
命令\label\refstepcounter已被更改,以允许
\protect'ed 命令正常工作。例如,
\def\thechapter{\protect\foo{\arabic{chapter}.\roman{section}}}
将导致\label{bar}命令定义\ref{bar}扩展为类似 的内容\foo{4.d}。更改于 88 年 7 月 20 日。

32 \def\label#1{\@bsphack
33   \protected@write\@auxout{}%
34          {\string\newlabel{#1}{{\@currentlabel}{\thepage}}}%
35   \@esphack}
36 \def\refstepcounter#1{\stepcounter{#1}%
37     \protected@edef\@currentlabel
38        {\csname p@#1\endcsname\csname the#1\endcsname}%
39 }

当查看重新定义\protected@edef中的 which时,您会看到您可以重新定义,以便它触发的顶层扩展,从而在传递另一个以其为参数的控制序列标记之前产生控制序列标记。\refstepcounter\@currentlabel\p@⟨counter⟩\csname the⟨counter⟩\endcsname\the⟨counter⟩\the⟨counter⟩

例如,如果您希望每个对章节编号的引用都以粗体显示并嵌套在方括号中,则可以这样做

\documentclass{article}
\usepackage{hyperref}

\makeatletter
\renewcommand\p@section{\expandafter\wrapinsquarebrackets}%
\newcommand\wrapinsquarebrackets[1]{\textbf{[#1]}}%
\makeatother

\begin{document}

\section{A section}\label{a section}
Reference to the section will be boldface and wrapped into square brackets:
\ref{a section}

\end{document}

在此处输入图片描述

请注意,如果使用 hyperref-bundle,来自的内容将成为超链接的一部分。\p@⟨counter⟩

在某些情况下,这是需要的。
但也有不需要的情况:
例如,如果您打算使用自动创建脚注并附上参考的附加注释,那么您将获得所谓的嵌套链接:脚注标记应是指向脚注文本的超链接,同时它将成为指向参考文本段落的超链接的一部分。\p@⟨counter⟩

还要注意,也可以用于添加后缀 - 只需执行以下操作:\p@⟨counter⟩

\def\p@⟨counter⟩{\expandafter\AddPrefixAndPostfixTo⟨counter⟩}%
\def\AddPrefixAndPostfixTo⟨counter⟩#1{%
  ⟨prefix-tokens⟩#1⟨postfix-tokens⟩%
}%

答案2

定义\newcounter{foo}了三个对象:

  1. \c@foo,这是一个 TeX 计数寄存器;
  2. \thefoo,计数器值的表示;
  3. \p@foo,即“前缀”;
  4. \cl@foo,重置类foo(这个就不讨论了)。

当这样做时\refstepcounter{foo},宏\@currentlabel将根据以下方式重新定义

% latex.ltx, line 4199:
\def\refstepcounter#1{\stepcounter{#1}%
    \protected@edef\@currentlabel
       {\csname p@#1\endcsname\csname the#1\endcsname}%
}

\label{baz}以下命令将\refstepcounter{foo}存储文件的扩展名\@currentlabel和当前页面.aux

% latex.ltx, line 4195:
\def\label#1{\@bsphack
  \protected@write\@auxout{}%
         {\string\newlabel{#1}{{\@currentlabel}{\thepage}}}%
  \@esphack}

请注意,\protected@write进行完全(受保护)扩展以冻结当前情况,即的foo。1

在这种情况下,`\label{baz} 将使用值

\csname p@foo\endcsname\csname thefoo\endcsname

即与 相同\p@foo\thefoo

的默认含义\p@foo是“无”;更准确地说,\newcounter{foo}是执行\let\p@foo\@empty

前缀是干什么用的?下面是一个例子,来自article.cls

\renewcommand\theenumi{\@arabic\c@enumi}
\renewcommand\theenumii{\@alph\c@enumii}
\renewcommand\theenumiii{\@roman\c@enumiii}
\renewcommand\theenumiv{\@Alph\c@enumiv}
\newcommand\labelenumi{\theenumi.}
\newcommand\labelenumii{(\theenumii)}
\newcommand\labelenumiii{\theenumiii.}
\newcommand\labelenumiv{\theenumiv.}
\renewcommand\p@enumii{\theenumi}
\renewcommand\p@enumiii{\theenumi(\theenumii)}
\renewcommand\p@enumiv{\p@enumiii\theenumiii}

内核已分配计数器enumienumii和 ,enumiii用于enumiv构建四层嵌套的枚举列表。假设我们处于第三层enumerate、第四项,并且\item\label{baz}

在这种情况下,LaTeX 将执行\refstepcounter{enumiii}以下操作,导致\@currentlabel加载

\p@enumiii\theenumiii

将成为,当\protected@write进入行动

\theenumi(\theenumii)\@roman\c@enumiii

如果第一级在项目 3,第二级在项目 2,我们将获得

3(b)iv

写入.aux文件中,因此\ref{baz}将打印“3(b)iv”。

revtex4-1文档类也使用了类似的机制

\def\thesection{\Roman{section}}
\def\p@section{}
\def\thesubsection{\Alph{subsection}}
\def\p@subsection{\thesection\,}
\def\thesubsubsection{\arabic{subsubsection}}
\def\p@subsubsection{\thesection\,\thesubsection\,}
\def\theparagraph{\alph{paragraph}}%
\def\p@paragraph {\thesection\,\thesubsection\,\thesubsubsection\,}
\def\thesubparagraph{\arabic{subparagraph}}
\def\p@subparagraph{\thesection\,\thesubsection\,\thesubsubsection\,\theparagraph\,}

(这个选项rtx,我会略过一些细节)。这样

\section{Title}\label{a}
\subsection{Title}\label{b}
\subsubsection{Title}\label{c}

将打印

我标题
一个标题
1 标题

\ref{a}\ref{b}并且\ref{c}将打印

1
1

(带有细小的空间)。方程式编号也使用类似的机制(但略有修改)。

没有用于定义的用户界面\p@<counter>,可能是因为这被认为只能在文档类中使用。

另一个缺陷是缺乏后缀,这对于后处理标记非常方便。


脚注

1但是\thepage不会当场扩展,因为它在 中被明确禁止\protected@write;扩展将在将标记写入文件时发生.aux,此时页码的值是精确已知的。

答案3

从 source2e 获得的文档texdoc source2e中可以看出,计数器部分的第 145 页为撰写本文时的版本(版本 v1.1l 2018/04/22)。

\p@foo 宏扩展为计数器 foo 的打印“引用前缀”。执行 \label 命令时,任何对计数器 foo 创建的值的 \ref 都会产生 \p@foo\thefoo 的扩展。有关此机制的扩展,请参阅文件 ltxref.dtx。

这个问题已经在评论中回答了,由于没有人写答案,所以这个答案将是一个社区维基如果原始回答者没有亲自回答,则回答。这是将这个问题从未回答列表中删除。原始答案来自@campa。

相关内容