为什么 enumitem 需要宏已经存在?

为什么 enumitem 需要宏已经存在?

我正在使用pgfenumitem定义十六进制枚举方案如下:

\documentclass{article}
\usepackage{pgf,enumitem}

\makeatletter

\newcommand*{\Hex}[1]{%
  \expandafter\@Hex\csname c@#1\endcsname
}
\newcommand*{\@Hex}[1]{%
  \pgfmathdectoBase\The@Hex{#1}{16}\The@Hex
}

\AddEnumerateCounter{\Hex}{\@Hex}{E}

%------------------------------------------------------------
% Why does cutting this line cause it to fail?
%------------------------------------------------------------
\AtBeginDocument{\pgfmathdectoBase\The@Hex{1}{16}}
%------------------------------------------------------------

\makeatother

\begin{document}

\begin{enumerate}[label=\Hex*]
\item First
\item Second\addtocounter{enumi}{10}
\item Letters
\item More
\item Another
\item Ten!
\end{enumerate}
\end{document}

现在,如果我删除突出显示的行,编译就会失败,我不明白为什么。它告诉我:

! Undefined control sequence.
<argument> \The@Hex 

我试图理解为什么需要定义这个宏才能使枚举工作,特别是因为的值\The@Hex直到使用枚举重新定义后才真正被使用...

答案1

有一种方法可以避免赋值,使得转换为十六进制完全可扩展:

\input{binhex}
\newcommand*{\Hex}[1]{\expandafter\hex\csname c@#1\endcsname}
\AddEnumerateCounter{\Hex}{\hex}{E}

binhex.tex作者是大卫·卡斯特鲁普 (David Kastrup)。

正如 Martin 所解释的那样, 的一个问题是\pgfmathdectoBase执行分配,因此无法用于定义 的数字表示\ref,因为系统必须使用\edef( 的形式\protected@edef)才能在辅助文件中写入实际数字,而不是命令。 根据您的定义,分配\label给某个项目并尝试使用\ref它会导致错误。

由于 anenumerate可能不太长,因此可以使用

\newcommand{\Hex}[1]{\expandafter\@Hex\csname c@#1\endcsname}
\newcommand{\@Hex[1]{\ifnum#1>15 \@ctrerr\else\hexnumber@{#1}\fi}

也许可以扩大其定义\hexnumber@以涵盖更多情况。

答案2

错误是由于标签代码应该是完全可扩展的而引起的。您的代码实际上很脆弱,导致\The@Hexin\pgfmathdectoBase\The@Hex在分配之前就被扩展(有一个\protected@edef用于设置\@currentlabelin \refstepcounter.)。解决此问题的方法是更改​​宏的定义。正如 egreg 指出的那样,使宏变得健壮可以避免该错误,但在枚举项被编辑时会导致问题\label。请注意,LaTeX 提供了可用于数字 0-15 的宏\hexnumber@(有关更大的范围,请参阅 egreg 的答案)。

相关内容