以下简单文件在编译期间出现错误:
\documentclass{article}
\newcommand{\enda}{E}
\begin{document}
dddd
\end{document}
错误信息是:
! LaTeX Error: Command \enda already defined.
Or name \end... illegal, see p.192 of the manual.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.2 \newcommand{\enda}{E}
Your command was ignored.
Type I <command> <return> to replace it with another command,
or <return> to continue without it.
似乎无论我在 Latex 后面输入什么\end
(例如\endb
,\endklghfsgfljs
或任何有效的命令名称)都会产生相同的错误。当将d
ofend
更改为另一个字母(例如,s
)时,这似乎没问题。
我如何定义一个我想要的名称的命令?
笔记:我的问题不是这是否是保留字,而是如何绕过阻塞。一个稍微不同的问题是在 latex2e 中保留的结束宏名称。我无法找到符合我意图的问题。我希望遇到和我相同问题的人能比链接中的问题更容易找到这个问题。
答案1
这是由于环境的工作方式而“设计”的。不过,你可以使用 TeX\def
原语
\documentclass{article}
\def\enda{\operatorname{End}}
\begin{document}
dddd \enda
\end{document}
但前提是所调用的环境a
将是一个问题!
答案2
\NewDocumentCommand
您可以利用不检查初始的事实\end
,但只不允许定义现存的(即已经明确定义的)命令。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\newendcommand}{smO{0}om}
{
\cs_if_exist:NTF #2
{% don't want to redefine anyway
\newcommand{#2}{}%
}
{
\IfBooleanTF { #1 }
{% short
\tl_set:Nn \l__farreo_newendcommand_arg_tl { m }
}
{% long
\tl_set:Nn \l__farreo_newendcommand_arg_tl { +m }
}
\farreo_newendcommand:nnnn { #2 } { #3 } { #4 } { #5 }
}
}
\tl_new:N \l__farreo_newendcommand_arg_tl
\cs_new_protected:Nn \farreo_newendcommand:nnnn
{
\tl_if_novalue:nTF { #3 }
{% no optional argument
\exp_args:NNx
\NewExpandableDocumentCommand
#1
{ \prg_replicate:nn { #2 } { \l__farreo_newendcommand_arg_tl } }
{ #4 }
}
{
\exp_args:NNx
\NewDocumentCommand
#1
{
\exp_not:n { +O{#3} }
\prg_replicate:nn { #2 - 1 } { \l__farreo_newendcommand_arg_tl }
}
{ #4 }
}
}
\ExplSyntaxOff
\newendcommand\endenumerate[1]{x} % <-- error
\newendcommand{\endo}{E}
\newendcommand{\endopt}[2][OPT]{{\ttfamily\#1=#1, \#2=\detokenize{#2}}}
\newendcommand*{\endstar}[1]{{\ttfamily\#1=#1}}
\begin{document}
\endo
\endopt{x}
\endopt[Y]{x\par}
\endstar{x\par} % <-- error
\end{document}
当然,您可以直接使用\NewDocumentCommand
;它需要与不同的语法\newcommand
,但功能更强大。
该指令\newendcommand{\endenumerate}{}
引发错误
! LaTeX Error: Command \endenumerate already defined.
Or name \end... illegal, see p.192 of the manual.
最后一次调用\endstar{x\par}
却引发了错误
Runaway argument?
{x
! Paragraph ended before \endstar was complete.
因为\endstar
已被调用\newendcommand*
。相反,在其参数中\endopt
接受。\par
答案3
\newcommand
内部用于\@ifdefinable
检查命令是否可定义。
在其他内容下,\@ifdefinable
检查相关命令名称的前三个字母是否为e
, n
, d
。为此,\ifx
将对宏进行比较,\@qend
该宏的扩展会将这些字母作为类别代码 12(其他)的显式字符标记。
如果愿意,您可以暂时用\@qend
在您想要的命令名称的“字符串化”中未出现的标记序列覆盖定义:
\documentclass{article}
\makeatletter
\newcommand\savedqend{}
\newcommand\changeqend[1]{\let\savedqend=\@qend \long\def\@qend{#1}}%
\newcommand\restoreqend{\let\@qend=\savedqend}%
\makeatother
\changeqend{ThisStuffIsNotOfCatcodeTwelveButOfCatCodeEleven}
\newcommand{\endomorphism}{Endomorphism}
\restoreqend
\begin{document}
\endomorphism
\end{document}
\renewcommand
但如果您坚持使用 LaTeX 语法,您也可以使用:
\renewcommand
不使用\@ifdefinable
,因此不检查相关命令名称的前三个字母。只需通过 分配一个虚拟定义\def
,然后执行\renewcommand
。
以下代码提供了宏\mynicenewcommand
和,\myniceprovidecommand
它们为您执行这些操作。\renewcommand
并且\DeclareRobustCommand
不需要mynice
‑变体,因为它们不使用\@ifdefinable
:
\documentclass{article}
\makeatletter
\newcommand\myniceprovidecommand[1]{%
\edef\reserved@a{\expandafter\@gobble\string#1}%
\@ifundefined\reserved@a{\def#1{Dummy}\renewcommand#1}%
{\renewcommand\reserved@a}%
}%
\newcommand\mynicenewcommand[1]{%
\edef\reserved@a{\expandafter\@gobble\string#1}%
\@ifundefined\reserved@a{\def#1{Dummy}\renewcommand}%
{\newcommand}%
#1%
}%
\makeatother
\mynicenewcommand{\endomorphism}{Endomorphism}
\myniceprovidecommand{\endomorphism}{EndomorphismB}
\begin{document}
\endomorphism
\end{document}