如何在宏中重复使用参数?

如何在宏中重复使用参数?

我有附录宏的代码:

\newcommand{\application}[1]{\refstepcounter{application}%
{
  \par\vspace{\the\baselineskip}\centering{\bfseries\scshape%
  Приложение \theapplication \par}%
  (обязательное) \par%
  #1 \par%
  \vspace{\the\baselineskip}\par}%
  \addcontentsline{toc}{section}{\scshape Приложение \theapplication ⟨here have to be #1 again⟩}%
}

我想重复使用命令名称(属性)将其添加到目录中。

答案1

请注意,在对显式字符标记进行标记之后{}在正常情况下,它们会被标记成类别代码 1(开始组)和 2(结束组)的显式字符标记),以及在对控制符号标记进行标记之后(控制符号标记是控制序列标记,其名称由类别代码不是 11(字母)的单个字符组成),.tex 输入当前行中的空格字符会被标记成空格标记(类别代码为 10(空格)和字符代码为 32 的字符标记)。空格标记反过来会在(受限)水平模式下产生水平粘合。

还要注意,LaTeX 会对 .tex 输入文件逐行进行预处理。

在预处理阶段,(La)TeX 会删除行右端的所有空格字符,然后在该行中附加一个字符,该字符在 (La)TeX 的内部字符编码方案中的代码点编号(在传统 TeX 引擎中为 ASCII,在现代 TeX 引擎中为 unicode)对应于整数参数的值\endlinechar。通常整数参数的值为\endlinechar13,而 13 是返回字符在 ASCII 和 unicode 中的代码点编号。
通常返回字符的类别代码为 5(行尾)。
如果在对类别代码为 5(行尾)的字符进行标记时,LaTeX 的读取设备处于状态 S(跳过空格),则该字符根本不会将标记插入到标记流中。如果在对类别代码 5(行尾)的字符进行标记时,LaTeX 的读取装置处于状态 N(换行),则该字符将导致将标记插入\par到标记流中(无论当前的含义是什么\par)。如果在对类别代码 5(行尾)的字符进行标记时,LaTeX 的读取装置处于状态 M(行中),则该字符将导致将空格标记插入到标记流中。(空格标记是类别代码 10(空格)和字符代码 32 的显式字符标记;32 表示空格字符在 ASCII 和 unicode 中的编码点数,它们是 (La)TeX 引擎可能使用的内部字符编码方案。)

因此,在第二行的开括号后面

\newcommand{\application}[1]{\refstepcounter{application}%
{

LaTeX 将由于\endlinechar-thingie 而插入一个回车符。

在标记该返回字符时

  • LaTeX 只会将左花括号标记为类别代码 1(开始组)的显式字符标记,因此 LaTeX 的读取装置将处于状态 M(行中间),并且
  • 该回车符的类别代码为 5(行尾)。

因此插入的回车符将被标记为空格标记。

反过来,空格标记在水平模式下产生水平粘连。

由于水平粘连位于段落末尾,因此它将被丢弃,所以无关紧要。

尽管如此,你可以通过完全不让空格标记出现来节省 (La)TeX 的一些工作。

您的命令可能也会按如下方式运行:

\newcommand{\application}[1]{%
  \refstepcounter{application}%
  {% <-begin of horizontally-centering-group
    \par
    \vspace{\baselineskip}%
    \centering
    {% <-begin of bf/sc-group
      \bfseries\scshape
      Приложение~\theapplication
      \par
    }% <-end of bf/sc-group
    (обязательное)%
    \par
    #1%
    \par
    \vspace{\baselineskip}%
    \par
  }% <-end of horizontally-centering-group
  \addcontentsline{toc}{section}{%
    {\protect\scshape Приложение\protect~\theapplication\space#1}%
  }%
}%

但你最好使用\text..命令:

\newcommand{\application}[1]{%
  \refstepcounter{application}%
  {% <-begin of horizontally-centering-group
    \par
    \vspace{\baselineskip}%
    \centering
    \textsc{\textbf{Приложение~\theapplication}}%
    \par
    (обязательное)%
    \par
    #1%
    \par
    \vspace{\baselineskip}%
    \par
  }% <-end of horizontally-centering-group
  \addcontentsline{toc}{section}{%
    \textsc{Приложение\protect~\theapplication\space#1}%
  }%
}%

无论如何,您都应该在\application-command 的文档中提到,它\application不应该嵌套在\application的参数中,因为在这种情况下,例如\addcontentsline-entries 会出错。

而且可能您不希望经常使用它,从而由于-hook 等\par而触发插入(垂直) -glue 和标记,但希望在某些地方使用 - 因此也许:\parskipeverypar\linebreak

\newcommand{\application}[1]{%
  \ifhmode\strut\fi % <- make sure the line above has some depth
  \par % <- finish the paragraph LaTeX is about to produce
       %    and switch to vertical mode.
  \refstepcounter{application}%
  %---------------------------------------------------------
  % Probably at this place locally redefine \application
  % to yield an error-message about nesting of \application
  % inside \application's argument not being allowed.
  %---------------------------------------------------------
  \vspace{\baselineskip}%
  \vbox{%
    % Things inside \vbox will always end up on same page.
    \centering
    \addcontentsline{toc}{section}{%
      \textsc{Приложение\protect~\theapplication\space#1}%
    }%
    \textsc{\textbf{Приложение~\theapplication}}%
    \linebreak % \par ?
    (обязательное)%
    \linebreak % \par ?
    #1%
    \ifhmode\strut\fi
  }%
  \vspace{\baselineskip}%
  % LaTeX should still be in vertical mode.
  % \parindent-glue/\parskip-glue etc will be added when LaTeX in
  % subsequent input finds things that cause it to enter (non-
  % restricted) horizontal mode which is the mode where you don't
  % do linebreaking manually but where LaTeX will break text of a
  % paragraph into lines for you.
}%

相关内容