使 \refstepcounter (\@currentlabel) 在其组之外可见

使 \refstepcounter (\@currentlabel) 在其组之外可见

我定义了自己的列表环境。请参阅以下 MWE:(如果您问我为什么不使用标准列表,实际定义要复杂得多)

\documentclass{article}

\makeatletter

\newcounter{mylist}
\renewcommand*{\themylist}{\Alph{mylist}}
\newcommand*{\labelmylist}{\themylist}

\newcommand*{\makemylabel}[1]{%
\refstepcounter{mylist}%
\@mklab{\labelmylist}%
}

\newenvironment{mylist}{
  \list{\@empty}{
    \let\makelabel\makemylabel
    \setcounter{mylist}{0}
  }
}{
  \endlist
}

\makeatother

\begin{document}

\section{Section Title}

\begin{mylist}
  \item\label{foo} List entry 1
\end{mylist}

The reference are wrong: \ref{foo}.

\end{document}

错误在于\ļabel{foo}创建了对子部分计数器的引用,从而\ref{foo}打印了错误的标签。

我理解,\refstepcounter重新定义\@currentlabel\label发送\@currentlabel至辅助文件。

\refstepcounter使用\edef(而非\xdef),因此在命令结束\@currentlabel后重置为旧定义\makemylabel。因此\label{foo}使用 的计数器\section

我如何\label{foo}使用正确的计数器?

根据评论进行更新

由于 @david-carlisle 和 @alan-munn 提出的问题,MWE 不再那么小

\documentclass{article}

\makeatletter

\newcounter{mylist}
\renewcommand*{\themylist}{FA-\Alph{mylist}}
\newcommand*{\labelmylist}{\themylist}

\newcommand*{\makemylabel}[1]{%
\if#1\@empty\else\setcounter{mylist}{#1}\addtocounter{mylist}{-1}\fi%
\refstepcounter{mylist}%
\@mklab{\labelmylist}%
}

\newenvironment{mylist}{
  \list{\@empty}{
    \let\makelabel\makemylabel
    \setcounter{mylist}{0}
  }
}{
  \endlist
}

\makeatother

\begin{document}

\section{Section Title}

\begin{mylist}
  \item\label{foo} List entry A
  \item[5] List entry E
  \item\label{bar} List entry F
\end{mylist}

The reference are wrong: \ref{foo} and \ref{bar}.

\end{document}

答案1

我认为最好构造代码以使用第一个参数,\list该参数专门用于控制用于引用的计数器,但是从您所在的位置开始,您可以使用以下方法将定义\@currentlabel从组中提出\aftergroup

\documentclass{article}

\makeatletter

\newcounter{mylist}
\renewcommand*{\themylist}{FA-\Alph{mylist}}
\newcommand*{\labelmylist}{\themylist}

\newcommand*{\makemylabel}[1]{%
\if#1\@empty% you probably want \ifx\relax#1\relax
  \else\setcounter{mylist}{#1}\addtocounter{mylist}{-1}\fi%
\refstepcounter{mylist}%
\protected@xdef\zzz{\def\noexpand\@currentlabel{\@currentlabel}}%
\aftergroup\zzz
\@mklab{\labelmylist}%
}

\newenvironment{mylist}{%%%%% 
  \list{}{%%%%%
    \let\makelabel\makemylabel
    \setcounter{mylist}{0}%%%%%
  }
}{%%%%%%%%%%
  \endlist
}

\makeatother

\begin{document}

\section{Section Title}

\begin{mylist}
  \item\label{foo} List entry A
  \item[5] List entry E
  \item\label{bar} List entry F
\end{mylist}

The reference are wrong: \ref{foo} and \ref{bar}.

\end{document}

相关内容