新实施

新实施

我希望能够对文档中的任意对象(在我的情况下是化合物)进行编号。理想情况下,这将涉及一个有点像 \ref 的命令,但您不需要 \label。第一次为特定标记名称调用 \ref 时,将创建标签并增加计数器,后续调用将返回相应的数字。

原因是没有具体的“定义”,只是应该按照它们在文本中首次出现的顺序进行编号。

\cref{one} -> 1
\cref{two} -> 2
...
\cref{one} -> 1

我认为这样做的方法如下(免责声明:我以前从未发出过新命令!)

\newcounter{cref}
\newcommand{\cref}[1]{
   IF MARKER #1 DOESN'T EXIST:
      \refstepcounter{cref}\thecref\label{#1}
   \ref{#1}
}

问题:

  1. 以前有人做过这个吗?我找不到包裹……
  2. 这是一个明智的做法吗?
  3. 是否可以检查特定标记是否尚未定义?

答案1

\newcounter{chrefcnt}
\newcommand{\chref}[1]{%
  \ifcsname chref@#1\endcsname
    % do nothing, the command is already defined
  \else
    \stepcounter{chrefcnt}%
    \expandafter\xdef\csname chref@#1\endcsname{\thechrefcnt}%
  \fi
  % now print the number
  \csname chref@#1\endcsname}

\chref{one} \chref{two} \chref{one}将得到输出 1 2 1。

最好使用前缀,以免与现有宏冲突,我使用了chref@。可能需要更多检查。在这种情况下,无需使用\label-\ref系统。我们只需定义与标签相对应的命令以扩展到指定的数字。

(感谢 lockstep 指出名称冲突。)

新实施

根据 Richard 的建议,这里有一个新的实现,其中包含一个可选的“子化合物”参数

\documentclass{article}
\makeatletter
\newcounter{chref@cnt}
\def\chrefstyle{\textbf}
\newcommand{\chref}[2][]{%
  \ifcsname chref@#2\endcsname
    % do nothing, the compound is already defined
  \else
    \stepcounter{chref@cnt}%
    \expandafter\xdef\csname chref@#2\endcsname{\arabic{chref@cnt}}%
    \expandafter\gdef\csname chrefsub@#2\endcsname{0}%
  \fi  
  % now print the number
  \chrefstyle{\csname chref@#2\endcsname}%
  \if\relax\detokenize{#1}\relax
    % do nothing, there's no optional argument
  \else
    \ifcsname chref@#2@#1\endcsname
      % do nothing, the subcompound is already defined
    \else
      \@tempcnta=\csname chrefsub@#2\endcsname
      \advance\@tempcnta\@ne
      \expandafter\xdef\csname chref@#2@#1\endcsname{\@alph\@tempcnta}%
      \expandafter\xdef\csname chrefsub@#2\endcsname{\number\@tempcnta}%
    \fi
    % now print the letter
    \chrefstyle{\csname chref@#2@#1\endcsname}
  \fi}
\makeatother

\begin{document}

\chref[X]{one} $\to$ 1a

\chref[Y]{one} $\to$ 1b

\chref{two} $\to$ 2

\chref[Z]{one} $\to$ 1c

\chref{one} $\to$ 1

\chref[A]{two} $\to$ 2a

\end{document}

对于每个主化合物,我们记住已定义的子化合物的数量,将其初始化为 0;对于\chref{one}我们定义\chrefsub@one0。如果请求子化合物但尚未定义,我们将临时计数寄存器设置为迄今为止记住的子化合物数量,\@tempcnta并将其加一。我们定义相应的控制序列(因为\chref[X]{one}它将是\chref@one@X)以扩展为 值的字母表示\@tempcnta并记住“迄今为止的子化合物”的值。

答案2

你看过chemcompounds包?这个\compound宏似乎几乎涵盖了你想要的一切。

答案3

从 egreg 的回答开始,我得出了以下结论:

\makeatletter
\newcounter{chref@cnt}
\def\chrefstyle{\textbf}
\newcommand{\chref}[2][]{%
  \ifcsname chref@#2\endcsname
    % do nothing, the compound is already defined
  \else
    \stepcounter{chref@cnt}%
    \expandafter\xdef\csname chref@#2\endcsname{\arabic{chref@cnt}}%
    \newcounter{chref@#2@cnt}%
  \fi  
  % now print the number
  \chrefstyle{\csname chref@#2\endcsname}%
  \ifthenelse{\equal{#1}{}}{}{%
    \ifcsname chref@#2@#1\endcsname
      % do nothing, the subcompound is already defined
    \else
      \stepcounter{chref@#2@cnt}%
      \expandafter\xdef\csname chref@#2@#1\endcsname{\alph{chref@#2@cnt}}%
    \fi
    % now print the letter
    \chrefstyle{\csname chref@#2@#1\endcsname}}}
\makeatother

然后:

\chref[X]{one} -> 1a
\chref[Y]{one} -> 1b
\chref[X]{one} -> 1a
\chref{one}    -> 1

答案4

回答你的第一个问题

以前有人做过这个吗?我找不到包裹……

除了 Joseph 已经提到的包(下面列表中的第二个)之外,实际上还有几个用于对化合物进行编号的包:

  1. chemnum \cmpd{main.sub}=>1a
  2. chemcompounds \declarecompound[1a]{label}\compound{label}=>1a
  3. bpchem \CNlabelsub{main}{sub}=>1a
  4. chemcono(我不能凭良心推荐这个:()

相关内容