我已经使用 LaTeX 很长时间了,我发现自己经常去这个网站解决问题。这通常包括复制粘贴包含和 的代码。我想是时候开始学习如何使用它们了\newcommand
,这样我就可以自己解决问题了!如果你真的知道代码里发生了什么,那就更好了。\newenvironment
\def
我想知道是否有任何教程或书籍介绍如何使用这些命令。或者最好的学习方法是随意处理一个文件?
提前致谢!
(这也是我使用这个网站这么长时间后第一次在这里发帖,我真的很感谢在这里发帖并试图帮助其他人的每个人!)
答案1
用于定义自定义命令和环境的 LaTeX 宏包括:
\newcommand
\newcommand*
\renewcommand
\renewcommand*
\providecommand
\providecommand*
\newenvironment
\newenvironment*
\renewenvironment
\renewenvironment*
最好从这些开始,因为您应该更喜欢它们而不是 TeX 宏,例如\def
。但是,有时只有 TeX 宏才有效。\def
一旦您很好地理解了 LaTeX 宏的工作原理,就会更容易理解何时以及为什么需要和朋友。
定义、重新定义和提供命令
\newcommand[<n>][<default>]{<definition>}
其中<n>
是参数的总数,<definition>
是命令的定义。如果<n>
没有指定,LaTeX 会假定命令不能接受参数。如果<default>
给出了,第一个参数是可选的,如果缺失,则<default>
使用。
例如,这是\tableofcontents
在 中的定义article.cls
:
\newcommand\tableofcontents{%
\section*{\contentsname
\@mkboth{%
\MakeUppercase\contentsname}{\MakeUppercase\contentsname}}%
\@starttoc{toc}%
}
该命令不接受任何参数,无论是强制的还是可选的,因此只给出宏名称\tableofcontents
和宏的定义。
下面是一个具有单个强制参数的示例\ltnews.cls
:
\newcommand\cs[1]{\texttt{\textbackslash#1}}
指#1
的是第一个参数。
这是定义新命令的示例latex.ltx
,该命令需要 2 个参数,一个是必需的,一个是可选的。如果未提供可选参数,0
则将使用的默认值#1
:
\newcommand\qbezier[2][0]{\bezier{#1}#2}
参数数量不得超过 9 个,并且使用 不能指定超过一个可选参数\newcommand
。所有其他参数都必须是必需的。此外,如果有可选参数,则必须先指定它,并且定义命令的语法始终是\mycommand[optional]{mandatory}{mandatory}{mand...
。
\newcommand
检查是否存在同名的现有命令,如果找到则产生错误。因此有一个内置检查可以防止意外覆盖现有命令。
\newcommand*
就像\newcommand
,但是它的参数不能包含段落分隔符。
要重新定义现有命令,可以使用\renewcommand
或\renewcommand*
。在这种情况下,LaTeX 会检查该命令是否已存在,如果不存在则会产生错误。
如果仅当命令不存在时才定义该命令,则可以使用\providecommand
或\providecommand*
。
定义和重新定义环境
\newenvironment{<env name>}[<n>][<default>]{<begin env>}{<end env>}
其中<env name>
是新环境的名称,<n>
是参数的数量(如果未指定则为 0),<default>
如果第一个参数是可选的,则为第一个参数的默认值(如果未指定,则所有参数都是必需的)。<begin env>
并<end env>
指定在环境开始和结束时要执行的代码。
这很像\newcommand
。<n>
不能超过 9,只有一个参数可以是可选的,并且它必须是第一个参数,并且如果已经存在同名的环境,LaTeX 会抱怨。#1
,...#9
如果适用,请参考给予环境的参数。
下面是一个包含 3 个参数的示例cuisine.sty
,所有参数都是必需的:
\newenvironment{recipe}[3]{%
\stepcounter{r@cipenumber}
\let\newstep\m@thodend
\let\recipen@wpage\newpage
\let\newpage\r@cipen@wpage
\let\0\d@grees
\let\degrees\d@grees
\let\fr\fr@ction
\let\ing\ingr@dient
\let\ingredient\ingr@dient
\let\freeform\fr@eform
\n@wpagingfalse%
\setlength{\parindent}{0pt}
\savebox{\st@pingrbox}[\R@cipeIQUWidth]{}
\savebox{\st@pmethodbox}[\R@cipeMethodWidth]{}
\ifind@xing
\addcontentsline{toc}{subsection}{#1}
\fi
\r@cipetitle{#1}{#2}{#3}
\vskip0.2cm%
\p@stingred%
}%
{%
\pr@ingred%
\ifnum\value{st@pnumber}=0% then complain!
\PackageWarning{cuisine}{The recipe did not have any steps}%
\fi%
\pagebreak[0]%
\medskip%
\@endpetrue%
}%
\newenvironment*
就像\newenvironment
,但是它的参数不能包含段落分隔符。
要重新定义现有环境,请使用\renewenvironment
或\renewenvironment*
。同样,如果环境不存在,LaTeX 会在这种情况下发出警告。
超越 LaTeX 2e
当您熟悉这些自定义方法后,您会发现自己所能做的事情是有限的。此时,开始查看\def
和朋友。在此阶段,您可能还应该查看xparse
它提供了比开发 LaTeX 3 的工作更强大和更灵活的选项。但是,一旦您熟悉了 LaTeX 2e 宏提供的可能性,这些方法将更有意义。